// ce-1.28.2184 e289c6892f9d0029883f1e63a3da22c15c0c5100
// Copyright 2013-2016 Evernote Corp. All rights reserved.
// http://www.evernote.com

/* @preserve
 * The MIT License (MIT)
 * 
 * Copyright (c) 2013-2015 Petka Antonov
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 * 
 */
/**
 * bluebird build version 3.4.5
 * Features enabled: core, race, call_get, generators, map, nodeify, promisify, props, reduce, settle, some, using, timers, filter, any, each
*/
!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.Promise=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof _dereq_=="function"&&_dereq_;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof _dereq_=="function"&&_dereq_;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise) {
var SomePromiseArray = Promise._SomePromiseArray;
function any(promises) {
    var ret = new SomePromiseArray(promises);
    var promise = ret.promise();
    ret.setHowMany(1);
    ret.setUnwrap();
    ret.init();
    return promise;
}

Promise.any = function (promises) {
    return any(promises);
};

Promise.prototype.any = function () {
    return any(this);
};

};

},{}],2:[function(_dereq_,module,exports){
"use strict";
var firstLineError;
try {throw new Error(); } catch (e) {firstLineError = e;}
var schedule = _dereq_("./schedule");
var Queue = _dereq_("./queue");
var util = _dereq_("./util");

function Async() {
    this._customScheduler = false;
    this._isTickUsed = false;
    this._lateQueue = new Queue(16);
    this._normalQueue = new Queue(16);
    this._haveDrainedQueues = false;
    this._trampolineEnabled = true;
    var self = this;
    this.drainQueues = function () {
        self._drainQueues();
    };
    this._schedule = schedule;
}

Async.prototype.setScheduler = function(fn) {
    var prev = this._schedule;
    this._schedule = fn;
    this._customScheduler = true;
    return prev;
};

Async.prototype.hasCustomScheduler = function() {
    return this._customScheduler;
};

Async.prototype.enableTrampoline = function() {
    this._trampolineEnabled = true;
};

Async.prototype.disableTrampolineIfNecessary = function() {
    if (util.hasDevTools) {
        this._trampolineEnabled = false;
    }
};

Async.prototype.haveItemsQueued = function () {
    return this._isTickUsed || this._haveDrainedQueues;
};


Async.prototype.fatalError = function(e, isNode) {
    if (isNode) {
        process.stderr.write("Fatal " + (e instanceof Error ? e.stack : e) +
            "\n");
        process.exit(2);
    } else {
        this.throwLater(e);
    }
};

Async.prototype.throwLater = function(fn, arg) {
    if (arguments.length === 1) {
        arg = fn;
        fn = function () { throw arg; };
    }
    if (typeof setTimeout !== "undefined") {
        setTimeout(function() {
            fn(arg);
        }, 0);
    } else try {
        this._schedule(function() {
            fn(arg);
        });
    } catch (e) {
        throw new Error("No async scheduler available\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
};

function AsyncInvokeLater(fn, receiver, arg) {
    this._lateQueue.push(fn, receiver, arg);
    this._queueTick();
}

function AsyncInvoke(fn, receiver, arg) {
    this._normalQueue.push(fn, receiver, arg);
    this._queueTick();
}

function AsyncSettlePromises(promise) {
    this._normalQueue._pushOne(promise);
    this._queueTick();
}

if (!util.hasDevTools) {
    Async.prototype.invokeLater = AsyncInvokeLater;
    Async.prototype.invoke = AsyncInvoke;
    Async.prototype.settlePromises = AsyncSettlePromises;
} else {
    Async.prototype.invokeLater = function (fn, receiver, arg) {
        if (this._trampolineEnabled) {
            AsyncInvokeLater.call(this, fn, receiver, arg);
        } else {
            this._schedule(function() {
                setTimeout(function() {
                    fn.call(receiver, arg);
                }, 100);
            });
        }
    };

    Async.prototype.invoke = function (fn, receiver, arg) {
        if (this._trampolineEnabled) {
            AsyncInvoke.call(this, fn, receiver, arg);
        } else {
            this._schedule(function() {
                fn.call(receiver, arg);
            });
        }
    };

    Async.prototype.settlePromises = function(promise) {
        if (this._trampolineEnabled) {
            AsyncSettlePromises.call(this, promise);
        } else {
            this._schedule(function() {
                promise._settlePromises();
            });
        }
    };
}

Async.prototype.invokeFirst = function (fn, receiver, arg) {
    this._normalQueue.unshift(fn, receiver, arg);
    this._queueTick();
};

Async.prototype._drainQueue = function(queue) {
    while (queue.length() > 0) {
        var fn = queue.shift();
        if (typeof fn !== "function") {
            fn._settlePromises();
            continue;
        }
        var receiver = queue.shift();
        var arg = queue.shift();
        fn.call(receiver, arg);
    }
};

Async.prototype._drainQueues = function () {
    this._drainQueue(this._normalQueue);
    this._reset();
    this._haveDrainedQueues = true;
    this._drainQueue(this._lateQueue);
};

Async.prototype._queueTick = function () {
    if (!this._isTickUsed) {
        this._isTickUsed = true;
        this._schedule(this.drainQueues);
    }
};

Async.prototype._reset = function () {
    this._isTickUsed = false;
};

module.exports = Async;
module.exports.firstLineError = firstLineError;

},{"./queue":26,"./schedule":29,"./util":36}],3:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, INTERNAL, tryConvertToPromise, debug) {
var calledBind = false;
var rejectThis = function(_, e) {
    this._reject(e);
};

var targetRejected = function(e, context) {
    context.promiseRejectionQueued = true;
    context.bindingPromise._then(rejectThis, rejectThis, null, this, e);
};

var bindingResolved = function(thisArg, context) {
    if (((this._bitField & 50397184) === 0)) {
        this._resolveCallback(context.target);
    }
};

var bindingRejected = function(e, context) {
    if (!context.promiseRejectionQueued) this._reject(e);
};

Promise.prototype.bind = function (thisArg) {
    if (!calledBind) {
        calledBind = true;
        Promise.prototype._propagateFrom = debug.propagateFromFunction();
        Promise.prototype._boundValue = debug.boundValueFunction();
    }
    var maybePromise = tryConvertToPromise(thisArg);
    var ret = new Promise(INTERNAL);
    ret._propagateFrom(this, 1);
    var target = this._target();
    ret._setBoundTo(maybePromise);
    if (maybePromise instanceof Promise) {
        var context = {
            promiseRejectionQueued: false,
            promise: ret,
            target: target,
            bindingPromise: maybePromise
        };
        target._then(INTERNAL, targetRejected, undefined, ret, context);
        maybePromise._then(
            bindingResolved, bindingRejected, undefined, ret, context);
        ret._setOnCancel(maybePromise);
    } else {
        ret._resolveCallback(target);
    }
    return ret;
};

Promise.prototype._setBoundTo = function (obj) {
    if (obj !== undefined) {
        this._bitField = this._bitField | 2097152;
        this._boundTo = obj;
    } else {
        this._bitField = this._bitField & (~2097152);
    }
};

Promise.prototype._isBound = function () {
    return (this._bitField & 2097152) === 2097152;
};

Promise.bind = function (thisArg, value) {
    return Promise.resolve(value).bind(thisArg);
};
};

},{}],4:[function(_dereq_,module,exports){
"use strict";
var old;
if (typeof Promise !== "undefined") old = Promise;
function noConflict() {
    try { if (Promise === bluebird) Promise = old; }
    catch (e) {}
    return bluebird;
}
var bluebird = _dereq_("./promise")();
bluebird.noConflict = noConflict;
module.exports = bluebird;

},{"./promise":22}],5:[function(_dereq_,module,exports){
"use strict";
var cr = Object.create;
if (cr) {
    var callerCache = cr(null);
    var getterCache = cr(null);
    callerCache[" size"] = getterCache[" size"] = 0;
}

module.exports = function(Promise) {
var util = _dereq_("./util");
var canEvaluate = util.canEvaluate;
var isIdentifier = util.isIdentifier;

var getMethodCaller;
var getGetter;
if (!true) {
var makeMethodCaller = function (methodName) {
    return new Function("ensureMethod", "                                    \n\
        return function(obj) {                                               \n\
            'use strict'                                                     \n\
            var len = this.length;                                           \n\
            ensureMethod(obj, 'methodName');                                 \n\
            switch(len) {                                                    \n\
                case 1: return obj.methodName(this[0]);                      \n\
                case 2: return obj.methodName(this[0], this[1]);             \n\
                case 3: return obj.methodName(this[0], this[1], this[2]);    \n\
                case 0: return obj.methodName();                             \n\
                default:                                                     \n\
                    return obj.methodName.apply(obj, this);                  \n\
            }                                                                \n\
        };                                                                   \n\
        ".replace(/methodName/g, methodName))(ensureMethod);
};

var makeGetter = function (propertyName) {
    return new Function("obj", "                                             \n\
        'use strict';                                                        \n\
        return obj.propertyName;                                             \n\
        ".replace("propertyName", propertyName));
};

var getCompiled = function(name, compiler, cache) {
    var ret = cache[name];
    if (typeof ret !== "function") {
        if (!isIdentifier(name)) {
            return null;
        }
        ret = compiler(name);
        cache[name] = ret;
        cache[" size"]++;
        if (cache[" size"] > 512) {
            var keys = Object.keys(cache);
            for (var i = 0; i < 256; ++i) delete cache[keys[i]];
            cache[" size"] = keys.length - 256;
        }
    }
    return ret;
};

getMethodCaller = function(name) {
    return getCompiled(name, makeMethodCaller, callerCache);
};

getGetter = function(name) {
    return getCompiled(name, makeGetter, getterCache);
};
}

function ensureMethod(obj, methodName) {
    var fn;
    if (obj != null) fn = obj[methodName];
    if (typeof fn !== "function") {
        var message = "Object " + util.classString(obj) + " has no method '" +
            util.toString(methodName) + "'";
        throw new Promise.TypeError(message);
    }
    return fn;
}

function caller(obj) {
    var methodName = this.pop();
    var fn = ensureMethod(obj, methodName);
    return fn.apply(obj, this);
}
Promise.prototype.call = function (methodName) {
    var args = [].slice.call(arguments, 1);;
    if (!true) {
        if (canEvaluate) {
            var maybeCaller = getMethodCaller(methodName);
            if (maybeCaller !== null) {
                return this._then(
                    maybeCaller, undefined, undefined, args, undefined);
            }
        }
    }
    args.push(methodName);
    return this._then(caller, undefined, undefined, args, undefined);
};

function namedGetter(obj) {
    return obj[this];
}
function indexedGetter(obj) {
    var index = +this;
    if (index < 0) index = Math.max(0, index + obj.length);
    return obj[index];
}
Promise.prototype.get = function (propertyName) {
    var isIndex = (typeof propertyName === "number");
    var getter;
    if (!isIndex) {
        if (canEvaluate) {
            var maybeGetter = getGetter(propertyName);
            getter = maybeGetter !== null ? maybeGetter : namedGetter;
        } else {
            getter = namedGetter;
        }
    } else {
        getter = indexedGetter;
    }
    return this._then(getter, undefined, undefined, propertyName, undefined);
};
};

},{"./util":36}],6:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, PromiseArray, apiRejection, debug) {
var util = _dereq_("./util");
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;
var async = Promise._async;

Promise.prototype["break"] = Promise.prototype.cancel = function() {
    if (!debug.cancellation()) return this._warn("cancellation is disabled");

    var promise = this;
    var child = promise;
    while (promise._isCancellable()) {
        if (!promise._cancelBy(child)) {
            if (child._isFollowing()) {
                child._followee().cancel();
            } else {
                child._cancelBranched();
            }
            break;
        }

        var parent = promise._cancellationParent;
        if (parent == null || !parent._isCancellable()) {
            if (promise._isFollowing()) {
                promise._followee().cancel();
            } else {
                promise._cancelBranched();
            }
            break;
        } else {
            if (promise._isFollowing()) promise._followee().cancel();
            promise._setWillBeCancelled();
            child = promise;
            promise = parent;
        }
    }
};

Promise.prototype._branchHasCancelled = function() {
    this._branchesRemainingToCancel--;
};

Promise.prototype._enoughBranchesHaveCancelled = function() {
    return this._branchesRemainingToCancel === undefined ||
           this._branchesRemainingToCancel <= 0;
};

Promise.prototype._cancelBy = function(canceller) {
    if (canceller === this) {
        this._branchesRemainingToCancel = 0;
        this._invokeOnCancel();
        return true;
    } else {
        this._branchHasCancelled();
        if (this._enoughBranchesHaveCancelled()) {
            this._invokeOnCancel();
            return true;
        }
    }
    return false;
};

Promise.prototype._cancelBranched = function() {
    if (this._enoughBranchesHaveCancelled()) {
        this._cancel();
    }
};

Promise.prototype._cancel = function() {
    if (!this._isCancellable()) return;
    this._setCancelled();
    async.invoke(this._cancelPromises, this, undefined);
};

Promise.prototype._cancelPromises = function() {
    if (this._length() > 0) this._settlePromises();
};

Promise.prototype._unsetOnCancel = function() {
    this._onCancelField = undefined;
};

Promise.prototype._isCancellable = function() {
    return this.isPending() && !this._isCancelled();
};

Promise.prototype.isCancellable = function() {
    return this.isPending() && !this.isCancelled();
};

Promise.prototype._doInvokeOnCancel = function(onCancelCallback, internalOnly) {
    if (util.isArray(onCancelCallback)) {
        for (var i = 0; i < onCancelCallback.length; ++i) {
            this._doInvokeOnCancel(onCancelCallback[i], internalOnly);
        }
    } else if (onCancelCallback !== undefined) {
        if (typeof onCancelCallback === "function") {
            if (!internalOnly) {
                var e = tryCatch(onCancelCallback).call(this._boundValue());
                if (e === errorObj) {
                    this._attachExtraTrace(e.e);
                    async.throwLater(e.e);
                }
            }
        } else {
            onCancelCallback._resultCancelled(this);
        }
    }
};

Promise.prototype._invokeOnCancel = function() {
    var onCancelCallback = this._onCancel();
    this._unsetOnCancel();
    async.invoke(this._doInvokeOnCancel, this, onCancelCallback);
};

Promise.prototype._invokeInternalOnCancel = function() {
    if (this._isCancellable()) {
        this._doInvokeOnCancel(this._onCancel(), true);
        this._unsetOnCancel();
    }
};

Promise.prototype._resultCancelled = function() {
    this.cancel();
};

};

},{"./util":36}],7:[function(_dereq_,module,exports){
"use strict";
module.exports = function(NEXT_FILTER) {
var util = _dereq_("./util");
var getKeys = _dereq_("./es5").keys;
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;

function catchFilter(instances, cb, promise) {
    return function(e) {
        var boundTo = promise._boundValue();
        predicateLoop: for (var i = 0; i < instances.length; ++i) {
            var item = instances[i];

            if (item === Error ||
                (item != null && item.prototype instanceof Error)) {
                if (e instanceof item) {
                    return tryCatch(cb).call(boundTo, e);
                }
            } else if (typeof item === "function") {
                var matchesPredicate = tryCatch(item).call(boundTo, e);
                if (matchesPredicate === errorObj) {
                    return matchesPredicate;
                } else if (matchesPredicate) {
                    return tryCatch(cb).call(boundTo, e);
                }
            } else if (util.isObject(e)) {
                var keys = getKeys(item);
                for (var j = 0; j < keys.length; ++j) {
                    var key = keys[j];
                    if (item[key] != e[key]) {
                        continue predicateLoop;
                    }
                }
                return tryCatch(cb).call(boundTo, e);
            }
        }
        return NEXT_FILTER;
    };
}

return catchFilter;
};

},{"./es5":13,"./util":36}],8:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise) {
var longStackTraces = false;
var contextStack = [];

Promise.prototype._promiseCreated = function() {};
Promise.prototype._pushContext = function() {};
Promise.prototype._popContext = function() {return null;};
Promise._peekContext = Promise.prototype._peekContext = function() {};

function Context() {
    this._trace = new Context.CapturedTrace(peekContext());
}
Context.prototype._pushContext = function () {
    if (this._trace !== undefined) {
        this._trace._promiseCreated = null;
        contextStack.push(this._trace);
    }
};

Context.prototype._popContext = function () {
    if (this._trace !== undefined) {
        var trace = contextStack.pop();
        var ret = trace._promiseCreated;
        trace._promiseCreated = null;
        return ret;
    }
    return null;
};

function createContext() {
    if (longStackTraces) return new Context();
}

function peekContext() {
    var lastIndex = contextStack.length - 1;
    if (lastIndex >= 0) {
        return contextStack[lastIndex];
    }
    return undefined;
}
Context.CapturedTrace = null;
Context.create = createContext;
Context.deactivateLongStackTraces = function() {};
Context.activateLongStackTraces = function() {
    var Promise_pushContext = Promise.prototype._pushContext;
    var Promise_popContext = Promise.prototype._popContext;
    var Promise_PeekContext = Promise._peekContext;
    var Promise_peekContext = Promise.prototype._peekContext;
    var Promise_promiseCreated = Promise.prototype._promiseCreated;
    Context.deactivateLongStackTraces = function() {
        Promise.prototype._pushContext = Promise_pushContext;
        Promise.prototype._popContext = Promise_popContext;
        Promise._peekContext = Promise_PeekContext;
        Promise.prototype._peekContext = Promise_peekContext;
        Promise.prototype._promiseCreated = Promise_promiseCreated;
        longStackTraces = false;
    };
    longStackTraces = true;
    Promise.prototype._pushContext = Context.prototype._pushContext;
    Promise.prototype._popContext = Context.prototype._popContext;
    Promise._peekContext = Promise.prototype._peekContext = peekContext;
    Promise.prototype._promiseCreated = function() {
        var ctx = this._peekContext();
        if (ctx && ctx._promiseCreated == null) ctx._promiseCreated = this;
    };
};
return Context;
};

},{}],9:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, Context) {
var getDomain = Promise._getDomain;
var async = Promise._async;
var Warning = _dereq_("./errors").Warning;
var util = _dereq_("./util");
var canAttachTrace = util.canAttachTrace;
var unhandledRejectionHandled;
var possiblyUnhandledRejection;
var bluebirdFramePattern =
    /[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/;
var nodeFramePattern = /\((?:timers\.js):\d+:\d+\)/;
var parseLinePattern = /[\/<\(](.+?):(\d+):(\d+)\)?\s*$/;
var stackFramePattern = null;
var formatStack = null;
var indentStackFrames = false;
var printWarning;
var debugging = !!(util.env("BLUEBIRD_DEBUG") != 0 &&
                        (true ||
                         util.env("BLUEBIRD_DEBUG") ||
                         util.env("NODE_ENV") === "development"));

var warnings = !!(util.env("BLUEBIRD_WARNINGS") != 0 &&
    (debugging || util.env("BLUEBIRD_WARNINGS")));

var longStackTraces = !!(util.env("BLUEBIRD_LONG_STACK_TRACES") != 0 &&
    (debugging || util.env("BLUEBIRD_LONG_STACK_TRACES")));

var wForgottenReturn = util.env("BLUEBIRD_W_FORGOTTEN_RETURN") != 0 &&
    (warnings || !!util.env("BLUEBIRD_W_FORGOTTEN_RETURN"));

Promise.prototype.suppressUnhandledRejections = function() {
    var target = this._target();
    target._bitField = ((target._bitField & (~1048576)) |
                      524288);
};

Promise.prototype._ensurePossibleRejectionHandled = function () {
    if ((this._bitField & 524288) !== 0) return;
    this._setRejectionIsUnhandled();
    async.invokeLater(this._notifyUnhandledRejection, this, undefined);
};

Promise.prototype._notifyUnhandledRejectionIsHandled = function () {
    fireRejectionEvent("rejectionHandled",
                                  unhandledRejectionHandled, undefined, this);
};

Promise.prototype._setReturnedNonUndefined = function() {
    this._bitField = this._bitField | 268435456;
};

Promise.prototype._returnedNonUndefined = function() {
    return (this._bitField & 268435456) !== 0;
};

Promise.prototype._notifyUnhandledRejection = function () {
    if (this._isRejectionUnhandled()) {
        var reason = this._settledValue();
        this._setUnhandledRejectionIsNotified();
        fireRejectionEvent("unhandledRejection",
                                      possiblyUnhandledRejection, reason, this);
    }
};

Promise.prototype._setUnhandledRejectionIsNotified = function () {
    this._bitField = this._bitField | 262144;
};

Promise.prototype._unsetUnhandledRejectionIsNotified = function () {
    this._bitField = this._bitField & (~262144);
};

Promise.prototype._isUnhandledRejectionNotified = function () {
    return (this._bitField & 262144) > 0;
};

Promise.prototype._setRejectionIsUnhandled = function () {
    this._bitField = this._bitField | 1048576;
};

Promise.prototype._unsetRejectionIsUnhandled = function () {
    this._bitField = this._bitField & (~1048576);
    if (this._isUnhandledRejectionNotified()) {
        this._unsetUnhandledRejectionIsNotified();
        this._notifyUnhandledRejectionIsHandled();
    }
};

Promise.prototype._isRejectionUnhandled = function () {
    return (this._bitField & 1048576) > 0;
};

Promise.prototype._warn = function(message, shouldUseOwnTrace, promise) {
    return warn(message, shouldUseOwnTrace, promise || this);
};

Promise.onPossiblyUnhandledRejection = function (fn) {
    var domain = getDomain();
    possiblyUnhandledRejection =
        typeof fn === "function" ? (domain === null ?
                                            fn : util.domainBind(domain, fn))
                                 : undefined;
};

Promise.onUnhandledRejectionHandled = function (fn) {
    var domain = getDomain();
    unhandledRejectionHandled =
        typeof fn === "function" ? (domain === null ?
                                            fn : util.domainBind(domain, fn))
                                 : undefined;
};

var disableLongStackTraces = function() {};
Promise.longStackTraces = function () {
    if (async.haveItemsQueued() && !config.longStackTraces) {
        throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
    if (!config.longStackTraces && longStackTracesIsSupported()) {
        var Promise_captureStackTrace = Promise.prototype._captureStackTrace;
        var Promise_attachExtraTrace = Promise.prototype._attachExtraTrace;
        config.longStackTraces = true;
        disableLongStackTraces = function() {
            if (async.haveItemsQueued() && !config.longStackTraces) {
                throw new Error("cannot enable long stack traces after promises have been created\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
            }
            Promise.prototype._captureStackTrace = Promise_captureStackTrace;
            Promise.prototype._attachExtraTrace = Promise_attachExtraTrace;
            Context.deactivateLongStackTraces();
            async.enableTrampoline();
            config.longStackTraces = false;
        };
        Promise.prototype._captureStackTrace = longStackTracesCaptureStackTrace;
        Promise.prototype._attachExtraTrace = longStackTracesAttachExtraTrace;
        Context.activateLongStackTraces();
        async.disableTrampolineIfNecessary();
    }
};

Promise.hasLongStackTraces = function () {
    return config.longStackTraces && longStackTracesIsSupported();
};

var fireDomEvent = (function() {
    try {
        if (typeof CustomEvent === "function") {
            var event = new CustomEvent("CustomEvent");
            util.global.dispatchEvent(event);
            return function(name, event) {
                var domEvent = new CustomEvent(name.toLowerCase(), {
                    detail: event,
                    cancelable: true
                });
                return !util.global.dispatchEvent(domEvent);
            };
        } else if (typeof Event === "function") {
            var event = new Event("CustomEvent");
            util.global.dispatchEvent(event);
            return function(name, event) {
                var domEvent = new Event(name.toLowerCase(), {
                    cancelable: true
                });
                domEvent.detail = event;
                return !util.global.dispatchEvent(domEvent);
            };
        } else {
            var event = document.createEvent("CustomEvent");
            event.initCustomEvent("testingtheevent", false, true, {});
            util.global.dispatchEvent(event);
            return function(name, event) {
                var domEvent = document.createEvent("CustomEvent");
                domEvent.initCustomEvent(name.toLowerCase(), false, true,
                    event);
                return !util.global.dispatchEvent(domEvent);
            };
        }
    } catch (e) {}
    return function() {
        return false;
    };
})();

var fireGlobalEvent = (function() {
    if (util.isNode) {
        return function() {
            return process.emit.apply(process, arguments);
        };
    } else {
        if (!util.global) {
            return function() {
                return false;
            };
        }
        return function(name) {
            var methodName = "on" + name.toLowerCase();
            var method = util.global[methodName];
            if (!method) return false;
            method.apply(util.global, [].slice.call(arguments, 1));
            return true;
        };
    }
})();

function generatePromiseLifecycleEventObject(name, promise) {
    return {promise: promise};
}

var eventToObjectGenerator = {
    promiseCreated: generatePromiseLifecycleEventObject,
    promiseFulfilled: generatePromiseLifecycleEventObject,
    promiseRejected: generatePromiseLifecycleEventObject,
    promiseResolved: generatePromiseLifecycleEventObject,
    promiseCancelled: generatePromiseLifecycleEventObject,
    promiseChained: function(name, promise, child) {
        return {promise: promise, child: child};
    },
    warning: function(name, warning) {
        return {warning: warning};
    },
    unhandledRejection: function (name, reason, promise) {
        return {reason: reason, promise: promise};
    },
    rejectionHandled: generatePromiseLifecycleEventObject
};

var activeFireEvent = function (name) {
    var globalEventFired = false;
    try {
        globalEventFired = fireGlobalEvent.apply(null, arguments);
    } catch (e) {
        async.throwLater(e);
        globalEventFired = true;
    }

    var domEventFired = false;
    try {
        domEventFired = fireDomEvent(name,
                    eventToObjectGenerator[name].apply(null, arguments));
    } catch (e) {
        async.throwLater(e);
        domEventFired = true;
    }

    return domEventFired || globalEventFired;
};

Promise.config = function(opts) {
    opts = Object(opts);
    if ("longStackTraces" in opts) {
        if (opts.longStackTraces) {
            Promise.longStackTraces();
        } else if (!opts.longStackTraces && Promise.hasLongStackTraces()) {
            disableLongStackTraces();
        }
    }
    if ("warnings" in opts) {
        var warningsOption = opts.warnings;
        config.warnings = !!warningsOption;
        wForgottenReturn = config.warnings;

        if (util.isObject(warningsOption)) {
            if ("wForgottenReturn" in warningsOption) {
                wForgottenReturn = !!warningsOption.wForgottenReturn;
            }
        }
    }
    if ("cancellation" in opts && opts.cancellation && !config.cancellation) {
        if (async.haveItemsQueued()) {
            throw new Error(
                "cannot enable cancellation after promises are in use");
        }
        Promise.prototype._clearCancellationData =
            cancellationClearCancellationData;
        Promise.prototype._propagateFrom = cancellationPropagateFrom;
        Promise.prototype._onCancel = cancellationOnCancel;
        Promise.prototype._setOnCancel = cancellationSetOnCancel;
        Promise.prototype._attachCancellationCallback =
            cancellationAttachCancellationCallback;
        Promise.prototype._execute = cancellationExecute;
        propagateFromFunction = cancellationPropagateFrom;
        config.cancellation = true;
    }
    if ("monitoring" in opts) {
        if (opts.monitoring && !config.monitoring) {
            config.monitoring = true;
            Promise.prototype._fireEvent = activeFireEvent;
        } else if (!opts.monitoring && config.monitoring) {
            config.monitoring = false;
            Promise.prototype._fireEvent = defaultFireEvent;
        }
    }
};

function defaultFireEvent() { return false; }

Promise.prototype._fireEvent = defaultFireEvent;
Promise.prototype._execute = function(executor, resolve, reject) {
    try {
        executor(resolve, reject);
    } catch (e) {
        return e;
    }
};
Promise.prototype._onCancel = function () {};
Promise.prototype._setOnCancel = function (handler) { ; };
Promise.prototype._attachCancellationCallback = function(onCancel) {
    ;
};
Promise.prototype._captureStackTrace = function () {};
Promise.prototype._attachExtraTrace = function () {};
Promise.prototype._clearCancellationData = function() {};
Promise.prototype._propagateFrom = function (parent, flags) {
    ;
    ;
};

function cancellationExecute(executor, resolve, reject) {
    var promise = this;
    try {
        executor(resolve, reject, function(onCancel) {
            if (typeof onCancel !== "function") {
                throw new TypeError("onCancel must be a function, got: " +
                                    util.toString(onCancel));
            }
            promise._attachCancellationCallback(onCancel);
        });
    } catch (e) {
        return e;
    }
}

function cancellationAttachCancellationCallback(onCancel) {
    if (!this._isCancellable()) return this;

    var previousOnCancel = this._onCancel();
    if (previousOnCancel !== undefined) {
        if (util.isArray(previousOnCancel)) {
            previousOnCancel.push(onCancel);
        } else {
            this._setOnCancel([previousOnCancel, onCancel]);
        }
    } else {
        this._setOnCancel(onCancel);
    }
}

function cancellationOnCancel() {
    return this._onCancelField;
}

function cancellationSetOnCancel(onCancel) {
    this._onCancelField = onCancel;
}

function cancellationClearCancellationData() {
    this._cancellationParent = undefined;
    this._onCancelField = undefined;
}

function cancellationPropagateFrom(parent, flags) {
    if ((flags & 1) !== 0) {
        this._cancellationParent = parent;
        var branchesRemainingToCancel = parent._branchesRemainingToCancel;
        if (branchesRemainingToCancel === undefined) {
            branchesRemainingToCancel = 0;
        }
        parent._branchesRemainingToCancel = branchesRemainingToCancel + 1;
    }
    if ((flags & 2) !== 0 && parent._isBound()) {
        this._setBoundTo(parent._boundTo);
    }
}

function bindingPropagateFrom(parent, flags) {
    if ((flags & 2) !== 0 && parent._isBound()) {
        this._setBoundTo(parent._boundTo);
    }
}
var propagateFromFunction = bindingPropagateFrom;

function boundValueFunction() {
    var ret = this._boundTo;
    if (ret !== undefined) {
        if (ret instanceof Promise) {
            if (ret.isFulfilled()) {
                return ret.value();
            } else {
                return undefined;
            }
        }
    }
    return ret;
}

function longStackTracesCaptureStackTrace() {
    this._trace = new CapturedTrace(this._peekContext());
}

function longStackTracesAttachExtraTrace(error, ignoreSelf) {
    if (canAttachTrace(error)) {
        var trace = this._trace;
        if (trace !== undefined) {
            if (ignoreSelf) trace = trace._parent;
        }
        if (trace !== undefined) {
            trace.attachExtraTrace(error);
        } else if (!error.__stackCleaned__) {
            var parsed = parseStackAndMessage(error);
            util.notEnumerableProp(error, "stack",
                parsed.message + "\n" + parsed.stack.join("\n"));
            util.notEnumerableProp(error, "__stackCleaned__", true);
        }
    }
}

function checkForgottenReturns(returnValue, promiseCreated, name, promise,
                               parent) {
    if (returnValue === undefined && promiseCreated !== null &&
        wForgottenReturn) {
        if (parent !== undefined && parent._returnedNonUndefined()) return;
        if ((promise._bitField & 65535) === 0) return;

        if (name) name = name + " ";
        var handlerLine = "";
        var creatorLine = "";
        if (promiseCreated._trace) {
            var traceLines = promiseCreated._trace.stack.split("\n");
            var stack = cleanStack(traceLines);
            for (var i = stack.length - 1; i >= 0; --i) {
                var line = stack[i];
                if (!nodeFramePattern.test(line)) {
                    var lineMatches = line.match(parseLinePattern);
                    if (lineMatches) {
                        handlerLine  = "at " + lineMatches[1] +
                            ":" + lineMatches[2] + ":" + lineMatches[3] + " ";
                    }
                    break;
                }
            }

            if (stack.length > 0) {
                var firstUserLine = stack[0];
                for (var i = 0; i < traceLines.length; ++i) {

                    if (traceLines[i] === firstUserLine) {
                        if (i > 0) {
                            creatorLine = "\n" + traceLines[i - 1];
                        }
                        break;
                    }
                }

            }
        }
        var msg = "a promise was created in a " + name +
            "handler " + handlerLine + "but was not returned from it, " +
            "see http://goo.gl/rRqMUw" +
            creatorLine;
        promise._warn(msg, true, promiseCreated);
    }
}

function deprecated(name, replacement) {
    var message = name +
        " is deprecated and will be removed in a future version.";
    if (replacement) message += " Use " + replacement + " instead.";
    return warn(message);
}

function warn(message, shouldUseOwnTrace, promise) {
    if (!config.warnings) return;
    var warning = new Warning(message);
    var ctx;
    if (shouldUseOwnTrace) {
        promise._attachExtraTrace(warning);
    } else if (config.longStackTraces && (ctx = Promise._peekContext())) {
        ctx.attachExtraTrace(warning);
    } else {
        var parsed = parseStackAndMessage(warning);
        warning.stack = parsed.message + "\n" + parsed.stack.join("\n");
    }

    if (!activeFireEvent("warning", warning)) {
        formatAndLogError(warning, "", true);
    }
}

function reconstructStack(message, stacks) {
    for (var i = 0; i < stacks.length - 1; ++i) {
        stacks[i].push("From previous event:");
        stacks[i] = stacks[i].join("\n");
    }
    if (i < stacks.length) {
        stacks[i] = stacks[i].join("\n");
    }
    return message + "\n" + stacks.join("\n");
}

function removeDuplicateOrEmptyJumps(stacks) {
    for (var i = 0; i < stacks.length; ++i) {
        if (stacks[i].length === 0 ||
            ((i + 1 < stacks.length) && stacks[i][0] === stacks[i+1][0])) {
            stacks.splice(i, 1);
            i--;
        }
    }
}

function removeCommonRoots(stacks) {
    var current = stacks[0];
    for (var i = 1; i < stacks.length; ++i) {
        var prev = stacks[i];
        var currentLastIndex = current.length - 1;
        var currentLastLine = current[currentLastIndex];
        var commonRootMeetPoint = -1;

        for (var j = prev.length - 1; j >= 0; --j) {
            if (prev[j] === currentLastLine) {
                commonRootMeetPoint = j;
                break;
            }
        }

        for (var j = commonRootMeetPoint; j >= 0; --j) {
            var line = prev[j];
            if (current[currentLastIndex] === line) {
                current.pop();
                currentLastIndex--;
            } else {
                break;
            }
        }
        current = prev;
    }
}

function cleanStack(stack) {
    var ret = [];
    for (var i = 0; i < stack.length; ++i) {
        var line = stack[i];
        var isTraceLine = "    (No stack trace)" === line ||
            stackFramePattern.test(line);
        var isInternalFrame = isTraceLine && shouldIgnore(line);
        if (isTraceLine && !isInternalFrame) {
            if (indentStackFrames && line.charAt(0) !== " ") {
                line = "    " + line;
            }
            ret.push(line);
        }
    }
    return ret;
}

function stackFramesAsArray(error) {
    var stack = error.stack.replace(/\s+$/g, "").split("\n");
    for (var i = 0; i < stack.length; ++i) {
        var line = stack[i];
        if ("    (No stack trace)" === line || stackFramePattern.test(line)) {
            break;
        }
    }
    if (i > 0) {
        stack = stack.slice(i);
    }
    return stack;
}

function parseStackAndMessage(error) {
    var stack = error.stack;
    var message = error.toString();
    stack = typeof stack === "string" && stack.length > 0
                ? stackFramesAsArray(error) : ["    (No stack trace)"];
    return {
        message: message,
        stack: cleanStack(stack)
    };
}

function formatAndLogError(error, title, isSoft) {
    if (typeof console !== "undefined") {
        var message;
        if (util.isObject(error)) {
            var stack = error.stack;
            message = title + formatStack(stack, error);
        } else {
            message = title + String(error);
        }
        if (typeof printWarning === "function") {
            printWarning(message, isSoft);
        } else if (typeof console.log === "function" ||
            typeof console.log === "object") {
            console.log(message);
        }
    }
}

function fireRejectionEvent(name, localHandler, reason, promise) {
    var localEventFired = false;
    try {
        if (typeof localHandler === "function") {
            localEventFired = true;
            if (name === "rejectionHandled") {
                localHandler(promise);
            } else {
                localHandler(reason, promise);
            }
        }
    } catch (e) {
        async.throwLater(e);
    }

    if (name === "unhandledRejection") {
        if (!activeFireEvent(name, reason, promise) && !localEventFired) {
            formatAndLogError(reason, "Unhandled rejection ");
        }
    } else {
        activeFireEvent(name, promise);
    }
}

function formatNonError(obj) {
    var str;
    if (typeof obj === "function") {
        str = "[function " +
            (obj.name || "anonymous") +
            "]";
    } else {
        str = obj && typeof obj.toString === "function"
            ? obj.toString() : util.toString(obj);
        var ruselessToString = /\[object [a-zA-Z0-9$_]+\]/;
        if (ruselessToString.test(str)) {
            try {
                var newStr = JSON.stringify(obj);
                str = newStr;
            }
            catch(e) {

            }
        }
        if (str.length === 0) {
            str = "(empty array)";
        }
    }
    return ("(<" + snip(str) + ">, no stack trace)");
}

function snip(str) {
    var maxChars = 41;
    if (str.length < maxChars) {
        return str;
    }
    return str.substr(0, maxChars - 3) + "...";
}

function longStackTracesIsSupported() {
    return typeof captureStackTrace === "function";
}

var shouldIgnore = function() { return false; };
var parseLineInfoRegex = /[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;
function parseLineInfo(line) {
    var matches = line.match(parseLineInfoRegex);
    if (matches) {
        return {
            fileName: matches[1],
            line: parseInt(matches[2], 10)
        };
    }
}

function setBounds(firstLineError, lastLineError) {
    if (!longStackTracesIsSupported()) return;
    var firstStackLines = firstLineError.stack.split("\n");
    var lastStackLines = lastLineError.stack.split("\n");
    var firstIndex = -1;
    var lastIndex = -1;
    var firstFileName;
    var lastFileName;
    for (var i = 0; i < firstStackLines.length; ++i) {
        var result = parseLineInfo(firstStackLines[i]);
        if (result) {
            firstFileName = result.fileName;
            firstIndex = result.line;
            break;
        }
    }
    for (var i = 0; i < lastStackLines.length; ++i) {
        var result = parseLineInfo(lastStackLines[i]);
        if (result) {
            lastFileName = result.fileName;
            lastIndex = result.line;
            break;
        }
    }
    if (firstIndex < 0 || lastIndex < 0 || !firstFileName || !lastFileName ||
        firstFileName !== lastFileName || firstIndex >= lastIndex) {
        return;
    }

    shouldIgnore = function(line) {
        if (bluebirdFramePattern.test(line)) return true;
        var info = parseLineInfo(line);
        if (info) {
            if (info.fileName === firstFileName &&
                (firstIndex <= info.line && info.line <= lastIndex)) {
                return true;
            }
        }
        return false;
    };
}

function CapturedTrace(parent) {
    this._parent = parent;
    this._promisesCreated = 0;
    var length = this._length = 1 + (parent === undefined ? 0 : parent._length);
    captureStackTrace(this, CapturedTrace);
    if (length > 32) this.uncycle();
}
util.inherits(CapturedTrace, Error);
Context.CapturedTrace = CapturedTrace;

CapturedTrace.prototype.uncycle = function() {
    var length = this._length;
    if (length < 2) return;
    var nodes = [];
    var stackToIndex = {};

    for (var i = 0, node = this; node !== undefined; ++i) {
        nodes.push(node);
        node = node._parent;
    }
    length = this._length = i;
    for (var i = length - 1; i >= 0; --i) {
        var stack = nodes[i].stack;
        if (stackToIndex[stack] === undefined) {
            stackToIndex[stack] = i;
        }
    }
    for (var i = 0; i < length; ++i) {
        var currentStack = nodes[i].stack;
        var index = stackToIndex[currentStack];
        if (index !== undefined && index !== i) {
            if (index > 0) {
                nodes[index - 1]._parent = undefined;
                nodes[index - 1]._length = 1;
            }
            nodes[i]._parent = undefined;
            nodes[i]._length = 1;
            var cycleEdgeNode = i > 0 ? nodes[i - 1] : this;

            if (index < length - 1) {
                cycleEdgeNode._parent = nodes[index + 1];
                cycleEdgeNode._parent.uncycle();
                cycleEdgeNode._length =
                    cycleEdgeNode._parent._length + 1;
            } else {
                cycleEdgeNode._parent = undefined;
                cycleEdgeNode._length = 1;
            }
            var currentChildLength = cycleEdgeNode._length + 1;
            for (var j = i - 2; j >= 0; --j) {
                nodes[j]._length = currentChildLength;
                currentChildLength++;
            }
            return;
        }
    }
};

CapturedTrace.prototype.attachExtraTrace = function(error) {
    if (error.__stackCleaned__) return;
    this.uncycle();
    var parsed = parseStackAndMessage(error);
    var message = parsed.message;
    var stacks = [parsed.stack];

    var trace = this;
    while (trace !== undefined) {
        stacks.push(cleanStack(trace.stack.split("\n")));
        trace = trace._parent;
    }
    removeCommonRoots(stacks);
    removeDuplicateOrEmptyJumps(stacks);
    util.notEnumerableProp(error, "stack", reconstructStack(message, stacks));
    util.notEnumerableProp(error, "__stackCleaned__", true);
};

var captureStackTrace = (function stackDetection() {
    var v8stackFramePattern = /^\s*at\s*/;
    var v8stackFormatter = function(stack, error) {
        if (typeof stack === "string") return stack;

        if (error.name !== undefined &&
            error.message !== undefined) {
            return error.toString();
        }
        return formatNonError(error);
    };

    if (typeof Error.stackTraceLimit === "number" &&
        typeof Error.captureStackTrace === "function") {
        Error.stackTraceLimit += 6;
        stackFramePattern = v8stackFramePattern;
        formatStack = v8stackFormatter;
        var captureStackTrace = Error.captureStackTrace;

        shouldIgnore = function(line) {
            return bluebirdFramePattern.test(line);
        };
        return function(receiver, ignoreUntil) {
            Error.stackTraceLimit += 6;
            captureStackTrace(receiver, ignoreUntil);
            Error.stackTraceLimit -= 6;
        };
    }
    var err = new Error();

    if (typeof err.stack === "string" &&
        err.stack.split("\n")[0].indexOf("stackDetection@") >= 0) {
        stackFramePattern = /@/;
        formatStack = v8stackFormatter;
        indentStackFrames = true;
        return function captureStackTrace(o) {
            o.stack = new Error().stack;
        };
    }

    var hasStackAfterThrow;
    try { throw new Error(); }
    catch(e) {
        hasStackAfterThrow = ("stack" in e);
    }
    if (!("stack" in err) && hasStackAfterThrow &&
        typeof Error.stackTraceLimit === "number") {
        stackFramePattern = v8stackFramePattern;
        formatStack = v8stackFormatter;
        return function captureStackTrace(o) {
            Error.stackTraceLimit += 6;
            try { throw new Error(); }
            catch(e) { o.stack = e.stack; }
            Error.stackTraceLimit -= 6;
        };
    }

    formatStack = function(stack, error) {
        if (typeof stack === "string") return stack;

        if ((typeof error === "object" ||
            typeof error === "function") &&
            error.name !== undefined &&
            error.message !== undefined) {
            return error.toString();
        }
        return formatNonError(error);
    };

    return null;

})([]);

if (typeof console !== "undefined" && typeof console.warn !== "undefined") {
    printWarning = function (message) {
        console.warn(message);
    };
    if (util.isNode && process.stderr.isTTY) {
        printWarning = function(message, isSoft) {
            var color = isSoft ? "\u001b[33m" : "\u001b[31m";
            console.warn(color + message + "\u001b[0m\n");
        };
    } else if (!util.isNode && typeof (new Error().stack) === "string") {
        printWarning = function(message, isSoft) {
            console.warn("%c" + message,
                        isSoft ? "color: darkorange" : "color: red");
        };
    }
}

var config = {
    warnings: warnings,
    longStackTraces: false,
    cancellation: false,
    monitoring: false
};

if (longStackTraces) Promise.longStackTraces();

return {
    longStackTraces: function() {
        return config.longStackTraces;
    },
    warnings: function() {
        return config.warnings;
    },
    cancellation: function() {
        return config.cancellation;
    },
    monitoring: function() {
        return config.monitoring;
    },
    propagateFromFunction: function() {
        return propagateFromFunction;
    },
    boundValueFunction: function() {
        return boundValueFunction;
    },
    checkForgottenReturns: checkForgottenReturns,
    setBounds: setBounds,
    warn: warn,
    deprecated: deprecated,
    CapturedTrace: CapturedTrace,
    fireDomEvent: fireDomEvent,
    fireGlobalEvent: fireGlobalEvent
};
};

},{"./errors":12,"./util":36}],10:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise) {
function returner() {
    return this.value;
}
function thrower() {
    throw this.reason;
}

Promise.prototype["return"] =
Promise.prototype.thenReturn = function (value) {
    if (value instanceof Promise) value.suppressUnhandledRejections();
    return this._then(
        returner, undefined, undefined, {value: value}, undefined);
};

Promise.prototype["throw"] =
Promise.prototype.thenThrow = function (reason) {
    return this._then(
        thrower, undefined, undefined, {reason: reason}, undefined);
};

Promise.prototype.catchThrow = function (reason) {
    if (arguments.length <= 1) {
        return this._then(
            undefined, thrower, undefined, {reason: reason}, undefined);
    } else {
        var _reason = arguments[1];
        var handler = function() {throw _reason;};
        return this.caught(reason, handler);
    }
};

Promise.prototype.catchReturn = function (value) {
    if (arguments.length <= 1) {
        if (value instanceof Promise) value.suppressUnhandledRejections();
        return this._then(
            undefined, returner, undefined, {value: value}, undefined);
    } else {
        var _value = arguments[1];
        if (_value instanceof Promise) _value.suppressUnhandledRejections();
        var handler = function() {return _value;};
        return this.caught(value, handler);
    }
};
};

},{}],11:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, INTERNAL) {
var PromiseReduce = Promise.reduce;
var PromiseAll = Promise.all;

function promiseAllThis() {
    return PromiseAll(this);
}

function PromiseMapSeries(promises, fn) {
    return PromiseReduce(promises, fn, INTERNAL, INTERNAL);
}

Promise.prototype.each = function (fn) {
    return PromiseReduce(this, fn, INTERNAL, 0)
              ._then(promiseAllThis, undefined, undefined, this, undefined);
};

Promise.prototype.mapSeries = function (fn) {
    return PromiseReduce(this, fn, INTERNAL, INTERNAL);
};

Promise.each = function (promises, fn) {
    return PromiseReduce(promises, fn, INTERNAL, 0)
              ._then(promiseAllThis, undefined, undefined, promises, undefined);
};

Promise.mapSeries = PromiseMapSeries;
};


},{}],12:[function(_dereq_,module,exports){
"use strict";
var es5 = _dereq_("./es5");
var Objectfreeze = es5.freeze;
var util = _dereq_("./util");
var inherits = util.inherits;
var notEnumerableProp = util.notEnumerableProp;

function subError(nameProperty, defaultMessage) {
    function SubError(message) {
        if (!(this instanceof SubError)) return new SubError(message);
        notEnumerableProp(this, "message",
            typeof message === "string" ? message : defaultMessage);
        notEnumerableProp(this, "name", nameProperty);
        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, this.constructor);
        } else {
            Error.call(this);
        }
    }
    inherits(SubError, Error);
    return SubError;
}

var _TypeError, _RangeError;
var Warning = subError("Warning", "warning");
var CancellationError = subError("CancellationError", "cancellation error");
var TimeoutError = subError("TimeoutError", "timeout error");
var AggregateError = subError("AggregateError", "aggregate error");
try {
    _TypeError = TypeError;
    _RangeError = RangeError;
} catch(e) {
    _TypeError = subError("TypeError", "type error");
    _RangeError = subError("RangeError", "range error");
}

var methods = ("join pop push shift unshift slice filter forEach some " +
    "every map indexOf lastIndexOf reduce reduceRight sort reverse").split(" ");

for (var i = 0; i < methods.length; ++i) {
    if (typeof Array.prototype[methods[i]] === "function") {
        AggregateError.prototype[methods[i]] = Array.prototype[methods[i]];
    }
}

es5.defineProperty(AggregateError.prototype, "length", {
    value: 0,
    configurable: false,
    writable: true,
    enumerable: true
});
AggregateError.prototype["isOperational"] = true;
var level = 0;
AggregateError.prototype.toString = function() {
    var indent = Array(level * 4 + 1).join(" ");
    var ret = "\n" + indent + "AggregateError of:" + "\n";
    level++;
    indent = Array(level * 4 + 1).join(" ");
    for (var i = 0; i < this.length; ++i) {
        var str = this[i] === this ? "[Circular AggregateError]" : this[i] + "";
        var lines = str.split("\n");
        for (var j = 0; j < lines.length; ++j) {
            lines[j] = indent + lines[j];
        }
        str = lines.join("\n");
        ret += str + "\n";
    }
    level--;
    return ret;
};

function OperationalError(message) {
    if (!(this instanceof OperationalError))
        return new OperationalError(message);
    notEnumerableProp(this, "name", "OperationalError");
    notEnumerableProp(this, "message", message);
    this.cause = message;
    this["isOperational"] = true;

    if (message instanceof Error) {
        notEnumerableProp(this, "message", message.message);
        notEnumerableProp(this, "stack", message.stack);
    } else if (Error.captureStackTrace) {
        Error.captureStackTrace(this, this.constructor);
    }

}
inherits(OperationalError, Error);

var errorTypes = Error["__BluebirdErrorTypes__"];
if (!errorTypes) {
    errorTypes = Objectfreeze({
        CancellationError: CancellationError,
        TimeoutError: TimeoutError,
        OperationalError: OperationalError,
        RejectionError: OperationalError,
        AggregateError: AggregateError
    });
    es5.defineProperty(Error, "__BluebirdErrorTypes__", {
        value: errorTypes,
        writable: false,
        enumerable: false,
        configurable: false
    });
}

module.exports = {
    Error: Error,
    TypeError: _TypeError,
    RangeError: _RangeError,
    CancellationError: errorTypes.CancellationError,
    OperationalError: errorTypes.OperationalError,
    TimeoutError: errorTypes.TimeoutError,
    AggregateError: errorTypes.AggregateError,
    Warning: Warning
};

},{"./es5":13,"./util":36}],13:[function(_dereq_,module,exports){
var isES5 = (function(){
    "use strict";
    return this === undefined;
})();

if (isES5) {
    module.exports = {
        freeze: Object.freeze,
        defineProperty: Object.defineProperty,
        getDescriptor: Object.getOwnPropertyDescriptor,
        keys: Object.keys,
        names: Object.getOwnPropertyNames,
        getPrototypeOf: Object.getPrototypeOf,
        isArray: Array.isArray,
        isES5: isES5,
        propertyIsWritable: function(obj, prop) {
            var descriptor = Object.getOwnPropertyDescriptor(obj, prop);
            return !!(!descriptor || descriptor.writable || descriptor.set);
        }
    };
} else {
    var has = {}.hasOwnProperty;
    var str = {}.toString;
    var proto = {}.constructor.prototype;

    var ObjectKeys = function (o) {
        var ret = [];
        for (var key in o) {
            if (has.call(o, key)) {
                ret.push(key);
            }
        }
        return ret;
    };

    var ObjectGetDescriptor = function(o, key) {
        return {value: o[key]};
    };

    var ObjectDefineProperty = function (o, key, desc) {
        o[key] = desc.value;
        return o;
    };

    var ObjectFreeze = function (obj) {
        return obj;
    };

    var ObjectGetPrototypeOf = function (obj) {
        try {
            return Object(obj).constructor.prototype;
        }
        catch (e) {
            return proto;
        }
    };

    var ArrayIsArray = function (obj) {
        try {
            return str.call(obj) === "[object Array]";
        }
        catch(e) {
            return false;
        }
    };

    module.exports = {
        isArray: ArrayIsArray,
        keys: ObjectKeys,
        names: ObjectKeys,
        defineProperty: ObjectDefineProperty,
        getDescriptor: ObjectGetDescriptor,
        freeze: ObjectFreeze,
        getPrototypeOf: ObjectGetPrototypeOf,
        isES5: isES5,
        propertyIsWritable: function() {
            return true;
        }
    };
}

},{}],14:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, INTERNAL) {
var PromiseMap = Promise.map;

Promise.prototype.filter = function (fn, options) {
    return PromiseMap(this, fn, options, INTERNAL);
};

Promise.filter = function (promises, fn, options) {
    return PromiseMap(promises, fn, options, INTERNAL);
};
};

},{}],15:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, tryConvertToPromise) {
var util = _dereq_("./util");
var CancellationError = Promise.CancellationError;
var errorObj = util.errorObj;

function PassThroughHandlerContext(promise, type, handler) {
    this.promise = promise;
    this.type = type;
    this.handler = handler;
    this.called = false;
    this.cancelPromise = null;
}

PassThroughHandlerContext.prototype.isFinallyHandler = function() {
    return this.type === 0;
};

function FinallyHandlerCancelReaction(finallyHandler) {
    this.finallyHandler = finallyHandler;
}

FinallyHandlerCancelReaction.prototype._resultCancelled = function() {
    checkCancel(this.finallyHandler);
};

function checkCancel(ctx, reason) {
    if (ctx.cancelPromise != null) {
        if (arguments.length > 1) {
            ctx.cancelPromise._reject(reason);
        } else {
            ctx.cancelPromise._cancel();
        }
        ctx.cancelPromise = null;
        return true;
    }
    return false;
}

function succeed() {
    return finallyHandler.call(this, this.promise._target()._settledValue());
}
function fail(reason) {
    if (checkCancel(this, reason)) return;
    errorObj.e = reason;
    return errorObj;
}
function finallyHandler(reasonOrValue) {
    var promise = this.promise;
    var handler = this.handler;

    if (!this.called) {
        this.called = true;
        var ret = this.isFinallyHandler()
            ? handler.call(promise._boundValue())
            : handler.call(promise._boundValue(), reasonOrValue);
        if (ret !== undefined) {
            promise._setReturnedNonUndefined();
            var maybePromise = tryConvertToPromise(ret, promise);
            if (maybePromise instanceof Promise) {
                if (this.cancelPromise != null) {
                    if (maybePromise._isCancelled()) {
                        var reason =
                            new CancellationError("late cancellation observer");
                        promise._attachExtraTrace(reason);
                        errorObj.e = reason;
                        return errorObj;
                    } else if (maybePromise.isPending()) {
                        maybePromise._attachCancellationCallback(
                            new FinallyHandlerCancelReaction(this));
                    }
                }
                return maybePromise._then(
                    succeed, fail, undefined, this, undefined);
            }
        }
    }

    if (promise.isRejected()) {
        checkCancel(this);
        errorObj.e = reasonOrValue;
        return errorObj;
    } else {
        checkCancel(this);
        return reasonOrValue;
    }
}

Promise.prototype._passThrough = function(handler, type, success, fail) {
    if (typeof handler !== "function") return this.then();
    return this._then(success,
                      fail,
                      undefined,
                      new PassThroughHandlerContext(this, type, handler),
                      undefined);
};

Promise.prototype.lastly =
Promise.prototype["finally"] = function (handler) {
    return this._passThrough(handler,
                             0,
                             finallyHandler,
                             finallyHandler);
};

Promise.prototype.tap = function (handler) {
    return this._passThrough(handler, 1, finallyHandler);
};

return PassThroughHandlerContext;
};

},{"./util":36}],16:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise,
                          apiRejection,
                          INTERNAL,
                          tryConvertToPromise,
                          Proxyable,
                          debug) {
var errors = _dereq_("./errors");
var TypeError = errors.TypeError;
var util = _dereq_("./util");
var errorObj = util.errorObj;
var tryCatch = util.tryCatch;
var yieldHandlers = [];

function promiseFromYieldHandler(value, yieldHandlers, traceParent) {
    for (var i = 0; i < yieldHandlers.length; ++i) {
        traceParent._pushContext();
        var result = tryCatch(yieldHandlers[i])(value);
        traceParent._popContext();
        if (result === errorObj) {
            traceParent._pushContext();
            var ret = Promise.reject(errorObj.e);
            traceParent._popContext();
            return ret;
        }
        var maybePromise = tryConvertToPromise(result, traceParent);
        if (maybePromise instanceof Promise) return maybePromise;
    }
    return null;
}

function PromiseSpawn(generatorFunction, receiver, yieldHandler, stack) {
    if (debug.cancellation()) {
        var internal = new Promise(INTERNAL);
        var _finallyPromise = this._finallyPromise = new Promise(INTERNAL);
        this._promise = internal.lastly(function() {
            return _finallyPromise;
        });
        internal._captureStackTrace();
        internal._setOnCancel(this);
    } else {
        var promise = this._promise = new Promise(INTERNAL);
        promise._captureStackTrace();
    }
    this._stack = stack;
    this._generatorFunction = generatorFunction;
    this._receiver = receiver;
    this._generator = undefined;
    this._yieldHandlers = typeof yieldHandler === "function"
        ? [yieldHandler].concat(yieldHandlers)
        : yieldHandlers;
    this._yieldedPromise = null;
    this._cancellationPhase = false;
}
util.inherits(PromiseSpawn, Proxyable);

PromiseSpawn.prototype._isResolved = function() {
    return this._promise === null;
};

PromiseSpawn.prototype._cleanup = function() {
    this._promise = this._generator = null;
    if (debug.cancellation() && this._finallyPromise !== null) {
        this._finallyPromise._fulfill();
        this._finallyPromise = null;
    }
};

PromiseSpawn.prototype._promiseCancelled = function() {
    if (this._isResolved()) return;
    var implementsReturn = typeof this._generator["return"] !== "undefined";

    var result;
    if (!implementsReturn) {
        var reason = new Promise.CancellationError(
            "generator .return() sentinel");
        Promise.coroutine.returnSentinel = reason;
        this._promise._attachExtraTrace(reason);
        this._promise._pushContext();
        result = tryCatch(this._generator["throw"]).call(this._generator,
                                                         reason);
        this._promise._popContext();
    } else {
        this._promise._pushContext();
        result = tryCatch(this._generator["return"]).call(this._generator,
                                                          undefined);
        this._promise._popContext();
    }
    this._cancellationPhase = true;
    this._yieldedPromise = null;
    this._continue(result);
};

PromiseSpawn.prototype._promiseFulfilled = function(value) {
    this._yieldedPromise = null;
    this._promise._pushContext();
    var result = tryCatch(this._generator.next).call(this._generator, value);
    this._promise._popContext();
    this._continue(result);
};

PromiseSpawn.prototype._promiseRejected = function(reason) {
    this._yieldedPromise = null;
    this._promise._attachExtraTrace(reason);
    this._promise._pushContext();
    var result = tryCatch(this._generator["throw"])
        .call(this._generator, reason);
    this._promise._popContext();
    this._continue(result);
};

PromiseSpawn.prototype._resultCancelled = function() {
    if (this._yieldedPromise instanceof Promise) {
        var promise = this._yieldedPromise;
        this._yieldedPromise = null;
        promise.cancel();
    }
};

PromiseSpawn.prototype.promise = function () {
    return this._promise;
};

PromiseSpawn.prototype._run = function () {
    this._generator = this._generatorFunction.call(this._receiver);
    this._receiver =
        this._generatorFunction = undefined;
    this._promiseFulfilled(undefined);
};

PromiseSpawn.prototype._continue = function (result) {
    var promise = this._promise;
    if (result === errorObj) {
        this._cleanup();
        if (this._cancellationPhase) {
            return promise.cancel();
        } else {
            return promise._rejectCallback(result.e, false);
        }
    }

    var value = result.value;
    if (result.done === true) {
        this._cleanup();
        if (this._cancellationPhase) {
            return promise.cancel();
        } else {
            return promise._resolveCallback(value);
        }
    } else {
        var maybePromise = tryConvertToPromise(value, this._promise);
        if (!(maybePromise instanceof Promise)) {
            maybePromise =
                promiseFromYieldHandler(maybePromise,
                                        this._yieldHandlers,
                                        this._promise);
            if (maybePromise === null) {
                this._promiseRejected(
                    new TypeError(
                        "A value %s was yielded that could not be treated as a promise\u000a\u000a    See http://goo.gl/MqrFmX\u000a\u000a".replace("%s", value) +
                        "From coroutine:\u000a" +
                        this._stack.split("\n").slice(1, -7).join("\n")
                    )
                );
                return;
            }
        }
        maybePromise = maybePromise._target();
        var bitField = maybePromise._bitField;
        ;
        if (((bitField & 50397184) === 0)) {
            this._yieldedPromise = maybePromise;
            maybePromise._proxy(this, null);
        } else if (((bitField & 33554432) !== 0)) {
            Promise._async.invoke(
                this._promiseFulfilled, this, maybePromise._value()
            );
        } else if (((bitField & 16777216) !== 0)) {
            Promise._async.invoke(
                this._promiseRejected, this, maybePromise._reason()
            );
        } else {
            this._promiseCancelled();
        }
    }
};

Promise.coroutine = function (generatorFunction, options) {
    if (typeof generatorFunction !== "function") {
        throw new TypeError("generatorFunction must be a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
    var yieldHandler = Object(options).yieldHandler;
    var PromiseSpawn$ = PromiseSpawn;
    var stack = new Error().stack;
    return function () {
        var generator = generatorFunction.apply(this, arguments);
        var spawn = new PromiseSpawn$(undefined, undefined, yieldHandler,
                                      stack);
        var ret = spawn.promise();
        spawn._generator = generator;
        spawn._promiseFulfilled(undefined);
        return ret;
    };
};

Promise.coroutine.addYieldHandler = function(fn) {
    if (typeof fn !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(fn));
    }
    yieldHandlers.push(fn);
};

Promise.spawn = function (generatorFunction) {
    debug.deprecated("Promise.spawn()", "Promise.coroutine()");
    if (typeof generatorFunction !== "function") {
        return apiRejection("generatorFunction must be a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
    var spawn = new PromiseSpawn(generatorFunction, this);
    var ret = spawn.promise();
    spawn._run(Promise.spawn);
    return ret;
};
};

},{"./errors":12,"./util":36}],17:[function(_dereq_,module,exports){
"use strict";
module.exports =
function(Promise, PromiseArray, tryConvertToPromise, INTERNAL, async,
         getDomain) {
var util = _dereq_("./util");
var canEvaluate = util.canEvaluate;
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;
var reject;

if (!true) {
if (canEvaluate) {
    var thenCallback = function(i) {
        return new Function("value", "holder", "                             \n\
            'use strict';                                                    \n\
            holder.pIndex = value;                                           \n\
            holder.checkFulfillment(this);                                   \n\
            ".replace(/Index/g, i));
    };

    var promiseSetter = function(i) {
        return new Function("promise", "holder", "                           \n\
            'use strict';                                                    \n\
            holder.pIndex = promise;                                         \n\
            ".replace(/Index/g, i));
    };

    var generateHolderClass = function(total) {
        var props = new Array(total);
        for (var i = 0; i < props.length; ++i) {
            props[i] = "this.p" + (i+1);
        }
        var assignment = props.join(" = ") + " = null;";
        var cancellationCode= "var promise;\n" + props.map(function(prop) {
            return "                                                         \n\
                promise = " + prop + ";                                      \n\
                if (promise instanceof Promise) {                            \n\
                    promise.cancel();                                        \n\
                }                                                            \n\
            ";
        }).join("\n");
        var passedArguments = props.join(", ");
        var name = "Holder$" + total;


        var code = "return function(tryCatch, errorObj, Promise, async) {    \n\
            'use strict';                                                    \n\
            function [TheName](fn) {                                         \n\
                [TheProperties]                                              \n\
                this.fn = fn;                                                \n\
                this.asyncNeeded = true;                                     \n\
                this.now = 0;                                                \n\
            }                                                                \n\
                                                                             \n\
            [TheName].prototype._callFunction = function(promise) {          \n\
                promise._pushContext();                                      \n\
                var ret = tryCatch(this.fn)([ThePassedArguments]);           \n\
                promise._popContext();                                       \n\
                if (ret === errorObj) {                                      \n\
                    promise._rejectCallback(ret.e, false);                   \n\
                } else {                                                     \n\
                    promise._resolveCallback(ret);                           \n\
                }                                                            \n\
            };                                                               \n\
                                                                             \n\
            [TheName].prototype.checkFulfillment = function(promise) {       \n\
                var now = ++this.now;                                        \n\
                if (now === [TheTotal]) {                                    \n\
                    if (this.asyncNeeded) {                                  \n\
                        async.invoke(this._callFunction, this, promise);     \n\
                    } else {                                                 \n\
                        this._callFunction(promise);                         \n\
                    }                                                        \n\
                                                                             \n\
                }                                                            \n\
            };                                                               \n\
                                                                             \n\
            [TheName].prototype._resultCancelled = function() {              \n\
                [CancellationCode]                                           \n\
            };                                                               \n\
                                                                             \n\
            return [TheName];                                                \n\
        }(tryCatch, errorObj, Promise, async);                               \n\
        ";

        code = code.replace(/\[TheName\]/g, name)
            .replace(/\[TheTotal\]/g, total)
            .replace(/\[ThePassedArguments\]/g, passedArguments)
            .replace(/\[TheProperties\]/g, assignment)
            .replace(/\[CancellationCode\]/g, cancellationCode);

        return new Function("tryCatch", "errorObj", "Promise", "async", code)
                           (tryCatch, errorObj, Promise, async);
    };

    var holderClasses = [];
    var thenCallbacks = [];
    var promiseSetters = [];

    for (var i = 0; i < 8; ++i) {
        holderClasses.push(generateHolderClass(i + 1));
        thenCallbacks.push(thenCallback(i + 1));
        promiseSetters.push(promiseSetter(i + 1));
    }

    reject = function (reason) {
        this._reject(reason);
    };
}}

Promise.join = function () {
    var last = arguments.length - 1;
    var fn;
    if (last > 0 && typeof arguments[last] === "function") {
        fn = arguments[last];
        if (!true) {
            if (last <= 8 && canEvaluate) {
                var ret = new Promise(INTERNAL);
                ret._captureStackTrace();
                var HolderClass = holderClasses[last - 1];
                var holder = new HolderClass(fn);
                var callbacks = thenCallbacks;

                for (var i = 0; i < last; ++i) {
                    var maybePromise = tryConvertToPromise(arguments[i], ret);
                    if (maybePromise instanceof Promise) {
                        maybePromise = maybePromise._target();
                        var bitField = maybePromise._bitField;
                        ;
                        if (((bitField & 50397184) === 0)) {
                            maybePromise._then(callbacks[i], reject,
                                               undefined, ret, holder);
                            promiseSetters[i](maybePromise, holder);
                            holder.asyncNeeded = false;
                        } else if (((bitField & 33554432) !== 0)) {
                            callbacks[i].call(ret,
                                              maybePromise._value(), holder);
                        } else if (((bitField & 16777216) !== 0)) {
                            ret._reject(maybePromise._reason());
                        } else {
                            ret._cancel();
                        }
                    } else {
                        callbacks[i].call(ret, maybePromise, holder);
                    }
                }

                if (!ret._isFateSealed()) {
                    if (holder.asyncNeeded) {
                        var domain = getDomain();
                        if (domain !== null) {
                            holder.fn = util.domainBind(domain, holder.fn);
                        }
                    }
                    ret._setAsyncGuaranteed();
                    ret._setOnCancel(holder);
                }
                return ret;
            }
        }
    }
    var args = [].slice.call(arguments);;
    if (fn) args.pop();
    var ret = new PromiseArray(args).promise();
    return fn !== undefined ? ret.spread(fn) : ret;
};

};

},{"./util":36}],18:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise,
                          PromiseArray,
                          apiRejection,
                          tryConvertToPromise,
                          INTERNAL,
                          debug) {
var getDomain = Promise._getDomain;
var util = _dereq_("./util");
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;

function MappingPromiseArray(promises, fn, limit, _filter) {
    this.constructor$(promises);
    this._promise._captureStackTrace();
    var domain = getDomain();
    this._callback = domain === null ? fn : util.domainBind(domain, fn);
    this._preservedValues = _filter === INTERNAL
        ? new Array(this.length())
        : null;
    this._limit = limit;
    this._inFlight = 0;
    this._queue = [];
    this._init$(undefined, -2);
}
util.inherits(MappingPromiseArray, PromiseArray);

MappingPromiseArray.prototype._init = function () {};

MappingPromiseArray.prototype._promiseFulfilled = function (value, index) {
    var values = this._values;
    var length = this.length();
    var preservedValues = this._preservedValues;
    var limit = this._limit;

    if (index < 0) {
        index = (index * -1) - 1;
        values[index] = value;
        if (limit >= 1) {
            this._inFlight--;
            this._drainQueue();
            if (this._isResolved()) return true;
        }
    } else {
        if (limit >= 1 && this._inFlight >= limit) {
            values[index] = value;
            this._queue.push(index);
            return false;
        }
        if (preservedValues !== null) preservedValues[index] = value;

        var promise = this._promise;
        var callback = this._callback;
        var receiver = promise._boundValue();
        promise._pushContext();
        var ret = tryCatch(callback).call(receiver, value, index, length);
        var promiseCreated = promise._popContext();
        debug.checkForgottenReturns(
            ret,
            promiseCreated,
            preservedValues !== null ? "Promise.filter" : "Promise.map",
            promise
        );
        if (ret === errorObj) {
            this._reject(ret.e);
            return true;
        }

        var maybePromise = tryConvertToPromise(ret, this._promise);
        if (maybePromise instanceof Promise) {
            maybePromise = maybePromise._target();
            var bitField = maybePromise._bitField;
            ;
            if (((bitField & 50397184) === 0)) {
                if (limit >= 1) this._inFlight++;
                values[index] = maybePromise;
                maybePromise._proxy(this, (index + 1) * -1);
                return false;
            } else if (((bitField & 33554432) !== 0)) {
                ret = maybePromise._value();
            } else if (((bitField & 16777216) !== 0)) {
                this._reject(maybePromise._reason());
                return true;
            } else {
                this._cancel();
                return true;
            }
        }
        values[index] = ret;
    }
    var totalResolved = ++this._totalResolved;
    if (totalResolved >= length) {
        if (preservedValues !== null) {
            this._filter(values, preservedValues);
        } else {
            this._resolve(values);
        }
        return true;
    }
    return false;
};

MappingPromiseArray.prototype._drainQueue = function () {
    var queue = this._queue;
    var limit = this._limit;
    var values = this._values;
    while (queue.length > 0 && this._inFlight < limit) {
        if (this._isResolved()) return;
        var index = queue.pop();
        this._promiseFulfilled(values[index], index);
    }
};

MappingPromiseArray.prototype._filter = function (booleans, values) {
    var len = values.length;
    var ret = new Array(len);
    var j = 0;
    for (var i = 0; i < len; ++i) {
        if (booleans[i]) ret[j++] = values[i];
    }
    ret.length = j;
    this._resolve(ret);
};

MappingPromiseArray.prototype.preservedValues = function () {
    return this._preservedValues;
};

function map(promises, fn, options, _filter) {
    if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
    }

    var limit = 0;
    if (options !== undefined) {
        if (typeof options === "object" && options !== null) {
            if (typeof options.concurrency !== "number") {
                return Promise.reject(
                    new TypeError("'concurrency' must be a number but it is " +
                                    util.classString(options.concurrency)));
            }
            limit = options.concurrency;
        } else {
            return Promise.reject(new TypeError(
                            "options argument must be an object but it is " +
                             util.classString(options)));
        }
    }
    limit = typeof limit === "number" &&
        isFinite(limit) && limit >= 1 ? limit : 0;
    return new MappingPromiseArray(promises, fn, limit, _filter).promise();
}

Promise.prototype.map = function (fn, options) {
    return map(this, fn, options, null);
};

Promise.map = function (promises, fn, options, _filter) {
    return map(promises, fn, options, _filter);
};


};

},{"./util":36}],19:[function(_dereq_,module,exports){
"use strict";
module.exports =
function(Promise, INTERNAL, tryConvertToPromise, apiRejection, debug) {
var util = _dereq_("./util");
var tryCatch = util.tryCatch;

Promise.method = function (fn) {
    if (typeof fn !== "function") {
        throw new Promise.TypeError("expecting a function but got " + util.classString(fn));
    }
    return function () {
        var ret = new Promise(INTERNAL);
        ret._captureStackTrace();
        ret._pushContext();
        var value = tryCatch(fn).apply(this, arguments);
        var promiseCreated = ret._popContext();
        debug.checkForgottenReturns(
            value, promiseCreated, "Promise.method", ret);
        ret._resolveFromSyncValue(value);
        return ret;
    };
};

Promise.attempt = Promise["try"] = function (fn) {
    if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
    }
    var ret = new Promise(INTERNAL);
    ret._captureStackTrace();
    ret._pushContext();
    var value;
    if (arguments.length > 1) {
        debug.deprecated("calling Promise.try with more than 1 argument");
        var arg = arguments[1];
        var ctx = arguments[2];
        value = util.isArray(arg) ? tryCatch(fn).apply(ctx, arg)
                                  : tryCatch(fn).call(ctx, arg);
    } else {
        value = tryCatch(fn)();
    }
    var promiseCreated = ret._popContext();
    debug.checkForgottenReturns(
        value, promiseCreated, "Promise.try", ret);
    ret._resolveFromSyncValue(value);
    return ret;
};

Promise.prototype._resolveFromSyncValue = function (value) {
    if (value === util.errorObj) {
        this._rejectCallback(value.e, false);
    } else {
        this._resolveCallback(value, true);
    }
};
};

},{"./util":36}],20:[function(_dereq_,module,exports){
"use strict";
var util = _dereq_("./util");
var maybeWrapAsError = util.maybeWrapAsError;
var errors = _dereq_("./errors");
var OperationalError = errors.OperationalError;
var es5 = _dereq_("./es5");

function isUntypedError(obj) {
    return obj instanceof Error &&
        es5.getPrototypeOf(obj) === Error.prototype;
}

var rErrorKey = /^(?:name|message|stack|cause)$/;
function wrapAsOperationalError(obj) {
    var ret;
    if (isUntypedError(obj)) {
        ret = new OperationalError(obj);
        ret.name = obj.name;
        ret.message = obj.message;
        ret.stack = obj.stack;
        var keys = es5.keys(obj);
        for (var i = 0; i < keys.length; ++i) {
            var key = keys[i];
            if (!rErrorKey.test(key)) {
                ret[key] = obj[key];
            }
        }
        return ret;
    }
    util.markAsOriginatingFromRejection(obj);
    return obj;
}

function nodebackForPromise(promise, multiArgs) {
    return function(err, value) {
        if (promise === null) return;
        if (err) {
            var wrapped = wrapAsOperationalError(maybeWrapAsError(err));
            promise._attachExtraTrace(wrapped);
            promise._reject(wrapped);
        } else if (!multiArgs) {
            promise._fulfill(value);
        } else {
            var args = [].slice.call(arguments, 1);;
            promise._fulfill(args);
        }
        promise = null;
    };
}

module.exports = nodebackForPromise;

},{"./errors":12,"./es5":13,"./util":36}],21:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise) {
var util = _dereq_("./util");
var async = Promise._async;
var tryCatch = util.tryCatch;
var errorObj = util.errorObj;

function spreadAdapter(val, nodeback) {
    var promise = this;
    if (!util.isArray(val)) return successAdapter.call(promise, val, nodeback);
    var ret =
        tryCatch(nodeback).apply(promise._boundValue(), [null].concat(val));
    if (ret === errorObj) {
        async.throwLater(ret.e);
    }
}

function successAdapter(val, nodeback) {
    var promise = this;
    var receiver = promise._boundValue();
    var ret = val === undefined
        ? tryCatch(nodeback).call(receiver, null)
        : tryCatch(nodeback).call(receiver, null, val);
    if (ret === errorObj) {
        async.throwLater(ret.e);
    }
}
function errorAdapter(reason, nodeback) {
    var promise = this;
    if (!reason) {
        var newReason = new Error(reason + "");
        newReason.cause = reason;
        reason = newReason;
    }
    var ret = tryCatch(nodeback).call(promise._boundValue(), reason);
    if (ret === errorObj) {
        async.throwLater(ret.e);
    }
}

Promise.prototype.asCallback = Promise.prototype.nodeify = function (nodeback,
                                                                     options) {
    if (typeof nodeback == "function") {
        var adapter = successAdapter;
        if (options !== undefined && Object(options).spread) {
            adapter = spreadAdapter;
        }
        this._then(
            adapter,
            errorAdapter,
            undefined,
            this,
            nodeback
        );
    }
    return this;
};
};

},{"./util":36}],22:[function(_dereq_,module,exports){
"use strict";
module.exports = function() {
var makeSelfResolutionError = function () {
    return new TypeError("circular promise resolution chain\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
};
var reflectHandler = function() {
    return new Promise.PromiseInspection(this._target());
};
var apiRejection = function(msg) {
    return Promise.reject(new TypeError(msg));
};
function Proxyable() {}
var UNDEFINED_BINDING = {};
var util = _dereq_("./util");

var getDomain;
if (util.isNode) {
    getDomain = function() {
        var ret = process.domain;
        if (ret === undefined) ret = null;
        return ret;
    };
} else {
    getDomain = function() {
        return null;
    };
}
util.notEnumerableProp(Promise, "_getDomain", getDomain);

var es5 = _dereq_("./es5");
var Async = _dereq_("./async");
var async = new Async();
es5.defineProperty(Promise, "_async", {value: async});
var errors = _dereq_("./errors");
var TypeError = Promise.TypeError = errors.TypeError;
Promise.RangeError = errors.RangeError;
var CancellationError = Promise.CancellationError = errors.CancellationError;
Promise.TimeoutError = errors.TimeoutError;
Promise.OperationalError = errors.OperationalError;
Promise.RejectionError = errors.OperationalError;
Promise.AggregateError = errors.AggregateError;
var INTERNAL = function(){};
var APPLY = {};
var NEXT_FILTER = {};
var tryConvertToPromise = _dereq_("./thenables")(Promise, INTERNAL);
var PromiseArray =
    _dereq_("./promise_array")(Promise, INTERNAL,
                               tryConvertToPromise, apiRejection, Proxyable);
var Context = _dereq_("./context")(Promise);
 /*jshint unused:false*/
var createContext = Context.create;
var debug = _dereq_("./debuggability")(Promise, Context);
var CapturedTrace = debug.CapturedTrace;
var PassThroughHandlerContext =
    _dereq_("./finally")(Promise, tryConvertToPromise);
var catchFilter = _dereq_("./catch_filter")(NEXT_FILTER);
var nodebackForPromise = _dereq_("./nodeback");
var errorObj = util.errorObj;
var tryCatch = util.tryCatch;
function check(self, executor) {
    if (typeof executor !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(executor));
    }
    if (self.constructor !== Promise) {
        throw new TypeError("the promise constructor cannot be invoked directly\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
}

function Promise(executor) {
    this._bitField = 0;
    this._fulfillmentHandler0 = undefined;
    this._rejectionHandler0 = undefined;
    this._promise0 = undefined;
    this._receiver0 = undefined;
    if (executor !== INTERNAL) {
        check(this, executor);
        this._resolveFromExecutor(executor);
    }
    this._promiseCreated();
    this._fireEvent("promiseCreated", this);
}

Promise.prototype.toString = function () {
    return "[object Promise]";
};

Promise.prototype.caught = Promise.prototype["catch"] = function (fn) {
    var len = arguments.length;
    if (len > 1) {
        var catchInstances = new Array(len - 1),
            j = 0, i;
        for (i = 0; i < len - 1; ++i) {
            var item = arguments[i];
            if (util.isObject(item)) {
                catchInstances[j++] = item;
            } else {
                return apiRejection("expecting an object but got " +
                    "A catch statement predicate " + util.classString(item));
            }
        }
        catchInstances.length = j;
        fn = arguments[i];
        return this.then(undefined, catchFilter(catchInstances, fn, this));
    }
    return this.then(undefined, fn);
};

Promise.prototype.reflect = function () {
    return this._then(reflectHandler,
        reflectHandler, undefined, this, undefined);
};

Promise.prototype.then = function (didFulfill, didReject) {
    if (debug.warnings() && arguments.length > 0 &&
        typeof didFulfill !== "function" &&
        typeof didReject !== "function") {
        var msg = ".then() only accepts functions but was passed: " +
                util.classString(didFulfill);
        if (arguments.length > 1) {
            msg += ", " + util.classString(didReject);
        }
        this._warn(msg);
    }
    return this._then(didFulfill, didReject, undefined, undefined, undefined);
};

Promise.prototype.done = function (didFulfill, didReject) {
    var promise =
        this._then(didFulfill, didReject, undefined, undefined, undefined);
    promise._setIsFinal();
};

Promise.prototype.spread = function (fn) {
    if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
    }
    return this.all()._then(fn, undefined, undefined, APPLY, undefined);
};

Promise.prototype.toJSON = function () {
    var ret = {
        isFulfilled: false,
        isRejected: false,
        fulfillmentValue: undefined,
        rejectionReason: undefined
    };
    if (this.isFulfilled()) {
        ret.fulfillmentValue = this.value();
        ret.isFulfilled = true;
    } else if (this.isRejected()) {
        ret.rejectionReason = this.reason();
        ret.isRejected = true;
    }
    return ret;
};

Promise.prototype.all = function () {
    if (arguments.length > 0) {
        this._warn(".all() was passed arguments but it does not take any");
    }
    return new PromiseArray(this).promise();
};

Promise.prototype.error = function (fn) {
    return this.caught(util.originatesFromRejection, fn);
};

Promise.getNewLibraryCopy = module.exports;

Promise.is = function (val) {
    return val instanceof Promise;
};

Promise.fromNode = Promise.fromCallback = function(fn) {
    var ret = new Promise(INTERNAL);
    ret._captureStackTrace();
    var multiArgs = arguments.length > 1 ? !!Object(arguments[1]).multiArgs
                                         : false;
    var result = tryCatch(fn)(nodebackForPromise(ret, multiArgs));
    if (result === errorObj) {
        ret._rejectCallback(result.e, true);
    }
    if (!ret._isFateSealed()) ret._setAsyncGuaranteed();
    return ret;
};

Promise.all = function (promises) {
    return new PromiseArray(promises).promise();
};

Promise.cast = function (obj) {
    var ret = tryConvertToPromise(obj);
    if (!(ret instanceof Promise)) {
        ret = new Promise(INTERNAL);
        ret._captureStackTrace();
        ret._setFulfilled();
        ret._rejectionHandler0 = obj;
    }
    return ret;
};

Promise.resolve = Promise.fulfilled = Promise.cast;

Promise.reject = Promise.rejected = function (reason) {
    var ret = new Promise(INTERNAL);
    ret._captureStackTrace();
    ret._rejectCallback(reason, true);
    return ret;
};

Promise.setScheduler = function(fn) {
    if (typeof fn !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(fn));
    }
    return async.setScheduler(fn);
};

Promise.prototype._then = function (
    didFulfill,
    didReject,
    _,    receiver,
    internalData
) {
    var haveInternalData = internalData !== undefined;
    var promise = haveInternalData ? internalData : new Promise(INTERNAL);
    var target = this._target();
    var bitField = target._bitField;

    if (!haveInternalData) {
        promise._propagateFrom(this, 3);
        promise._captureStackTrace();
        if (receiver === undefined &&
            ((this._bitField & 2097152) !== 0)) {
            if (!((bitField & 50397184) === 0)) {
                receiver = this._boundValue();
            } else {
                receiver = target === this ? undefined : this._boundTo;
            }
        }
        this._fireEvent("promiseChained", this, promise);
    }

    var domain = getDomain();
    if (!((bitField & 50397184) === 0)) {
        var handler, value, settler = target._settlePromiseCtx;
        if (((bitField & 33554432) !== 0)) {
            value = target._rejectionHandler0;
            handler = didFulfill;
        } else if (((bitField & 16777216) !== 0)) {
            value = target._fulfillmentHandler0;
            handler = didReject;
            target._unsetRejectionIsUnhandled();
        } else {
            settler = target._settlePromiseLateCancellationObserver;
            value = new CancellationError("late cancellation observer");
            target._attachExtraTrace(value);
            handler = didReject;
        }

        async.invoke(settler, target, {
            handler: domain === null ? handler
                : (typeof handler === "function" &&
                    util.domainBind(domain, handler)),
            promise: promise,
            receiver: receiver,
            value: value
        });
    } else {
        target._addCallbacks(didFulfill, didReject, promise, receiver, domain);
    }

    return promise;
};

Promise.prototype._length = function () {
    return this._bitField & 65535;
};

Promise.prototype._isFateSealed = function () {
    return (this._bitField & 117506048) !== 0;
};

Promise.prototype._isFollowing = function () {
    return (this._bitField & 67108864) === 67108864;
};

Promise.prototype._setLength = function (len) {
    this._bitField = (this._bitField & -65536) |
        (len & 65535);
};

Promise.prototype._setFulfilled = function () {
    this._bitField = this._bitField | 33554432;
    this._fireEvent("promiseFulfilled", this);
};

Promise.prototype._setRejected = function () {
    this._bitField = this._bitField | 16777216;
    this._fireEvent("promiseRejected", this);
};

Promise.prototype._setFollowing = function () {
    this._bitField = this._bitField | 67108864;
    this._fireEvent("promiseResolved", this);
};

Promise.prototype._setIsFinal = function () {
    this._bitField = this._bitField | 4194304;
};

Promise.prototype._isFinal = function () {
    return (this._bitField & 4194304) > 0;
};

Promise.prototype._unsetCancelled = function() {
    this._bitField = this._bitField & (~65536);
};

Promise.prototype._setCancelled = function() {
    this._bitField = this._bitField | 65536;
    this._fireEvent("promiseCancelled", this);
};

Promise.prototype._setWillBeCancelled = function() {
    this._bitField = this._bitField | 8388608;
};

Promise.prototype._setAsyncGuaranteed = function() {
    if (async.hasCustomScheduler()) return;
    this._bitField = this._bitField | 134217728;
};

Promise.prototype._receiverAt = function (index) {
    var ret = index === 0 ? this._receiver0 : this[
            index * 4 - 4 + 3];
    if (ret === UNDEFINED_BINDING) {
        return undefined;
    } else if (ret === undefined && this._isBound()) {
        return this._boundValue();
    }
    return ret;
};

Promise.prototype._promiseAt = function (index) {
    return this[
            index * 4 - 4 + 2];
};

Promise.prototype._fulfillmentHandlerAt = function (index) {
    return this[
            index * 4 - 4 + 0];
};

Promise.prototype._rejectionHandlerAt = function (index) {
    return this[
            index * 4 - 4 + 1];
};

Promise.prototype._boundValue = function() {};

Promise.prototype._migrateCallback0 = function (follower) {
    var bitField = follower._bitField;
    var fulfill = follower._fulfillmentHandler0;
    var reject = follower._rejectionHandler0;
    var promise = follower._promise0;
    var receiver = follower._receiverAt(0);
    if (receiver === undefined) receiver = UNDEFINED_BINDING;
    this._addCallbacks(fulfill, reject, promise, receiver, null);
};

Promise.prototype._migrateCallbackAt = function (follower, index) {
    var fulfill = follower._fulfillmentHandlerAt(index);
    var reject = follower._rejectionHandlerAt(index);
    var promise = follower._promiseAt(index);
    var receiver = follower._receiverAt(index);
    if (receiver === undefined) receiver = UNDEFINED_BINDING;
    this._addCallbacks(fulfill, reject, promise, receiver, null);
};

Promise.prototype._addCallbacks = function (
    fulfill,
    reject,
    promise,
    receiver,
    domain
) {
    var index = this._length();

    if (index >= 65535 - 4) {
        index = 0;
        this._setLength(0);
    }

    if (index === 0) {
        this._promise0 = promise;
        this._receiver0 = receiver;
        if (typeof fulfill === "function") {
            this._fulfillmentHandler0 =
                domain === null ? fulfill : util.domainBind(domain, fulfill);
        }
        if (typeof reject === "function") {
            this._rejectionHandler0 =
                domain === null ? reject : util.domainBind(domain, reject);
        }
    } else {
        var base = index * 4 - 4;
        this[base + 2] = promise;
        this[base + 3] = receiver;
        if (typeof fulfill === "function") {
            this[base + 0] =
                domain === null ? fulfill : util.domainBind(domain, fulfill);
        }
        if (typeof reject === "function") {
            this[base + 1] =
                domain === null ? reject : util.domainBind(domain, reject);
        }
    }
    this._setLength(index + 1);
    return index;
};

Promise.prototype._proxy = function (proxyable, arg) {
    this._addCallbacks(undefined, undefined, arg, proxyable, null);
};

Promise.prototype._resolveCallback = function(value, shouldBind) {
    if (((this._bitField & 117506048) !== 0)) return;
    if (value === this)
        return this._rejectCallback(makeSelfResolutionError(), false);
    var maybePromise = tryConvertToPromise(value, this);
    if (!(maybePromise instanceof Promise)) return this._fulfill(value);

    if (shouldBind) this._propagateFrom(maybePromise, 2);

    var promise = maybePromise._target();

    if (promise === this) {
        this._reject(makeSelfResolutionError());
        return;
    }

    var bitField = promise._bitField;
    if (((bitField & 50397184) === 0)) {
        var len = this._length();
        if (len > 0) promise._migrateCallback0(this);
        for (var i = 1; i < len; ++i) {
            promise._migrateCallbackAt(this, i);
        }
        this._setFollowing();
        this._setLength(0);
        this._setFollowee(promise);
    } else if (((bitField & 33554432) !== 0)) {
        this._fulfill(promise._value());
    } else if (((bitField & 16777216) !== 0)) {
        this._reject(promise._reason());
    } else {
        var reason = new CancellationError("late cancellation observer");
        promise._attachExtraTrace(reason);
        this._reject(reason);
    }
};

Promise.prototype._rejectCallback =
function(reason, synchronous, ignoreNonErrorWarnings) {
    var trace = util.ensureErrorObject(reason);
    var hasStack = trace === reason;
    if (!hasStack && !ignoreNonErrorWarnings && debug.warnings()) {
        var message = "a promise was rejected with a non-error: " +
            util.classString(reason);
        this._warn(message, true);
    }
    this._attachExtraTrace(trace, synchronous ? hasStack : false);
    this._reject(reason);
};

Promise.prototype._resolveFromExecutor = function (executor) {
    var promise = this;
    this._captureStackTrace();
    this._pushContext();
    var synchronous = true;
    var r = this._execute(executor, function(value) {
        promise._resolveCallback(value);
    }, function (reason) {
        promise._rejectCallback(reason, synchronous);
    });
    synchronous = false;
    this._popContext();

    if (r !== undefined) {
        promise._rejectCallback(r, true);
    }
};

Promise.prototype._settlePromiseFromHandler = function (
    handler, receiver, value, promise
) {
    var bitField = promise._bitField;
    if (((bitField & 65536) !== 0)) return;
    promise._pushContext();
    var x;
    if (receiver === APPLY) {
        if (!value || typeof value.length !== "number") {
            x = errorObj;
            x.e = new TypeError("cannot .spread() a non-array: " +
                                    util.classString(value));
        } else {
            x = tryCatch(handler).apply(this._boundValue(), value);
        }
    } else {
        x = tryCatch(handler).call(receiver, value);
    }
    var promiseCreated = promise._popContext();
    bitField = promise._bitField;
    if (((bitField & 65536) !== 0)) return;

    if (x === NEXT_FILTER) {
        promise._reject(value);
    } else if (x === errorObj) {
        promise._rejectCallback(x.e, false);
    } else {
        debug.checkForgottenReturns(x, promiseCreated, "",  promise, this);
        promise._resolveCallback(x);
    }
};

Promise.prototype._target = function() {
    var ret = this;
    while (ret._isFollowing()) ret = ret._followee();
    return ret;
};

Promise.prototype._followee = function() {
    return this._rejectionHandler0;
};

Promise.prototype._setFollowee = function(promise) {
    this._rejectionHandler0 = promise;
};

Promise.prototype._settlePromise = function(promise, handler, receiver, value) {
    var isPromise = promise instanceof Promise;
    var bitField = this._bitField;
    var asyncGuaranteed = ((bitField & 134217728) !== 0);
    if (((bitField & 65536) !== 0)) {
        if (isPromise) promise._invokeInternalOnCancel();

        if (receiver instanceof PassThroughHandlerContext &&
            receiver.isFinallyHandler()) {
            receiver.cancelPromise = promise;
            if (tryCatch(handler).call(receiver, value) === errorObj) {
                promise._reject(errorObj.e);
            }
        } else if (handler === reflectHandler) {
            promise._fulfill(reflectHandler.call(receiver));
        } else if (receiver instanceof Proxyable) {
            receiver._promiseCancelled(promise);
        } else if (isPromise || promise instanceof PromiseArray) {
            promise._cancel();
        } else {
            receiver.cancel();
        }
    } else if (typeof handler === "function") {
        if (!isPromise) {
            handler.call(receiver, value, promise);
        } else {
            if (asyncGuaranteed) promise._setAsyncGuaranteed();
            this._settlePromiseFromHandler(handler, receiver, value, promise);
        }
    } else if (receiver instanceof Proxyable) {
        if (!receiver._isResolved()) {
            if (((bitField & 33554432) !== 0)) {
                receiver._promiseFulfilled(value, promise);
            } else {
                receiver._promiseRejected(value, promise);
            }
        }
    } else if (isPromise) {
        if (asyncGuaranteed) promise._setAsyncGuaranteed();
        if (((bitField & 33554432) !== 0)) {
            promise._fulfill(value);
        } else {
            promise._reject(value);
        }
    }
};

Promise.prototype._settlePromiseLateCancellationObserver = function(ctx) {
    var handler = ctx.handler;
    var promise = ctx.promise;
    var receiver = ctx.receiver;
    var value = ctx.value;
    if (typeof handler === "function") {
        if (!(promise instanceof Promise)) {
            handler.call(receiver, value, promise);
        } else {
            this._settlePromiseFromHandler(handler, receiver, value, promise);
        }
    } else if (promise instanceof Promise) {
        promise._reject(value);
    }
};

Promise.prototype._settlePromiseCtx = function(ctx) {
    this._settlePromise(ctx.promise, ctx.handler, ctx.receiver, ctx.value);
};

Promise.prototype._settlePromise0 = function(handler, value, bitField) {
    var promise = this._promise0;
    var receiver = this._receiverAt(0);
    this._promise0 = undefined;
    this._receiver0 = undefined;
    this._settlePromise(promise, handler, receiver, value);
};

Promise.prototype._clearCallbackDataAtIndex = function(index) {
    var base = index * 4 - 4;
    this[base + 2] =
    this[base + 3] =
    this[base + 0] =
    this[base + 1] = undefined;
};

Promise.prototype._fulfill = function (value) {
    var bitField = this._bitField;
    if (((bitField & 117506048) >>> 16)) return;
    if (value === this) {
        var err = makeSelfResolutionError();
        this._attachExtraTrace(err);
        return this._reject(err);
    }
    this._setFulfilled();
    this._rejectionHandler0 = value;

    if ((bitField & 65535) > 0) {
        if (((bitField & 134217728) !== 0)) {
            this._settlePromises();
        } else {
            async.settlePromises(this);
        }
    }
};

Promise.prototype._reject = function (reason) {
    var bitField = this._bitField;
    if (((bitField & 117506048) >>> 16)) return;
    this._setRejected();
    this._fulfillmentHandler0 = reason;

    if (this._isFinal()) {
        return async.fatalError(reason, util.isNode);
    }

    if ((bitField & 65535) > 0) {
        async.settlePromises(this);
    } else {
        this._ensurePossibleRejectionHandled();
    }
};

Promise.prototype._fulfillPromises = function (len, value) {
    for (var i = 1; i < len; i++) {
        var handler = this._fulfillmentHandlerAt(i);
        var promise = this._promiseAt(i);
        var receiver = this._receiverAt(i);
        this._clearCallbackDataAtIndex(i);
        this._settlePromise(promise, handler, receiver, value);
    }
};

Promise.prototype._rejectPromises = function (len, reason) {
    for (var i = 1; i < len; i++) {
        var handler = this._rejectionHandlerAt(i);
        var promise = this._promiseAt(i);
        var receiver = this._receiverAt(i);
        this._clearCallbackDataAtIndex(i);
        this._settlePromise(promise, handler, receiver, reason);
    }
};

Promise.prototype._settlePromises = function () {
    var bitField = this._bitField;
    var len = (bitField & 65535);

    if (len > 0) {
        if (((bitField & 16842752) !== 0)) {
            var reason = this._fulfillmentHandler0;
            this._settlePromise0(this._rejectionHandler0, reason, bitField);
            this._rejectPromises(len, reason);
        } else {
            var value = this._rejectionHandler0;
            this._settlePromise0(this._fulfillmentHandler0, value, bitField);
            this._fulfillPromises(len, value);
        }
        this._setLength(0);
    }
    this._clearCancellationData();
};

Promise.prototype._settledValue = function() {
    var bitField = this._bitField;
    if (((bitField & 33554432) !== 0)) {
        return this._rejectionHandler0;
    } else if (((bitField & 16777216) !== 0)) {
        return this._fulfillmentHandler0;
    }
};

function deferResolve(v) {this.promise._resolveCallback(v);}
function deferReject(v) {this.promise._rejectCallback(v, false);}

Promise.defer = Promise.pending = function() {
    debug.deprecated("Promise.defer", "new Promise");
    var promise = new Promise(INTERNAL);
    return {
        promise: promise,
        resolve: deferResolve,
        reject: deferReject
    };
};

util.notEnumerableProp(Promise,
                       "_makeSelfResolutionError",
                       makeSelfResolutionError);

_dereq_("./method")(Promise, INTERNAL, tryConvertToPromise, apiRejection,
    debug);
_dereq_("./bind")(Promise, INTERNAL, tryConvertToPromise, debug);
_dereq_("./cancel")(Promise, PromiseArray, apiRejection, debug);
_dereq_("./direct_resolve")(Promise);
_dereq_("./synchronous_inspection")(Promise);
_dereq_("./join")(
    Promise, PromiseArray, tryConvertToPromise, INTERNAL, async, getDomain);
Promise.Promise = Promise;
Promise.version = "3.4.5";
_dereq_('./map.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
_dereq_('./call_get.js')(Promise);
_dereq_('./using.js')(Promise, apiRejection, tryConvertToPromise, createContext, INTERNAL, debug);
_dereq_('./timers.js')(Promise, INTERNAL, debug);
_dereq_('./generators.js')(Promise, apiRejection, INTERNAL, tryConvertToPromise, Proxyable, debug);
_dereq_('./nodeify.js')(Promise);
_dereq_('./promisify.js')(Promise, INTERNAL);
_dereq_('./props.js')(Promise, PromiseArray, tryConvertToPromise, apiRejection);
_dereq_('./race.js')(Promise, INTERNAL, tryConvertToPromise, apiRejection);
_dereq_('./reduce.js')(Promise, PromiseArray, apiRejection, tryConvertToPromise, INTERNAL, debug);
_dereq_('./settle.js')(Promise, PromiseArray, debug);
_dereq_('./some.js')(Promise, PromiseArray, apiRejection);
_dereq_('./filter.js')(Promise, INTERNAL);
_dereq_('./each.js')(Promise, INTERNAL);
_dereq_('./any.js')(Promise);
                                                         
    util.toFastProperties(Promise);                                          
    util.toFastProperties(Promise.prototype);                                
    function fillTypes(value) {                                              
        var p = new Promise(INTERNAL);                                       
        p._fulfillmentHandler0 = value;                                      
        p._rejectionHandler0 = value;                                        
        p._promise0 = value;                                                 
        p._receiver0 = value;                                                
    }                                                                        
    // Complete slack tracking, opt out of field-type tracking and           
    // stabilize map                                                         
    fillTypes({a: 1});                                                       
    fillTypes({b: 2});                                                       
    fillTypes({c: 3});                                                       
    fillTypes(1);                                                            
    fillTypes(function(){});                                                 
    fillTypes(undefined);                                                    
    fillTypes(false);                                                        
    fillTypes(new Promise(INTERNAL));                                        
    debug.setBounds(Async.firstLineError, util.lastLineError);               
    return Promise;                                                          

};

},{"./any.js":1,"./async":2,"./bind":3,"./call_get.js":5,"./cancel":6,"./catch_filter":7,"./context":8,"./debuggability":9,"./direct_resolve":10,"./each.js":11,"./errors":12,"./es5":13,"./filter.js":14,"./finally":15,"./generators.js":16,"./join":17,"./map.js":18,"./method":19,"./nodeback":20,"./nodeify.js":21,"./promise_array":23,"./promisify.js":24,"./props.js":25,"./race.js":27,"./reduce.js":28,"./settle.js":30,"./some.js":31,"./synchronous_inspection":32,"./thenables":33,"./timers.js":34,"./using.js":35,"./util":36}],23:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, INTERNAL, tryConvertToPromise,
    apiRejection, Proxyable) {
var util = _dereq_("./util");
var isArray = util.isArray;

function toResolutionValue(val) {
    switch(val) {
    case -2: return [];
    case -3: return {};
    }
}

function PromiseArray(values) {
    var promise = this._promise = new Promise(INTERNAL);
    if (values instanceof Promise) {
        promise._propagateFrom(values, 3);
    }
    promise._setOnCancel(this);
    this._values = values;
    this._length = 0;
    this._totalResolved = 0;
    this._init(undefined, -2);
}
util.inherits(PromiseArray, Proxyable);

PromiseArray.prototype.length = function () {
    return this._length;
};

PromiseArray.prototype.promise = function () {
    return this._promise;
};

PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) {
    var values = tryConvertToPromise(this._values, this._promise);
    if (values instanceof Promise) {
        values = values._target();
        var bitField = values._bitField;
        ;
        this._values = values;

        if (((bitField & 50397184) === 0)) {
            this._promise._setAsyncGuaranteed();
            return values._then(
                init,
                this._reject,
                undefined,
                this,
                resolveValueIfEmpty
           );
        } else if (((bitField & 33554432) !== 0)) {
            values = values._value();
        } else if (((bitField & 16777216) !== 0)) {
            return this._reject(values._reason());
        } else {
            return this._cancel();
        }
    }
    values = util.asArray(values);
    if (values === null) {
        var err = apiRejection(
            "expecting an array or an iterable object but got " + util.classString(values)).reason();
        this._promise._rejectCallback(err, false);
        return;
    }

    if (values.length === 0) {
        if (resolveValueIfEmpty === -5) {
            this._resolveEmptyArray();
        }
        else {
            this._resolve(toResolutionValue(resolveValueIfEmpty));
        }
        return;
    }
    this._iterate(values);
};

PromiseArray.prototype._iterate = function(values) {
    var len = this.getActualLength(values.length);
    this._length = len;
    this._values = this.shouldCopyValues() ? new Array(len) : this._values;
    var result = this._promise;
    var isResolved = false;
    var bitField = null;
    for (var i = 0; i < len; ++i) {
        var maybePromise = tryConvertToPromise(values[i], result);

        if (maybePromise instanceof Promise) {
            maybePromise = maybePromise._target();
            bitField = maybePromise._bitField;
        } else {
            bitField = null;
        }

        if (isResolved) {
            if (bitField !== null) {
                maybePromise.suppressUnhandledRejections();
            }
        } else if (bitField !== null) {
            if (((bitField & 50397184) === 0)) {
                maybePromise._proxy(this, i);
                this._values[i] = maybePromise;
            } else if (((bitField & 33554432) !== 0)) {
                isResolved = this._promiseFulfilled(maybePromise._value(), i);
            } else if (((bitField & 16777216) !== 0)) {
                isResolved = this._promiseRejected(maybePromise._reason(), i);
            } else {
                isResolved = this._promiseCancelled(i);
            }
        } else {
            isResolved = this._promiseFulfilled(maybePromise, i);
        }
    }
    if (!isResolved) result._setAsyncGuaranteed();
};

PromiseArray.prototype._isResolved = function () {
    return this._values === null;
};

PromiseArray.prototype._resolve = function (value) {
    this._values = null;
    this._promise._fulfill(value);
};

PromiseArray.prototype._cancel = function() {
    if (this._isResolved() || !this._promise._isCancellable()) return;
    this._values = null;
    this._promise._cancel();
};

PromiseArray.prototype._reject = function (reason) {
    this._values = null;
    this._promise._rejectCallback(reason, false);
};

PromiseArray.prototype._promiseFulfilled = function (value, index) {
    this._values[index] = value;
    var totalResolved = ++this._totalResolved;
    if (totalResolved >= this._length) {
        this._resolve(this._values);
        return true;
    }
    return false;
};

PromiseArray.prototype._promiseCancelled = function() {
    this._cancel();
    return true;
};

PromiseArray.prototype._promiseRejected = function (reason) {
    this._totalResolved++;
    this._reject(reason);
    return true;
};

PromiseArray.prototype._resultCancelled = function() {
    if (this._isResolved()) return;
    var values = this._values;
    this._cancel();
    if (values instanceof Promise) {
        values.cancel();
    } else {
        for (var i = 0; i < values.length; ++i) {
            if (values[i] instanceof Promise) {
                values[i].cancel();
            }
        }
    }
};

PromiseArray.prototype.shouldCopyValues = function () {
    return true;
};

PromiseArray.prototype.getActualLength = function (len) {
    return len;
};

return PromiseArray;
};

},{"./util":36}],24:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, INTERNAL) {
var THIS = {};
var util = _dereq_("./util");
var nodebackForPromise = _dereq_("./nodeback");
var withAppended = util.withAppended;
var maybeWrapAsError = util.maybeWrapAsError;
var canEvaluate = util.canEvaluate;
var TypeError = _dereq_("./errors").TypeError;
var defaultSuffix = "Async";
var defaultPromisified = {__isPromisified__: true};
var noCopyProps = [
    "arity",    "length",
    "name",
    "arguments",
    "caller",
    "callee",
    "prototype",
    "__isPromisified__"
];
var noCopyPropsPattern = new RegExp("^(?:" + noCopyProps.join("|") + ")$");

var defaultFilter = function(name) {
    return util.isIdentifier(name) &&
        name.charAt(0) !== "_" &&
        name !== "constructor";
};

function propsFilter(key) {
    return !noCopyPropsPattern.test(key);
}

function isPromisified(fn) {
    try {
        return fn.__isPromisified__ === true;
    }
    catch (e) {
        return false;
    }
}

function hasPromisified(obj, key, suffix) {
    var val = util.getDataPropertyOrDefault(obj, key + suffix,
                                            defaultPromisified);
    return val ? isPromisified(val) : false;
}
function checkValid(ret, suffix, suffixRegexp) {
    for (var i = 0; i < ret.length; i += 2) {
        var key = ret[i];
        if (suffixRegexp.test(key)) {
            var keyWithoutAsyncSuffix = key.replace(suffixRegexp, "");
            for (var j = 0; j < ret.length; j += 2) {
                if (ret[j] === keyWithoutAsyncSuffix) {
                    throw new TypeError("Cannot promisify an API that has normal methods with '%s'-suffix\u000a\u000a    See http://goo.gl/MqrFmX\u000a"
                        .replace("%s", suffix));
                }
            }
        }
    }
}

function promisifiableMethods(obj, suffix, suffixRegexp, filter) {
    var keys = util.inheritedDataKeys(obj);
    var ret = [];
    for (var i = 0; i < keys.length; ++i) {
        var key = keys[i];
        var value = obj[key];
        var passesDefaultFilter = filter === defaultFilter
            ? true : defaultFilter(key, value, obj);
        if (typeof value === "function" &&
            !isPromisified(value) &&
            !hasPromisified(obj, key, suffix) &&
            filter(key, value, obj, passesDefaultFilter)) {
            ret.push(key, value);
        }
    }
    checkValid(ret, suffix, suffixRegexp);
    return ret;
}

var escapeIdentRegex = function(str) {
    return str.replace(/([$])/, "\\$");
};

var makeNodePromisifiedEval;
if (!true) {
var switchCaseArgumentOrder = function(likelyArgumentCount) {
    var ret = [likelyArgumentCount];
    var min = Math.max(0, likelyArgumentCount - 1 - 3);
    for(var i = likelyArgumentCount - 1; i >= min; --i) {
        ret.push(i);
    }
    for(var i = likelyArgumentCount + 1; i <= 3; ++i) {
        ret.push(i);
    }
    return ret;
};

var argumentSequence = function(argumentCount) {
    return util.filledRange(argumentCount, "_arg", "");
};

var parameterDeclaration = function(parameterCount) {
    return util.filledRange(
        Math.max(parameterCount, 3), "_arg", "");
};

var parameterCount = function(fn) {
    if (typeof fn.length === "number") {
        return Math.max(Math.min(fn.length, 1023 + 1), 0);
    }
    return 0;
};

makeNodePromisifiedEval =
function(callback, receiver, originalName, fn, _, multiArgs) {
    var newParameterCount = Math.max(0, parameterCount(fn) - 1);
    var argumentOrder = switchCaseArgumentOrder(newParameterCount);
    var shouldProxyThis = typeof callback === "string" || receiver === THIS;

    function generateCallForArgumentCount(count) {
        var args = argumentSequence(count).join(", ");
        var comma = count > 0 ? ", " : "";
        var ret;
        if (shouldProxyThis) {
            ret = "ret = callback.call(this, {{args}}, nodeback); break;\n";
        } else {
            ret = receiver === undefined
                ? "ret = callback({{args}}, nodeback); break;\n"
                : "ret = callback.call(receiver, {{args}}, nodeback); break;\n";
        }
        return ret.replace("{{args}}", args).replace(", ", comma);
    }

    function generateArgumentSwitchCase() {
        var ret = "";
        for (var i = 0; i < argumentOrder.length; ++i) {
            ret += "case " + argumentOrder[i] +":" +
                generateCallForArgumentCount(argumentOrder[i]);
        }

        ret += "                                                             \n\
        default:                                                             \n\
            var args = new Array(len + 1);                                   \n\
            var i = 0;                                                       \n\
            for (var i = 0; i < len; ++i) {                                  \n\
               args[i] = arguments[i];                                       \n\
            }                                                                \n\
            args[i] = nodeback;                                              \n\
            [CodeForCall]                                                    \n\
            break;                                                           \n\
        ".replace("[CodeForCall]", (shouldProxyThis
                                ? "ret = callback.apply(this, args);\n"
                                : "ret = callback.apply(receiver, args);\n"));
        return ret;
    }

    var getFunctionCode = typeof callback === "string"
                                ? ("this != null ? this['"+callback+"'] : fn")
                                : "fn";
    var body = "'use strict';                                                \n\
        var ret = function (Parameters) {                                    \n\
            'use strict';                                                    \n\
            var len = arguments.length;                                      \n\
            var promise = new Promise(INTERNAL);                             \n\
            promise._captureStackTrace();                                    \n\
            var nodeback = nodebackForPromise(promise, " + multiArgs + ");   \n\
            var ret;                                                         \n\
            var callback = tryCatch([GetFunctionCode]);                      \n\
            switch(len) {                                                    \n\
                [CodeForSwitchCase]                                          \n\
            }                                                                \n\
            if (ret === errorObj) {                                          \n\
                promise._rejectCallback(maybeWrapAsError(ret.e), true, true);\n\
            }                                                                \n\
            if (!promise._isFateSealed()) promise._setAsyncGuaranteed();     \n\
            return promise;                                                  \n\
        };                                                                   \n\
        notEnumerableProp(ret, '__isPromisified__', true);                   \n\
        return ret;                                                          \n\
    ".replace("[CodeForSwitchCase]", generateArgumentSwitchCase())
        .replace("[GetFunctionCode]", getFunctionCode);
    body = body.replace("Parameters", parameterDeclaration(newParameterCount));
    return new Function("Promise",
                        "fn",
                        "receiver",
                        "withAppended",
                        "maybeWrapAsError",
                        "nodebackForPromise",
                        "tryCatch",
                        "errorObj",
                        "notEnumerableProp",
                        "INTERNAL",
                        body)(
                    Promise,
                    fn,
                    receiver,
                    withAppended,
                    maybeWrapAsError,
                    nodebackForPromise,
                    util.tryCatch,
                    util.errorObj,
                    util.notEnumerableProp,
                    INTERNAL);
};
}

function makeNodePromisifiedClosure(callback, receiver, _, fn, __, multiArgs) {
    var defaultThis = (function() {return this;})();
    var method = callback;
    if (typeof method === "string") {
        callback = fn;
    }
    function promisified() {
        var _receiver = receiver;
        if (receiver === THIS) _receiver = this;
        var promise = new Promise(INTERNAL);
        promise._captureStackTrace();
        var cb = typeof method === "string" && this !== defaultThis
            ? this[method] : callback;
        var fn = nodebackForPromise(promise, multiArgs);
        try {
            cb.apply(_receiver, withAppended(arguments, fn));
        } catch(e) {
            promise._rejectCallback(maybeWrapAsError(e), true, true);
        }
        if (!promise._isFateSealed()) promise._setAsyncGuaranteed();
        return promise;
    }
    util.notEnumerableProp(promisified, "__isPromisified__", true);
    return promisified;
}

var makeNodePromisified = canEvaluate
    ? makeNodePromisifiedEval
    : makeNodePromisifiedClosure;

function promisifyAll(obj, suffix, filter, promisifier, multiArgs) {
    var suffixRegexp = new RegExp(escapeIdentRegex(suffix) + "$");
    var methods =
        promisifiableMethods(obj, suffix, suffixRegexp, filter);

    for (var i = 0, len = methods.length; i < len; i+= 2) {
        var key = methods[i];
        var fn = methods[i+1];
        var promisifiedKey = key + suffix;
        if (promisifier === makeNodePromisified) {
            obj[promisifiedKey] =
                makeNodePromisified(key, THIS, key, fn, suffix, multiArgs);
        } else {
            var promisified = promisifier(fn, function() {
                return makeNodePromisified(key, THIS, key,
                                           fn, suffix, multiArgs);
            });
            util.notEnumerableProp(promisified, "__isPromisified__", true);
            obj[promisifiedKey] = promisified;
        }
    }
    util.toFastProperties(obj);
    return obj;
}

function promisify(callback, receiver, multiArgs) {
    return makeNodePromisified(callback, receiver, undefined,
                                callback, null, multiArgs);
}

Promise.promisify = function (fn, options) {
    if (typeof fn !== "function") {
        throw new TypeError("expecting a function but got " + util.classString(fn));
    }
    if (isPromisified(fn)) {
        return fn;
    }
    options = Object(options);
    var receiver = options.context === undefined ? THIS : options.context;
    var multiArgs = !!options.multiArgs;
    var ret = promisify(fn, receiver, multiArgs);
    util.copyDescriptors(fn, ret, propsFilter);
    return ret;
};

Promise.promisifyAll = function (target, options) {
    if (typeof target !== "function" && typeof target !== "object") {
        throw new TypeError("the target of promisifyAll must be an object or a function\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
    options = Object(options);
    var multiArgs = !!options.multiArgs;
    var suffix = options.suffix;
    if (typeof suffix !== "string") suffix = defaultSuffix;
    var filter = options.filter;
    if (typeof filter !== "function") filter = defaultFilter;
    var promisifier = options.promisifier;
    if (typeof promisifier !== "function") promisifier = makeNodePromisified;

    if (!util.isIdentifier(suffix)) {
        throw new RangeError("suffix must be a valid identifier\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }

    var keys = util.inheritedDataKeys(target);
    for (var i = 0; i < keys.length; ++i) {
        var value = target[keys[i]];
        if (keys[i] !== "constructor" &&
            util.isClass(value)) {
            promisifyAll(value.prototype, suffix, filter, promisifier,
                multiArgs);
            promisifyAll(value, suffix, filter, promisifier, multiArgs);
        }
    }

    return promisifyAll(target, suffix, filter, promisifier, multiArgs);
};
};


},{"./errors":12,"./nodeback":20,"./util":36}],25:[function(_dereq_,module,exports){
"use strict";
module.exports = function(
    Promise, PromiseArray, tryConvertToPromise, apiRejection) {
var util = _dereq_("./util");
var isObject = util.isObject;
var es5 = _dereq_("./es5");
var Es6Map;
if (typeof Map === "function") Es6Map = Map;

var mapToEntries = (function() {
    var index = 0;
    var size = 0;

    function extractEntry(value, key) {
        this[index] = value;
        this[index + size] = key;
        index++;
    }

    return function mapToEntries(map) {
        size = map.size;
        index = 0;
        var ret = new Array(map.size * 2);
        map.forEach(extractEntry, ret);
        return ret;
    };
})();

var entriesToMap = function(entries) {
    var ret = new Es6Map();
    var length = entries.length / 2 | 0;
    for (var i = 0; i < length; ++i) {
        var key = entries[length + i];
        var value = entries[i];
        ret.set(key, value);
    }
    return ret;
};

function PropertiesPromiseArray(obj) {
    var isMap = false;
    var entries;
    if (Es6Map !== undefined && obj instanceof Es6Map) {
        entries = mapToEntries(obj);
        isMap = true;
    } else {
        var keys = es5.keys(obj);
        var len = keys.length;
        entries = new Array(len * 2);
        for (var i = 0; i < len; ++i) {
            var key = keys[i];
            entries[i] = obj[key];
            entries[i + len] = key;
        }
    }
    this.constructor$(entries);
    this._isMap = isMap;
    this._init$(undefined, -3);
}
util.inherits(PropertiesPromiseArray, PromiseArray);

PropertiesPromiseArray.prototype._init = function () {};

PropertiesPromiseArray.prototype._promiseFulfilled = function (value, index) {
    this._values[index] = value;
    var totalResolved = ++this._totalResolved;
    if (totalResolved >= this._length) {
        var val;
        if (this._isMap) {
            val = entriesToMap(this._values);
        } else {
            val = {};
            var keyOffset = this.length();
            for (var i = 0, len = this.length(); i < len; ++i) {
                val[this._values[i + keyOffset]] = this._values[i];
            }
        }
        this._resolve(val);
        return true;
    }
    return false;
};

PropertiesPromiseArray.prototype.shouldCopyValues = function () {
    return false;
};

PropertiesPromiseArray.prototype.getActualLength = function (len) {
    return len >> 1;
};

function props(promises) {
    var ret;
    var castValue = tryConvertToPromise(promises);

    if (!isObject(castValue)) {
        return apiRejection("cannot await properties of a non-object\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    } else if (castValue instanceof Promise) {
        ret = castValue._then(
            Promise.props, undefined, undefined, undefined, undefined);
    } else {
        ret = new PropertiesPromiseArray(castValue).promise();
    }

    if (castValue instanceof Promise) {
        ret._propagateFrom(castValue, 2);
    }
    return ret;
}

Promise.prototype.props = function () {
    return props(this);
};

Promise.props = function (promises) {
    return props(promises);
};
};

},{"./es5":13,"./util":36}],26:[function(_dereq_,module,exports){
"use strict";
function arrayMove(src, srcIndex, dst, dstIndex, len) {
    for (var j = 0; j < len; ++j) {
        dst[j + dstIndex] = src[j + srcIndex];
        src[j + srcIndex] = void 0;
    }
}

function Queue(capacity) {
    this._capacity = capacity;
    this._length = 0;
    this._front = 0;
}

Queue.prototype._willBeOverCapacity = function (size) {
    return this._capacity < size;
};

Queue.prototype._pushOne = function (arg) {
    var length = this.length();
    this._checkCapacity(length + 1);
    var i = (this._front + length) & (this._capacity - 1);
    this[i] = arg;
    this._length = length + 1;
};

Queue.prototype._unshiftOne = function(value) {
    var capacity = this._capacity;
    this._checkCapacity(this.length() + 1);
    var front = this._front;
    var i = (((( front - 1 ) &
                    ( capacity - 1) ) ^ capacity ) - capacity );
    this[i] = value;
    this._front = i;
    this._length = this.length() + 1;
};

Queue.prototype.unshift = function(fn, receiver, arg) {
    this._unshiftOne(arg);
    this._unshiftOne(receiver);
    this._unshiftOne(fn);
};

Queue.prototype.push = function (fn, receiver, arg) {
    var length = this.length() + 3;
    if (this._willBeOverCapacity(length)) {
        this._pushOne(fn);
        this._pushOne(receiver);
        this._pushOne(arg);
        return;
    }
    var j = this._front + length - 3;
    this._checkCapacity(length);
    var wrapMask = this._capacity - 1;
    this[(j + 0) & wrapMask] = fn;
    this[(j + 1) & wrapMask] = receiver;
    this[(j + 2) & wrapMask] = arg;
    this._length = length;
};

Queue.prototype.shift = function () {
    var front = this._front,
        ret = this[front];

    this[front] = undefined;
    this._front = (front + 1) & (this._capacity - 1);
    this._length--;
    return ret;
};

Queue.prototype.length = function () {
    return this._length;
};

Queue.prototype._checkCapacity = function (size) {
    if (this._capacity < size) {
        this._resizeTo(this._capacity << 1);
    }
};

Queue.prototype._resizeTo = function (capacity) {
    var oldCapacity = this._capacity;
    this._capacity = capacity;
    var front = this._front;
    var length = this._length;
    var moveItemsCount = (front + length) & (oldCapacity - 1);
    arrayMove(this, 0, this, oldCapacity, moveItemsCount);
};

module.exports = Queue;

},{}],27:[function(_dereq_,module,exports){
"use strict";
module.exports = function(
    Promise, INTERNAL, tryConvertToPromise, apiRejection) {
var util = _dereq_("./util");

var raceLater = function (promise) {
    return promise.then(function(array) {
        return race(array, promise);
    });
};

function race(promises, parent) {
    var maybePromise = tryConvertToPromise(promises);

    if (maybePromise instanceof Promise) {
        return raceLater(maybePromise);
    } else {
        promises = util.asArray(promises);
        if (promises === null)
            return apiRejection("expecting an array or an iterable object but got " + util.classString(promises));
    }

    var ret = new Promise(INTERNAL);
    if (parent !== undefined) {
        ret._propagateFrom(parent, 3);
    }
    var fulfill = ret._fulfill;
    var reject = ret._reject;
    for (var i = 0, len = promises.length; i < len; ++i) {
        var val = promises[i];

        if (val === undefined && !(i in promises)) {
            continue;
        }

        Promise.cast(val)._then(fulfill, reject, undefined, ret, null);
    }
    return ret;
}

Promise.race = function (promises) {
    return race(promises, undefined);
};

Promise.prototype.race = function () {
    return race(this, undefined);
};

};

},{"./util":36}],28:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise,
                          PromiseArray,
                          apiRejection,
                          tryConvertToPromise,
                          INTERNAL,
                          debug) {
var getDomain = Promise._getDomain;
var util = _dereq_("./util");
var tryCatch = util.tryCatch;

function ReductionPromiseArray(promises, fn, initialValue, _each) {
    this.constructor$(promises);
    var domain = getDomain();
    this._fn = domain === null ? fn : util.domainBind(domain, fn);
    if (initialValue !== undefined) {
        initialValue = Promise.resolve(initialValue);
        initialValue._attachCancellationCallback(this);
    }
    this._initialValue = initialValue;
    this._currentCancellable = null;
    if(_each === INTERNAL) {
        this._eachValues = Array(this._length);
    } else if (_each === 0) {
        this._eachValues = null;
    } else {
        this._eachValues = undefined;
    }
    this._promise._captureStackTrace();
    this._init$(undefined, -5);
}
util.inherits(ReductionPromiseArray, PromiseArray);

ReductionPromiseArray.prototype._gotAccum = function(accum) {
    if (this._eachValues !== undefined && 
        this._eachValues !== null && 
        accum !== INTERNAL) {
        this._eachValues.push(accum);
    }
};

ReductionPromiseArray.prototype._eachComplete = function(value) {
    if (this._eachValues !== null) {
        this._eachValues.push(value);
    }
    return this._eachValues;
};

ReductionPromiseArray.prototype._init = function() {};

ReductionPromiseArray.prototype._resolveEmptyArray = function() {
    this._resolve(this._eachValues !== undefined ? this._eachValues
                                                 : this._initialValue);
};

ReductionPromiseArray.prototype.shouldCopyValues = function () {
    return false;
};

ReductionPromiseArray.prototype._resolve = function(value) {
    this._promise._resolveCallback(value);
    this._values = null;
};

ReductionPromiseArray.prototype._resultCancelled = function(sender) {
    if (sender === this._initialValue) return this._cancel();
    if (this._isResolved()) return;
    this._resultCancelled$();
    if (this._currentCancellable instanceof Promise) {
        this._currentCancellable.cancel();
    }
    if (this._initialValue instanceof Promise) {
        this._initialValue.cancel();
    }
};

ReductionPromiseArray.prototype._iterate = function (values) {
    this._values = values;
    var value;
    var i;
    var length = values.length;
    if (this._initialValue !== undefined) {
        value = this._initialValue;
        i = 0;
    } else {
        value = Promise.resolve(values[0]);
        i = 1;
    }

    this._currentCancellable = value;

    if (!value.isRejected()) {
        for (; i < length; ++i) {
            var ctx = {
                accum: null,
                value: values[i],
                index: i,
                length: length,
                array: this
            };
            value = value._then(gotAccum, undefined, undefined, ctx, undefined);
        }
    }

    if (this._eachValues !== undefined) {
        value = value
            ._then(this._eachComplete, undefined, undefined, this, undefined);
    }
    value._then(completed, completed, undefined, value, this);
};

Promise.prototype.reduce = function (fn, initialValue) {
    return reduce(this, fn, initialValue, null);
};

Promise.reduce = function (promises, fn, initialValue, _each) {
    return reduce(promises, fn, initialValue, _each);
};

function completed(valueOrReason, array) {
    if (this.isFulfilled()) {
        array._resolve(valueOrReason);
    } else {
        array._reject(valueOrReason);
    }
}

function reduce(promises, fn, initialValue, _each) {
    if (typeof fn !== "function") {
        return apiRejection("expecting a function but got " + util.classString(fn));
    }
    var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
    return array.promise();
}

function gotAccum(accum) {
    this.accum = accum;
    this.array._gotAccum(accum);
    var value = tryConvertToPromise(this.value, this.array._promise);
    if (value instanceof Promise) {
        this.array._currentCancellable = value;
        return value._then(gotValue, undefined, undefined, this, undefined);
    } else {
        return gotValue.call(this, value);
    }
}

function gotValue(value) {
    var array = this.array;
    var promise = array._promise;
    var fn = tryCatch(array._fn);
    promise._pushContext();
    var ret;
    if (array._eachValues !== undefined) {
        ret = fn.call(promise._boundValue(), value, this.index, this.length);
    } else {
        ret = fn.call(promise._boundValue(),
                              this.accum, value, this.index, this.length);
    }
    if (ret instanceof Promise) {
        array._currentCancellable = ret;
    }
    var promiseCreated = promise._popContext();
    debug.checkForgottenReturns(
        ret,
        promiseCreated,
        array._eachValues !== undefined ? "Promise.each" : "Promise.reduce",
        promise
    );
    return ret;
}
};

},{"./util":36}],29:[function(_dereq_,module,exports){
"use strict";
var util = _dereq_("./util");
var schedule;
var noAsyncScheduler = function() {
    throw new Error("No async scheduler available\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
};
var NativePromise = util.getNativePromise();
if (util.isNode && typeof MutationObserver === "undefined") {
    var GlobalSetImmediate = global.setImmediate;
    var ProcessNextTick = process.nextTick;
    schedule = util.isRecentNode
                ? function(fn) { GlobalSetImmediate.call(global, fn); }
                : function(fn) { ProcessNextTick.call(process, fn); };
} else if (typeof NativePromise === "function" &&
           typeof NativePromise.resolve === "function") {
    var nativePromise = NativePromise.resolve();
    schedule = function(fn) {
        nativePromise.then(fn);
    };
} else if ((typeof MutationObserver !== "undefined") &&
          !(typeof window !== "undefined" &&
            window.navigator &&
            (window.navigator.standalone || window.cordova))) {
    schedule = (function() {
        var div = document.createElement("div");
        var opts = {attributes: true};
        var toggleScheduled = false;
        var div2 = document.createElement("div");
        var o2 = new MutationObserver(function() {
            div.classList.toggle("foo");
            toggleScheduled = false;
        });
        o2.observe(div2, opts);

        var scheduleToggle = function() {
            if (toggleScheduled) return;
                toggleScheduled = true;
                div2.classList.toggle("foo");
            };

            return function schedule(fn) {
            var o = new MutationObserver(function() {
                o.disconnect();
                fn();
            });
            o.observe(div, opts);
            scheduleToggle();
        };
    })();
} else if (typeof setImmediate !== "undefined") {
    schedule = function (fn) {
        setImmediate(fn);
    };
} else if (typeof setTimeout !== "undefined") {
    schedule = function (fn) {
        setTimeout(fn, 0);
    };
} else {
    schedule = noAsyncScheduler;
}
module.exports = schedule;

},{"./util":36}],30:[function(_dereq_,module,exports){
"use strict";
module.exports =
    function(Promise, PromiseArray, debug) {
var PromiseInspection = Promise.PromiseInspection;
var util = _dereq_("./util");

function SettledPromiseArray(values) {
    this.constructor$(values);
}
util.inherits(SettledPromiseArray, PromiseArray);

SettledPromiseArray.prototype._promiseResolved = function (index, inspection) {
    this._values[index] = inspection;
    var totalResolved = ++this._totalResolved;
    if (totalResolved >= this._length) {
        this._resolve(this._values);
        return true;
    }
    return false;
};

SettledPromiseArray.prototype._promiseFulfilled = function (value, index) {
    var ret = new PromiseInspection();
    ret._bitField = 33554432;
    ret._settledValueField = value;
    return this._promiseResolved(index, ret);
};
SettledPromiseArray.prototype._promiseRejected = function (reason, index) {
    var ret = new PromiseInspection();
    ret._bitField = 16777216;
    ret._settledValueField = reason;
    return this._promiseResolved(index, ret);
};

Promise.settle = function (promises) {
    debug.deprecated(".settle()", ".reflect()");
    return new SettledPromiseArray(promises).promise();
};

Promise.prototype.settle = function () {
    return Promise.settle(this);
};
};

},{"./util":36}],31:[function(_dereq_,module,exports){
"use strict";
module.exports =
function(Promise, PromiseArray, apiRejection) {
var util = _dereq_("./util");
var RangeError = _dereq_("./errors").RangeError;
var AggregateError = _dereq_("./errors").AggregateError;
var isArray = util.isArray;
var CANCELLATION = {};


function SomePromiseArray(values) {
    this.constructor$(values);
    this._howMany = 0;
    this._unwrap = false;
    this._initialized = false;
}
util.inherits(SomePromiseArray, PromiseArray);

SomePromiseArray.prototype._init = function () {
    if (!this._initialized) {
        return;
    }
    if (this._howMany === 0) {
        this._resolve([]);
        return;
    }
    this._init$(undefined, -5);
    var isArrayResolved = isArray(this._values);
    if (!this._isResolved() &&
        isArrayResolved &&
        this._howMany > this._canPossiblyFulfill()) {
        this._reject(this._getRangeError(this.length()));
    }
};

SomePromiseArray.prototype.init = function () {
    this._initialized = true;
    this._init();
};

SomePromiseArray.prototype.setUnwrap = function () {
    this._unwrap = true;
};

SomePromiseArray.prototype.howMany = function () {
    return this._howMany;
};

SomePromiseArray.prototype.setHowMany = function (count) {
    this._howMany = count;
};

SomePromiseArray.prototype._promiseFulfilled = function (value) {
    this._addFulfilled(value);
    if (this._fulfilled() === this.howMany()) {
        this._values.length = this.howMany();
        if (this.howMany() === 1 && this._unwrap) {
            this._resolve(this._values[0]);
        } else {
            this._resolve(this._values);
        }
        return true;
    }
    return false;

};
SomePromiseArray.prototype._promiseRejected = function (reason) {
    this._addRejected(reason);
    return this._checkOutcome();
};

SomePromiseArray.prototype._promiseCancelled = function () {
    if (this._values instanceof Promise || this._values == null) {
        return this._cancel();
    }
    this._addRejected(CANCELLATION);
    return this._checkOutcome();
};

SomePromiseArray.prototype._checkOutcome = function() {
    if (this.howMany() > this._canPossiblyFulfill()) {
        var e = new AggregateError();
        for (var i = this.length(); i < this._values.length; ++i) {
            if (this._values[i] !== CANCELLATION) {
                e.push(this._values[i]);
            }
        }
        if (e.length > 0) {
            this._reject(e);
        } else {
            this._cancel();
        }
        return true;
    }
    return false;
};

SomePromiseArray.prototype._fulfilled = function () {
    return this._totalResolved;
};

SomePromiseArray.prototype._rejected = function () {
    return this._values.length - this.length();
};

SomePromiseArray.prototype._addRejected = function (reason) {
    this._values.push(reason);
};

SomePromiseArray.prototype._addFulfilled = function (value) {
    this._values[this._totalResolved++] = value;
};

SomePromiseArray.prototype._canPossiblyFulfill = function () {
    return this.length() - this._rejected();
};

SomePromiseArray.prototype._getRangeError = function (count) {
    var message = "Input array must contain at least " +
            this._howMany + " items but contains only " + count + " items";
    return new RangeError(message);
};

SomePromiseArray.prototype._resolveEmptyArray = function () {
    this._reject(this._getRangeError(0));
};

function some(promises, howMany) {
    if ((howMany | 0) !== howMany || howMany < 0) {
        return apiRejection("expecting a positive integer\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
    var ret = new SomePromiseArray(promises);
    var promise = ret.promise();
    ret.setHowMany(howMany);
    ret.init();
    return promise;
}

Promise.some = function (promises, howMany) {
    return some(promises, howMany);
};

Promise.prototype.some = function (howMany) {
    return some(this, howMany);
};

Promise._SomePromiseArray = SomePromiseArray;
};

},{"./errors":12,"./util":36}],32:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise) {
function PromiseInspection(promise) {
    if (promise !== undefined) {
        promise = promise._target();
        this._bitField = promise._bitField;
        this._settledValueField = promise._isFateSealed()
            ? promise._settledValue() : undefined;
    }
    else {
        this._bitField = 0;
        this._settledValueField = undefined;
    }
}

PromiseInspection.prototype._settledValue = function() {
    return this._settledValueField;
};

var value = PromiseInspection.prototype.value = function () {
    if (!this.isFulfilled()) {
        throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
    return this._settledValue();
};

var reason = PromiseInspection.prototype.error =
PromiseInspection.prototype.reason = function () {
    if (!this.isRejected()) {
        throw new TypeError("cannot get rejection reason of a non-rejected promise\u000a\u000a    See http://goo.gl/MqrFmX\u000a");
    }
    return this._settledValue();
};

var isFulfilled = PromiseInspection.prototype.isFulfilled = function() {
    return (this._bitField & 33554432) !== 0;
};

var isRejected = PromiseInspection.prototype.isRejected = function () {
    return (this._bitField & 16777216) !== 0;
};

var isPending = PromiseInspection.prototype.isPending = function () {
    return (this._bitField & 50397184) === 0;
};

var isResolved = PromiseInspection.prototype.isResolved = function () {
    return (this._bitField & 50331648) !== 0;
};

PromiseInspection.prototype.isCancelled = function() {
    return (this._bitField & 8454144) !== 0;
};

Promise.prototype.__isCancelled = function() {
    return (this._bitField & 65536) === 65536;
};

Promise.prototype._isCancelled = function() {
    return this._target().__isCancelled();
};

Promise.prototype.isCancelled = function() {
    return (this._target()._bitField & 8454144) !== 0;
};

Promise.prototype.isPending = function() {
    return isPending.call(this._target());
};

Promise.prototype.isRejected = function() {
    return isRejected.call(this._target());
};

Promise.prototype.isFulfilled = function() {
    return isFulfilled.call(this._target());
};

Promise.prototype.isResolved = function() {
    return isResolved.call(this._target());
};

Promise.prototype.value = function() {
    return value.call(this._target());
};

Promise.prototype.reason = function() {
    var target = this._target();
    target._unsetRejectionIsUnhandled();
    return reason.call(target);
};

Promise.prototype._value = function() {
    return this._settledValue();
};

Promise.prototype._reason = function() {
    this._unsetRejectionIsUnhandled();
    return this._settledValue();
};

Promise.PromiseInspection = PromiseInspection;
};

},{}],33:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, INTERNAL) {
var util = _dereq_("./util");
var errorObj = util.errorObj;
var isObject = util.isObject;

function tryConvertToPromise(obj, context) {
    if (isObject(obj)) {
        if (obj instanceof Promise) return obj;
        var then = getThen(obj);
        if (then === errorObj) {
            if (context) context._pushContext();
            var ret = Promise.reject(then.e);
            if (context) context._popContext();
            return ret;
        } else if (typeof then === "function") {
            if (isAnyBluebirdPromise(obj)) {
                var ret = new Promise(INTERNAL);
                obj._then(
                    ret._fulfill,
                    ret._reject,
                    undefined,
                    ret,
                    null
                );
                return ret;
            }
            return doThenable(obj, then, context);
        }
    }
    return obj;
}

function doGetThen(obj) {
    return obj.then;
}

function getThen(obj) {
    try {
        return doGetThen(obj);
    } catch (e) {
        errorObj.e = e;
        return errorObj;
    }
}

var hasProp = {}.hasOwnProperty;
function isAnyBluebirdPromise(obj) {
    try {
        return hasProp.call(obj, "_promise0");
    } catch (e) {
        return false;
    }
}

function doThenable(x, then, context) {
    var promise = new Promise(INTERNAL);
    var ret = promise;
    if (context) context._pushContext();
    promise._captureStackTrace();
    if (context) context._popContext();
    var synchronous = true;
    var result = util.tryCatch(then).call(x, resolve, reject);
    synchronous = false;

    if (promise && result === errorObj) {
        promise._rejectCallback(result.e, true, true);
        promise = null;
    }

    function resolve(value) {
        if (!promise) return;
        promise._resolveCallback(value);
        promise = null;
    }

    function reject(reason) {
        if (!promise) return;
        promise._rejectCallback(reason, synchronous, true);
        promise = null;
    }
    return ret;
}

return tryConvertToPromise;
};

},{"./util":36}],34:[function(_dereq_,module,exports){
"use strict";
module.exports = function(Promise, INTERNAL, debug) {
var util = _dereq_("./util");
var TimeoutError = Promise.TimeoutError;

function HandleWrapper(handle)  {
    this.handle = handle;
}

HandleWrapper.prototype._resultCancelled = function() {
    clearTimeout(this.handle);
};

var afterValue = function(value) { return delay(+this).thenReturn(value); };
var delay = Promise.delay = function (ms, value) {
    var ret;
    var handle;
    if (value !== undefined) {
        ret = Promise.resolve(value)
                ._then(afterValue, null, null, ms, undefined);
        if (debug.cancellation() && value instanceof Promise) {
            ret._setOnCancel(value);
        }
    } else {
        ret = new Promise(INTERNAL);
        handle = setTimeout(function() { ret._fulfill(); }, +ms);
        if (debug.cancellation()) {
            ret._setOnCancel(new HandleWrapper(handle));
        }
        ret._captureStackTrace();
    }
    ret._setAsyncGuaranteed();
    return ret;
};

Promise.prototype.delay = function (ms) {
    return delay(ms, this);
};

var afterTimeout = function (promise, message, parent) {
    var err;
    if (typeof message !== "string") {
        if (message instanceof Error) {
            err = message;
        } else {
            err = new TimeoutError("operation timed out");
        }
    } else {
        err = new TimeoutError(message);
    }
    util.markAsOriginatingFromRejection(err);
    promise._attachExtraTrace(err);
    promise._reject(err);

    if (parent != null) {
        parent.cancel();
    }
};

function successClear(value) {
    clearTimeout(this.handle);
    return value;
}

function failureClear(reason) {
    clearTimeout(this.handle);
    throw reason;
}

Promise.prototype.timeout = function (ms, message) {
    ms = +ms;
    var ret, parent;

    var handleWrapper = new HandleWrapper(setTimeout(function timeoutTimeout() {
        if (ret.isPending()) {
            afterTimeout(ret, message, parent);
        }
    }, ms));

    if (debug.cancellation()) {
        parent = this.then();
        ret = parent._then(successClear, failureClear,
                            undefined, handleWrapper, undefined);
        ret._setOnCancel(handleWrapper);
    } else {
        ret = this._then(successClear, failureClear,
                            undefined, handleWrapper, undefined);
    }

    return ret;
};

};

},{"./util":36}],35:[function(_dereq_,module,exports){
"use strict";
module.exports = function (Promise, apiRejection, tryConvertToPromise,
    createContext, INTERNAL, debug) {
    var util = _dereq_("./util");
    var TypeError = _dereq_("./errors").TypeError;
    var inherits = _dereq_("./util").inherits;
    var errorObj = util.errorObj;
    var tryCatch = util.tryCatch;
    var NULL = {};

    function thrower(e) {
        setTimeout(function(){throw e;}, 0);
    }

    function castPreservingDisposable(thenable) {
        var maybePromise = tryConvertToPromise(thenable);
        if (maybePromise !== thenable &&
            typeof thenable._isDisposable === "function" &&
            typeof thenable._getDisposer === "function" &&
            thenable._isDisposable()) {
            maybePromise._setDisposable(thenable._getDisposer());
        }
        return maybePromise;
    }
    function dispose(resources, inspection) {
        var i = 0;
        var len = resources.length;
        var ret = new Promise(INTERNAL);
        function iterator() {
            if (i >= len) return ret._fulfill();
            var maybePromise = castPreservingDisposable(resources[i++]);
            if (maybePromise instanceof Promise &&
                maybePromise._isDisposable()) {
                try {
                    maybePromise = tryConvertToPromise(
                        maybePromise._getDisposer().tryDispose(inspection),
                        resources.promise);
                } catch (e) {
                    return thrower(e);
                }
                if (maybePromise instanceof Promise) {
                    return maybePromise._then(iterator, thrower,
                                              null, null, null);
                }
            }
            iterator();
        }
        iterator();
        return ret;
    }

    function Disposer(data, promise, context) {
        this._data = data;
        this._promise = promise;
        this._context = context;
    }

    Disposer.prototype.data = function () {
        return this._data;
    };

    Disposer.prototype.promise = function () {
        return this._promise;
    };

    Disposer.prototype.resource = function () {
        if (this.promise().isFulfilled()) {
            return this.promise().value();
        }
        return NULL;
    };

    Disposer.prototype.tryDispose = function(inspection) {
        var resource = this.resource();
        var context = this._context;
        if (context !== undefined) context._pushContext();
        var ret = resource !== NULL
            ? this.doDispose(resource, inspection) : null;
        if (context !== undefined) context._popContext();
        this._promise._unsetDisposable();
        this._data = null;
        return ret;
    };

    Disposer.isDisposer = function (d) {
        return (d != null &&
                typeof d.resource === "function" &&
                typeof d.tryDispose === "function");
    };

    function FunctionDisposer(fn, promise, context) {
        this.constructor$(fn, promise, context);
    }
    inherits(FunctionDisposer, Disposer);

    FunctionDisposer.prototype.doDispose = function (resource, inspection) {
        var fn = this.data();
        return fn.call(resource, resource, inspection);
    };

    function maybeUnwrapDisposer(value) {
        if (Disposer.isDisposer(value)) {
            this.resources[this.index]._setDisposable(value);
            return value.promise();
        }
        return value;
    }

    function ResourceList(length) {
        this.length = length;
        this.promise = null;
        this[length-1] = null;
    }

    ResourceList.prototype._resultCancelled = function() {
        var len = this.length;
        for (var i = 0; i < len; ++i) {
            var item = this[i];
            if (item instanceof Promise) {
                item.cancel();
            }
        }
    };

    Promise.using = function () {
        var len = arguments.length;
        if (len < 2) return apiRejection(
                        "you must pass at least 2 arguments to Promise.using");
        var fn = arguments[len - 1];
        if (typeof fn !== "function") {
            return apiRejection("expecting a function but got " + util.classString(fn));
        }
        var input;
        var spreadArgs = true;
        if (len === 2 && Array.isArray(arguments[0])) {
            input = arguments[0];
            len = input.length;
            spreadArgs = false;
        } else {
            input = arguments;
            len--;
        }
        var resources = new ResourceList(len);
        for (var i = 0; i < len; ++i) {
            var resource = input[i];
            if (Disposer.isDisposer(resource)) {
                var disposer = resource;
                resource = resource.promise();
                resource._setDisposable(disposer);
            } else {
                var maybePromise = tryConvertToPromise(resource);
                if (maybePromise instanceof Promise) {
                    resource =
                        maybePromise._then(maybeUnwrapDisposer, null, null, {
                            resources: resources,
                            index: i
                    }, undefined);
                }
            }
            resources[i] = resource;
        }

        var reflectedResources = new Array(resources.length);
        for (var i = 0; i < reflectedResources.length; ++i) {
            reflectedResources[i] = Promise.resolve(resources[i]).reflect();
        }

        var resultPromise = Promise.all(reflectedResources)
            .then(function(inspections) {
                for (var i = 0; i < inspections.length; ++i) {
                    var inspection = inspections[i];
                    if (inspection.isRejected()) {
                        errorObj.e = inspection.error();
                        return errorObj;
                    } else if (!inspection.isFulfilled()) {
                        resultPromise.cancel();
                        return;
                    }
                    inspections[i] = inspection.value();
                }
                promise._pushContext();

                fn = tryCatch(fn);
                var ret = spreadArgs
                    ? fn.apply(undefined, inspections) : fn(inspections);
                var promiseCreated = promise._popContext();
                debug.checkForgottenReturns(
                    ret, promiseCreated, "Promise.using", promise);
                return ret;
            });

        var promise = resultPromise.lastly(function() {
            var inspection = new Promise.PromiseInspection(resultPromise);
            return dispose(resources, inspection);
        });
        resources.promise = promise;
        promise._setOnCancel(resources);
        return promise;
    };

    Promise.prototype._setDisposable = function (disposer) {
        this._bitField = this._bitField | 131072;
        this._disposer = disposer;
    };

    Promise.prototype._isDisposable = function () {
        return (this._bitField & 131072) > 0;
    };

    Promise.prototype._getDisposer = function () {
        return this._disposer;
    };

    Promise.prototype._unsetDisposable = function () {
        this._bitField = this._bitField & (~131072);
        this._disposer = undefined;
    };

    Promise.prototype.disposer = function (fn) {
        if (typeof fn === "function") {
            return new FunctionDisposer(fn, this, createContext());
        }
        throw new TypeError();
    };

};

},{"./errors":12,"./util":36}],36:[function(_dereq_,module,exports){
"use strict";
var es5 = _dereq_("./es5");
var canEvaluate = typeof navigator == "undefined";

var errorObj = {e: {}};
var tryCatchTarget;
var globalObject = typeof self !== "undefined" ? self :
    typeof window !== "undefined" ? window :
    typeof global !== "undefined" ? global :
    this !== undefined ? this : null;

function tryCatcher() {
    try {
        var target = tryCatchTarget;
        tryCatchTarget = null;
        return target.apply(this, arguments);
    } catch (e) {
        errorObj.e = e;
        return errorObj;
    }
}
function tryCatch(fn) {
    tryCatchTarget = fn;
    return tryCatcher;
}

var inherits = function(Child, Parent) {
    var hasProp = {}.hasOwnProperty;

    function T() {
        this.constructor = Child;
        this.constructor$ = Parent;
        for (var propertyName in Parent.prototype) {
            if (hasProp.call(Parent.prototype, propertyName) &&
                propertyName.charAt(propertyName.length-1) !== "$"
           ) {
                this[propertyName + "$"] = Parent.prototype[propertyName];
            }
        }
    }
    T.prototype = Parent.prototype;
    Child.prototype = new T();
    return Child.prototype;
};


function isPrimitive(val) {
    return val == null || val === true || val === false ||
        typeof val === "string" || typeof val === "number";

}

function isObject(value) {
    return typeof value === "function" ||
           typeof value === "object" && value !== null;
}

function maybeWrapAsError(maybeError) {
    if (!isPrimitive(maybeError)) return maybeError;

    return new Error(safeToString(maybeError));
}

function withAppended(target, appendee) {
    var len = target.length;
    var ret = new Array(len + 1);
    var i;
    for (i = 0; i < len; ++i) {
        ret[i] = target[i];
    }
    ret[i] = appendee;
    return ret;
}

function getDataPropertyOrDefault(obj, key, defaultValue) {
    if (es5.isES5) {
        var desc = Object.getOwnPropertyDescriptor(obj, key);

        if (desc != null) {
            return desc.get == null && desc.set == null
                    ? desc.value
                    : defaultValue;
        }
    } else {
        return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined;
    }
}

function notEnumerableProp(obj, name, value) {
    if (isPrimitive(obj)) return obj;
    var descriptor = {
        value: value,
        configurable: true,
        enumerable: false,
        writable: true
    };
    es5.defineProperty(obj, name, descriptor);
    return obj;
}

function thrower(r) {
    throw r;
}

var inheritedDataKeys = (function() {
    var excludedPrototypes = [
        Array.prototype,
        Object.prototype,
        Function.prototype
    ];

    var isExcludedProto = function(val) {
        for (var i = 0; i < excludedPrototypes.length; ++i) {
            if (excludedPrototypes[i] === val) {
                return true;
            }
        }
        return false;
    };

    if (es5.isES5) {
        var getKeys = Object.getOwnPropertyNames;
        return function(obj) {
            var ret = [];
            var visitedKeys = Object.create(null);
            while (obj != null && !isExcludedProto(obj)) {
                var keys;
                try {
                    keys = getKeys(obj);
                } catch (e) {
                    return ret;
                }
                for (var i = 0; i < keys.length; ++i) {
                    var key = keys[i];
                    if (visitedKeys[key]) continue;
                    visitedKeys[key] = true;
                    var desc = Object.getOwnPropertyDescriptor(obj, key);
                    if (desc != null && desc.get == null && desc.set == null) {
                        ret.push(key);
                    }
                }
                obj = es5.getPrototypeOf(obj);
            }
            return ret;
        };
    } else {
        var hasProp = {}.hasOwnProperty;
        return function(obj) {
            if (isExcludedProto(obj)) return [];
            var ret = [];

            /*jshint forin:false */
            enumeration: for (var key in obj) {
                if (hasProp.call(obj, key)) {
                    ret.push(key);
                } else {
                    for (var i = 0; i < excludedPrototypes.length; ++i) {
                        if (hasProp.call(excludedPrototypes[i], key)) {
                            continue enumeration;
                        }
                    }
                    ret.push(key);
                }
            }
            return ret;
        };
    }

})();

var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/;
function isClass(fn) {
    try {
        if (typeof fn === "function") {
            var keys = es5.names(fn.prototype);

            var hasMethods = es5.isES5 && keys.length > 1;
            var hasMethodsOtherThanConstructor = keys.length > 0 &&
                !(keys.length === 1 && keys[0] === "constructor");
            var hasThisAssignmentAndStaticMethods =
                thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0;

            if (hasMethods || hasMethodsOtherThanConstructor ||
                hasThisAssignmentAndStaticMethods) {
                return true;
            }
        }
        return false;
    } catch (e) {
        return false;
    }
}

function toFastProperties(obj) {
    /*jshint -W027,-W055,-W031*/
    function FakeConstructor() {}
    FakeConstructor.prototype = obj;
    var l = 8;
    while (l--) new FakeConstructor();
    return obj;
    eval(obj);
}

var rident = /^[a-z$_][a-z$_0-9]*$/i;
function isIdentifier(str) {
    return rident.test(str);
}

function filledRange(count, prefix, suffix) {
    var ret = new Array(count);
    for(var i = 0; i < count; ++i) {
        ret[i] = prefix + i + suffix;
    }
    return ret;
}

function safeToString(obj) {
    try {
        return obj + "";
    } catch (e) {
        return "[no string representation]";
    }
}

function isError(obj) {
    return obj !== null &&
           typeof obj === "object" &&
           typeof obj.message === "string" &&
           typeof obj.name === "string";
}

function markAsOriginatingFromRejection(e) {
    try {
        notEnumerableProp(e, "isOperational", true);
    }
    catch(ignore) {}
}

function originatesFromRejection(e) {
    if (e == null) return false;
    return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) ||
        e["isOperational"] === true);
}

function canAttachTrace(obj) {
    return isError(obj) && es5.propertyIsWritable(obj, "stack");
}

var ensureErrorObject = (function() {
    if (!("stack" in new Error())) {
        return function(value) {
            if (canAttachTrace(value)) return value;
            try {throw new Error(safeToString(value));}
            catch(err) {return err;}
        };
    } else {
        return function(value) {
            if (canAttachTrace(value)) return value;
            return new Error(safeToString(value));
        };
    }
})();

function classString(obj) {
    return {}.toString.call(obj);
}

function copyDescriptors(from, to, filter) {
    var keys = es5.names(from);
    for (var i = 0; i < keys.length; ++i) {
        var key = keys[i];
        if (filter(key)) {
            try {
                es5.defineProperty(to, key, es5.getDescriptor(from, key));
            } catch (ignore) {}
        }
    }
}

var asArray = function(v) {
    if (es5.isArray(v)) {
        return v;
    }
    return null;
};

if (typeof Symbol !== "undefined" && Symbol.iterator) {
    var ArrayFrom = typeof Array.from === "function" ? function(v) {
        return Array.from(v);
    } : function(v) {
        var ret = [];
        var it = v[Symbol.iterator]();
        var itResult;
        while (!((itResult = it.next()).done)) {
            ret.push(itResult.value);
        }
        return ret;
    };

    asArray = function(v) {
        if (es5.isArray(v)) {
            return v;
        } else if (v != null && typeof v[Symbol.iterator] === "function") {
            return ArrayFrom(v);
        }
        return null;
    };
}

var isNode = typeof process !== "undefined" &&
        classString(process).toLowerCase() === "[object process]";

function env(key, def) {
    return isNode ? process.env[key] : def;
}

function getNativePromise() {
    if (typeof Promise === "function") {
        try {
            var promise = new Promise(function(){});
            if ({}.toString.call(promise) === "[object Promise]") {
                return Promise;
            }
        } catch (e) {}
    }
}

function domainBind(self, cb) {
    return self.bind(cb);
}

var ret = {
    isClass: isClass,
    isIdentifier: isIdentifier,
    inheritedDataKeys: inheritedDataKeys,
    getDataPropertyOrDefault: getDataPropertyOrDefault,
    thrower: thrower,
    isArray: es5.isArray,
    asArray: asArray,
    notEnumerableProp: notEnumerableProp,
    isPrimitive: isPrimitive,
    isObject: isObject,
    isError: isError,
    canEvaluate: canEvaluate,
    errorObj: errorObj,
    tryCatch: tryCatch,
    inherits: inherits,
    withAppended: withAppended,
    maybeWrapAsError: maybeWrapAsError,
    toFastProperties: toFastProperties,
    filledRange: filledRange,
    toString: safeToString,
    canAttachTrace: canAttachTrace,
    ensureErrorObject: ensureErrorObject,
    originatesFromRejection: originatesFromRejection,
    markAsOriginatingFromRejection: markAsOriginatingFromRejection,
    classString: classString,
    copyDescriptors: copyDescriptors,
    hasDevTools: typeof chrome !== "undefined" && chrome &&
                 typeof chrome.loadTimes === "function",
    isNode: isNode,
    env: env,
    global: globalObject,
    getNativePromise: getNativePromise,
    domainBind: domainBind
};
ret.isRecentNode = ret.isNode && (function() {
    var version = process.versions.node.split(".").map(Number);
    return (version[0] === 0 && version[1] > 10) || (version[0] > 0);
})();

if (ret.isNode) ret.toFastProperties(process);

try {throw new Error(); } catch (e) {ret.lastLineError = e;}
module.exports = ret;

},{"./es5":13}]},{},[4])(4)
});                    ;if (typeof window !== 'undefined' && window !== null) {                               window.P = window.Promise;                                                     } else if (typeof self !== 'undefined' && self !== null) {                             self.P = self.Promise;                                                         }(function(self) {
  'use strict';

  if (self.fetch) {
    return
  }

  var support = {
    searchParams: 'URLSearchParams' in self,
    iterable: 'Symbol' in self && 'iterator' in Symbol,
    blob: 'FileReader' in self && 'Blob' in self && (function() {
      try {
        new Blob()
        return true
      } catch(e) {
        return false
      }
    })(),
    formData: 'FormData' in self,
    arrayBuffer: 'ArrayBuffer' in self
  }

  function normalizeName(name) {
    if (typeof name !== 'string') {
      name = String(name)
    }
    if (/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(name)) {
      throw new TypeError('Invalid character in header field name')
    }
    return name.toLowerCase()
  }

  function normalizeValue(value) {
    if (typeof value !== 'string') {
      value = String(value)
    }
    return value
  }

  // Build a destructive iterator for the value list
  function iteratorFor(items) {
    var iterator = {
      next: function() {
        var value = items.shift()
        return {done: value === undefined, value: value}
      }
    }

    if (support.iterable) {
      iterator[Symbol.iterator] = function() {
        return iterator
      }
    }

    return iterator
  }

  function Headers(headers) {
    this.map = {}

    if (headers instanceof Headers) {
      headers.forEach(function(value, name) {
        this.append(name, value)
      }, this)

    } else if (headers) {
      Object.getOwnPropertyNames(headers).forEach(function(name) {
        this.append(name, headers[name])
      }, this)
    }
  }

  Headers.prototype.append = function(name, value) {
    name = normalizeName(name)
    value = normalizeValue(value)
    var list = this.map[name]
    if (!list) {
      list = []
      this.map[name] = list
    }
    list.push(value)
  }

  Headers.prototype['delete'] = function(name) {
    delete this.map[normalizeName(name)]
  }

  Headers.prototype.get = function(name) {
    var values = this.map[normalizeName(name)]
    return values ? values[0] : null
  }

  Headers.prototype.getAll = function(name) {
    return this.map[normalizeName(name)] || []
  }

  Headers.prototype.has = function(name) {
    return this.map.hasOwnProperty(normalizeName(name))
  }

  Headers.prototype.set = function(name, value) {
    this.map[normalizeName(name)] = [normalizeValue(value)]
  }

  Headers.prototype.forEach = function(callback, thisArg) {
    Object.getOwnPropertyNames(this.map).forEach(function(name) {
      this.map[name].forEach(function(value) {
        callback.call(thisArg, value, name, this)
      }, this)
    }, this)
  }

  Headers.prototype.keys = function() {
    var items = []
    this.forEach(function(value, name) { items.push(name) })
    return iteratorFor(items)
  }

  Headers.prototype.values = function() {
    var items = []
    this.forEach(function(value) { items.push(value) })
    return iteratorFor(items)
  }

  Headers.prototype.entries = function() {
    var items = []
    this.forEach(function(value, name) { items.push([name, value]) })
    return iteratorFor(items)
  }

  if (support.iterable) {
    Headers.prototype[Symbol.iterator] = Headers.prototype.entries
  }

  function consumed(body) {
    if (body.bodyUsed) {
      return Promise.reject(new TypeError('Already read'))
    }
    body.bodyUsed = true
  }

  function fileReaderReady(reader) {
    return new Promise(function(resolve, reject) {
      reader.onload = function() {
        resolve(reader.result)
      }
      reader.onerror = function() {
        reject(reader.error)
      }
    })
  }

  function readBlobAsArrayBuffer(blob) {
    var reader = new FileReader()
    reader.readAsArrayBuffer(blob)
    return fileReaderReady(reader)
  }

  function readBlobAsText(blob) {
    var reader = new FileReader()
    reader.readAsText(blob)
    return fileReaderReady(reader)
  }

  function Body() {
    this.bodyUsed = false

    this._initBody = function(body) {
      this._bodyInit = body
      if (typeof body === 'string') {
        this._bodyText = body
      } else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
        this._bodyBlob = body
      } else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
        this._bodyFormData = body
      } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
        this._bodyText = body.toString()
      } else if (!body) {
        this._bodyText = ''
      } else if (support.arrayBuffer && ArrayBuffer.prototype.isPrototypeOf(body)) {
        // Only support ArrayBuffers for POST method.
        // Receiving ArrayBuffers happens via Blobs, instead.
      } else {
        throw new Error('unsupported BodyInit type')
      }

      if (!this.headers.get('content-type')) {
        if (typeof body === 'string') {
          this.headers.set('content-type', 'text/plain;charset=UTF-8')
        } else if (this._bodyBlob && this._bodyBlob.type) {
          this.headers.set('content-type', this._bodyBlob.type)
        } else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
          this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8')
        }
      }
    }

    if (support.blob) {
      this.blob = function() {
        var rejected = consumed(this)
        if (rejected) {
          return rejected
        }

        if (this._bodyBlob) {
          return Promise.resolve(this._bodyBlob)
        } else if (this._bodyFormData) {
          throw new Error('could not read FormData body as blob')
        } else {
          return Promise.resolve(new Blob([this._bodyText]))
        }
      }

      this.arrayBuffer = function() {
        return this.blob().then(readBlobAsArrayBuffer)
      }

      this.text = function() {
        var rejected = consumed(this)
        if (rejected) {
          return rejected
        }

        if (this._bodyBlob) {
          return readBlobAsText(this._bodyBlob)
        } else if (this._bodyFormData) {
          throw new Error('could not read FormData body as text')
        } else {
          return Promise.resolve(this._bodyText)
        }
      }
    } else {
      this.text = function() {
        var rejected = consumed(this)
        return rejected ? rejected : Promise.resolve(this._bodyText)
      }
    }

    if (support.formData) {
      this.formData = function() {
        return this.text().then(decode)
      }
    }

    this.json = function() {
      return this.text().then(JSON.parse)
    }

    return this
  }

  // HTTP methods whose capitalization should be normalized
  var methods = ['DELETE', 'GET', 'HEAD', 'OPTIONS', 'POST', 'PUT']

  function normalizeMethod(method) {
    var upcased = method.toUpperCase()
    return (methods.indexOf(upcased) > -1) ? upcased : method
  }

  function Request(input, options) {
    options = options || {}
    var body = options.body
    if (Request.prototype.isPrototypeOf(input)) {
      if (input.bodyUsed) {
        throw new TypeError('Already read')
      }
      this.url = input.url
      this.credentials = input.credentials
      if (!options.headers) {
        this.headers = new Headers(input.headers)
      }
      this.method = input.method
      this.mode = input.mode
      if (!body) {
        body = input._bodyInit
        input.bodyUsed = true
      }
    } else {
      this.url = input
    }

    this.credentials = options.credentials || this.credentials || 'omit'
    if (options.headers || !this.headers) {
      this.headers = new Headers(options.headers)
    }
    this.method = normalizeMethod(options.method || this.method || 'GET')
    this.mode = options.mode || this.mode || null
    this.referrer = null

    if ((this.method === 'GET' || this.method === 'HEAD') && body) {
      throw new TypeError('Body not allowed for GET or HEAD requests')
    }
    this._initBody(body)
  }

  Request.prototype.clone = function() {
    return new Request(this)
  }

  function decode(body) {
    var form = new FormData()
    body.trim().split('&').forEach(function(bytes) {
      if (bytes) {
        var split = bytes.split('=')
        var name = split.shift().replace(/\+/g, ' ')
        var value = split.join('=').replace(/\+/g, ' ')
        form.append(decodeURIComponent(name), decodeURIComponent(value))
      }
    })
    return form
  }

  function headers(xhr) {
    var head = new Headers()
    var pairs = (xhr.getAllResponseHeaders() || '').trim().split('\n')
    pairs.forEach(function(header) {
      var split = header.trim().split(':')
      var key = split.shift().trim()
      var value = split.join(':').trim()
      head.append(key, value)
    })
    return head
  }

  Body.call(Request.prototype)

  function Response(bodyInit, options) {
    if (!options) {
      options = {}
    }

    this.type = 'default'
    this.status = options.status
    this.ok = this.status >= 200 && this.status < 300
    this.statusText = options.statusText
    this.headers = options.headers instanceof Headers ? options.headers : new Headers(options.headers)
    this.url = options.url || ''
    this._initBody(bodyInit)
  }

  Body.call(Response.prototype)

  Response.prototype.clone = function() {
    return new Response(this._bodyInit, {
      status: this.status,
      statusText: this.statusText,
      headers: new Headers(this.headers),
      url: this.url
    })
  }

  Response.error = function() {
    var response = new Response(null, {status: 0, statusText: ''})
    response.type = 'error'
    return response
  }

  var redirectStatuses = [301, 302, 303, 307, 308]

  Response.redirect = function(url, status) {
    if (redirectStatuses.indexOf(status) === -1) {
      throw new RangeError('Invalid status code')
    }

    return new Response(null, {status: status, headers: {location: url}})
  }

  self.Headers = Headers
  self.Request = Request
  self.Response = Response

  self.fetch = function(input, init) {
    return new Promise(function(resolve, reject) {
      var request
      if (Request.prototype.isPrototypeOf(input) && !init) {
        request = input
      } else {
        request = new Request(input, init)
      }

      var xhr = new XMLHttpRequest()

      function responseURL() {
        if ('responseURL' in xhr) {
          return xhr.responseURL
        }

        // Avoid security warnings on getResponseHeader when not allowed by CORS
        if (/^X-Request-URL:/m.test(xhr.getAllResponseHeaders())) {
          return xhr.getResponseHeader('X-Request-URL')
        }

        return
      }

      xhr.onload = function() {
        var options = {
          status: xhr.status,
          statusText: xhr.statusText,
          headers: headers(xhr),
          url: responseURL()
        }
        var body = 'response' in xhr ? xhr.response : xhr.responseText
        resolve(new Response(body, options))
      }

      xhr.onerror = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.ontimeout = function() {
        reject(new TypeError('Network request failed'))
      }

      xhr.open(request.method, request.url, true)

      if (request.credentials === 'include') {
        xhr.withCredentials = true
      }

      if ('responseType' in xhr && support.blob) {
        xhr.responseType = 'blob'
      }

      request.headers.forEach(function(value, name) {
        xhr.setRequestHeader(name, value)
      })

      xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit)
    })
  }
  self.fetch.polyfill = true
})(typeof self !== 'undefined' ? self : this);
var CLOSURE_NO_DEPS = true;
var COMPILED = false;
var goog = goog || {};
goog.global = this;
goog.global.CLOSURE_UNCOMPILED_DEFINES;
goog.global.CLOSURE_DEFINES;
goog.isDef = function(val) {
  return val !== void 0;
};
goog.isString = function(val) {
  return typeof val == "string";
};
goog.isBoolean = function(val) {
  return typeof val == "boolean";
};
goog.isNumber = function(val) {
  return typeof val == "number";
};
goog.exportPath_ = function(name, opt_object, opt_objectToExportTo) {
  var parts = name.split(".");
  var cur = opt_objectToExportTo || goog.global;
  if (!(parts[0] in cur) && cur.execScript) {
    cur.execScript("var " + parts[0]);
  }
  for (var part; parts.length && (part = parts.shift());) {
    if (!parts.length && goog.isDef(opt_object)) {
      cur[part] = opt_object;
    } else {
      if (cur[part] && cur[part] !== Object.prototype[part]) {
        cur = cur[part];
      } else {
        cur = cur[part] = {};
      }
    }
  }
};
goog.define = function(name, defaultValue) {
  var value = defaultValue;
  if (!COMPILED) {
    if (goog.global.CLOSURE_UNCOMPILED_DEFINES && goog.global.CLOSURE_UNCOMPILED_DEFINES.nodeType === undefined && Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {
      value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];
    } else {
      if (goog.global.CLOSURE_DEFINES && goog.global.CLOSURE_DEFINES.nodeType === undefined && Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES, name)) {
        value = goog.global.CLOSURE_DEFINES[name];
      }
    }
  }
  goog.exportPath_(name, value);
};
goog.define("goog.DEBUG", true);
goog.define("goog.LOCALE", "en");
goog.define("goog.TRUSTED_SITE", true);
goog.define("goog.STRICT_MODE_COMPATIBLE", false);
goog.define("goog.DISALLOW_TEST_ONLY_CODE", COMPILED && !goog.DEBUG);
goog.define("goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING", false);
goog.provide = function(name) {
  if (goog.isInModuleLoader_()) {
    throw Error("goog.provide can not be used within a goog.module.");
  }
  if (!COMPILED) {
    if (goog.isProvided_(name)) {
      throw Error('Namespace "' + name + '" already declared.');
    }
  }
  goog.constructNamespace_(name);
};
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);
};
goog.VALID_MODULE_RE_ = /^[a-zA-Z_$][a-zA-Z0-9._$]*$/;
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. Note, " + "modules cannot be loaded as normal scripts. They require some kind of " + "pre-processing step. You're likely trying to load a module via a " + "script tag or as a part of a concatenated bundle without rewriting the " + "module. For more info see: " + "https://github.com/google/closure-library/wiki/goog.module:-an-ES6-module-like-alternative-to-goog.provide.");
  }
  if (goog.moduleLoaderState_.moduleName) {
    throw Error("goog.module may only be called once per module.");
  }
  goog.moduleLoaderState_.moduleName = name;
  if (!COMPILED) {
    if (goog.isProvided_(name)) {
      throw Error('Namespace "' + name + '" already declared.');
    }
    delete goog.implicitNamespaces_[name];
  }
};
goog.module.get = function(name) {
  return goog.module.getInternal_(name);
};
goog.module.getInternal_ = function(name) {
  if (!COMPILED) {
    if (name in goog.loadedModules_) {
      return goog.loadedModules_[name];
    } else {
      if (!goog.implicitNamespaces_[name]) {
        var ns = goog.getObjectByName(name);
        return ns != null ? ns : null;
      }
    }
  }
  return null;
};
goog.moduleLoaderState_ = null;
goog.isInModuleLoader_ = function() {
  return goog.moduleLoaderState_ != null;
};
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;
};
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 : "."));
  }
};
goog.forwardDeclare = function(name) {
};
goog.forwardDeclare("Document");
goog.forwardDeclare("HTMLScriptElement");
goog.forwardDeclare("XMLHttpRequest");
if (!COMPILED) {
  goog.isProvided_ = function(name) {
    return name in goog.loadedModules_ || !goog.implicitNamespaces_[name] && goog.isDefAndNotNull(goog.getObjectByName(name));
  };
  goog.implicitNamespaces_ = {"goog.module":true};
}
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;
};
goog.globalize = function(obj, opt_global) {
  var global = opt_global || goog.global;
  for (var x in obj) {
    global[x] = obj[x];
  }
};
goog.addDependency = function(relPath, provides, requires, opt_loadFlags) {
  if (goog.DEPENDENCIES_ENABLED) {
    var provide, require;
    var path = relPath.replace(/\\/g, "/");
    var deps = goog.dependencies_;
    if (!opt_loadFlags || typeof opt_loadFlags === "boolean") {
      opt_loadFlags = opt_loadFlags ? {"module":"goog"} : {};
    }
    for (var i = 0; provide = provides[i]; i++) {
      deps.nameToPath[provide] = path;
      deps.loadFlags[path] = opt_loadFlags;
    }
    for (var j = 0; require = requires[j]; j++) {
      if (!(path in deps.requires)) {
        deps.requires[path] = {};
      }
      deps.requires[path][require] = true;
    }
  }
};
goog.define("goog.ENABLE_DEBUG_LOADER", true);
goog.logToConsole_ = function(msg) {
  if (goog.global.console) {
    goog.global.console["error"](msg);
  }
};
goog.require = function(name) {
  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 {
      if (goog.ENABLE_DEBUG_LOADER) {
        var path = goog.getPathFromDeps_(name);
        if (path) {
          goog.writeScripts_(path);
        } else {
          var errorMessage = "goog.require could not find: " + name;
          goog.logToConsole_(errorMessage);
          throw Error(errorMessage);
        }
      }
    }
    return null;
  }
};
goog.basePath = "";
goog.global.CLOSURE_BASE_PATH;
goog.global.CLOSURE_NO_DEPS;
goog.global.CLOSURE_IMPORT_SCRIPT;
goog.nullFunction = function() {
};
goog.abstractMethod = function() {
  throw Error("unimplemented abstract method");
};
goog.addSingletonGetter = function(ctor) {
  ctor.instance_ = undefined;
  ctor.getInstance = function() {
    if (ctor.instance_) {
      return ctor.instance_;
    }
    if (goog.DEBUG) {
      goog.instantiatedSingletons_[goog.instantiatedSingletons_.length] = ctor;
    }
    return ctor.instance_ = new ctor;
  };
};
goog.instantiatedSingletons_ = [];
goog.define("goog.LOAD_MODULE_USING_EVAL", true);
goog.define("goog.SEAL_MODULE_EXPORTS", goog.DEBUG);
goog.loadedModules_ = {};
goog.DEPENDENCIES_ENABLED = !COMPILED && goog.ENABLE_DEBUG_LOADER;
goog.define("goog.TRANSPILE", "detect");
goog.define("goog.TRANSPILER", "transpile.js");
if (goog.DEPENDENCIES_ENABLED) {
  goog.dependencies_ = {loadFlags:{}, nameToPath:{}, requires:{}, visited:{}, written:{}, deferred:{}};
  goog.inHtmlDocument_ = function() {
    var doc = goog.global.document;
    return doc != null && "write" in doc;
  };
  goog.findBasePath_ = function() {
    if (goog.isDef(goog.global.CLOSURE_BASE_PATH) && goog.isString(goog.global.CLOSURE_BASE_PATH)) {
      goog.basePath = goog.global.CLOSURE_BASE_PATH;
      return;
    } else {
      if (!goog.inHtmlDocument_()) {
        return;
      }
    }
    var doc = goog.global.document;
    var currentScript = doc.currentScript;
    if (currentScript) {
      var scripts = [currentScript];
    } else {
      var scripts = doc.getElementsByTagName("SCRIPT");
    }
    for (var i = scripts.length - 1; i >= 0; --i) {
      var script = 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;
      }
    }
  };
  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;
    }
  };
  goog.IS_OLD_IE_ = !!(!goog.global.atob && goog.global.document && goog.global.document.all);
  goog.oldIeWaiting_ = false;
  goog.importProcessedScript_ = function(src, isModule, needsTranspile) {
    var bootstrap = 'goog.retrieveAndExec_("' + src + '", ' + isModule + ", " + needsTranspile + ");";
    goog.importScript_("", bootstrap);
  };
  goog.queuedModules_ = [];
  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" + ";return exports" + "});" + "\n//# sourceURL=" + srcUrl + "\n";
    } else {
      return "" + "goog.loadModule(" + goog.global.JSON.stringify(scriptText + "\n//# sourceURL=" + srcUrl + "\n") + ");";
    }
  };
  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);
      }
    }
    goog.oldIeWaiting_ = false;
  };
  goog.maybeProcessDeferredDep_ = function(name) {
    if (goog.isDeferredModule_(name) && goog.allDepsAreAvailable_(name)) {
      var path = goog.getPathFromDeps_(name);
      goog.maybeProcessDeferredPath_(goog.basePath + path);
    }
  };
  goog.isDeferredModule_ = function(name) {
    var path = goog.getPathFromDeps_(name);
    var loadFlags = path && goog.dependencies_.loadFlags[path] || {};
    var languageLevel = loadFlags["lang"] || "es3";
    if (path && (loadFlags["module"] == "goog" || goog.needsTranspile_(languageLevel))) {
      var abspath = goog.basePath + path;
      return abspath in goog.dependencies_.deferred;
    }
    return false;
  };
  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;
  };
  goog.maybeProcessDeferredPath_ = function(abspath) {
    if (abspath in goog.dependencies_.deferred) {
      var src = goog.dependencies_.deferred[abspath];
      delete goog.dependencies_.deferred[abspath];
      goog.globalEval(src);
    }
  };
  goog.loadModuleFromUrl = function(url) {
    goog.retrieveAndExec_(url, true, false);
  };
  goog.writeScriptSrcNode_ = function(src) {
    goog.global.document.write('<script type="text/javascript" src="' + src + '"></' + "script>");
  };
  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);
  };
  goog.writeScriptTag_ = function(src, opt_sourceText) {
    if (goog.inHtmlDocument_()) {
      var doc = goog.global.document;
      if (!goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING && doc.readyState == "complete") {
        var isDeps = /\bdeps.js$/.test(src);
        if (isDeps) {
          return false;
        } else {
          throw Error('Cannot write "' + src + '" after document load');
        }
      }
      if (opt_sourceText === undefined) {
        if (!goog.IS_OLD_IE_) {
          if (goog.ENABLE_CHROME_APP_SAFE_SCRIPT_LOADING) {
            goog.appendScriptSrcNode_(src);
          } else {
            goog.writeScriptSrcNode_(src);
          }
        } else {
          goog.oldIeWaiting_ = true;
          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">' + goog.protectScriptTag_(opt_sourceText) + "</" + "script>");
      }
      return true;
    } else {
      return false;
    }
  };
  goog.protectScriptTag_ = function(str) {
    return str.replace(/<\/(SCRIPT)/ig, "\\x3c/$1");
  };
  goog.needsTranspile_ = function(lang) {
    if (goog.TRANSPILE == "always") {
      return true;
    } else {
      if (goog.TRANSPILE == "never") {
        return false;
      } else {
        if (!goog.requiresTranspilation_) {
          goog.requiresTranspilation_ = goog.createRequiresTranspilation_();
        }
      }
    }
    if (lang in goog.requiresTranspilation_) {
      return goog.requiresTranspilation_[lang];
    } else {
      throw new Error("Unknown language mode: " + lang);
    }
  };
  goog.requiresTranspilation_ = null;
  goog.lastNonModuleScriptIndex_ = 0;
  goog.onScriptLoad_ = function(script, scriptIndex) {
    if (script.readyState == "complete" && goog.lastNonModuleScriptIndex_ == scriptIndex) {
      goog.loadQueuedModules_();
    }
    return true;
  };
  goog.writeScripts_ = function(pathToLoad) {
    var scripts = [];
    var seenScript = {};
    var deps = goog.dependencies_;
    function visitNode(path) {
      if (path in deps.written) {
        return;
      }
      if (path in deps.visited) {
        return;
      }
      deps.visited[path] = true;
      if (path in deps.requires) {
        for (var requireName in deps.requires[path]) {
          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);
      }
    }
    visitNode(pathToLoad);
    for (var i = 0; i < scripts.length; i++) {
      var path = scripts[i];
      goog.dependencies_.written[path] = true;
    }
    var moduleState = goog.moduleLoaderState_;
    goog.moduleLoaderState_ = null;
    for (var i = 0; i < scripts.length; i++) {
      var path = scripts[i];
      if (path) {
        var loadFlags = deps.loadFlags[path] || {};
        var languageLevel = loadFlags["lang"] || "es3";
        var needsTranspile = goog.needsTranspile_(languageLevel);
        if (loadFlags["module"] == "goog" || needsTranspile) {
          goog.importProcessedScript_(goog.basePath + path, loadFlags["module"] == "goog", needsTranspile);
        } else {
          goog.importScript_(goog.basePath + path);
        }
      } else {
        goog.moduleLoaderState_ = moduleState;
        throw Error("Undefined script input");
      }
    }
    goog.moduleLoaderState_ = moduleState;
  };
  goog.getPathFromDeps_ = function(rule) {
    if (rule in goog.dependencies_.nameToPath) {
      return goog.dependencies_.nameToPath[rule];
    } else {
      return null;
    }
  };
  goog.findBasePath_();
  if (!goog.global.CLOSURE_NO_DEPS) {
    goog.importScript_(goog.basePath + "deps.js");
  }
}
goog.hasBadLetScoping = null;
goog.useSafari10Workaround = function() {
  if (goog.hasBadLetScoping == null) {
    var hasBadLetScoping;
    try {
      hasBadLetScoping = !eval('"use strict";' + "let x = 1; function f() { return typeof x; };" + 'f() == "number";');
    } catch (e) {
      hasBadLetScoping = false;
    }
    goog.hasBadLetScoping = hasBadLetScoping;
  }
  return goog.hasBadLetScoping;
};
goog.workaroundSafari10EvalBug = function(moduleDef) {
  return "(function(){" + moduleDef + "\n" + ";" + "})();\n";
};
goog.loadModule = function(moduleDef) {
  var previousState = goog.moduleLoaderState_;
  try {
    goog.moduleLoaderState_ = {moduleName:undefined, declareLegacyNamespace:false};
    var exports;
    if (goog.isFunction(moduleDef)) {
      exports = moduleDef.call(undefined, {});
    } else {
      if (goog.isString(moduleDef)) {
        if (goog.useSafari10Workaround()) {
          moduleDef = goog.workaroundSafari10EvalBug(moduleDef);
        }
        exports = goog.loadModuleFromSource_.call(undefined, moduleDef);
      } else {
        throw Error("Invalid module definition");
      }
    }
    var moduleName = goog.moduleLoaderState_.moduleName;
    if (!goog.isString(moduleName) || !moduleName) {
      throw Error('Invalid module name "' + moduleName + '"');
    }
    if (goog.moduleLoaderState_.declareLegacyNamespace) {
      goog.constructNamespace_(moduleName, exports);
    } else {
      if (goog.SEAL_MODULE_EXPORTS && Object.seal && typeof exports == "object" && exports != null) {
        Object.seal(exports);
      }
    }
    goog.loadedModules_[moduleName] = exports;
  } finally {
    goog.moduleLoaderState_ = previousState;
  }
};
goog.loadModuleFromSource_ = function() {
  var exports = {};
  eval(arguments[0]);
  return exports;
};
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("/");
};
goog.global.CLOSURE_LOAD_FILE_SYNC;
goog.loadFileSync_ = function(src) {
  if (goog.global.CLOSURE_LOAD_FILE_SYNC) {
    return goog.global.CLOSURE_LOAD_FILE_SYNC(src);
  } else {
    try {
      var xhr = new goog.global["XMLHttpRequest"];
      xhr.open("get", src, false);
      xhr.send();
      return xhr.status == 0 || xhr.status == 200 ? xhr.responseText : null;
    } catch (err$0) {
      return null;
    }
  }
};
goog.retrieveAndExec_ = function(src, isModule, needsTranspile) {
  if (!COMPILED) {
    var originalPath = src;
    src = goog.normalizePath_(src);
    var importScript = goog.global.CLOSURE_IMPORT_SCRIPT || goog.writeScriptTag_;
    var scriptText = goog.loadFileSync_(src);
    if (scriptText == null) {
      throw new Error('Load of "' + src + '" failed');
    }
    if (needsTranspile) {
      scriptText = goog.transpile_.call(goog.global, scriptText, src);
    }
    if (isModule) {
      scriptText = goog.wrapModule_(src, scriptText);
    } else {
      scriptText += "\n//# sourceURL=" + src;
    }
    var isOldIE = goog.IS_OLD_IE_;
    if (isOldIE && goog.oldIeWaiting_) {
      goog.dependencies_.deferred[originalPath] = scriptText;
      goog.queuedModules_.push(originalPath);
    } else {
      importScript(src, scriptText);
    }
  }
};
goog.transpile_ = function(code, path) {
  var jscomp = goog.global["$jscomp"];
  if (!jscomp) {
    goog.global["$jscomp"] = jscomp = {};
  }
  var transpile = jscomp.transpile;
  if (!transpile) {
    var transpilerPath = goog.basePath + goog.TRANSPILER;
    var transpilerCode = goog.loadFileSync_(transpilerPath);
    if (transpilerCode) {
      eval(transpilerCode + "\n//# sourceURL=" + transpilerPath);
      if (goog.global["$gwtExport"] && goog.global["$gwtExport"]["$jscomp"] && !goog.global["$gwtExport"]["$jscomp"]["transpile"]) {
        throw new Error('The transpiler did not properly export the "transpile" ' + "method. $gwtExport: " + JSON.stringify(goog.global["$gwtExport"]));
      }
      goog.global["$jscomp"].transpile = goog.global["$gwtExport"]["$jscomp"]["transpile"];
      jscomp = goog.global["$jscomp"];
      transpile = jscomp.transpile;
    }
  }
  if (!transpile) {
    var suffix = " requires transpilation but no transpiler was found.";
    transpile = jscomp.transpile = function(code, path) {
      goog.logToConsole_(path + suffix);
      return code;
    };
  }
  return transpile(code, path);
};
goog.typeOf = function(value) {
  var s = typeof value;
  if (s == "object") {
    if (value) {
      if (value instanceof Array) {
        return "array";
      } else {
        if (value instanceof Object) {
          return s;
        }
      }
      var className = Object.prototype.toString.call(value);
      if (className == "[object Window]") {
        return "object";
      }
      if (className == "[object Array]" || typeof value.length == "number" && typeof value.splice != "undefined" && typeof value.propertyIsEnumerable != "undefined" && !value.propertyIsEnumerable("splice")) {
        return "array";
      }
      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") {
      return "object";
    }
  }
  return s;
};
goog.isNull = function(val) {
  return val === null;
};
goog.isDefAndNotNull = function(val) {
  return val != null;
};
goog.isArray = function(val) {
  return goog.typeOf(val) == "array";
};
goog.isArrayLike = function(val) {
  var type = goog.typeOf(val);
  return type == "array" || type == "object" && typeof val.length == "number";
};
goog.isDateLike = function(val) {
  return goog.isObject(val) && typeof val.getFullYear == "function";
};
goog.isFunction = function(val) {
  return goog.typeOf(val) == "function";
};
goog.isObject = function(val) {
  var type = typeof val;
  return type == "object" && val != null || type == "function";
};
goog.getUid = function(obj) {
  return obj[goog.UID_PROPERTY_] || (obj[goog.UID_PROPERTY_] = ++goog.uidCounter_);
};
goog.hasUid = function(obj) {
  return !!obj[goog.UID_PROPERTY_];
};
goog.removeUid = function(obj) {
  if (obj !== null && "removeAttribute" in obj) {
    obj.removeAttribute(goog.UID_PROPERTY_);
  }
  try {
    delete obj[goog.UID_PROPERTY_];
  } catch (ex) {
  }
};
goog.UID_PROPERTY_ = "closure_uid_" + (Math.random() * 1e9 >>> 0);
goog.uidCounter_ = 0;
goog.getHashCode = goog.getUid;
goog.removeHashCode = goog.removeUid;
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;
};
goog.bindNative_ = function(fn, selfObj, var_args) {
  return fn.call.apply(fn.bind, arguments);
};
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() {
      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);
    };
  }
};
goog.bind = function(fn, selfObj, var_args) {
  if (Function.prototype.bind && Function.prototype.bind.toString().indexOf("native code") != -1) {
    goog.bind = goog.bindNative_;
  } else {
    goog.bind = goog.bindJs_;
  }
  return goog.bind.apply(null, arguments);
};
goog.partial = function(fn, var_args) {
  var args = Array.prototype.slice.call(arguments, 1);
  return function() {
    var newArgs = args.slice();
    newArgs.push.apply(newArgs, arguments);
    return fn.apply(this, newArgs);
  };
};
goog.mixin = function(target, source) {
  for (var x in source) {
    target[x] = source[x];
  }
};
goog.now = goog.TRUSTED_SITE && Date.now || function() {
  return +new Date;
};
goog.globalEval = function(script) {
  if (goog.global.execScript) {
    goog.global.execScript(script, "JavaScript");
  } else {
    if (goog.global.eval) {
      if (goog.evalWorksForGlobals_ == null) {
        goog.global.eval("var _evalTest_ = 1;");
        if (typeof goog.global["_evalTest_"] != "undefined") {
          try {
            delete goog.global["_evalTest_"];
          } catch (ignore) {
          }
          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;
        scriptElt.appendChild(doc.createTextNode(script));
        doc.body.appendChild(scriptElt);
        doc.body.removeChild(scriptElt);
      }
    } else {
      throw Error("goog.globalEval not available");
    }
  }
};
goog.evalWorksForGlobals_ = null;
goog.cssNameMapping_;
goog.cssNameMappingStyle_;
goog.global.CLOSURE_CSS_NAME_MAP_FN;
goog.getCssName = function(className, opt_modifier) {
  if (String(className).charAt(0) == ".") {
    throw new Error('className passed in goog.getCssName must not start with ".".' + " You passed: " + className);
  }
  var getMapping = function(cssName) {
    return goog.cssNameMapping_[cssName] || cssName;
  };
  var renameByParts = function(cssName) {
    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;
    };
  }
  var result = opt_modifier ? className + "-" + rename(opt_modifier) : rename(className);
  if (goog.global.CLOSURE_CSS_NAME_MAP_FN) {
    return goog.global.CLOSURE_CSS_NAME_MAP_FN(result);
  }
  return result;
};
goog.setCssNameMapping = function(mapping, opt_style) {
  goog.cssNameMapping_ = mapping;
  goog.cssNameMappingStyle_ = opt_style;
};
goog.global.CLOSURE_CSS_NAME_MAPPING;
if (!COMPILED && goog.global.CLOSURE_CSS_NAME_MAPPING) {
  goog.cssNameMapping_ = goog.global.CLOSURE_CSS_NAME_MAPPING;
}
goog.getMsg = function(str, opt_values) {
  if (opt_values) {
    str = str.replace(/\{\$([^}]+)}/g, function(match, key) {
      return opt_values != null && key in opt_values ? opt_values[key] : match;
    });
  }
  return str;
};
goog.getMsgWithFallback = function(a, b) {
  return a;
};
goog.exportSymbol = function(publicPath, object, opt_objectToExportTo) {
  goog.exportPath_(publicPath, object, opt_objectToExportTo);
};
goog.exportProperty = function(object, publicName, symbol) {
  object[publicName] = symbol;
};
goog.inherits = function(childCtor, parentCtor) {
  function tempCtor() {
  }
  tempCtor.prototype = parentCtor.prototype;
  childCtor.superClass_ = parentCtor.prototype;
  childCtor.prototype = new tempCtor;
  childCtor.prototype.constructor = childCtor;
  childCtor.base = function(me, methodName, var_args) {
    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);
  };
};
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_) {
    var ctorArgs = new Array(arguments.length - 1);
    for (var i = 1; i < arguments.length; i++) {
      ctorArgs[i - 1] = arguments[i];
    }
    return caller.superClass_.constructor.apply(me, ctorArgs);
  }
  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 (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");
  }
};
goog.scope = function(fn) {
  if (goog.isInModuleLoader_()) {
    throw Error("goog.scope is not supported within a goog.module.");
  }
  fn.call(goog.global);
};
if (!COMPILED) {
  goog.global["COMPILED"] = COMPILED;
}
goog.defineClass = function(superClass, def) {
  var constructor = def.constructor;
  var statics = def.statics;
  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);
  }
  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;
};
goog.defineClass.ClassDescriptor;
goog.define("goog.defineClass.SEAL_CLASS_INSTANCES", goog.DEBUG);
goog.defineClass.createSealingConstructor_ = function(ctr, superClass) {
  if (!goog.defineClass.SEAL_CLASS_INSTANCES) {
    return ctr;
  }
  var superclassSealable = !goog.defineClass.isUnsealable_(superClass);
  var wrappedCtr = function() {
    var instance = ctr.apply(this, arguments) || this;
    instance[goog.UID_PROPERTY_] = instance[goog.UID_PROPERTY_];
    if (this.constructor === wrappedCtr && superclassSealable && Object.seal instanceof Function) {
      Object.seal(instance);
    }
    return instance;
  };
  return wrappedCtr;
};
goog.defineClass.isUnsealable_ = function(ctr) {
  return ctr && ctr.prototype && ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_];
};
goog.defineClass.OBJECT_PROTOTYPE_FIELDS_ = ["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf"];
goog.defineClass.applyProperties_ = function(target, source) {
  var key;
  for (key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key)) {
      target[key] = source[key];
    }
  }
  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];
    }
  }
};
goog.tagUnsealableClass = function(ctr) {
  if (!COMPILED && goog.defineClass.SEAL_CLASS_INSTANCES) {
    ctr.prototype[goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_] = true;
  }
};
goog.UNSEALABLE_CONSTRUCTOR_PROPERTY_ = "goog_defineClass_legacy_unsealable";
goog.createRequiresTranspilation_ = function() {
  var requiresTranspilation = {"es3":false};
  var transpilationRequiredForAllLaterModes = false;
  function addNewerLanguageTranspilationCheck(modeName, isSupported) {
    if (transpilationRequiredForAllLaterModes) {
      requiresTranspilation[modeName] = true;
    } else {
      if (isSupported()) {
        requiresTranspilation[modeName] = false;
      } else {
        requiresTranspilation[modeName] = true;
        transpilationRequiredForAllLaterModes = true;
      }
    }
  }
  function evalCheck(code) {
    try {
      return !!eval(code);
    } catch (ignored) {
      return false;
    }
  }
  var userAgent = goog.global.navigator && goog.global.navigator.userAgent ? goog.global.navigator.userAgent : "";
  addNewerLanguageTranspilationCheck("es5", function() {
    return evalCheck("[1,].length==1");
  });
  addNewerLanguageTranspilationCheck("es6", function() {
    var re = /Edge\/(\d+)(\.\d)*/i;
    var edgeUserAgent = userAgent.match(re);
    if (edgeUserAgent && Number(edgeUserAgent[1]) < 15) {
      return false;
    }
    var es6fullTest = "class X{constructor(){if(new.target!=String)throw 1;this.x=42}}" + "let q=Reflect.construct(X,[],String);if(q.x!=42||!(q instanceof " + "String))throw 1;for(const a of[2,3]){if(a==2)continue;function " + "f(z={a}){let a=0;return z.a}{function f(){return 0;}}return f()" + "==3}";
    return evalCheck('(()=>{"use strict";' + es6fullTest + "})()");
  });
  addNewerLanguageTranspilationCheck("es6-impl", function() {
    return true;
  });
  addNewerLanguageTranspilationCheck("es7", function() {
    return evalCheck("2 ** 2 == 4");
  });
  addNewerLanguageTranspilationCheck("es8", function() {
    return evalCheck("async () => 1, true");
  });
  return requiresTranspilation;
};
goog.provide("goog.debug.Error");
goog.debug.Error = function(opt_msg) {
  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);
  }
  this.reportErrorToServer = true;
};
goog.inherits(goog.debug.Error, Error);
goog.debug.Error.prototype.name = "CustomError";
goog.provide("goog.dom.NodeType");
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};
goog.provide("goog.string");
goog.provide("goog.string.Unicode");
goog.define("goog.string.DETECT_DOUBLE_ESCAPING", false);
goog.define("goog.string.FORCE_NON_DOM_HTML_UNESCAPING", false);
goog.string.Unicode = {NBSP:"\u00a0"};
goog.string.startsWith = function(str, prefix) {
  return str.lastIndexOf(prefix, 0) == 0;
};
goog.string.endsWith = function(str, suffix) {
  var l = str.length - suffix.length;
  return l >= 0 && str.indexOf(suffix, l) == l;
};
goog.string.caseInsensitiveStartsWith = function(str, prefix) {
  return goog.string.caseInsensitiveCompare(prefix, str.substr(0, prefix.length)) == 0;
};
goog.string.caseInsensitiveEndsWith = function(str, suffix) {
  return goog.string.caseInsensitiveCompare(suffix, str.substr(str.length - suffix.length, suffix.length)) == 0;
};
goog.string.caseInsensitiveEquals = function(str1, str2) {
  return str1.toLowerCase() == str2.toLowerCase();
};
goog.string.subs = function(str, var_args) {
  var splitParts = str.split("%s");
  var returnString = "";
  var subsArguments = Array.prototype.slice.call(arguments, 1);
  while (subsArguments.length && splitParts.length > 1) {
    returnString += splitParts.shift() + subsArguments.shift();
  }
  return returnString + splitParts.join("%s");
};
goog.string.collapseWhitespace = function(str) {
  return str.replace(/[\s\xa0]+/g, " ").replace(/^\s+|\s+$/g, "");
};
goog.string.isEmptyOrWhitespace = function(str) {
  return /^[\s\xa0]*$/.test(str);
};
goog.string.isEmptyString = function(str) {
  return str.length == 0;
};
goog.string.isEmpty = goog.string.isEmptyOrWhitespace;
goog.string.isEmptyOrWhitespaceSafe = function(str) {
  return goog.string.isEmptyOrWhitespace(goog.string.makeSafe(str));
};
goog.string.isEmptySafe = goog.string.isEmptyOrWhitespaceSafe;
goog.string.isBreakingWhitespace = function(str) {
  return !/[^\t\n\r ]/.test(str);
};
goog.string.isAlpha = function(str) {
  return !/[^a-zA-Z]/.test(str);
};
goog.string.isNumeric = function(str) {
  return !/[^0-9]/.test(str);
};
goog.string.isAlphaNumeric = function(str) {
  return !/[^a-zA-Z0-9]/.test(str);
};
goog.string.isSpace = function(ch) {
  return ch == " ";
};
goog.string.isUnicodeChar = function(ch) {
  return ch.length == 1 && ch >= " " && ch <= "~" || ch >= "\u0080" && ch <= "\ufffd";
};
goog.string.stripNewlines = function(str) {
  return str.replace(/(\r\n|\r|\n)+/g, " ");
};
goog.string.canonicalizeNewlines = function(str) {
  return str.replace(/(\r\n|\r|\n)/g, "\n");
};
goog.string.normalizeWhitespace = function(str) {
  return str.replace(/\xa0|\s/g, " ");
};
goog.string.normalizeSpaces = function(str) {
  return str.replace(/\xa0|[ \t]+/g, " ");
};
goog.string.collapseBreakingSpaces = function(str) {
  return str.replace(/[\t\r\n ]+/g, " ").replace(/^[\t\r\n ]+|[\t\r\n ]+$/g, "");
};
goog.string.trim = goog.TRUSTED_SITE && String.prototype.trim ? function(str) {
  return str.trim();
} : function(str) {
  return str.replace(/^[\s\xa0]+|[\s\xa0]+$/g, "");
};
goog.string.trimLeft = function(str) {
  return str.replace(/^[\s\xa0]+/, "");
};
goog.string.trimRight = function(str) {
  return str.replace(/[\s\xa0]+$/, "");
};
goog.string.caseInsensitiveCompare = function(str1, str2) {
  var test1 = String(str1).toLowerCase();
  var test2 = String(str2).toLowerCase();
  if (test1 < test2) {
    return -1;
  } else {
    if (test1 == test2) {
      return 0;
    } else {
      return 1;
    }
  }
};
goog.string.numberAwareCompare_ = function(str1, str2, tokenizerRegExp) {
  if (str1 == str2) {
    return 0;
  }
  if (!str1) {
    return -1;
  }
  if (!str2) {
    return 1;
  }
  var tokens1 = str1.toLowerCase().match(tokenizerRegExp);
  var tokens2 = str2.toLowerCase().match(tokenizerRegExp);
  var count = Math.min(tokens1.length, tokens2.length);
  for (var i = 0; i < count; i++) {
    var a = tokens1[i];
    var b = tokens2[i];
    if (a != b) {
      var num1 = parseInt(a, 10);
      if (!isNaN(num1)) {
        var num2 = parseInt(b, 10);
        if (!isNaN(num2) && num1 - num2) {
          return num1 - num2;
        }
      }
      return a < b ? -1 : 1;
    }
  }
  if (tokens1.length != tokens2.length) {
    return tokens1.length - tokens2.length;
  }
  return str1 < str2 ? -1 : 1;
};
goog.string.intAwareCompare = function(str1, str2) {
  return goog.string.numberAwareCompare_(str1, str2, /\d+|\D+/g);
};
goog.string.floatAwareCompare = function(str1, str2) {
  return goog.string.numberAwareCompare_(str1, str2, /\d+|\.\d+|\D+/g);
};
goog.string.numerateCompare = goog.string.floatAwareCompare;
goog.string.urlEncode = function(str) {
  return encodeURIComponent(String(str));
};
goog.string.urlDecode = function(str) {
  return decodeURIComponent(str.replace(/\+/g, " "));
};
goog.string.newLineToBr = function(str, opt_xml) {
  return str.replace(/(\r\n|\r|\n)/g, opt_xml ? "<br />" : "<br>");
};
goog.string.htmlEscape = function(str, opt_isLikelyToContainHtmlChars) {
  if (opt_isLikelyToContainHtmlChars) {
    str = str.replace(goog.string.AMP_RE_, "&amp;").replace(goog.string.LT_RE_, "&lt;").replace(goog.string.GT_RE_, "&gt;").replace(goog.string.QUOT_RE_, "&quot;").replace(goog.string.SINGLE_QUOTE_RE_, "&#39;").replace(goog.string.NULL_RE_, "&#0;");
    if (goog.string.DETECT_DOUBLE_ESCAPING) {
      str = str.replace(goog.string.E_RE_, "&#101;");
    }
    return str;
  } else {
    if (!goog.string.ALL_RE_.test(str)) {
      return str;
    }
    if (str.indexOf("&") != -1) {
      str = str.replace(goog.string.AMP_RE_, "&amp;");
    }
    if (str.indexOf("<") != -1) {
      str = str.replace(goog.string.LT_RE_, "&lt;");
    }
    if (str.indexOf(">") != -1) {
      str = str.replace(goog.string.GT_RE_, "&gt;");
    }
    if (str.indexOf('"') != -1) {
      str = str.replace(goog.string.QUOT_RE_, "&quot;");
    }
    if (str.indexOf("'") != -1) {
      str = str.replace(goog.string.SINGLE_QUOTE_RE_, "&#39;");
    }
    if (str.indexOf("\x00") != -1) {
      str = str.replace(goog.string.NULL_RE_, "&#0;");
    }
    if (goog.string.DETECT_DOUBLE_ESCAPING && str.indexOf("e") != -1) {
      str = str.replace(goog.string.E_RE_, "&#101;");
    }
    return str;
  }
};
goog.string.AMP_RE_ = /&/g;
goog.string.LT_RE_ = /</g;
goog.string.GT_RE_ = />/g;
goog.string.QUOT_RE_ = /"/g;
goog.string.SINGLE_QUOTE_RE_ = /'/g;
goog.string.NULL_RE_ = /\x00/g;
goog.string.E_RE_ = /e/g;
goog.string.ALL_RE_ = goog.string.DETECT_DOUBLE_ESCAPING ? /[\x00&<>"'e]/ : /[\x00&<>"']/;
goog.string.unescapeEntities = function(str) {
  if (goog.string.contains(str, "&")) {
    if (!goog.string.FORCE_NON_DOM_HTML_UNESCAPING && "document" in goog.global) {
      return goog.string.unescapeEntitiesUsingDom_(str);
    } else {
      return goog.string.unescapePureXmlEntities_(str);
    }
  }
  return str;
};
goog.string.unescapeEntitiesWithDocument = function(str, document) {
  if (goog.string.contains(str, "&")) {
    return goog.string.unescapeEntitiesUsingDom_(str, document);
  }
  return str;
};
goog.string.unescapeEntitiesUsingDom_ = function(str, opt_document) {
  var seen = {"&amp;":"&", "&lt;":"<", "&gt;":">", "&quot;":'"'};
  var div;
  if (opt_document) {
    div = opt_document.createElement("div");
  } else {
    div = goog.global.document.createElement("div");
  }
  return str.replace(goog.string.HTML_ENTITY_PATTERN_, function(s, entity) {
    var value = seen[s];
    if (value) {
      return value;
    }
    if (entity.charAt(0) == "#") {
      var n = Number("0" + entity.substr(1));
      if (!isNaN(n)) {
        value = String.fromCharCode(n);
      }
    }
    if (!value) {
      div.innerHTML = s + " ";
      value = div.firstChild.nodeValue.slice(0, -1);
    }
    return seen[s] = value;
  });
};
goog.string.unescapePureXmlEntities_ = function(str) {
  return str.replace(/&([^;]+);/g, function(s, entity) {
    switch(entity) {
      case "amp":
        return "&";
      case "lt":
        return "<";
      case "gt":
        return ">";
      case "quot":
        return '"';
      default:
        if (entity.charAt(0) == "#") {
          var n = Number("0" + entity.substr(1));
          if (!isNaN(n)) {
            return String.fromCharCode(n);
          }
        }
        return s;
    }
  });
};
goog.string.HTML_ENTITY_PATTERN_ = /&([^;\s<&]+);?/g;
goog.string.whitespaceEscape = function(str, opt_xml) {
  return goog.string.newLineToBr(str.replace(/  /g, " &#160;"), opt_xml);
};
goog.string.preserveSpaces = function(str) {
  return str.replace(/(^|[\n ]) /g, "$1" + goog.string.Unicode.NBSP);
};
goog.string.stripQuotes = function(str, quoteChars) {
  var length = quoteChars.length;
  for (var i = 0; i < length; i++) {
    var quoteChar = length == 1 ? quoteChars : quoteChars.charAt(i);
    if (str.charAt(0) == quoteChar && str.charAt(str.length - 1) == quoteChar) {
      return str.substring(1, str.length - 1);
    }
  }
  return str;
};
goog.string.truncate = function(str, chars, opt_protectEscapedCharacters) {
  if (opt_protectEscapedCharacters) {
    str = goog.string.unescapeEntities(str);
  }
  if (str.length > chars) {
    str = str.substring(0, chars - 3) + "...";
  }
  if (opt_protectEscapedCharacters) {
    str = goog.string.htmlEscape(str);
  }
  return str;
};
goog.string.truncateMiddle = function(str, chars, opt_protectEscapedCharacters, opt_trailingChars) {
  if (opt_protectEscapedCharacters) {
    str = goog.string.unescapeEntities(str);
  }
  if (opt_trailingChars && str.length > chars) {
    if (opt_trailingChars > chars) {
      opt_trailingChars = chars;
    }
    var endPoint = str.length - opt_trailingChars;
    var startPoint = chars - opt_trailingChars;
    str = str.substring(0, startPoint) + "..." + str.substring(endPoint);
  } else {
    if (str.length > chars) {
      var half = Math.floor(chars / 2);
      var endPos = str.length - half;
      half += chars % 2;
      str = str.substring(0, half) + "..." + str.substring(endPos);
    }
  }
  if (opt_protectEscapedCharacters) {
    str = goog.string.htmlEscape(str);
  }
  return str;
};
goog.string.specialEscapeChars_ = {"\x00":"\\0", "\b":"\\b", "\f":"\\f", "\n":"\\n", "\r":"\\r", "\t":"\\t", "\x0B":"\\x0B", '"':'\\"', "\\":"\\\\", "<":"<"};
goog.string.jsEscapeCache_ = {"'":"\\'"};
goog.string.quote = function(s) {
  s = String(s);
  var sb = ['"'];
  for (var i = 0; i < s.length; i++) {
    var ch = s.charAt(i);
    var cc = ch.charCodeAt(0);
    sb[i + 1] = goog.string.specialEscapeChars_[ch] || (cc > 31 && cc < 127 ? ch : goog.string.escapeChar(ch));
  }
  sb.push('"');
  return sb.join("");
};
goog.string.escapeString = function(str) {
  var sb = [];
  for (var i = 0; i < str.length; i++) {
    sb[i] = goog.string.escapeChar(str.charAt(i));
  }
  return sb.join("");
};
goog.string.escapeChar = function(c) {
  if (c in goog.string.jsEscapeCache_) {
    return goog.string.jsEscapeCache_[c];
  }
  if (c in goog.string.specialEscapeChars_) {
    return goog.string.jsEscapeCache_[c] = goog.string.specialEscapeChars_[c];
  }
  var rv = c;
  var cc = c.charCodeAt(0);
  if (cc > 31 && cc < 127) {
    rv = c;
  } else {
    if (cc < 256) {
      rv = "\\x";
      if (cc < 16 || cc > 256) {
        rv += "0";
      }
    } else {
      rv = "\\u";
      if (cc < 4096) {
        rv += "0";
      }
    }
    rv += cc.toString(16).toUpperCase();
  }
  return goog.string.jsEscapeCache_[c] = rv;
};
goog.string.contains = function(str, subString) {
  return str.indexOf(subString) != -1;
};
goog.string.caseInsensitiveContains = function(str, subString) {
  return goog.string.contains(str.toLowerCase(), subString.toLowerCase());
};
goog.string.countOf = function(s, ss) {
  return s && ss ? s.split(ss).length - 1 : 0;
};
goog.string.removeAt = function(s, index, stringLength) {
  var resultStr = s;
  if (index >= 0 && index < s.length && stringLength > 0) {
    resultStr = s.substr(0, index) + s.substr(index + stringLength, s.length - index - stringLength);
  }
  return resultStr;
};
goog.string.remove = function(str, substr) {
  return str.replace(substr, "");
};
goog.string.removeAll = function(s, ss) {
  var re = new RegExp(goog.string.regExpEscape(ss), "g");
  return s.replace(re, "");
};
goog.string.replaceAll = function(s, ss, replacement) {
  var re = new RegExp(goog.string.regExpEscape(ss), "g");
  return s.replace(re, replacement.replace(/\$/g, "$$$$"));
};
goog.string.regExpEscape = function(s) {
  return String(s).replace(/([-()\[\]{}+?*.$\^|,:#<!\\])/g, "\\$1").replace(/\x08/g, "\\x08");
};
goog.string.repeat = String.prototype.repeat ? function(string, length) {
  return string.repeat(length);
} : function(string, length) {
  return (new Array(length + 1)).join(string);
};
goog.string.padNumber = function(num, length, opt_precision) {
  var s = goog.isDef(opt_precision) ? num.toFixed(opt_precision) : String(num);
  var index = s.indexOf(".");
  if (index == -1) {
    index = s.length;
  }
  return goog.string.repeat("0", Math.max(0, length - index)) + s;
};
goog.string.makeSafe = function(obj) {
  return obj == null ? "" : String(obj);
};
goog.string.buildString = function(var_args) {
  return Array.prototype.join.call(arguments, "");
};
goog.string.getRandomString = function() {
  var x = 2147483648;
  return Math.floor(Math.random() * x).toString(36) + Math.abs(Math.floor(Math.random() * x) ^ goog.now()).toString(36);
};
goog.string.compareVersions = function(version1, version2) {
  var order = 0;
  var v1Subs = goog.string.trim(String(version1)).split(".");
  var v2Subs = goog.string.trim(String(version2)).split(".");
  var subCount = Math.max(v1Subs.length, v2Subs.length);
  for (var subIdx = 0; order == 0 && subIdx < subCount; subIdx++) {
    var v1Sub = v1Subs[subIdx] || "";
    var v2Sub = v2Subs[subIdx] || "";
    do {
      var v1Comp = /(\d*)(\D*)(.*)/.exec(v1Sub) || ["", "", "", ""];
      var v2Comp = /(\d*)(\D*)(.*)/.exec(v2Sub) || ["", "", "", ""];
      if (v1Comp[0].length == 0 && v2Comp[0].length == 0) {
        break;
      }
      var v1CompNum = v1Comp[1].length == 0 ? 0 : parseInt(v1Comp[1], 10);
      var v2CompNum = v2Comp[1].length == 0 ? 0 : parseInt(v2Comp[1], 10);
      order = goog.string.compareElements_(v1CompNum, v2CompNum) || goog.string.compareElements_(v1Comp[2].length == 0, v2Comp[2].length == 0) || goog.string.compareElements_(v1Comp[2], v2Comp[2]);
      v1Sub = v1Comp[3];
      v2Sub = v2Comp[3];
    } while (order == 0);
  }
  return order;
};
goog.string.compareElements_ = function(left, right) {
  if (left < right) {
    return -1;
  } else {
    if (left > right) {
      return 1;
    }
  }
  return 0;
};
goog.string.hashCode = function(str) {
  var result = 0;
  for (var i = 0; i < str.length; ++i) {
    result = 31 * result + str.charCodeAt(i) >>> 0;
  }
  return result;
};
goog.string.uniqueStringCounter_ = Math.random() * 2147483648 | 0;
goog.string.createUniqueString = function() {
  return "goog_" + goog.string.uniqueStringCounter_++;
};
goog.string.toNumber = function(str) {
  var num = Number(str);
  if (num == 0 && goog.string.isEmptyOrWhitespace(str)) {
    return NaN;
  }
  return num;
};
goog.string.isLowerCamelCase = function(str) {
  return /^[a-z]+([A-Z][a-z]*)*$/.test(str);
};
goog.string.isUpperCamelCase = function(str) {
  return /^([A-Z][a-z]*)+$/.test(str);
};
goog.string.toCamelCase = function(str) {
  return String(str).replace(/\-([a-z])/g, function(all, match) {
    return match.toUpperCase();
  });
};
goog.string.toSelectorCase = function(str) {
  return String(str).replace(/([A-Z])/g, "-$1").toLowerCase();
};
goog.string.toTitleCase = function(str, opt_delimiters) {
  var delimiters = goog.isString(opt_delimiters) ? goog.string.regExpEscape(opt_delimiters) : "\\s";
  delimiters = delimiters ? "|[" + delimiters + "]+" : "";
  var regexp = new RegExp("(^" + delimiters + ")([a-z])", "g");
  return str.replace(regexp, function(all, p1, p2) {
    return p1 + p2.toUpperCase();
  });
};
goog.string.capitalize = function(str) {
  return String(str.charAt(0)).toUpperCase() + String(str.substr(1)).toLowerCase();
};
goog.string.parseInt = function(value) {
  if (isFinite(value)) {
    value = String(value);
  }
  if (goog.isString(value)) {
    return /^\s*-?0x/i.test(value) ? parseInt(value, 16) : parseInt(value, 10);
  }
  return NaN;
};
goog.string.splitLimit = function(str, separator, limit) {
  var parts = str.split(separator);
  var returnVal = [];
  while (limit > 0 && parts.length) {
    returnVal.push(parts.shift());
    limit--;
  }
  if (parts.length) {
    returnVal.push(parts.join(separator));
  }
  return returnVal;
};
goog.string.lastComponent = function(str, separators) {
  if (!separators) {
    return str;
  } else {
    if (typeof separators == "string") {
      separators = [separators];
    }
  }
  var lastSeparatorIndex = -1;
  for (var i = 0; i < separators.length; i++) {
    if (separators[i] == "") {
      continue;
    }
    var currentSeparatorIndex = str.lastIndexOf(separators[i]);
    if (currentSeparatorIndex > lastSeparatorIndex) {
      lastSeparatorIndex = currentSeparatorIndex;
    }
  }
  if (lastSeparatorIndex == -1) {
    return str;
  }
  return str.slice(lastSeparatorIndex + 1);
};
goog.string.editDistance = function(a, b) {
  var v0 = [];
  var v1 = [];
  if (a == b) {
    return 0;
  }
  if (!a.length || !b.length) {
    return Math.max(a.length, b.length);
  }
  for (var i = 0; i < b.length + 1; i++) {
    v0[i] = i;
  }
  for (var i = 0; i < a.length; i++) {
    v1[0] = i + 1;
    for (var j = 0; j < b.length; j++) {
      var cost = Number(a[i] != b[j]);
      v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);
    }
    for (var j = 0; j < v0.length; j++) {
      v0[j] = v1[j];
    }
  }
  return v1[b.length];
};
goog.provide("goog.asserts");
goog.provide("goog.asserts.AssertionError");
goog.require("goog.debug.Error");
goog.require("goog.dom.NodeType");
goog.require("goog.string");
goog.define("goog.asserts.ENABLE_ASSERTS", goog.DEBUG);
goog.asserts.AssertionError = function(messagePattern, messageArgs) {
  messageArgs.unshift(messagePattern);
  goog.debug.Error.call(this, goog.string.subs.apply(null, messageArgs));
  messageArgs.shift();
  this.messagePattern = messagePattern;
};
goog.inherits(goog.asserts.AssertionError, goog.debug.Error);
goog.asserts.AssertionError.prototype.name = "AssertionError";
goog.asserts.DEFAULT_ERROR_HANDLER = function(e) {
  throw e;
};
goog.asserts.errorHandler_ = goog.asserts.DEFAULT_ERROR_HANDLER;
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;
    }
  }
  var e = new goog.asserts.AssertionError("" + message, args || []);
  goog.asserts.errorHandler_(e);
};
goog.asserts.setErrorHandler = function(errorHandler) {
  if (goog.asserts.ENABLE_ASSERTS) {
    goog.asserts.errorHandler_ = errorHandler;
  }
};
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;
};
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)));
  }
};
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 value;
};
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 value;
};
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 value;
};
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 value;
};
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 value;
};
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 value;
};
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 value;
};
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;
};
goog.asserts.assertObjectPrototypeIsIntact = function() {
  for (var key in Object.prototype) {
    goog.asserts.fail(key + " should not be enumerable in Object.prototype.");
  }
};
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;
    }
  }
};
goog.provide("goog.array");
goog.require("goog.asserts");
goog.define("goog.NATIVE_ARRAY_PROTOTYPES", goog.TRUSTED_SITE);
goog.define("goog.array.ASSUME_NATIVE_FUNCTIONS", false);
goog.array.peek = function(array) {
  return array[array.length - 1];
};
goog.array.last = goog.array.peek;
goog.array.indexOf = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.indexOf) ? function(arr, obj, opt_fromIndex) {
  goog.asserts.assert(arr.length != null);
  return 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)) {
    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;
};
goog.array.lastIndexOf = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.lastIndexOf) ? function(arr, obj, opt_fromIndex) {
  goog.asserts.assert(arr.length != null);
  var fromIndex = opt_fromIndex == null ? arr.length - 1 : opt_fromIndex;
  return 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)) {
    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;
};
goog.array.forEach = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.forEach) ? function(arr, f, opt_obj) {
  goog.asserts.assert(arr.length != null);
  Array.prototype.forEach.call(arr, f, opt_obj);
} : function(arr, f, opt_obj) {
  var l = arr.length;
  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);
    }
  }
};
goog.array.forEachRight = function(arr, f, opt_obj) {
  var l = arr.length;
  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);
    }
  }
};
goog.array.filter = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.filter) ? function(arr, f, opt_obj) {
  goog.asserts.assert(arr.length != null);
  return Array.prototype.filter.call(arr, f, opt_obj);
} : function(arr, f, opt_obj) {
  var l = arr.length;
  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];
      if (f.call(opt_obj, val, i, arr)) {
        res[resLength++] = val;
      }
    }
  }
  return res;
};
goog.array.map = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.map) ? function(arr, f, opt_obj) {
  goog.asserts.assert(arr.length != null);
  return Array.prototype.map.call(arr, f, opt_obj);
} : function(arr, f, opt_obj) {
  var l = arr.length;
  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;
};
goog.array.reduce = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || 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 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;
};
goog.array.reduceRight = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.reduceRight) ? function(arr, f, val, opt_obj) {
  goog.asserts.assert(arr.length != null);
  goog.asserts.assert(f != null);
  if (opt_obj) {
    f = goog.bind(f, opt_obj);
  }
  return 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;
};
goog.array.some = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.some) ? function(arr, f, opt_obj) {
  goog.asserts.assert(arr.length != null);
  return Array.prototype.some.call(arr, f, opt_obj);
} : function(arr, f, opt_obj) {
  var l = arr.length;
  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;
};
goog.array.every = goog.NATIVE_ARRAY_PROTOTYPES && (goog.array.ASSUME_NATIVE_FUNCTIONS || Array.prototype.every) ? function(arr, f, opt_obj) {
  goog.asserts.assert(arr.length != null);
  return Array.prototype.every.call(arr, f, opt_obj);
} : function(arr, f, opt_obj) {
  var l = arr.length;
  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;
};
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;
};
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];
};
goog.array.findIndex = function(arr, f, opt_obj) {
  var l = arr.length;
  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;
};
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];
};
goog.array.findIndexRight = function(arr, f, opt_obj) {
  var l = arr.length;
  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;
};
goog.array.contains = function(arr, obj) {
  return goog.array.indexOf(arr, obj) >= 0;
};
goog.array.isEmpty = function(arr) {
  return arr.length == 0;
};
goog.array.clear = function(arr) {
  if (!goog.isArray(arr)) {
    for (var i = arr.length - 1; i >= 0; i--) {
      delete arr[i];
    }
  }
  arr.length = 0;
};
goog.array.insert = function(arr, obj) {
  if (!goog.array.contains(arr, obj)) {
    arr.push(obj);
  }
};
goog.array.insertAt = function(arr, obj, opt_i) {
  goog.array.splice(arr, opt_i, 0, obj);
};
goog.array.insertArrayAt = function(arr, elementsToAdd, opt_i) {
  goog.partial(goog.array.splice, arr, opt_i, 0).apply(null, elementsToAdd);
};
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);
  }
};
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;
};
goog.array.removeLast = function(arr, obj) {
  var i = goog.array.lastIndexOf(arr, obj);
  if (i >= 0) {
    goog.array.removeAt(arr, i);
    return true;
  }
  return false;
};
goog.array.removeAt = function(arr, i) {
  goog.asserts.assert(arr.length != null);
  return Array.prototype.splice.call(arr, i, 1).length == 1;
};
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;
};
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;
};
goog.array.concat = function(var_args) {
  return Array.prototype.concat.apply([], arguments);
};
goog.array.join = function(var_args) {
  return Array.prototype.concat.apply([], arguments);
};
goog.array.toArray = function(object) {
  var length = object.length;
  if (length > 0) {
    var rv = new Array(length);
    for (var i = 0; i < length; i++) {
      rv[i] = object[i];
    }
    return rv;
  }
  return [];
};
goog.array.clone = goog.array.toArray;
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);
    }
  }
};
goog.array.splice = function(arr, index, howMany, var_args) {
  goog.asserts.assert(arr.length != null);
  return Array.prototype.splice.apply(arr, goog.array.slice(arguments, 1));
};
goog.array.slice = function(arr, start, opt_end) {
  goog.asserts.assert(arr.length != null);
  if (arguments.length <= 2) {
    return Array.prototype.slice.call(arr, start);
  } else {
    return Array.prototype.slice.call(arr, start, opt_end);
  }
};
goog.array.removeDuplicates = function(arr, opt_rv, opt_hashFn) {
  var returnArray = opt_rv || arr;
  var defaultHashFn = function(item) {
    return goog.isObject(item) ? "o" + goog.getUid(item) : (typeof item).charAt(0) + item;
  };
  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;
};
goog.array.binarySearch = function(arr, target, opt_compareFn) {
  return goog.array.binarySearch_(arr, opt_compareFn || goog.array.defaultCompare, false, target);
};
goog.array.binarySelect = function(arr, evaluator, opt_obj) {
  return goog.array.binarySearch_(arr, evaluator, true, undefined, opt_obj);
};
goog.array.binarySearch_ = function(arr, compareFn, isEvaluator, opt_target, opt_selfObj) {
  var left = 0;
  var right = arr.length;
  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;
      found = !compareResult;
    }
  }
  return found ? left : ~left;
};
goog.array.sort = function(arr, opt_compareFn) {
  arr.sort(opt_compareFn || goog.array.defaultCompare);
};
goog.array.stableSort = function(arr, opt_compareFn) {
  var compArr = new Array(arr.length);
  for (var i = 0; i < arr.length; i++) {
    compArr[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(compArr, stableCompareFn);
  for (var i = 0; i < arr.length; i++) {
    arr[i] = compArr[i].value;
  }
};
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));
  });
};
goog.array.sortObjectsByKey = function(arr, key, opt_compareFn) {
  goog.array.sortByKey(arr, function(obj) {
    return obj[key];
  }, opt_compareFn);
};
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;
};
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;
};
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);
};
goog.array.defaultCompare = function(a, b) {
  return a > b ? 1 : a < b ? -1 : 0;
};
goog.array.inverseDefaultCompare = function(a, b) {
  return -goog.array.defaultCompare(a, b);
};
goog.array.defaultCompareEquality = function(a, b) {
  return a === b;
};
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;
};
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;
};
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)) {
      var bucket = buckets[key] || (buckets[key] = []);
      bucket.push(value);
    }
  }
  return buckets;
};
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;
};
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) {
    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;
};
goog.array.repeat = function(value, n) {
  var array = [];
  for (var i = 0; i < n; i++) {
    array[i] = value;
  }
  return array;
};
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;
};
goog.array.rotate = function(array, n) {
  goog.asserts.assert(array.length != null);
  if (array.length) {
    n %= array.length;
    if (n > 0) {
      Array.prototype.unshift.apply(array, array.splice(-n, n));
    } else {
      if (n < 0) {
        Array.prototype.push.apply(array, array.splice(0, -n));
      }
    }
  }
  return array;
};
goog.array.moveItem = function(arr, fromIndex, toIndex) {
  goog.asserts.assert(fromIndex >= 0 && fromIndex < arr.length);
  goog.asserts.assert(toIndex >= 0 && toIndex < arr.length);
  var removedItems = Array.prototype.splice.call(arr, fromIndex, 1);
  Array.prototype.splice.call(arr, toIndex, 0, removedItems[0]);
};
goog.array.zip = function(var_args) {
  if (!arguments.length) {
    return [];
  }
  var result = [];
  var minLen = arguments[0].length;
  for (var i = 1; i < arguments.length; i++) {
    if (arguments[i].length < minLen) {
      minLen = arguments[i].length;
    }
  }
  for (var i = 0; i < minLen; i++) {
    var value = [];
    for (var j = 0; j < arguments.length; j++) {
      value.push(arguments[j][i]);
    }
    result.push(value);
  }
  return result;
};
goog.array.shuffle = function(arr, opt_randFn) {
  var randFn = opt_randFn || Math.random;
  for (var i = arr.length - 1; i > 0; i--) {
    var j = Math.floor(randFn() * (i + 1));
    var tmp = arr[i];
    arr[i] = arr[j];
    arr[j] = tmp;
  }
};
goog.array.copyByIndex = function(arr, index_arr) {
  var result = [];
  goog.array.forEach(index_arr, function(index) {
    result.push(arr[index]);
  });
  return result;
};
goog.array.concatMap = function(arr, f, opt_obj) {
  return goog.array.concat.apply([], goog.array.map(arr, f, opt_obj));
};
goog.provide("goog.labs.userAgent.util");
goog.require("goog.string");
goog.labs.userAgent.util.getNativeUserAgentString_ = function() {
  var navigator = goog.labs.userAgent.util.getNavigator_();
  if (navigator) {
    var userAgent = navigator.userAgent;
    if (userAgent) {
      return userAgent;
    }
  }
  return "";
};
goog.labs.userAgent.util.getNavigator_ = function() {
  return goog.global.navigator;
};
goog.labs.userAgent.util.userAgent_ = goog.labs.userAgent.util.getNativeUserAgentString_();
goog.labs.userAgent.util.setUserAgent = function(opt_userAgent) {
  goog.labs.userAgent.util.userAgent_ = opt_userAgent || goog.labs.userAgent.util.getNativeUserAgentString_();
};
goog.labs.userAgent.util.getUserAgent = function() {
  return goog.labs.userAgent.util.userAgent_;
};
goog.labs.userAgent.util.matchUserAgent = function(str) {
  var userAgent = goog.labs.userAgent.util.getUserAgent();
  return goog.string.contains(userAgent, str);
};
goog.labs.userAgent.util.matchUserAgentIgnoreCase = function(str) {
  var userAgent = goog.labs.userAgent.util.getUserAgent();
  return goog.string.caseInsensitiveContains(userAgent, str);
};
goog.labs.userAgent.util.extractVersionTuples = function(userAgent) {
  var versionRegExp = new RegExp("(\\w[\\w ]+)" + "/" + "([^\\s]+)" + "\\s*" + "(?:\\((.*?)\\))?", "g");
  var data = [];
  var match;
  while (match = versionRegExp.exec(userAgent)) {
    data.push([match[1], match[2], match[3] || undefined]);
  }
  return data;
};
goog.provide("goog.object");
goog.object.is = function(v, v2) {
  if (v === v2) {
    return v !== 0 || 1 / v === 1 / v2;
  }
  return v !== v && v2 !== v2;
};
goog.object.forEach = function(obj, f, opt_obj) {
  for (var key in obj) {
    f.call(opt_obj, obj[key], key, obj);
  }
};
goog.object.filter = function(obj, f, opt_obj) {
  var res = {};
  for (var key in obj) {
    if (f.call(opt_obj, obj[key], key, obj)) {
      res[key] = obj[key];
    }
  }
  return res;
};
goog.object.map = function(obj, f, opt_obj) {
  var res = {};
  for (var key in obj) {
    res[key] = f.call(opt_obj, obj[key], key, obj);
  }
  return res;
};
goog.object.some = function(obj, f, opt_obj) {
  for (var key in obj) {
    if (f.call(opt_obj, obj[key], key, obj)) {
      return true;
    }
  }
  return false;
};
goog.object.every = function(obj, f, opt_obj) {
  for (var key in obj) {
    if (!f.call(opt_obj, obj[key], key, obj)) {
      return false;
    }
  }
  return true;
};
goog.object.getCount = function(obj) {
  var rv = 0;
  for (var key in obj) {
    rv++;
  }
  return rv;
};
goog.object.getAnyKey = function(obj) {
  for (var key in obj) {
    return key;
  }
};
goog.object.getAnyValue = function(obj) {
  for (var key in obj) {
    return obj[key];
  }
};
goog.object.contains = function(obj, val) {
  return goog.object.containsValue(obj, val);
};
goog.object.getValues = function(obj) {
  var res = [];
  var i = 0;
  for (var key in obj) {
    res[i++] = obj[key];
  }
  return res;
};
goog.object.getKeys = function(obj) {
  var res = [];
  var i = 0;
  for (var key in obj) {
    res[i++] = key;
  }
  return res;
};
goog.object.getValueByKeys = function(obj, var_args) {
  var isArrayLike = goog.isArrayLike(var_args);
  var keys = isArrayLike ? var_args : arguments;
  for (var i = isArrayLike ? 0 : 1; i < keys.length; i++) {
    obj = obj[keys[i]];
    if (!goog.isDef(obj)) {
      break;
    }
  }
  return obj;
};
goog.object.containsKey = function(obj, key) {
  return obj !== null && key in obj;
};
goog.object.containsValue = function(obj, val) {
  for (var key in obj) {
    if (obj[key] == val) {
      return true;
    }
  }
  return false;
};
goog.object.findKey = function(obj, f, opt_this) {
  for (var key in obj) {
    if (f.call(opt_this, obj[key], key, obj)) {
      return key;
    }
  }
  return undefined;
};
goog.object.findValue = function(obj, f, opt_this) {
  var key = goog.object.findKey(obj, f, opt_this);
  return key && obj[key];
};
goog.object.isEmpty = function(obj) {
  for (var key in obj) {
    return false;
  }
  return true;
};
goog.object.clear = function(obj) {
  for (var i in obj) {
    delete obj[i];
  }
};
goog.object.remove = function(obj, key) {
  var rv;
  if (rv = key in obj) {
    delete obj[key];
  }
  return rv;
};
goog.object.add = function(obj, key, val) {
  if (obj !== null && key in obj) {
    throw Error('The object already contains the key "' + key + '"');
  }
  goog.object.set(obj, key, val);
};
goog.object.get = function(obj, key, opt_val) {
  if (obj !== null && key in obj) {
    return obj[key];
  }
  return opt_val;
};
goog.object.set = function(obj, key, value) {
  obj[key] = value;
};
goog.object.setIfUndefined = function(obj, key, value) {
  return key in obj ? obj[key] : obj[key] = value;
};
goog.object.setWithReturnValueIfNotSet = function(obj, key, f) {
  if (key in obj) {
    return obj[key];
  }
  var val = f();
  obj[key] = val;
  return val;
};
goog.object.equals = function(a, b) {
  for (var k in a) {
    if (!(k in b) || a[k] !== b[k]) {
      return false;
    }
  }
  for (var k in b) {
    if (!(k in a)) {
      return false;
    }
  }
  return true;
};
goog.object.clone = function(obj) {
  var res = {};
  for (var key in obj) {
    res[key] = obj[key];
  }
  return res;
};
goog.object.unsafeClone = function(obj) {
  var type = goog.typeOf(obj);
  if (type == "object" || type == "array") {
    if (goog.isFunction(obj.clone)) {
      return obj.clone();
    }
    var clone = type == "array" ? [] : {};
    for (var key in obj) {
      clone[key] = goog.object.unsafeClone(obj[key]);
    }
    return clone;
  }
  return obj;
};
goog.object.transpose = function(obj) {
  var transposed = {};
  for (var key in obj) {
    transposed[obj[key]] = key;
  }
  return transposed;
};
goog.object.PROTOTYPE_FIELDS_ = ["constructor", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", "toLocaleString", "toString", "valueOf"];
goog.object.extend = function(target, var_args) {
  var key, source;
  for (var i = 1; i < arguments.length; i++) {
    source = arguments[i];
    for (key in source) {
      target[key] = source[key];
    }
    for (var j = 0; j < goog.object.PROTOTYPE_FIELDS_.length; j++) {
      key = goog.object.PROTOTYPE_FIELDS_[j];
      if (Object.prototype.hasOwnProperty.call(source, key)) {
        target[key] = source[key];
      }
    }
  }
};
goog.object.create = function(var_args) {
  var argLength = arguments.length;
  if (argLength == 1 && goog.isArray(arguments[0])) {
    return goog.object.create.apply(null, arguments[0]);
  }
  if (argLength % 2) {
    throw Error("Uneven number of arguments");
  }
  var rv = {};
  for (var i = 0; i < argLength; i += 2) {
    rv[arguments[i]] = arguments[i + 1];
  }
  return rv;
};
goog.object.createSet = function(var_args) {
  var argLength = arguments.length;
  if (argLength == 1 && goog.isArray(arguments[0])) {
    return goog.object.createSet.apply(null, arguments[0]);
  }
  var rv = {};
  for (var i = 0; i < argLength; i++) {
    rv[arguments[i]] = true;
  }
  return rv;
};
goog.object.createImmutableView = function(obj) {
  var result = obj;
  if (Object.isFrozen && !Object.isFrozen(obj)) {
    result = Object.create(obj);
    Object.freeze(result);
  }
  return result;
};
goog.object.isImmutableView = function(obj) {
  return !!Object.isFrozen && Object.isFrozen(obj);
};
goog.object.getAllPropertyNames = function(obj, opt_includeObjectPrototype, opt_includeFunctionPrototype) {
  if (!obj) {
    return [];
  }
  if (!Object.getOwnPropertyNames || !Object.getPrototypeOf) {
    return goog.object.getKeys(obj);
  }
  var visitedSet = {};
  var proto = obj;
  while (proto && (proto !== Object.prototype || !!opt_includeObjectPrototype) && (proto !== Function.prototype || !!opt_includeFunctionPrototype)) {
    var names = Object.getOwnPropertyNames(proto);
    for (var i = 0; i < names.length; i++) {
      visitedSet[names[i]] = true;
    }
    proto = Object.getPrototypeOf(proto);
  }
  return goog.object.getKeys(visitedSet);
};
goog.provide("goog.labs.userAgent.browser");
goog.require("goog.array");
goog.require("goog.labs.userAgent.util");
goog.require("goog.object");
goog.require("goog.string");
goog.labs.userAgent.browser.matchOpera_ = function() {
  return goog.labs.userAgent.util.matchUserAgent("Opera");
};
goog.labs.userAgent.browser.matchIE_ = function() {
  return goog.labs.userAgent.util.matchUserAgent("Trident") || goog.labs.userAgent.util.matchUserAgent("MSIE");
};
goog.labs.userAgent.browser.matchEdge_ = function() {
  return goog.labs.userAgent.util.matchUserAgent("Edge");
};
goog.labs.userAgent.browser.matchFirefox_ = function() {
  return goog.labs.userAgent.util.matchUserAgent("Firefox");
};
goog.labs.userAgent.browser.matchSafari_ = function() {
  return goog.labs.userAgent.util.matchUserAgent("Safari") && !(goog.labs.userAgent.browser.matchChrome_() || goog.labs.userAgent.browser.matchCoast_() || goog.labs.userAgent.browser.matchOpera_() || goog.labs.userAgent.browser.matchEdge_() || goog.labs.userAgent.browser.isSilk() || goog.labs.userAgent.util.matchUserAgent("Android"));
};
goog.labs.userAgent.browser.matchCoast_ = function() {
  return goog.labs.userAgent.util.matchUserAgent("Coast");
};
goog.labs.userAgent.browser.matchIosWebview_ = function() {
  return (goog.labs.userAgent.util.matchUserAgent("iPad") || goog.labs.userAgent.util.matchUserAgent("iPhone")) && !goog.labs.userAgent.browser.matchSafari_() && !goog.labs.userAgent.browser.matchChrome_() && !goog.labs.userAgent.browser.matchCoast_() && goog.labs.userAgent.util.matchUserAgent("AppleWebKit");
};
goog.labs.userAgent.browser.matchChrome_ = function() {
  return (goog.labs.userAgent.util.matchUserAgent("Chrome") || goog.labs.userAgent.util.matchUserAgent("CriOS")) && !goog.labs.userAgent.browser.matchEdge_();
};
goog.labs.userAgent.browser.matchAndroidBrowser_ = function() {
  return goog.labs.userAgent.util.matchUserAgent("Android") && !(goog.labs.userAgent.browser.isChrome() || goog.labs.userAgent.browser.isFirefox() || goog.labs.userAgent.browser.isOpera() || goog.labs.userAgent.browser.isSilk());
};
goog.labs.userAgent.browser.isOpera = goog.labs.userAgent.browser.matchOpera_;
goog.labs.userAgent.browser.isIE = goog.labs.userAgent.browser.matchIE_;
goog.labs.userAgent.browser.isEdge = goog.labs.userAgent.browser.matchEdge_;
goog.labs.userAgent.browser.isFirefox = goog.labs.userAgent.browser.matchFirefox_;
goog.labs.userAgent.browser.isSafari = goog.labs.userAgent.browser.matchSafari_;
goog.labs.userAgent.browser.isCoast = goog.labs.userAgent.browser.matchCoast_;
goog.labs.userAgent.browser.isIosWebview = goog.labs.userAgent.browser.matchIosWebview_;
goog.labs.userAgent.browser.isChrome = goog.labs.userAgent.browser.matchChrome_;
goog.labs.userAgent.browser.isAndroidBrowser = goog.labs.userAgent.browser.matchAndroidBrowser_;
goog.labs.userAgent.browser.isSilk = function() {
  return goog.labs.userAgent.util.matchUserAgent("Silk");
};
goog.labs.userAgent.browser.getVersion = function() {
  var userAgentString = goog.labs.userAgent.util.getUserAgent();
  if (goog.labs.userAgent.browser.isIE()) {
    return goog.labs.userAgent.browser.getIEVersion_(userAgentString);
  }
  var versionTuples = goog.labs.userAgent.util.extractVersionTuples(userAgentString);
  var versionMap = {};
  goog.array.forEach(versionTuples, function(tuple) {
    var key = tuple[0];
    var value = tuple[1];
    versionMap[key] = value;
  });
  var versionMapHasKey = goog.partial(goog.object.containsKey, versionMap);
  function lookUpValueWithKeys(keys) {
    var key = goog.array.find(keys, versionMapHasKey);
    return versionMap[key] || "";
  }
  if (goog.labs.userAgent.browser.isOpera()) {
    return lookUpValueWithKeys(["Version", "Opera"]);
  }
  if (goog.labs.userAgent.browser.isEdge()) {
    return lookUpValueWithKeys(["Edge"]);
  }
  if (goog.labs.userAgent.browser.isChrome()) {
    return lookUpValueWithKeys(["Chrome", "CriOS"]);
  }
  var tuple = versionTuples[2];
  return tuple && tuple[1] || "";
};
goog.labs.userAgent.browser.isVersionOrHigher = function(version) {
  return goog.string.compareVersions(goog.labs.userAgent.browser.getVersion(), version) >= 0;
};
goog.labs.userAgent.browser.getIEVersion_ = function(userAgent) {
  var rv = /rv: *([\d\.]*)/.exec(userAgent);
  if (rv && rv[1]) {
    return rv[1];
  }
  var version = "";
  var msie = /MSIE +([\d\.]+)/.exec(userAgent);
  if (msie && msie[1]) {
    var tridentVersion = /Trident\/(\d.\d)/.exec(userAgent);
    if (msie[1] == "7.0") {
      if (tridentVersion && tridentVersion[1]) {
        switch(tridentVersion[1]) {
          case "4.0":
            version = "8.0";
            break;
          case "5.0":
            version = "9.0";
            break;
          case "6.0":
            version = "10.0";
            break;
          case "7.0":
            version = "11.0";
            break;
        }
      } else {
        version = "7.0";
      }
    } else {
      version = msie[1];
    }
  }
  return version;
};
goog.provide("goog.labs.userAgent.engine");
goog.require("goog.array");
goog.require("goog.labs.userAgent.util");
goog.require("goog.string");
goog.labs.userAgent.engine.isPresto = function() {
  return goog.labs.userAgent.util.matchUserAgent("Presto");
};
goog.labs.userAgent.engine.isTrident = function() {
  return goog.labs.userAgent.util.matchUserAgent("Trident") || goog.labs.userAgent.util.matchUserAgent("MSIE");
};
goog.labs.userAgent.engine.isEdge = function() {
  return goog.labs.userAgent.util.matchUserAgent("Edge");
};
goog.labs.userAgent.engine.isWebKit = function() {
  return goog.labs.userAgent.util.matchUserAgentIgnoreCase("WebKit") && !goog.labs.userAgent.engine.isEdge();
};
goog.labs.userAgent.engine.isGecko = function() {
  return goog.labs.userAgent.util.matchUserAgent("Gecko") && !goog.labs.userAgent.engine.isWebKit() && !goog.labs.userAgent.engine.isTrident() && !goog.labs.userAgent.engine.isEdge();
};
goog.labs.userAgent.engine.getVersion = function() {
  var userAgentString = goog.labs.userAgent.util.getUserAgent();
  if (userAgentString) {
    var tuples = goog.labs.userAgent.util.extractVersionTuples(userAgentString);
    var engineTuple = goog.labs.userAgent.engine.getEngineTuple_(tuples);
    if (engineTuple) {
      if (engineTuple[0] == "Gecko") {
        return goog.labs.userAgent.engine.getVersionForKey_(tuples, "Firefox");
      }
      return engineTuple[1];
    }
    var browserTuple = tuples[0];
    var info;
    if (browserTuple && (info = browserTuple[2])) {
      var match = /Trident\/([^\s;]+)/.exec(info);
      if (match) {
        return match[1];
      }
    }
  }
  return "";
};
goog.labs.userAgent.engine.getEngineTuple_ = function(tuples) {
  if (!goog.labs.userAgent.engine.isEdge()) {
    return tuples[1];
  }
  for (var i = 0; i < tuples.length; i++) {
    var tuple = tuples[i];
    if (tuple[0] == "Edge") {
      return tuple;
    }
  }
};
goog.labs.userAgent.engine.isVersionOrHigher = function(version) {
  return goog.string.compareVersions(goog.labs.userAgent.engine.getVersion(), version) >= 0;
};
goog.labs.userAgent.engine.getVersionForKey_ = function(tuples, key) {
  var pair = goog.array.find(tuples, function(pair) {
    return key == pair[0];
  });
  return pair && pair[1] || "";
};
goog.provide("goog.labs.userAgent.platform");
goog.require("goog.labs.userAgent.util");
goog.require("goog.string");
goog.labs.userAgent.platform.isAndroid = function() {
  return goog.labs.userAgent.util.matchUserAgent("Android");
};
goog.labs.userAgent.platform.isIpod = function() {
  return goog.labs.userAgent.util.matchUserAgent("iPod");
};
goog.labs.userAgent.platform.isIphone = function() {
  return goog.labs.userAgent.util.matchUserAgent("iPhone") && !goog.labs.userAgent.util.matchUserAgent("iPod") && !goog.labs.userAgent.util.matchUserAgent("iPad");
};
goog.labs.userAgent.platform.isIpad = function() {
  return goog.labs.userAgent.util.matchUserAgent("iPad");
};
goog.labs.userAgent.platform.isIos = function() {
  return goog.labs.userAgent.platform.isIphone() || goog.labs.userAgent.platform.isIpad() || goog.labs.userAgent.platform.isIpod();
};
goog.labs.userAgent.platform.isMacintosh = function() {
  return goog.labs.userAgent.util.matchUserAgent("Macintosh");
};
goog.labs.userAgent.platform.isLinux = function() {
  return goog.labs.userAgent.util.matchUserAgent("Linux");
};
goog.labs.userAgent.platform.isWindows = function() {
  return goog.labs.userAgent.util.matchUserAgent("Windows");
};
goog.labs.userAgent.platform.isChromeOS = function() {
  return goog.labs.userAgent.util.matchUserAgent("CrOS");
};
goog.labs.userAgent.platform.getVersion = function() {
  var userAgentString = goog.labs.userAgent.util.getUserAgent();
  var version = "", re;
  if (goog.labs.userAgent.platform.isWindows()) {
    re = /Windows (?:NT|Phone) ([0-9.]+)/;
    var match = re.exec(userAgentString);
    if (match) {
      version = match[1];
    } else {
      version = "0.0";
    }
  } else {
    if (goog.labs.userAgent.platform.isIos()) {
      re = /(?:iPhone|iPod|iPad|CPU)\s+OS\s+(\S+)/;
      var match = re.exec(userAgentString);
      version = match && match[1].replace(/_/g, ".");
    } else {
      if (goog.labs.userAgent.platform.isMacintosh()) {
        re = /Mac OS X ([0-9_.]+)/;
        var match = re.exec(userAgentString);
        version = match ? match[1].replace(/_/g, ".") : "10";
      } else {
        if (goog.labs.userAgent.platform.isAndroid()) {
          re = /Android\s+([^\);]+)(\)|;)/;
          var match = re.exec(userAgentString);
          version = match && match[1];
        } else {
          if (goog.labs.userAgent.platform.isChromeOS()) {
            re = /(?:CrOS\s+(?:i686|x86_64)\s+([0-9.]+))/;
            var match = re.exec(userAgentString);
            version = match && match[1];
          }
        }
      }
    }
  }
  return version || "";
};
goog.labs.userAgent.platform.isVersionOrHigher = function(version) {
  return goog.string.compareVersions(goog.labs.userAgent.platform.getVersion(), version) >= 0;
};
goog.provide("goog.reflect");
goog.reflect.object = function(type, object) {
  return object;
};
goog.reflect.objectProperty = function(prop, object) {
  return prop;
};
goog.reflect.sinkValue = function(x) {
  goog.reflect.sinkValue[" "](x);
  return x;
};
goog.reflect.sinkValue[" "] = goog.nullFunction;
goog.reflect.canAccessProperty = function(obj, prop) {
  try {
    goog.reflect.sinkValue(obj[prop]);
    return true;
  } catch (e) {
  }
  return false;
};
goog.reflect.cache = function(cacheObj, key, valueFn, opt_keyFn) {
  var storedKey = opt_keyFn ? opt_keyFn(key) : key;
  if (Object.prototype.hasOwnProperty.call(cacheObj, storedKey)) {
    return cacheObj[storedKey];
  }
  return cacheObj[storedKey] = valueFn(key);
};
goog.provide("goog.userAgent");
goog.require("goog.labs.userAgent.browser");
goog.require("goog.labs.userAgent.engine");
goog.require("goog.labs.userAgent.platform");
goog.require("goog.labs.userAgent.util");
goog.require("goog.reflect");
goog.require("goog.string");
goog.define("goog.userAgent.ASSUME_IE", false);
goog.define("goog.userAgent.ASSUME_EDGE", false);
goog.define("goog.userAgent.ASSUME_GECKO", false);
goog.define("goog.userAgent.ASSUME_WEBKIT", false);
goog.define("goog.userAgent.ASSUME_MOBILE_WEBKIT", false);
goog.define("goog.userAgent.ASSUME_OPERA", false);
goog.define("goog.userAgent.ASSUME_ANY_VERSION", false);
goog.userAgent.BROWSER_KNOWN_ = goog.userAgent.ASSUME_IE || goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_GECKO || goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_OPERA;
goog.userAgent.getUserAgentString = function() {
  return goog.labs.userAgent.util.getUserAgent();
};
goog.userAgent.getNavigator = function() {
  return goog.global["navigator"] || null;
};
goog.userAgent.OPERA = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_OPERA : goog.labs.userAgent.browser.isOpera();
goog.userAgent.IE = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_IE : goog.labs.userAgent.browser.isIE();
goog.userAgent.EDGE = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_EDGE : goog.labs.userAgent.engine.isEdge();
goog.userAgent.EDGE_OR_IE = goog.userAgent.EDGE || goog.userAgent.IE;
goog.userAgent.GECKO = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_GECKO : goog.labs.userAgent.engine.isGecko();
goog.userAgent.WEBKIT = goog.userAgent.BROWSER_KNOWN_ ? goog.userAgent.ASSUME_WEBKIT || goog.userAgent.ASSUME_MOBILE_WEBKIT : goog.labs.userAgent.engine.isWebKit();
goog.userAgent.isMobile_ = function() {
  return goog.userAgent.WEBKIT && goog.labs.userAgent.util.matchUserAgent("Mobile");
};
goog.userAgent.MOBILE = goog.userAgent.ASSUME_MOBILE_WEBKIT || goog.userAgent.isMobile_();
goog.userAgent.SAFARI = goog.userAgent.WEBKIT;
goog.userAgent.determinePlatform_ = function() {
  var navigator = goog.userAgent.getNavigator();
  return navigator && navigator.platform || "";
};
goog.userAgent.PLATFORM = goog.userAgent.determinePlatform_();
goog.define("goog.userAgent.ASSUME_MAC", false);
goog.define("goog.userAgent.ASSUME_WINDOWS", false);
goog.define("goog.userAgent.ASSUME_LINUX", false);
goog.define("goog.userAgent.ASSUME_X11", false);
goog.define("goog.userAgent.ASSUME_ANDROID", false);
goog.define("goog.userAgent.ASSUME_IPHONE", false);
goog.define("goog.userAgent.ASSUME_IPAD", false);
goog.define("goog.userAgent.ASSUME_IPOD", false);
goog.userAgent.PLATFORM_KNOWN_ = goog.userAgent.ASSUME_MAC || goog.userAgent.ASSUME_WINDOWS || goog.userAgent.ASSUME_LINUX || goog.userAgent.ASSUME_X11 || goog.userAgent.ASSUME_ANDROID || goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD || goog.userAgent.ASSUME_IPOD;
goog.userAgent.MAC = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_MAC : goog.labs.userAgent.platform.isMacintosh();
goog.userAgent.WINDOWS = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_WINDOWS : goog.labs.userAgent.platform.isWindows();
goog.userAgent.isLegacyLinux_ = function() {
  return goog.labs.userAgent.platform.isLinux() || goog.labs.userAgent.platform.isChromeOS();
};
goog.userAgent.LINUX = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_LINUX : goog.userAgent.isLegacyLinux_();
goog.userAgent.isX11_ = function() {
  var navigator = goog.userAgent.getNavigator();
  return !!navigator && goog.string.contains(navigator["appVersion"] || "", "X11");
};
goog.userAgent.X11 = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_X11 : goog.userAgent.isX11_();
goog.userAgent.ANDROID = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_ANDROID : goog.labs.userAgent.platform.isAndroid();
goog.userAgent.IPHONE = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_IPHONE : goog.labs.userAgent.platform.isIphone();
goog.userAgent.IPAD = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_IPAD : goog.labs.userAgent.platform.isIpad();
goog.userAgent.IPOD = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_IPOD : goog.labs.userAgent.platform.isIpod();
goog.userAgent.IOS = goog.userAgent.PLATFORM_KNOWN_ ? goog.userAgent.ASSUME_IPHONE || goog.userAgent.ASSUME_IPAD || goog.userAgent.ASSUME_IPOD : goog.labs.userAgent.platform.isIos();
goog.userAgent.determineVersion_ = function() {
  var version = "";
  var arr = goog.userAgent.getVersionRegexResult_();
  if (arr) {
    version = arr ? arr[1] : "";
  }
  if (goog.userAgent.IE) {
    var docMode = goog.userAgent.getDocumentMode_();
    if (docMode != null && docMode > parseFloat(version)) {
      return String(docMode);
    }
  }
  return version;
};
goog.userAgent.getVersionRegexResult_ = function() {
  var userAgent = goog.userAgent.getUserAgentString();
  if (goog.userAgent.GECKO) {
    return /rv\:([^\);]+)(\)|;)/.exec(userAgent);
  }
  if (goog.userAgent.EDGE) {
    return /Edge\/([\d\.]+)/.exec(userAgent);
  }
  if (goog.userAgent.IE) {
    return /\b(?:MSIE|rv)[: ]([^\);]+)(\)|;)/.exec(userAgent);
  }
  if (goog.userAgent.WEBKIT) {
    return /WebKit\/(\S+)/.exec(userAgent);
  }
  if (goog.userAgent.OPERA) {
    return /(?:Version)[ \/]?(\S+)/.exec(userAgent);
  }
  return undefined;
};
goog.userAgent.getDocumentMode_ = function() {
  var doc = goog.global["document"];
  return doc ? doc["documentMode"] : undefined;
};
goog.userAgent.VERSION = goog.userAgent.determineVersion_();
goog.userAgent.compare = function(v1, v2) {
  return goog.string.compareVersions(v1, v2);
};
goog.userAgent.isVersionOrHigherCache_ = {};
goog.userAgent.isVersionOrHigher = function(version) {
  return goog.userAgent.ASSUME_ANY_VERSION || goog.reflect.cache(goog.userAgent.isVersionOrHigherCache_, version, function() {
    return goog.string.compareVersions(goog.userAgent.VERSION, version) >= 0;
  });
};
goog.userAgent.isVersion = goog.userAgent.isVersionOrHigher;
goog.userAgent.isDocumentModeOrHigher = function(documentMode) {
  return Number(goog.userAgent.DOCUMENT_MODE) >= documentMode;
};
goog.userAgent.isDocumentMode = goog.userAgent.isDocumentModeOrHigher;
goog.userAgent.DOCUMENT_MODE = function() {
  var doc = goog.global["document"];
  var mode = goog.userAgent.getDocumentMode_();
  if (!doc || !goog.userAgent.IE) {
    return undefined;
  }
  return mode || (doc["compatMode"] == "CSS1Compat" ? parseInt(goog.userAgent.VERSION, 10) : 5);
}();
goog.provide("goog.debug");
goog.require("goog.array");
goog.require("goog.userAgent");
goog.define("goog.debug.LOGGING_ENABLED", goog.DEBUG);
goog.define("goog.debug.FORCE_SLOPPY_STACKS", false);
goog.debug.catchErrors = function(logFunc, opt_cancel, opt_target) {
  var target = opt_target || goog.global;
  var oldErrorHandler = target.onerror;
  var retVal = !!opt_cancel;
  if (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher("535.3")) {
    retVal = !retVal;
  }
  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;
  };
};
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 + " = ";
    try {
      s += obj[x];
    } catch (e) {
      s += "*** " + e + " ***";
    }
    str.push(s);
  }
  return str.join("\n");
};
goog.debug.deepExpose = function(obj, opt_showFn) {
  var str = [];
  var uidsToCleanup = [];
  var ancestorUids = {};
  var helper = function(obj, space) {
    var nestspace = space + "  ";
    var indentMultiline = function(str) {
      return str.replace(/\n/g, "\n" + space);
    };
    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 (!goog.hasUid(obj)) {
                  uidsToCleanup.push(obj);
                }
                var uid = goog.getUid(obj);
                if (ancestorUids[uid]) {
                  str.push("*** reference loop detected (id=" + uid + ") ***");
                } else {
                  ancestorUids[uid] = true;
                  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);
                  }
                  str.push("\n" + space + "}");
                  delete ancestorUids[uid];
                }
              } else {
                str.push(obj);
              }
            }
          }
        }
      }
    } catch (e) {
      str.push("*** " + e + " ***");
    }
  };
  helper(obj, "");
  for (var i = 0; i < uidsToCleanup.length; i++) {
    goog.removeUid(uidsToCleanup[i]);
  }
  return str.join("");
};
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(", ") + " ]";
};
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) {
    lineNumber = "Not available";
    threwError = true;
  }
  try {
    fileName = err.fileName || err.filename || err.sourceURL || goog.global["$googDebugFname"] || href;
  } catch (e$1) {
    fileName = "Not available";
    threwError = true;
  }
  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"};
  }
  return err;
};
goog.debug.enhanceError = function(err, opt_message) {
  var error;
  if (!(err instanceof Error)) {
    error = Error(err);
    if (Error.captureStackTrace) {
      Error.captureStackTrace(error, goog.debug.enhanceError);
    }
  } else {
    error = err;
  }
  if (!error.stack) {
    error.stack = goog.debug.getStacktrace(goog.debug.enhanceError);
  }
  if (opt_message) {
    var x = 0;
    while (error["message" + x]) {
      ++x;
    }
    error["message" + x] = String(opt_message);
  }
  return error;
};
goog.debug.getStacktraceSimple = function(opt_depth) {
  if (!goog.debug.FORCE_SLOPPY_STACKS) {
    var stack = goog.debug.getNativeStackTrace_(goog.debug.getStacktraceSimple);
    if (stack) {
      return stack;
    }
  }
  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");
    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("");
};
goog.debug.MAX_STACK_DEPTH = 50;
goog.debug.getNativeStackTrace_ = function(fn) {
  var tempErr = new Error;
  if (Error.captureStackTrace) {
    Error.captureStackTrace(tempErr, fn);
    return String(tempErr.stack);
  } else {
    try {
      throw tempErr;
    } catch (e) {
      tempErr = e;
    }
    var stack = tempErr.stack;
    if (stack) {
      return String(stack);
    }
  }
  return null;
};
goog.debug.getStacktrace = function(fn) {
  var stack;
  if (!goog.debug.FORCE_SLOPPY_STACKS) {
    var contextFn = fn || goog.debug.getStacktrace;
    stack = goog.debug.getNativeStackTrace_(contextFn);
  }
  if (!stack) {
    stack = goog.debug.getStacktraceHelper_(fn || arguments.callee.caller, []);
  }
  return stack;
};
goog.debug.getStacktraceHelper_ = function(fn, visited) {
  var sb = [];
  if (goog.array.contains(visited, fn)) {
    sb.push("[...circular reference...]");
  } else {
    if (fn && visited.length < goog.debug.MAX_STACK_DEPTH) {
      sb.push(goog.debug.getFunctionName(fn) + "(");
      var args = fn.arguments;
      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");
      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("");
};
goog.debug.setFunctionResolver = function(resolver) {
  goog.debug.fnNameResolver_ = resolver;
};
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;
    }
  }
  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];
};
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]");
};
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;
    }
  }
};
goog.debug.fnNameCache_ = {};
goog.debug.fnNameResolver_;
goog.provide("goog.debug.LogRecord");
goog.debug.LogRecord = function(level, msg, loggerName, opt_time, opt_sequenceNumber) {
  this.reset(level, msg, loggerName, opt_time, opt_sequenceNumber);
};
goog.debug.LogRecord.prototype.time_;
goog.debug.LogRecord.prototype.level_;
goog.debug.LogRecord.prototype.msg_;
goog.debug.LogRecord.prototype.loggerName_;
goog.debug.LogRecord.prototype.sequenceNumber_ = 0;
goog.debug.LogRecord.prototype.exception_ = null;
goog.define("goog.debug.LogRecord.ENABLE_SEQUENCE_NUMBERS", true);
goog.debug.LogRecord.nextSequenceNumber_ = 0;
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_;
};
goog.debug.LogRecord.prototype.getLoggerName = function() {
  return this.loggerName_;
};
goog.debug.LogRecord.prototype.getException = function() {
  return this.exception_;
};
goog.debug.LogRecord.prototype.setException = function(exception) {
  this.exception_ = exception;
};
goog.debug.LogRecord.prototype.setLoggerName = function(loggerName) {
  this.loggerName_ = loggerName;
};
goog.debug.LogRecord.prototype.getLevel = function() {
  return this.level_;
};
goog.debug.LogRecord.prototype.setLevel = function(level) {
  this.level_ = level;
};
goog.debug.LogRecord.prototype.getMessage = function() {
  return this.msg_;
};
goog.debug.LogRecord.prototype.setMessage = function(msg) {
  this.msg_ = msg;
};
goog.debug.LogRecord.prototype.getMillis = function() {
  return this.time_;
};
goog.debug.LogRecord.prototype.setMillis = function(time) {
  this.time_ = time;
};
goog.debug.LogRecord.prototype.getSequenceNumber = function() {
  return this.sequenceNumber_;
};
goog.provide("goog.debug.LogBuffer");
goog.require("goog.asserts");
goog.require("goog.debug.LogRecord");
goog.debug.LogBuffer = function() {
  goog.asserts.assert(goog.debug.LogBuffer.isBufferingEnabled(), "Cannot use goog.debug.LogBuffer without defining " + "goog.debug.LogBuffer.CAPACITY.");
  this.clear();
};
goog.debug.LogBuffer.getInstance = function() {
  if (!goog.debug.LogBuffer.instance_) {
    goog.debug.LogBuffer.instance_ = new goog.debug.LogBuffer;
  }
  return goog.debug.LogBuffer.instance_;
};
goog.define("goog.debug.LogBuffer.CAPACITY", 0);
goog.debug.LogBuffer.prototype.buffer_;
goog.debug.LogBuffer.prototype.curIndex_;
goog.debug.LogBuffer.prototype.isFull_;
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);
};
goog.debug.LogBuffer.isBufferingEnabled = function() {
  return goog.debug.LogBuffer.CAPACITY > 0;
};
goog.debug.LogBuffer.prototype.clear = function() {
  this.buffer_ = new Array(goog.debug.LogBuffer.CAPACITY);
  this.curIndex_ = -1;
  this.isFull_ = false;
};
goog.debug.LogBuffer.prototype.forEachRecord = function(func) {
  var buffer = this.buffer_;
  if (!buffer[0]) {
    return;
  }
  var curIndex = this.curIndex_;
  var i = this.isFull_ ? curIndex : -1;
  do {
    i = (i + 1) % goog.debug.LogBuffer.CAPACITY;
    func(buffer[i]);
  } while (i != curIndex);
};
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");
goog.debug.Loggable;
goog.debug.Logger = function(name) {
  this.name_ = name;
  this.parent_ = null;
  this.level_ = null;
  this.children_ = null;
  this.handlers_ = null;
};
goog.debug.Logger.ROOT_LOGGER_NAME = "";
goog.define("goog.debug.Logger.ENABLE_HIERARCHY", true);
if (!goog.debug.Logger.ENABLE_HIERARCHY) {
  goog.debug.Logger.rootHandlers_ = [];
  goog.debug.Logger.rootLevel_;
}
goog.debug.Logger.Level = function(name, value) {
  this.name = name;
  this.value = value;
};
goog.debug.Logger.Level.prototype.toString = function() {
  return this.name;
};
goog.debug.Logger.Level.OFF = new goog.debug.Logger.Level("OFF", Infinity);
goog.debug.Logger.Level.SHOUT = new goog.debug.Logger.Level("SHOUT", 1200);
goog.debug.Logger.Level.SEVERE = new goog.debug.Logger.Level("SEVERE", 1000);
goog.debug.Logger.Level.WARNING = new goog.debug.Logger.Level("WARNING", 900);
goog.debug.Logger.Level.INFO = new goog.debug.Logger.Level("INFO", 800);
goog.debug.Logger.Level.CONFIG = new goog.debug.Logger.Level("CONFIG", 700);
goog.debug.Logger.Level.FINE = new goog.debug.Logger.Level("FINE", 500);
goog.debug.Logger.Level.FINER = new goog.debug.Logger.Level("FINER", 400);
goog.debug.Logger.Level.FINEST = new goog.debug.Logger.Level("FINEST", 300);
goog.debug.Logger.Level.ALL = new goog.debug.Logger.Level("ALL", 0);
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];
goog.debug.Logger.Level.predefinedLevelsCache_ = null;
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;
  }
};
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;
};
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;
};
goog.debug.Logger.getLogger = function(name) {
  return goog.debug.LogManager.getLogger(name);
};
goog.debug.Logger.logToProfilers = function(msg) {
  if (goog.global["console"]) {
    if (goog.global["console"]["timeStamp"]) {
      goog.global["console"]["timeStamp"](msg);
    } else {
      if (goog.global["console"]["markTimeline"]) {
        goog.global["console"]["markTimeline"](msg);
      }
    }
  }
  if (goog.global["msWriteProfilerMark"]) {
    goog.global["msWriteProfilerMark"](msg);
  }
};
goog.debug.Logger.prototype.getName = function() {
  return this.name_;
};
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);
    }
  }
};
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;
  }
};
goog.debug.Logger.prototype.getParent = function() {
  return this.parent_;
};
goog.debug.Logger.prototype.getChildren = function() {
  if (!this.children_) {
    this.children_ = {};
  }
  return this.children_;
};
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;
    }
  }
};
goog.debug.Logger.prototype.getLevel = function() {
  return goog.debug.LOGGING_ENABLED ? this.level_ : goog.debug.Logger.Level.OFF;
};
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;
};
goog.debug.Logger.prototype.isLoggable = function(level) {
  return goog.debug.LOGGING_ENABLED && level.value >= this.getEffectiveLevel().value;
};
goog.debug.Logger.prototype.log = function(level, msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED && this.isLoggable(level)) {
    if (goog.isFunction(msg)) {
      msg = msg();
    }
    this.doLogRecord_(this.getLogRecord(level, msg, opt_exception));
  }
};
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;
};
goog.debug.Logger.prototype.shout = function(msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED) {
    this.log(goog.debug.Logger.Level.SHOUT, msg, opt_exception);
  }
};
goog.debug.Logger.prototype.severe = function(msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED) {
    this.log(goog.debug.Logger.Level.SEVERE, msg, opt_exception);
  }
};
goog.debug.Logger.prototype.warning = function(msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED) {
    this.log(goog.debug.Logger.Level.WARNING, msg, opt_exception);
  }
};
goog.debug.Logger.prototype.info = function(msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED) {
    this.log(goog.debug.Logger.Level.INFO, msg, opt_exception);
  }
};
goog.debug.Logger.prototype.config = function(msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED) {
    this.log(goog.debug.Logger.Level.CONFIG, msg, opt_exception);
  }
};
goog.debug.Logger.prototype.fine = function(msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED) {
    this.log(goog.debug.Logger.Level.FINE, msg, opt_exception);
  }
};
goog.debug.Logger.prototype.finer = function(msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED) {
    this.log(goog.debug.Logger.Level.FINER, msg, opt_exception);
  }
};
goog.debug.Logger.prototype.finest = function(msg, opt_exception) {
  if (goog.debug.LOGGING_ENABLED) {
    this.log(goog.debug.Logger.Level.FINEST, msg, opt_exception);
  }
};
goog.debug.Logger.prototype.logRecord = function(logRecord) {
  if (goog.debug.LOGGING_ENABLED && this.isLoggable(logRecord.getLevel())) {
    this.doLogRecord_(logRecord);
  }
};
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);
    }
  }
};
goog.debug.Logger.prototype.callPublish_ = function(logRecord) {
  if (this.handlers_) {
    for (var i = 0, handler; handler = this.handlers_[i]; i++) {
      handler(logRecord);
    }
  }
};
goog.debug.Logger.prototype.setParent_ = function(parent) {
  this.parent_ = parent;
};
goog.debug.Logger.prototype.addChild_ = function(name, logger) {
  this.getChildren()[name] = logger;
};
goog.debug.LogManager = {};
goog.debug.LogManager.loggers_ = {};
goog.debug.LogManager.rootLogger_ = null;
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);
  }
};
goog.debug.LogManager.getLoggers = function() {
  return goog.debug.LogManager.loggers_;
};
goog.debug.LogManager.getRoot = function() {
  goog.debug.LogManager.initialize();
  return goog.debug.LogManager.rootLogger_;
};
goog.debug.LogManager.getLogger = function(name) {
  goog.debug.LogManager.initialize();
  var ret = goog.debug.LogManager.loggers_[name];
  return ret || goog.debug.LogManager.createLogger_(name);
};
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 + ")");
  };
};
goog.debug.LogManager.createLogger_ = function(name) {
  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);
    parentLogger.addChild_(leafName, logger);
    logger.setParent_(parentLogger);
  }
  goog.debug.LogManager.loggers_[name] = logger;
  return logger;
};
goog.provide("goog.dom.BrowserFeature");
goog.require("goog.userAgent");
goog.dom.BrowserFeature = {CAN_ADD_NAME_OR_TYPE_ATTRIBUTES:!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9), 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"), CAN_USE_INNER_TEXT:goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("9"), CAN_USE_PARENT_ELEMENT_PROPERTY:goog.userAgent.IE || goog.userAgent.OPERA || goog.userAgent.WEBKIT, 
INNER_HTML_NEEDS_SCOPED_ELEMENT:goog.userAgent.IE, LEGACY_IE_RANGES:goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)};
goog.provide("goog.dom.HtmlElement");
goog.dom.HtmlElement = function() {
};
goog.provide("goog.dom.TagName");
goog.require("goog.dom.HtmlElement");
goog.dom.TagName = function(tagName) {
  this.tagName_ = tagName;
};
goog.dom.TagName.prototype.toString = function() {
  return this.tagName_;
};
goog.dom.TagName.A = new goog.dom.TagName("A");
goog.dom.TagName.ABBR = new goog.dom.TagName("ABBR");
goog.dom.TagName.ACRONYM = new goog.dom.TagName("ACRONYM");
goog.dom.TagName.ADDRESS = new goog.dom.TagName("ADDRESS");
goog.dom.TagName.APPLET = new goog.dom.TagName("APPLET");
goog.dom.TagName.AREA = new goog.dom.TagName("AREA");
goog.dom.TagName.ARTICLE = new goog.dom.TagName("ARTICLE");
goog.dom.TagName.ASIDE = new goog.dom.TagName("ASIDE");
goog.dom.TagName.AUDIO = new goog.dom.TagName("AUDIO");
goog.dom.TagName.B = new goog.dom.TagName("B");
goog.dom.TagName.BASE = new goog.dom.TagName("BASE");
goog.dom.TagName.BASEFONT = new goog.dom.TagName("BASEFONT");
goog.dom.TagName.BDI = new goog.dom.TagName("BDI");
goog.dom.TagName.BDO = new goog.dom.TagName("BDO");
goog.dom.TagName.BIG = new goog.dom.TagName("BIG");
goog.dom.TagName.BLOCKQUOTE = new goog.dom.TagName("BLOCKQUOTE");
goog.dom.TagName.BODY = new goog.dom.TagName("BODY");
goog.dom.TagName.BR = new goog.dom.TagName("BR");
goog.dom.TagName.BUTTON = new goog.dom.TagName("BUTTON");
goog.dom.TagName.CANVAS = new goog.dom.TagName("CANVAS");
goog.dom.TagName.CAPTION = new goog.dom.TagName("CAPTION");
goog.dom.TagName.CENTER = new goog.dom.TagName("CENTER");
goog.dom.TagName.CITE = new goog.dom.TagName("CITE");
goog.dom.TagName.CODE = new goog.dom.TagName("CODE");
goog.dom.TagName.COL = new goog.dom.TagName("COL");
goog.dom.TagName.COLGROUP = new goog.dom.TagName("COLGROUP");
goog.dom.TagName.COMMAND = new goog.dom.TagName("COMMAND");
goog.dom.TagName.DATA = new goog.dom.TagName("DATA");
goog.dom.TagName.DATALIST = new goog.dom.TagName("DATALIST");
goog.dom.TagName.DD = new goog.dom.TagName("DD");
goog.dom.TagName.DEL = new goog.dom.TagName("DEL");
goog.dom.TagName.DETAILS = new goog.dom.TagName("DETAILS");
goog.dom.TagName.DFN = new goog.dom.TagName("DFN");
goog.dom.TagName.DIALOG = new goog.dom.TagName("DIALOG");
goog.dom.TagName.DIR = new goog.dom.TagName("DIR");
goog.dom.TagName.DIV = new goog.dom.TagName("DIV");
goog.dom.TagName.DL = new goog.dom.TagName("DL");
goog.dom.TagName.DT = new goog.dom.TagName("DT");
goog.dom.TagName.EM = new goog.dom.TagName("EM");
goog.dom.TagName.EMBED = new goog.dom.TagName("EMBED");
goog.dom.TagName.FIELDSET = new goog.dom.TagName("FIELDSET");
goog.dom.TagName.FIGCAPTION = new goog.dom.TagName("FIGCAPTION");
goog.dom.TagName.FIGURE = new goog.dom.TagName("FIGURE");
goog.dom.TagName.FONT = new goog.dom.TagName("FONT");
goog.dom.TagName.FOOTER = new goog.dom.TagName("FOOTER");
goog.dom.TagName.FORM = new goog.dom.TagName("FORM");
goog.dom.TagName.FRAME = new goog.dom.TagName("FRAME");
goog.dom.TagName.FRAMESET = new goog.dom.TagName("FRAMESET");
goog.dom.TagName.H1 = new goog.dom.TagName("H1");
goog.dom.TagName.H2 = new goog.dom.TagName("H2");
goog.dom.TagName.H3 = new goog.dom.TagName("H3");
goog.dom.TagName.H4 = new goog.dom.TagName("H4");
goog.dom.TagName.H5 = new goog.dom.TagName("H5");
goog.dom.TagName.H6 = new goog.dom.TagName("H6");
goog.dom.TagName.HEAD = new goog.dom.TagName("HEAD");
goog.dom.TagName.HEADER = new goog.dom.TagName("HEADER");
goog.dom.TagName.HGROUP = new goog.dom.TagName("HGROUP");
goog.dom.TagName.HR = new goog.dom.TagName("HR");
goog.dom.TagName.HTML = new goog.dom.TagName("HTML");
goog.dom.TagName.I = new goog.dom.TagName("I");
goog.dom.TagName.IFRAME = new goog.dom.TagName("IFRAME");
goog.dom.TagName.IMG = new goog.dom.TagName("IMG");
goog.dom.TagName.INPUT = new goog.dom.TagName("INPUT");
goog.dom.TagName.INS = new goog.dom.TagName("INS");
goog.dom.TagName.ISINDEX = new goog.dom.TagName("ISINDEX");
goog.dom.TagName.KBD = new goog.dom.TagName("KBD");
goog.dom.TagName.KEYGEN = new goog.dom.TagName("KEYGEN");
goog.dom.TagName.LABEL = new goog.dom.TagName("LABEL");
goog.dom.TagName.LEGEND = new goog.dom.TagName("LEGEND");
goog.dom.TagName.LI = new goog.dom.TagName("LI");
goog.dom.TagName.LINK = new goog.dom.TagName("LINK");
goog.dom.TagName.MAP = new goog.dom.TagName("MAP");
goog.dom.TagName.MARK = new goog.dom.TagName("MARK");
goog.dom.TagName.MATH = new goog.dom.TagName("MATH");
goog.dom.TagName.MENU = new goog.dom.TagName("MENU");
goog.dom.TagName.META = new goog.dom.TagName("META");
goog.dom.TagName.METER = new goog.dom.TagName("METER");
goog.dom.TagName.NAV = new goog.dom.TagName("NAV");
goog.dom.TagName.NOFRAMES = new goog.dom.TagName("NOFRAMES");
goog.dom.TagName.NOSCRIPT = new goog.dom.TagName("NOSCRIPT");
goog.dom.TagName.OBJECT = new goog.dom.TagName("OBJECT");
goog.dom.TagName.OL = new goog.dom.TagName("OL");
goog.dom.TagName.OPTGROUP = new goog.dom.TagName("OPTGROUP");
goog.dom.TagName.OPTION = new goog.dom.TagName("OPTION");
goog.dom.TagName.OUTPUT = new goog.dom.TagName("OUTPUT");
goog.dom.TagName.P = new goog.dom.TagName("P");
goog.dom.TagName.PARAM = new goog.dom.TagName("PARAM");
goog.dom.TagName.PRE = new goog.dom.TagName("PRE");
goog.dom.TagName.PROGRESS = new goog.dom.TagName("PROGRESS");
goog.dom.TagName.Q = new goog.dom.TagName("Q");
goog.dom.TagName.RP = new goog.dom.TagName("RP");
goog.dom.TagName.RT = new goog.dom.TagName("RT");
goog.dom.TagName.RUBY = new goog.dom.TagName("RUBY");
goog.dom.TagName.S = new goog.dom.TagName("S");
goog.dom.TagName.SAMP = new goog.dom.TagName("SAMP");
goog.dom.TagName.SCRIPT = new goog.dom.TagName("SCRIPT");
goog.dom.TagName.SECTION = new goog.dom.TagName("SECTION");
goog.dom.TagName.SELECT = new goog.dom.TagName("SELECT");
goog.dom.TagName.SMALL = new goog.dom.TagName("SMALL");
goog.dom.TagName.SOURCE = new goog.dom.TagName("SOURCE");
goog.dom.TagName.SPAN = new goog.dom.TagName("SPAN");
goog.dom.TagName.STRIKE = new goog.dom.TagName("STRIKE");
goog.dom.TagName.STRONG = new goog.dom.TagName("STRONG");
goog.dom.TagName.STYLE = new goog.dom.TagName("STYLE");
goog.dom.TagName.SUB = new goog.dom.TagName("SUB");
goog.dom.TagName.SUMMARY = new goog.dom.TagName("SUMMARY");
goog.dom.TagName.SUP = new goog.dom.TagName("SUP");
goog.dom.TagName.SVG = new goog.dom.TagName("SVG");
goog.dom.TagName.TABLE = new goog.dom.TagName("TABLE");
goog.dom.TagName.TBODY = new goog.dom.TagName("TBODY");
goog.dom.TagName.TD = new goog.dom.TagName("TD");
goog.dom.TagName.TEMPLATE = new goog.dom.TagName("TEMPLATE");
goog.dom.TagName.TEXTAREA = new goog.dom.TagName("TEXTAREA");
goog.dom.TagName.TFOOT = new goog.dom.TagName("TFOOT");
goog.dom.TagName.TH = new goog.dom.TagName("TH");
goog.dom.TagName.THEAD = new goog.dom.TagName("THEAD");
goog.dom.TagName.TIME = new goog.dom.TagName("TIME");
goog.dom.TagName.TITLE = new goog.dom.TagName("TITLE");
goog.dom.TagName.TR = new goog.dom.TagName("TR");
goog.dom.TagName.TRACK = new goog.dom.TagName("TRACK");
goog.dom.TagName.TT = new goog.dom.TagName("TT");
goog.dom.TagName.U = new goog.dom.TagName("U");
goog.dom.TagName.UL = new goog.dom.TagName("UL");
goog.dom.TagName.VAR = new goog.dom.TagName("VAR");
goog.dom.TagName.VIDEO = new goog.dom.TagName("VIDEO");
goog.dom.TagName.WBR = new goog.dom.TagName("WBR");
goog.provide("goog.dom.tags");
goog.require("goog.object");
goog.dom.tags.VOID_TAGS_ = goog.object.createSet("area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr");
goog.dom.tags.isVoidTag = function(tagName) {
  return goog.dom.tags.VOID_TAGS_[tagName] === true;
};
goog.provide("goog.string.TypedString");
goog.string.TypedString = function() {
};
goog.string.TypedString.prototype.implementsGoogStringTypedString;
goog.string.TypedString.prototype.getTypedStringValue;
goog.provide("goog.string.Const");
goog.require("goog.asserts");
goog.require("goog.string.TypedString");
goog.string.Const = function() {
  this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ = "";
  this.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ = goog.string.Const.TYPE_MARKER_;
};
goog.string.Const.prototype.implementsGoogStringTypedString = true;
goog.string.Const.prototype.getTypedStringValue = function() {
  return this.stringConstValueWithSecurityContract__googStringSecurityPrivate_;
};
goog.string.Const.prototype.toString = function() {
  return "Const{" + this.stringConstValueWithSecurityContract__googStringSecurityPrivate_ + "}";
};
goog.string.Const.unwrap = function(stringConst) {
  if (stringConst instanceof goog.string.Const && stringConst.constructor === goog.string.Const && stringConst.STRING_CONST_TYPE_MARKER__GOOG_STRING_SECURITY_PRIVATE_ === goog.string.Const.TYPE_MARKER_) {
    return stringConst.stringConstValueWithSecurityContract__googStringSecurityPrivate_;
  } else {
    goog.asserts.fail("expected object of type Const, got '" + stringConst + "'");
    return "type_error:Const";
  }
};
goog.string.Const.from = function(s) {
  return goog.string.Const.create__googStringSecurityPrivate_(s);
};
goog.string.Const.TYPE_MARKER_ = {};
goog.string.Const.create__googStringSecurityPrivate_ = function(s) {
  var stringConst = new goog.string.Const;
  stringConst.stringConstValueWithSecurityContract__googStringSecurityPrivate_ = s;
  return stringConst;
};
goog.string.Const.EMPTY = goog.string.Const.from("");
goog.provide("goog.html.SafeScript");
goog.require("goog.asserts");
goog.require("goog.string.Const");
goog.require("goog.string.TypedString");
goog.html.SafeScript = function() {
  this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = "";
  this.SAFE_SCRIPT_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
};
goog.html.SafeScript.prototype.implementsGoogStringTypedString = true;
goog.html.SafeScript.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
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);
};
goog.html.SafeScript.prototype.getTypedStringValue = function() {
  return this.privateDoNotAccessOrElseSafeScriptWrappedValue_;
};
if (goog.DEBUG) {
  goog.html.SafeScript.prototype.toString = function() {
    return "SafeScript{" + this.privateDoNotAccessOrElseSafeScriptWrappedValue_ + "}";
  };
}
goog.html.SafeScript.unwrap = function(safeScript) {
  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 + "' of type " + goog.typeOf(safeScript));
    return "type_error:SafeScript";
  }
};
goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse = function(script) {
  return (new goog.html.SafeScript).initSecurityPrivateDoNotAccessOrElse_(script);
};
goog.html.SafeScript.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(script) {
  this.privateDoNotAccessOrElseSafeScriptWrappedValue_ = script;
  return this;
};
goog.html.SafeScript.EMPTY = goog.html.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse("");
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");
goog.html.SafeStyle = function() {
  this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = "";
  this.SAFE_STYLE_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
};
goog.html.SafeStyle.prototype.implementsGoogStringTypedString = true;
goog.html.SafeStyle.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
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);
};
goog.html.SafeStyle.checkStyle_ = function(style) {
  goog.asserts.assert(!/[<>]/.test(style), "Forbidden characters in style string: " + style);
};
goog.html.SafeStyle.prototype.getTypedStringValue = function() {
  return this.privateDoNotAccessOrElseSafeStyleWrappedValue_;
};
if (goog.DEBUG) {
  goog.html.SafeStyle.prototype.toString = function() {
    return "SafeStyle{" + this.privateDoNotAccessOrElseSafeStyleWrappedValue_ + "}";
  };
}
goog.html.SafeStyle.unwrap = function(safeStyle) {
  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 + "' of type " + goog.typeOf(safeStyle));
    return "type_error:SafeStyle";
  }
};
goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse = function(style) {
  return (new goog.html.SafeStyle).initSecurityPrivateDoNotAccessOrElse_(style);
};
goog.html.SafeStyle.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(style) {
  this.privateDoNotAccessOrElseSafeStyleWrappedValue_ = style;
  return this;
};
goog.html.SafeStyle.EMPTY = goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse("");
goog.html.SafeStyle.INNOCUOUS_STRING = "zClosurez";
goog.html.SafeStyle.PropertyMap;
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);
      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], rgb() and " + "rgba(), 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);
};
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;
};
goog.html.SafeStyle.VALUE_RE_ = /^([-,."'%_!# a-zA-Z0-9]+|(?:rgb|hsl)a?\([0-9.%, ]+\))$/;
goog.html.SafeStyle.concat = function(var_args) {
  var style = "";
  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);
};
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");
goog.html.SafeStyleSheet = function() {
  this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = "";
  this.SAFE_STYLE_SHEET_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
};
goog.html.SafeStyleSheet.prototype.implementsGoogStringTypedString = true;
goog.html.SafeStyleSheet.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
goog.html.SafeStyleSheet.concat = function(var_args) {
  var result = "";
  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);
};
goog.html.SafeStyleSheet.fromConstant = function(styleSheet) {
  var styleSheetString = goog.string.Const.unwrap(styleSheet);
  if (styleSheetString.length === 0) {
    return goog.html.SafeStyleSheet.EMPTY;
  }
  goog.asserts.assert(!goog.string.contains(styleSheetString, "<"), "Forbidden '<' character in style sheet string: " + styleSheetString);
  return goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheetString);
};
goog.html.SafeStyleSheet.prototype.getTypedStringValue = function() {
  return this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_;
};
if (goog.DEBUG) {
  goog.html.SafeStyleSheet.prototype.toString = function() {
    return "SafeStyleSheet{" + this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ + "}";
  };
}
goog.html.SafeStyleSheet.unwrap = function(safeStyleSheet) {
  if (safeStyleSheet instanceof goog.html.SafeStyleSheet && safeStyleSheet.constructor === goog.html.SafeStyleSheet && safeStyleSheet.SAFE_STYLE_SHEET_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 + "' of type " + goog.typeOf(safeStyleSheet));
    return "type_error:SafeStyleSheet";
  }
};
goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse = function(styleSheet) {
  return (new goog.html.SafeStyleSheet).initSecurityPrivateDoNotAccessOrElse_(styleSheet);
};
goog.html.SafeStyleSheet.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(styleSheet) {
  this.privateDoNotAccessOrElseSafeStyleSheetWrappedValue_ = styleSheet;
  return this;
};
goog.html.SafeStyleSheet.EMPTY = goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse("");
goog.provide("goog.fs.url");
goog.fs.url.createObjectUrl = function(blob) {
  return goog.fs.url.getUrlObject_().createObjectURL(blob);
};
goog.fs.url.revokeObjectUrl = function(url) {
  goog.fs.url.getUrlObject_().revokeObjectURL(url);
};
goog.fs.url.UrlObject_;
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");
  }
};
goog.fs.url.findUrlObject_ = function() {
  if (goog.isDef(goog.global.URL) && goog.isDef(goog.global.URL.createObjectURL)) {
    return goog.global.URL;
  } else {
    if (goog.isDef(goog.global.webkitURL) && goog.isDef(goog.global.webkitURL.createObjectURL)) {
      return goog.global.webkitURL;
    } else {
      if (goog.isDef(goog.global.createObjectURL)) {
        return goog.global;
      } else {
        return null;
      }
    }
  }
};
goog.fs.url.browserSupportsObjectUrls = function() {
  return goog.fs.url.findUrlObject_() != null;
};
goog.provide("goog.i18n.bidi");
goog.provide("goog.i18n.bidi.Dir");
goog.provide("goog.i18n.bidi.DirectionalString");
goog.provide("goog.i18n.bidi.Format");
goog.define("goog.i18n.bidi.FORCE_RTL", false);
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) == "_");
goog.i18n.bidi.Format = {LRE:"\u202a", RLE:"\u202b", PDF:"\u202c", LRM:"\u200e", RLM:"\u200f"};
goog.i18n.bidi.Dir = {LTR:1, RTL:-1, NEUTRAL:0};
goog.i18n.bidi.RIGHT = "right";
goog.i18n.bidi.LEFT = "left";
goog.i18n.bidi.I18N_RIGHT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.LEFT : goog.i18n.bidi.RIGHT;
goog.i18n.bidi.I18N_LEFT = goog.i18n.bidi.IS_RTL ? goog.i18n.bidi.RIGHT : goog.i18n.bidi.LEFT;
goog.i18n.bidi.toDir = function(givenDir, opt_noNeutral) {
  if (typeof givenDir == "number") {
    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 {
      return givenDir ? goog.i18n.bidi.Dir.RTL : goog.i18n.bidi.Dir.LTR;
    }
  }
};
goog.i18n.bidi.ltrChars_ = "A-Za-z\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02b8\u0300-\u0590\u0800-\u1fff" + "\u200e\u2c00-\ufb1c\ufe00-\ufe6f\ufefd-\uffff";
goog.i18n.bidi.rtlChars_ = "\u0591-\u06ef\u06fa-\u07ff\u200f\ufb1d-\ufdff\ufe70-\ufefc";
goog.i18n.bidi.htmlSkipReg_ = /<[^>]*>|&[^;]+;/g;
goog.i18n.bidi.stripHtmlIfNeeded_ = function(str, opt_isStripNeeded) {
  return opt_isStripNeeded ? str.replace(goog.i18n.bidi.htmlSkipReg_, "") : str;
};
goog.i18n.bidi.rtlCharReg_ = new RegExp("[" + goog.i18n.bidi.rtlChars_ + "]");
goog.i18n.bidi.ltrCharReg_ = new RegExp("[" + goog.i18n.bidi.ltrChars_ + "]");
goog.i18n.bidi.hasAnyRtl = function(str, opt_isHtml) {
  return goog.i18n.bidi.rtlCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
goog.i18n.bidi.hasRtlChar = goog.i18n.bidi.hasAnyRtl;
goog.i18n.bidi.hasAnyLtr = function(str, opt_isHtml) {
  return goog.i18n.bidi.ltrCharReg_.test(goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
goog.i18n.bidi.ltrRe_ = new RegExp("^[" + goog.i18n.bidi.ltrChars_ + "]");
goog.i18n.bidi.rtlRe_ = new RegExp("^[" + goog.i18n.bidi.rtlChars_ + "]");
goog.i18n.bidi.isRtlChar = function(str) {
  return goog.i18n.bidi.rtlRe_.test(str);
};
goog.i18n.bidi.isLtrChar = function(str) {
  return goog.i18n.bidi.ltrRe_.test(str);
};
goog.i18n.bidi.isNeutralChar = function(str) {
  return !goog.i18n.bidi.isLtrChar(str) && !goog.i18n.bidi.isRtlChar(str);
};
goog.i18n.bidi.ltrDirCheckRe_ = new RegExp("^[^" + goog.i18n.bidi.rtlChars_ + "]*[" + goog.i18n.bidi.ltrChars_ + "]");
goog.i18n.bidi.rtlDirCheckRe_ = new RegExp("^[^" + goog.i18n.bidi.ltrChars_ + "]*[" + goog.i18n.bidi.rtlChars_ + "]");
goog.i18n.bidi.startsWithRtl = function(str, opt_isHtml) {
  return goog.i18n.bidi.rtlDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
goog.i18n.bidi.isRtlText = goog.i18n.bidi.startsWithRtl;
goog.i18n.bidi.startsWithLtr = function(str, opt_isHtml) {
  return goog.i18n.bidi.ltrDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
goog.i18n.bidi.isLtrText = goog.i18n.bidi.startsWithLtr;
goog.i18n.bidi.isRequiredLtrRe_ = /^http:\/\/.*/;
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);
};
goog.i18n.bidi.ltrExitDirCheckRe_ = new RegExp("[" + goog.i18n.bidi.ltrChars_ + "][^" + goog.i18n.bidi.rtlChars_ + "]*$");
goog.i18n.bidi.rtlExitDirCheckRe_ = new RegExp("[" + goog.i18n.bidi.rtlChars_ + "][^" + goog.i18n.bidi.ltrChars_ + "]*$");
goog.i18n.bidi.endsWithLtr = function(str, opt_isHtml) {
  return goog.i18n.bidi.ltrExitDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
goog.i18n.bidi.isLtrExitText = goog.i18n.bidi.endsWithLtr;
goog.i18n.bidi.endsWithRtl = function(str, opt_isHtml) {
  return goog.i18n.bidi.rtlExitDirCheckRe_.test(goog.i18n.bidi.stripHtmlIfNeeded_(str, opt_isHtml));
};
goog.i18n.bidi.isRtlExitText = goog.i18n.bidi.endsWithRtl;
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");
goog.i18n.bidi.isRtlLanguage = function(lang) {
  return goog.i18n.bidi.rtlLocalesRe_.test(lang);
};
goog.i18n.bidi.bracketGuardTextRe_ = /(\(.*?\)+)|(\[.*?\]+)|(\{.*?\}+)|(<.*?>+)/g;
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);
};
goog.i18n.bidi.enforceRtlInHtml = function(html) {
  if (html.charAt(0) == "<") {
    return html.replace(/<\w+/, "$& dir=rtl");
  }
  return "\n<span dir=rtl>" + html + "</span>";
};
goog.i18n.bidi.enforceRtlInText = function(text) {
  return goog.i18n.bidi.Format.RLE + text + goog.i18n.bidi.Format.PDF;
};
goog.i18n.bidi.enforceLtrInHtml = function(html) {
  if (html.charAt(0) == "<") {
    return html.replace(/<\w+/, "$& dir=ltr");
  }
  return "\n<span dir=ltr>" + html + "</span>";
};
goog.i18n.bidi.enforceLtrInText = function(text) {
  return goog.i18n.bidi.Format.LRE + text + goog.i18n.bidi.Format.PDF;
};
goog.i18n.bidi.dimensionsRe_ = /:\s*([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)\s+([.\d][.\w]*)/g;
goog.i18n.bidi.leftRe_ = /left/gi;
goog.i18n.bidi.rightRe_ = /right/gi;
goog.i18n.bidi.tempRe_ = /%%%%/g;
goog.i18n.bidi.mirrorCSS = function(cssStr) {
  return cssStr.replace(goog.i18n.bidi.dimensionsRe_, ":$1 $4 $3 $2").replace(goog.i18n.bidi.leftRe_, "%%%%").replace(goog.i18n.bidi.rightRe_, goog.i18n.bidi.LEFT).replace(goog.i18n.bidi.tempRe_, goog.i18n.bidi.RIGHT);
};
goog.i18n.bidi.doubleQuoteSubstituteRe_ = /([\u0591-\u05f2])"/g;
goog.i18n.bidi.singleQuoteSubstituteRe_ = /([\u0591-\u05f2])'/g;
goog.i18n.bidi.normalizeHebrewQuote = function(str) {
  return str.replace(goog.i18n.bidi.doubleQuoteSubstituteRe_, "$1\u05f4").replace(goog.i18n.bidi.singleQuoteSubstituteRe_, "$1\u05f3");
};
goog.i18n.bidi.wordSeparatorRe_ = /\s+/;
goog.i18n.bidi.hasNumeralsRe_ = /[\d\u06f0-\u06f9]/;
goog.i18n.bidi.rtlDetectionThreshold_ = 0.40;
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;
};
goog.i18n.bidi.detectRtlDirectionality = function(str, opt_isHtml) {
  return goog.i18n.bidi.estimateDirection(str, opt_isHtml) == goog.i18n.bidi.Dir.RTL;
};
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";
    }
  }
};
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:
      element.removeAttribute("dir");
  }
};
goog.i18n.bidi.DirectionalString = function() {
};
goog.i18n.bidi.DirectionalString.prototype.implementsGoogI18nBidiDirectionalString;
goog.i18n.bidi.DirectionalString.prototype.getDirection;
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");
goog.html.TrustedResourceUrl = function() {
  this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = "";
  this.TRUSTED_RESOURCE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
};
goog.html.TrustedResourceUrl.prototype.implementsGoogStringTypedString = true;
goog.html.TrustedResourceUrl.prototype.getTypedStringValue = function() {
  return this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_;
};
goog.html.TrustedResourceUrl.prototype.implementsGoogI18nBidiDirectionalString = true;
goog.html.TrustedResourceUrl.prototype.getDirection = function() {
  return goog.i18n.bidi.Dir.LTR;
};
if (goog.DEBUG) {
  goog.html.TrustedResourceUrl.prototype.toString = function() {
    return "TrustedResourceUrl{" + this.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ + "}";
  };
}
goog.html.TrustedResourceUrl.unwrap = function(trustedResourceUrl) {
  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 + "' of type " + goog.typeOf(trustedResourceUrl));
    return "type_error:TrustedResourceUrl";
  }
};
goog.html.TrustedResourceUrl.format = function(format, args) {
  var formatStr = goog.string.Const.unwrap(format);
  if (!goog.html.TrustedResourceUrl.BASE_URL_.test(formatStr)) {
    throw new Error("Invalid TrustedResourceUrl format: " + formatStr);
  }
  var result = formatStr.replace(goog.html.TrustedResourceUrl.FORMAT_MARKER_, function(match, id) {
    if (!Object.prototype.hasOwnProperty.call(args, id)) {
      throw new Error('Found marker, "' + id + '", in format string, "' + formatStr + '", but no valid label mapping found ' + "in args: " + JSON.stringify(args));
    }
    var arg = args[id];
    if (arg instanceof goog.string.Const) {
      return goog.string.Const.unwrap(arg);
    } else {
      return encodeURIComponent(String(arg));
    }
  });
  return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(result);
};
goog.html.TrustedResourceUrl.FORMAT_MARKER_ = /%{(\w+)}/g;
goog.html.TrustedResourceUrl.BASE_URL_ = /^(?:https:)?\/\/[0-9a-z.:[\]-]+\/|^\/[^\/\\]|^about:blank(#|$)/i;
goog.html.TrustedResourceUrl.fromConstant = function(url) {
  return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(goog.string.Const.unwrap(url));
};
goog.html.TrustedResourceUrl.fromConstants = function(parts) {
  var unwrapped = "";
  for (var i = 0; i < parts.length; i++) {
    unwrapped += goog.string.Const.unwrap(parts[i]);
  }
  return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(unwrapped);
};
goog.html.TrustedResourceUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse = function(url) {
  var trustedResourceUrl = new goog.html.TrustedResourceUrl;
  trustedResourceUrl.privateDoNotAccessOrElseTrustedResourceUrlWrappedValue_ = url;
  return trustedResourceUrl;
};
goog.provide("goog.html.SafeUrl");
goog.require("goog.asserts");
goog.require("goog.fs.url");
goog.require("goog.html.TrustedResourceUrl");
goog.require("goog.i18n.bidi.Dir");
goog.require("goog.i18n.bidi.DirectionalString");
goog.require("goog.string");
goog.require("goog.string.Const");
goog.require("goog.string.TypedString");
goog.html.SafeUrl = function() {
  this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = "";
  this.SAFE_URL_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
};
goog.html.SafeUrl.INNOCUOUS_STRING = "about:invalid#zClosurez";
goog.html.SafeUrl.prototype.implementsGoogStringTypedString = true;
goog.html.SafeUrl.prototype.getTypedStringValue = function() {
  return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
};
goog.html.SafeUrl.prototype.implementsGoogI18nBidiDirectionalString = true;
goog.html.SafeUrl.prototype.getDirection = function() {
  return goog.i18n.bidi.Dir.LTR;
};
if (goog.DEBUG) {
  goog.html.SafeUrl.prototype.toString = function() {
    return "SafeUrl{" + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ + "}";
  };
}
goog.html.SafeUrl.unwrap = function(safeUrl) {
  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 + "' of type " + goog.typeOf(safeUrl));
    return "type_error:SafeUrl";
  }
};
goog.html.SafeUrl.fromConstant = function(url) {
  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(goog.string.Const.unwrap(url));
};
goog.html.SAFE_MIME_TYPE_PATTERN_ = /^(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm))$/i;
goog.html.SafeUrl.fromBlob = function(blob) {
  var url = goog.html.SAFE_MIME_TYPE_PATTERN_.test(blob.type) ? goog.fs.url.createObjectUrl(blob) : goog.html.SafeUrl.INNOCUOUS_STRING;
  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
};
goog.html.DATA_URL_PATTERN_ = /^data:([^;,]*);base64,[a-z0-9+\/]+=*$/i;
goog.html.SafeUrl.fromDataUrl = function(dataUrl) {
  var match = dataUrl.match(goog.html.DATA_URL_PATTERN_);
  var valid = match && goog.html.SAFE_MIME_TYPE_PATTERN_.test(match[1]);
  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(valid ? dataUrl : goog.html.SafeUrl.INNOCUOUS_STRING);
};
goog.html.SafeUrl.fromTelUrl = function(telUrl) {
  if (!goog.string.caseInsensitiveStartsWith(telUrl, "tel:")) {
    telUrl = goog.html.SafeUrl.INNOCUOUS_STRING;
  }
  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(telUrl);
};
goog.html.SafeUrl.fromTrustedResourceUrl = function(trustedResourceUrl) {
  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(goog.html.TrustedResourceUrl.unwrap(trustedResourceUrl));
};
goog.html.SAFE_URL_PATTERN_ = /^(?:(?:https?|mailto|ftp):|[^:/?#]*(?:[/?#]|$))/i;
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;
  }
  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
};
goog.html.SafeUrl.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse = function(url) {
  var safeUrl = new goog.html.SafeUrl;
  safeUrl.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = url;
  return safeUrl;
};
goog.html.SafeUrl.ABOUT_BLANK = goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse("about:blank");
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.SafeScript");
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.labs.userAgent.browser");
goog.require("goog.object");
goog.require("goog.string");
goog.require("goog.string.Const");
goog.require("goog.string.TypedString");
goog.html.SafeHtml = function() {
  this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = "";
  this.SAFE_HTML_TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_;
  this.dir_ = null;
};
goog.html.SafeHtml.prototype.implementsGoogI18nBidiDirectionalString = true;
goog.html.SafeHtml.prototype.getDirection = function() {
  return this.dir_;
};
goog.html.SafeHtml.prototype.implementsGoogStringTypedString = true;
goog.html.SafeHtml.prototype.getTypedStringValue = function() {
  return this.privateDoNotAccessOrElseSafeHtmlWrappedValue_;
};
if (goog.DEBUG) {
  goog.html.SafeHtml.prototype.toString = function() {
    return "SafeHtml{" + this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ + "}";
  };
}
goog.html.SafeHtml.unwrap = function(safeHtml) {
  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 + "' of type " + goog.typeOf(safeHtml));
    return "type_error:SafeHtml";
  }
};
goog.html.SafeHtml.TextOrHtml_;
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);
};
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());
};
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());
};
goog.html.SafeHtml.from = goog.html.SafeHtml.htmlEscape;
goog.html.SafeHtml.VALID_NAMES_IN_TAG_ = /^[a-zA-Z0-9-]+$/;
goog.html.SafeHtml.URL_ATTRIBUTES_ = goog.object.createSet("action", "cite", "data", "formaction", "href", "manifest", "poster", "src");
goog.html.SafeHtml.NOT_ALLOWED_TAG_NAMES_ = goog.object.createSet(goog.dom.TagName.APPLET, goog.dom.TagName.BASE, goog.dom.TagName.EMBED, goog.dom.TagName.IFRAME, goog.dom.TagName.LINK, goog.dom.TagName.MATH, goog.dom.TagName.META, goog.dom.TagName.OBJECT, goog.dom.TagName.SCRIPT, goog.dom.TagName.STYLE, goog.dom.TagName.SVG, goog.dom.TagName.TEMPLATE);
goog.html.SafeHtml.AttributeValue;
goog.html.SafeHtml.create = function(tagName, opt_attributes, opt_content) {
  goog.html.SafeHtml.verifyTagName(String(tagName));
  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse(String(tagName), opt_attributes, opt_content);
};
goog.html.SafeHtml.verifyTagName = function(tagName) {
  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.");
  }
};
goog.html.SafeHtml.createIframe = function(opt_src, opt_srcdoc, opt_attributes, opt_content) {
  if (opt_src) {
    goog.html.TrustedResourceUrl.unwrap(opt_src);
  }
  var fixedAttributes = {};
  fixedAttributes["src"] = opt_src || null;
  fixedAttributes["srcdoc"] = opt_srcdoc && goog.html.SafeHtml.unwrap(opt_srcdoc);
  var defaultAttributes = {"sandbox":""};
  var attributes = goog.html.SafeHtml.combineAttributes(fixedAttributes, defaultAttributes, opt_attributes);
  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse("iframe", attributes, opt_content);
};
goog.html.SafeHtml.createSandboxIframe = function(opt_src, opt_srcdoc, opt_attributes, opt_content) {
  if (!goog.html.SafeHtml.canUseSandboxIframe()) {
    throw new Error("The browser does not support sandboxed iframes.");
  }
  var fixedAttributes = {};
  if (opt_src) {
    fixedAttributes["src"] = goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(opt_src));
  } else {
    fixedAttributes["src"] = null;
  }
  fixedAttributes["srcdoc"] = opt_srcdoc || null;
  fixedAttributes["sandbox"] = "";
  var attributes = goog.html.SafeHtml.combineAttributes(fixedAttributes, {}, opt_attributes);
  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse("iframe", attributes, opt_content);
};
goog.html.SafeHtml.canUseSandboxIframe = function() {
  return goog.global["HTMLIFrameElement"] && "sandbox" in goog.global["HTMLIFrameElement"].prototype;
};
goog.html.SafeHtml.createScriptSrc = function(src, opt_attributes) {
  goog.html.TrustedResourceUrl.unwrap(src);
  var fixedAttributes = {"src":src};
  var defaultAttributes = {};
  var attributes = goog.html.SafeHtml.combineAttributes(fixedAttributes, defaultAttributes, opt_attributes);
  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse("script", attributes);
};
goog.html.SafeHtml.createScript = function(script, opt_attributes) {
  for (var attr in opt_attributes) {
    var attrLower = attr.toLowerCase();
    if (attrLower == "language" || attrLower == "src" || attrLower == "text" || attrLower == "type") {
      throw Error('Cannot set "' + attrLower + '" attribute');
    }
  }
  var content = "";
  script = goog.array.concat(script);
  for (var i = 0; i < script.length; i++) {
    content += goog.html.SafeScript.unwrap(script[i]);
  }
  var htmlContent = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(content, goog.i18n.bidi.Dir.NEUTRAL);
  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse("script", opt_attributes, htmlContent);
};
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]);
  }
  var htmlContent = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(content, goog.i18n.bidi.Dir.NEUTRAL);
  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse("style", attributes, htmlContent);
};
goog.html.SafeHtml.createMetaRefresh = function(url, opt_secs) {
  var unwrappedUrl = goog.html.SafeUrl.unwrap(goog.html.SafeUrl.sanitize(url));
  if (goog.labs.userAgent.browser.isIE() || goog.labs.userAgent.browser.isEdge()) {
    if (goog.string.contains(unwrappedUrl, ";")) {
      unwrappedUrl = "'" + unwrappedUrl.replace(/'/g, "%27") + "'";
    }
  }
  var attributes = {"http-equiv":"refresh", "content":(opt_secs || 0) + "; url=" + unwrappedUrl};
  return goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse("meta", attributes);
};
goog.html.SafeHtml.getAttrNameAndValue_ = function(tagName, name, value) {
  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)) {
        throw Error('Attribute "' + name + '" requires goog.string.Const value, "' + value + '" given.');
      } 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 {
              if (goog.isString(value)) {
                value = goog.html.SafeUrl.sanitize(value).getTypedStringValue();
              } else {
                throw Error('Attribute "' + name + '" on tag "' + tagName + '" requires goog.html.SafeUrl, goog.string.Const, or string,' + ' value "' + value + '" given.');
              }
            }
          }
        }
      }
    }
  }
  if (value.implementsGoogStringTypedString) {
    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)) + '"';
};
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)) {
    value = goog.html.SafeStyle.create(value);
  }
  return goog.html.SafeStyle.unwrap(value);
};
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;
};
goog.html.SafeHtml.concat = function(var_args) {
  var dir = goog.i18n.bidi.Dir.NEUTRAL;
  var content = "";
  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);
};
goog.html.SafeHtml.concatWithDir = function(dir, var_args) {
  var html = goog.html.SafeHtml.concat(goog.array.slice(arguments, 1));
  html.dir_ = dir;
  return html;
};
goog.html.SafeHtml.TYPE_MARKER_GOOG_HTML_SECURITY_PRIVATE_ = {};
goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse = function(html, dir) {
  return (new goog.html.SafeHtml).initSecurityPrivateDoNotAccessOrElse_(html, dir);
};
goog.html.SafeHtml.prototype.initSecurityPrivateDoNotAccessOrElse_ = function(html, dir) {
  this.privateDoNotAccessOrElseSafeHtmlWrappedValue_ = html;
  this.dir_ = dir;
  return this;
};
goog.html.SafeHtml.createSafeHtmlTagSecurityPrivateDoNotAccessOrElse = function(tagName, opt_attributes, opt_content) {
  var dir = null;
  var result = "<" + tagName;
  result += goog.html.SafeHtml.stringifyAttributes(tagName, opt_attributes);
  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)) {
      dir = goog.i18n.bidi.Dir.NEUTRAL;
    } else {
      dir = null;
    }
  }
  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(result, dir);
};
goog.html.SafeHtml.stringifyAttributes = function(tagName, opt_attributes) {
  var result = "";
  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);
    }
  }
  return result;
};
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;
};
goog.html.SafeHtml.DOCTYPE_HTML = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse("<!DOCTYPE html>", goog.i18n.bidi.Dir.NEUTRAL);
goog.html.SafeHtml.EMPTY = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse("", goog.i18n.bidi.Dir.NEUTRAL);
goog.html.SafeHtml.BR = goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse("<br>", goog.i18n.bidi.Dir.NEUTRAL);
goog.provide("goog.dom.safe");
goog.provide("goog.dom.safe.InsertAdjacentHtmlPosition");
goog.require("goog.asserts");
goog.require("goog.html.SafeHtml");
goog.require("goog.html.SafeScript");
goog.require("goog.html.SafeStyle");
goog.require("goog.html.SafeUrl");
goog.require("goog.html.TrustedResourceUrl");
goog.require("goog.string");
goog.require("goog.string.Const");
goog.dom.safe.InsertAdjacentHtmlPosition = {AFTERBEGIN:"afterbegin", AFTEREND:"afterend", BEFOREBEGIN:"beforebegin", BEFOREEND:"beforeend"};
goog.dom.safe.insertAdjacentHtml = function(node, position, html) {
  node.insertAdjacentHTML(position, goog.html.SafeHtml.unwrap(html));
};
goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_ = {"MATH":true, "SCRIPT":true, "STYLE":true, "SVG":true, "TEMPLATE":true};
goog.dom.safe.setInnerHtml = function(elem, html) {
  if (goog.asserts.ENABLE_ASSERTS) {
    var tagName = elem.tagName.toUpperCase();
    if (goog.dom.safe.SET_INNER_HTML_DISALLOWED_TAGS_[tagName]) {
      throw Error("goog.dom.safe.setInnerHtml cannot be used to set content of " + elem.tagName + ".");
    }
  }
  elem.innerHTML = goog.html.SafeHtml.unwrap(html);
};
goog.dom.safe.setOuterHtml = function(elem, html) {
  elem.outerHTML = goog.html.SafeHtml.unwrap(html);
};
goog.dom.safe.setStyle = function(elem, style) {
  elem.style.cssText = goog.html.SafeStyle.unwrap(style);
};
goog.dom.safe.documentWrite = function(doc, html) {
  doc.write(goog.html.SafeHtml.unwrap(html));
};
goog.dom.safe.setAnchorHref = function(anchor, url) {
  goog.dom.safe.assertIsHTMLAnchorElement_(anchor);
  var safeUrl;
  if (url instanceof goog.html.SafeUrl) {
    safeUrl = url;
  } else {
    safeUrl = goog.html.SafeUrl.sanitize(url);
  }
  anchor.href = goog.html.SafeUrl.unwrap(safeUrl);
};
goog.dom.safe.setImageSrc = function(imageElement, url) {
  goog.dom.safe.assertIsHTMLImageElement_(imageElement);
  var safeUrl;
  if (url instanceof goog.html.SafeUrl) {
    safeUrl = url;
  } else {
    safeUrl = goog.html.SafeUrl.sanitize(url);
  }
  imageElement.src = goog.html.SafeUrl.unwrap(safeUrl);
};
goog.dom.safe.setEmbedSrc = function(embed, url) {
  goog.dom.safe.assertIsHTMLEmbedElement_(embed);
  embed.src = goog.html.TrustedResourceUrl.unwrap(url);
};
goog.dom.safe.setFrameSrc = function(frame, url) {
  goog.dom.safe.assertIsHTMLFrameElement_(frame);
  frame.src = goog.html.TrustedResourceUrl.unwrap(url);
};
goog.dom.safe.setIframeSrc = function(iframe, url) {
  goog.dom.safe.assertIsHTMLIFrameElement_(iframe);
  iframe.src = goog.html.TrustedResourceUrl.unwrap(url);
};
goog.dom.safe.setIframeSrcdoc = function(iframe, html) {
  goog.dom.safe.assertIsHTMLIFrameElement_(iframe);
  iframe.srcdoc = goog.html.SafeHtml.unwrap(html);
};
goog.dom.safe.setLinkHrefAndRel = function(link, url, rel) {
  goog.dom.safe.assertIsHTMLLinkElement_(link);
  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 {
        link.href = goog.html.SafeUrl.sanitize(url).getTypedStringValue();
      }
    }
  }
};
goog.dom.safe.setObjectData = function(object, url) {
  goog.dom.safe.assertIsHTMLObjectElement_(object);
  object.data = goog.html.TrustedResourceUrl.unwrap(url);
};
goog.dom.safe.setScriptSrc = function(script, url) {
  goog.dom.safe.assertIsHTMLScriptElement_(script);
  script.src = goog.html.TrustedResourceUrl.unwrap(url);
};
goog.dom.safe.setScriptContent = function(script, content) {
  goog.dom.safe.assertIsHTMLScriptElement_(script);
  script.text = goog.html.SafeScript.unwrap(content);
};
goog.dom.safe.setLocationHref = function(loc, url) {
  goog.dom.safe.assertIsLocation_(loc);
  var safeUrl;
  if (url instanceof goog.html.SafeUrl) {
    safeUrl = url;
  } else {
    safeUrl = goog.html.SafeUrl.sanitize(url);
  }
  loc.href = goog.html.SafeUrl.unwrap(safeUrl);
};
goog.dom.safe.openInWindow = function(url, opt_openerWin, opt_name, opt_specs, opt_replace) {
  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), opt_name ? goog.string.Const.unwrap(opt_name) : "", opt_specs, opt_replace);
};
goog.dom.safe.assertIsLocation_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof Location != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof Location || !(o instanceof Element)), "Argument is not a Location (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.assertIsHTMLAnchorElement_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof HTMLAnchorElement != "undefined" && typeof Location != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof HTMLAnchorElement || !(o instanceof Location || o instanceof Element)), "Argument is not a HTMLAnchorElement (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.assertIsHTMLLinkElement_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof HTMLLinkElement != "undefined" && typeof Location != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof HTMLLinkElement || !(o instanceof Location || o instanceof Element)), "Argument is not a HTMLLinkElement (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.assertIsHTMLImageElement_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof HTMLImageElement != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof HTMLImageElement || !(o instanceof Element)), "Argument is not a HTMLImageElement (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.assertIsHTMLEmbedElement_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof HTMLEmbedElement != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof HTMLEmbedElement || !(o instanceof Element)), "Argument is not a HTMLEmbedElement (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.assertIsHTMLFrameElement_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof HTMLFrameElement != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof HTMLFrameElement || !(o instanceof Element)), "Argument is not a HTMLFrameElement (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.assertIsHTMLIFrameElement_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof HTMLIFrameElement != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof HTMLIFrameElement || !(o instanceof Element)), "Argument is not a HTMLIFrameElement (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.assertIsHTMLObjectElement_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof HTMLObjectElement != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof HTMLObjectElement || !(o instanceof Element)), "Argument is not a HTMLObjectElement (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.assertIsHTMLScriptElement_ = function(o) {
  if (goog.asserts.ENABLE_ASSERTS && typeof HTMLScriptElement != "undefined" && typeof Element != "undefined") {
    goog.asserts.assert(o && (o instanceof HTMLScriptElement || !(o instanceof Element)), "Argument is not a HTMLScriptElement (or a non-Element mock); got: %s", goog.dom.safe.debugStringForType_(o));
  }
  return o;
};
goog.dom.safe.debugStringForType_ = function(value) {
  if (goog.isObject(value)) {
    return value.constructor.displayName || value.constructor.name || Object.prototype.toString.call(value);
  } else {
    return value === undefined ? "undefined" : value === null ? "null" : typeof value;
  }
};
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");
goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract = function(justification, html, opt_dir) {
  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);
};
goog.html.uncheckedconversions.safeScriptFromStringKnownToSatisfyTypeContract = function(justification, script) {
  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.SafeScript.createSafeScriptSecurityPrivateDoNotAccessOrElse(script);
};
goog.html.uncheckedconversions.safeStyleFromStringKnownToSatisfyTypeContract = function(justification, style) {
  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);
};
goog.html.uncheckedconversions.safeStyleSheetFromStringKnownToSatisfyTypeContract = function(justification, styleSheet) {
  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);
};
goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract = function(justification, url) {
  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);
};
goog.html.uncheckedconversions.trustedResourceUrlFromStringKnownToSatisfyTypeContract = function(justification, url) {
  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);
};
goog.provide("goog.math");
goog.require("goog.array");
goog.require("goog.asserts");
goog.math.randomInt = function(a) {
  return Math.floor(Math.random() * a);
};
goog.math.uniformRandom = function(a, b) {
  return a + Math.random() * (b - a);
};
goog.math.clamp = function(value, min, max) {
  return Math.min(Math.max(value, min), max);
};
goog.math.modulo = function(a, b) {
  var r = a % b;
  return r * b < 0 ? r + b : r;
};
goog.math.lerp = function(a, b, x) {
  return a + x * (b - a);
};
goog.math.nearlyEquals = function(a, b, opt_tolerance) {
  return Math.abs(a - b) <= (opt_tolerance || 0.000001);
};
goog.math.standardAngle = function(angle) {
  return goog.math.modulo(angle, 360);
};
goog.math.standardAngleInRadians = function(angle) {
  return goog.math.modulo(angle, 2 * Math.PI);
};
goog.math.toRadians = function(angleDegrees) {
  return angleDegrees * Math.PI / 180;
};
goog.math.toDegrees = function(angleRadians) {
  return angleRadians * 180 / Math.PI;
};
goog.math.angleDx = function(degrees, radius) {
  return radius * Math.cos(goog.math.toRadians(degrees));
};
goog.math.angleDy = function(degrees, radius) {
  return radius * Math.sin(goog.math.toRadians(degrees));
};
goog.math.angle = function(x1, y1, x2, y2) {
  return goog.math.standardAngle(goog.math.toDegrees(Math.atan2(y2 - y1, x2 - x1)));
};
goog.math.angleDifference = function(startAngle, endAngle) {
  var d = goog.math.standardAngle(endAngle) - goog.math.standardAngle(startAngle);
  if (d > 180) {
    d = d - 360;
  } else {
    if (d <= -180) {
      d = 360 + d;
    }
  }
  return d;
};
goog.math.sign = function(x) {
  if (x > 0) {
    return 1;
  }
  if (x < 0) {
    return -1;
  }
  return x;
};
goog.math.longestCommonSubsequence = function(array1, array2, opt_compareFn, opt_collectorFn) {
  var compare = opt_compareFn || function(a, b) {
    return a == b;
  };
  var collect = opt_collectorFn || function(i1, i2) {
    return array1[i1];
  };
  var length1 = array1.length;
  var length2 = array2.length;
  var arr = [];
  for (var i = 0; i < length1 + 1; i++) {
    arr[i] = [];
    arr[i][0] = 0;
  }
  for (var j = 0; j < length2 + 1; j++) {
    arr[0][j] = 0;
  }
  for (i = 1; i <= length1; i++) {
    for (j = 1; j <= length2; j++) {
      if (compare(array1[i - 1], array2[j - 1])) {
        arr[i][j] = arr[i - 1][j - 1] + 1;
      } else {
        arr[i][j] = Math.max(arr[i - 1][j], arr[i][j - 1]);
      }
    }
  }
  var result = [];
  var i = length1, j = length2;
  while (i > 0 && j > 0) {
    if (compare(array1[i - 1], array2[j - 1])) {
      result.unshift(collect(i - 1, j - 1));
      i--;
      j--;
    } else {
      if (arr[i - 1][j] > arr[i][j - 1]) {
        i--;
      } else {
        j--;
      }
    }
  }
  return result;
};
goog.math.sum = function(var_args) {
  return goog.array.reduce(arguments, function(sum, value) {
    return sum + value;
  }, 0);
};
goog.math.average = function(var_args) {
  return goog.math.sum.apply(null, arguments) / arguments.length;
};
goog.math.sampleVariance = function(var_args) {
  var sampleSize = arguments.length;
  if (sampleSize < 2) {
    return 0;
  }
  var mean = goog.math.average.apply(null, arguments);
  var variance = goog.math.sum.apply(null, goog.array.map(arguments, function(val) {
    return Math.pow(val - mean, 2);
  })) / (sampleSize - 1);
  return variance;
};
goog.math.standardDeviation = function(var_args) {
  return Math.sqrt(goog.math.sampleVariance.apply(null, arguments));
};
goog.math.isInt = function(num) {
  return isFinite(num) && num % 1 == 0;
};
goog.math.isFiniteNumber = function(num) {
  return isFinite(num);
};
goog.math.isNegativeZero = function(num) {
  return num == 0 && 1 / num < 0;
};
goog.math.log10Floor = function(num) {
  if (num > 0) {
    var x = Math.round(Math.log(num) * Math.LOG10E);
    return x - (parseFloat("1e" + x) > num ? 1 : 0);
  }
  return num == 0 ? -Infinity : NaN;
};
goog.math.safeFloor = function(num, opt_epsilon) {
  goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
  return Math.floor(num + (opt_epsilon || 2e-15));
};
goog.math.safeCeil = function(num, opt_epsilon) {
  goog.asserts.assert(!goog.isDef(opt_epsilon) || opt_epsilon > 0);
  return Math.ceil(num - (opt_epsilon || 2e-15));
};
goog.provide("goog.math.Coordinate");
goog.require("goog.math");
goog.math.Coordinate = function(opt_x, opt_y) {
  this.x = goog.isDef(opt_x) ? opt_x : 0;
  this.y = goog.isDef(opt_y) ? opt_y : 0;
};
goog.math.Coordinate.prototype.clone = function() {
  return new goog.math.Coordinate(this.x, this.y);
};
if (goog.DEBUG) {
  goog.math.Coordinate.prototype.toString = function() {
    return "(" + this.x + ", " + this.y + ")";
  };
}
goog.math.Coordinate.prototype.equals = function(other) {
  return other instanceof goog.math.Coordinate && goog.math.Coordinate.equals(this, other);
};
goog.math.Coordinate.equals = function(a, b) {
  if (a == b) {
    return true;
  }
  if (!a || !b) {
    return false;
  }
  return a.x == b.x && a.y == b.y;
};
goog.math.Coordinate.distance = function(a, b) {
  var dx = a.x - b.x;
  var dy = a.y - b.y;
  return Math.sqrt(dx * dx + dy * dy);
};
goog.math.Coordinate.magnitude = function(a) {
  return Math.sqrt(a.x * a.x + a.y * a.y);
};
goog.math.Coordinate.azimuth = function(a) {
  return goog.math.angle(0, 0, a.x, a.y);
};
goog.math.Coordinate.squaredDistance = function(a, b) {
  var dx = a.x - b.x;
  var dy = a.y - b.y;
  return dx * dx + dy * dy;
};
goog.math.Coordinate.difference = function(a, b) {
  return new goog.math.Coordinate(a.x - b.x, a.y - b.y);
};
goog.math.Coordinate.sum = function(a, b) {
  return new goog.math.Coordinate(a.x + b.x, a.y + b.y);
};
goog.math.Coordinate.prototype.ceil = function() {
  this.x = Math.ceil(this.x);
  this.y = Math.ceil(this.y);
  return this;
};
goog.math.Coordinate.prototype.floor = function() {
  this.x = Math.floor(this.x);
  this.y = Math.floor(this.y);
  return this;
};
goog.math.Coordinate.prototype.round = function() {
  this.x = Math.round(this.x);
  this.y = Math.round(this.y);
  return this;
};
goog.math.Coordinate.prototype.translate = function(tx, opt_ty) {
  if (tx instanceof goog.math.Coordinate) {
    this.x += tx.x;
    this.y += tx.y;
  } else {
    this.x += Number(tx);
    if (goog.isNumber(opt_ty)) {
      this.y += opt_ty;
    }
  }
  return this;
};
goog.math.Coordinate.prototype.scale = function(sx, opt_sy) {
  var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
  this.x *= sx;
  this.y *= sy;
  return this;
};
goog.math.Coordinate.prototype.rotateRadians = function(radians, opt_center) {
  var center = opt_center || new goog.math.Coordinate(0, 0);
  var x = this.x;
  var y = this.y;
  var cos = Math.cos(radians);
  var sin = Math.sin(radians);
  this.x = (x - center.x) * cos - (y - center.y) * sin + center.x;
  this.y = (x - center.x) * sin + (y - center.y) * cos + center.y;
};
goog.math.Coordinate.prototype.rotateDegrees = function(degrees, opt_center) {
  this.rotateRadians(goog.math.toRadians(degrees), opt_center);
};
goog.provide("goog.math.Size");
goog.math.Size = function(width, height) {
  this.width = width;
  this.height = height;
};
goog.math.Size.equals = function(a, b) {
  if (a == b) {
    return true;
  }
  if (!a || !b) {
    return false;
  }
  return a.width == b.width && a.height == b.height;
};
goog.math.Size.prototype.clone = function() {
  return new goog.math.Size(this.width, this.height);
};
if (goog.DEBUG) {
  goog.math.Size.prototype.toString = function() {
    return "(" + this.width + " x " + this.height + ")";
  };
}
goog.math.Size.prototype.getLongest = function() {
  return Math.max(this.width, this.height);
};
goog.math.Size.prototype.getShortest = function() {
  return Math.min(this.width, this.height);
};
goog.math.Size.prototype.area = function() {
  return this.width * this.height;
};
goog.math.Size.prototype.perimeter = function() {
  return (this.width + this.height) * 2;
};
goog.math.Size.prototype.aspectRatio = function() {
  return this.width / this.height;
};
goog.math.Size.prototype.isEmpty = function() {
  return !this.area();
};
goog.math.Size.prototype.ceil = function() {
  this.width = Math.ceil(this.width);
  this.height = Math.ceil(this.height);
  return this;
};
goog.math.Size.prototype.fitsInside = function(target) {
  return this.width <= target.width && this.height <= target.height;
};
goog.math.Size.prototype.floor = function() {
  this.width = Math.floor(this.width);
  this.height = Math.floor(this.height);
  return this;
};
goog.math.Size.prototype.round = function() {
  this.width = Math.round(this.width);
  this.height = Math.round(this.height);
  return this;
};
goog.math.Size.prototype.scale = function(sx, opt_sy) {
  var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
  this.width *= sx;
  this.height *= sy;
  return this;
};
goog.math.Size.prototype.scaleToCover = function(target) {
  var s = this.aspectRatio() <= target.aspectRatio() ? target.width / this.width : target.height / this.height;
  return this.scale(s);
};
goog.math.Size.prototype.scaleToFit = function(target) {
  var s = this.aspectRatio() > target.aspectRatio() ? target.width / this.width : target.height / this.height;
  return this.scale(s);
};
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.html.uncheckedconversions");
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");
goog.define("goog.dom.ASSUME_QUIRKS_MODE", false);
goog.define("goog.dom.ASSUME_STANDARDS_MODE", false);
goog.dom.COMPAT_MODE_KNOWN_ = goog.dom.ASSUME_QUIRKS_MODE || goog.dom.ASSUME_STANDARDS_MODE;
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);
};
goog.dom.defaultDomHelper_;
goog.dom.getDocument = function() {
  return document;
};
goog.dom.getElement = function(element) {
  return goog.dom.getElementHelper_(document, element);
};
goog.dom.getElementHelper_ = function(doc, element) {
  return goog.isString(element) ? doc.getElementById(element) : element;
};
goog.dom.getRequiredElement = function(id) {
  return goog.dom.getRequiredElementHelper_(document, id);
};
goog.dom.getRequiredElementHelper_ = function(doc, id) {
  goog.asserts.assertString(id);
  var element = goog.dom.getElementHelper_(doc, id);
  element = goog.asserts.assertElement(element, "No element found with id: " + id);
  return element;
};
goog.dom.$ = goog.dom.getElement;
goog.dom.getElementsByTagName = function(tagName, opt_parent) {
  var parent = opt_parent || document;
  return parent.getElementsByTagName(String(tagName));
};
goog.dom.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {
  return goog.dom.getElementsByTagNameAndClass_(document, opt_tag, opt_class, opt_el);
};
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);
};
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;
};
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);
};
goog.dom.canUseQuerySelector_ = function(parent) {
  return !!(parent.querySelectorAll && parent.querySelector);
};
goog.dom.getElementsByTagNameAndClass_ = function(doc, opt_tag, opt_class, opt_el) {
  var parent = opt_el || doc;
  var tagName = opt_tag && opt_tag != "*" ? String(opt_tag).toUpperCase() : "";
  if (goog.dom.canUseQuerySelector_(parent) && (tagName || opt_class)) {
    var query = tagName + (opt_class ? "." + opt_class : "");
    return parent.querySelectorAll(query);
  }
  if (opt_class && parent.getElementsByClassName) {
    var els = parent.getElementsByClassName(opt_class);
    if (tagName) {
      var arrayLike = {};
      var len = 0;
      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;
      if (typeof className.split == "function" && goog.array.contains(className.split(/\s+/), opt_class)) {
        arrayLike[len++] = el;
      }
    }
    arrayLike.length = len;
    return arrayLike;
  } else {
    return els;
  }
};
goog.dom.$$ = goog.dom.getElementsByTagNameAndClass;
goog.dom.setProperties = function(element, properties) {
  goog.object.forEach(properties, function(val, key) {
    if (val && val.implementsGoogStringTypedString) {
      val = val.getTypedStringValue();
    }
    if (key == "style") {
      element.style.cssText = val;
    } else {
      if (key == "class") {
        element.className = val;
      } else {
        if (key == "for") {
          element.htmlFor = val;
        } else {
          if (goog.dom.DIRECT_ATTRIBUTE_MAP_.hasOwnProperty(key)) {
            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;
            }
          }
        }
      }
    }
  });
};
goog.dom.DIRECT_ATTRIBUTE_MAP_ = {"cellpadding":"cellPadding", "cellspacing":"cellSpacing", "colspan":"colSpan", "frameborder":"frameBorder", "height":"height", "maxlength":"maxLength", "nonce":"nonce", "role":"role", "rowspan":"rowSpan", "type":"type", "usemap":"useMap", "valign":"vAlign", "width":"width"};
goog.dom.getViewportSize = function(opt_window) {
  return goog.dom.getViewportSize_(opt_window || window);
};
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);
};
goog.dom.getDocumentHeight = function() {
  return goog.dom.getDocumentHeight_(window);
};
goog.dom.getDocumentHeightForWindow = function(win) {
  return goog.dom.getDocumentHeight_(win);
};
goog.dom.getDocumentHeight_ = function(win) {
  var doc = win.document;
  var height = 0;
  if (doc) {
    var body = doc.body;
    var docEl = doc.documentElement;
    if (!(docEl && body)) {
      return 0;
    }
    var vh = goog.dom.getViewportSize_(win).height;
    if (goog.dom.isCss1CompatMode_(doc) && docEl.scrollHeight) {
      height = docEl.scrollHeight != vh ? docEl.scrollHeight : docEl.offsetHeight;
    } else {
      var sh = docEl.scrollHeight;
      var oh = docEl.offsetHeight;
      if (docEl.clientHeight != oh) {
        sh = body.scrollHeight;
        oh = body.offsetHeight;
      }
      if (sh > vh) {
        height = sh > oh ? sh : oh;
      } else {
        height = sh < oh ? sh : oh;
      }
    }
  }
  return height;
};
goog.dom.getPageScroll = function(opt_window) {
  var win = opt_window || goog.global || window;
  return goog.dom.getDomHelper(win.document).getDocumentScroll();
};
goog.dom.getDocumentScroll = function() {
  return goog.dom.getDocumentScroll_(document);
};
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) {
    return new goog.math.Coordinate(el.scrollLeft, el.scrollTop);
  }
  return new goog.math.Coordinate(win.pageXOffset || el.scrollLeft, win.pageYOffset || el.scrollTop);
};
goog.dom.getDocumentScrollElement = function() {
  return goog.dom.getDocumentScrollElement_(document);
};
goog.dom.getDocumentScrollElement_ = function(doc) {
  if (doc.scrollingElement) {
    return doc.scrollingElement;
  }
  if (!goog.userAgent.WEBKIT && goog.dom.isCss1CompatMode_(doc)) {
    return doc.documentElement;
  }
  return doc.body || doc.documentElement;
};
goog.dom.getWindow = function(opt_doc) {
  return opt_doc ? goog.dom.getWindow_(opt_doc) : window;
};
goog.dom.getWindow_ = function(doc) {
  return doc.parentWindow || doc.defaultView;
};
goog.dom.createDom = function(tagName, opt_properties, var_args) {
  return goog.dom.createDom_(document, arguments);
};
goog.dom.createDom_ = function(doc, args) {
  var tagName = String(args[0]);
  var attributes = args[1];
  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), '"');
      var clone = {};
      goog.object.extend(clone, attributes);
      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;
};
goog.dom.append_ = function(doc, parent, args, startIndex) {
  function childHandler(child) {
    if (child) {
      parent.appendChild(goog.isString(child) ? doc.createTextNode(child) : child);
    }
  }
  for (var i = startIndex; i < args.length; i++) {
    var arg = args[i];
    if (goog.isArrayLike(arg) && !goog.dom.isNodeLike(arg)) {
      goog.array.forEach(goog.dom.isNodeList(arg) ? goog.array.toArray(arg) : arg, childHandler);
    } else {
      childHandler(arg);
    }
  }
};
goog.dom.$dom = goog.dom.createDom;
goog.dom.createElement = function(name) {
  return goog.dom.createElement_(document, name);
};
goog.dom.createElement_ = function(doc, name) {
  return doc.createElement(String(name));
};
goog.dom.createTextNode = function(content) {
  return document.createTextNode(String(content));
};
goog.dom.createTable = function(rows, columns, opt_fillWithNbsp) {
  return goog.dom.createTable_(document, rows, columns, !!opt_fillWithNbsp);
};
goog.dom.createTable_ = function(doc, rows, columns, fillWithNbsp) {
  var table = goog.dom.createElement_(doc, goog.dom.TagName.TABLE);
  var tbody = table.appendChild(goog.dom.createElement_(doc, goog.dom.TagName.TBODY));
  for (var i = 0; i < rows; i++) {
    var tr = goog.dom.createElement_(doc, goog.dom.TagName.TR);
    for (var j = 0; j < columns; j++) {
      var td = goog.dom.createElement_(doc, goog.dom.TagName.TD);
      if (fillWithNbsp) {
        goog.dom.setTextContent(td, goog.string.Unicode.NBSP);
      }
      tr.appendChild(td);
    }
    tbody.appendChild(tr);
  }
  return table;
};
goog.dom.constHtmlToNode = function(var_args) {
  var stringArray = goog.array.map(arguments, goog.string.Const.unwrap);
  var safeHtml = goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract(goog.string.Const.from("Constant HTML string, that gets turned into a " + "Node later, so it will be automatically balanced."), stringArray.join(""));
  return goog.dom.safeHtmlToNode(safeHtml);
};
goog.dom.safeHtmlToNode = function(html) {
  return goog.dom.safeHtmlToNode_(document, html);
};
goog.dom.safeHtmlToNode_ = function(doc, html) {
  var tempDiv = goog.dom.createElement_(doc, 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.BR, html));
    tempDiv.removeChild(tempDiv.firstChild);
  } else {
    goog.dom.safe.setInnerHtml(tempDiv, html);
  }
  return goog.dom.childrenToNode_(doc, tempDiv);
};
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;
  }
};
goog.dom.isCss1CompatMode = function() {
  return goog.dom.isCss1CompatMode_(document);
};
goog.dom.isCss1CompatMode_ = function(doc) {
  if (goog.dom.COMPAT_MODE_KNOWN_) {
    return goog.dom.ASSUME_STANDARDS_MODE;
  }
  return doc.compatMode == "CSS1Compat";
};
goog.dom.canHaveChildren = function(node) {
  if (node.nodeType != goog.dom.NodeType.ELEMENT) {
    return false;
  }
  switch(node.tagName) {
    case String(goog.dom.TagName.APPLET):
    case String(goog.dom.TagName.AREA):
    case String(goog.dom.TagName.BASE):
    case String(goog.dom.TagName.BR):
    case String(goog.dom.TagName.COL):
    case String(goog.dom.TagName.COMMAND):
    case String(goog.dom.TagName.EMBED):
    case String(goog.dom.TagName.FRAME):
    case String(goog.dom.TagName.HR):
    case String(goog.dom.TagName.IMG):
    case String(goog.dom.TagName.INPUT):
    case String(goog.dom.TagName.IFRAME):
    case String(goog.dom.TagName.ISINDEX):
    case String(goog.dom.TagName.KEYGEN):
    case String(goog.dom.TagName.LINK):
    case String(goog.dom.TagName.NOFRAMES):
    case String(goog.dom.TagName.NOSCRIPT):
    case String(goog.dom.TagName.META):
    case String(goog.dom.TagName.OBJECT):
    case String(goog.dom.TagName.PARAM):
    case String(goog.dom.TagName.SCRIPT):
    case String(goog.dom.TagName.SOURCE):
    case String(goog.dom.TagName.STYLE):
    case String(goog.dom.TagName.TRACK):
    case String(goog.dom.TagName.WBR):
      return false;
  }
  return true;
};
goog.dom.appendChild = function(parent, child) {
  parent.appendChild(child);
};
goog.dom.append = function(parent, var_args) {
  goog.dom.append_(goog.dom.getOwnerDocument(parent), parent, arguments, 1);
};
goog.dom.removeChildren = function(node) {
  var child;
  while (child = node.firstChild) {
    node.removeChild(child);
  }
};
goog.dom.insertSiblingBefore = function(newNode, refNode) {
  if (refNode.parentNode) {
    refNode.parentNode.insertBefore(newNode, refNode);
  }
};
goog.dom.insertSiblingAfter = function(newNode, refNode) {
  if (refNode.parentNode) {
    refNode.parentNode.insertBefore(newNode, refNode.nextSibling);
  }
};
goog.dom.insertChildAt = function(parent, child, index) {
  parent.insertBefore(child, parent.childNodes[index] || null);
};
goog.dom.removeNode = function(node) {
  return node && node.parentNode ? node.parentNode.removeChild(node) : null;
};
goog.dom.replaceNode = function(newNode, oldNode) {
  var parent = oldNode.parentNode;
  if (parent) {
    parent.replaceChild(newNode, oldNode);
  }
};
goog.dom.flattenElement = function(element) {
  var child, parent = element.parentNode;
  if (parent && parent.nodeType != goog.dom.NodeType.DOCUMENT_FRAGMENT) {
    if (element.removeNode) {
      return element.removeNode(false);
    } else {
      while (child = element.firstChild) {
        parent.insertBefore(child, element);
      }
      return goog.dom.removeNode(element);
    }
  }
};
goog.dom.getChildren = function(element) {
  if (goog.dom.BrowserFeature.CAN_USE_CHILDREN_ATTRIBUTE && element.children != undefined) {
    return element.children;
  }
  return goog.array.filter(element.childNodes, function(node) {
    return node.nodeType == goog.dom.NodeType.ELEMENT;
  });
};
goog.dom.getFirstElementChild = function(node) {
  if (goog.isDef(node.firstElementChild)) {
    return node.firstElementChild;
  }
  return goog.dom.getNextElementNode_(node.firstChild, true);
};
goog.dom.getLastElementChild = function(node) {
  if (goog.isDef(node.lastElementChild)) {
    return node.lastElementChild;
  }
  return goog.dom.getNextElementNode_(node.lastChild, false);
};
goog.dom.getNextElementSibling = function(node) {
  if (goog.isDef(node.nextElementSibling)) {
    return node.nextElementSibling;
  }
  return goog.dom.getNextElementNode_(node.nextSibling, true);
};
goog.dom.getPreviousElementSibling = function(node) {
  if (goog.isDef(node.previousElementSibling)) {
    return node.previousElementSibling;
  }
  return goog.dom.getNextElementNode_(node.previousSibling, false);
};
goog.dom.getNextElementNode_ = function(node, forward) {
  while (node && node.nodeType != goog.dom.NodeType.ELEMENT) {
    node = forward ? node.nextSibling : node.previousSibling;
  }
  return 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;
};
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;
};
goog.dom.isNodeLike = function(obj) {
  return goog.isObject(obj) && obj.nodeType > 0;
};
goog.dom.isElement = function(obj) {
  return goog.isObject(obj) && obj.nodeType == goog.dom.NodeType.ELEMENT;
};
goog.dom.isWindow = function(obj) {
  return goog.isObject(obj) && obj["window"] == obj;
};
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");
    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) ? parent : null;
};
goog.dom.contains = function(parent, descendant) {
  if (!parent || !descendant) {
    return false;
  }
  if (parent.contains && descendant.nodeType == goog.dom.NodeType.ELEMENT) {
    return parent == descendant || parent.contains(descendant);
  }
  if (typeof parent.compareDocumentPosition != "undefined") {
    return parent == descendant || Boolean(parent.compareDocumentPosition(descendant) & 16);
  }
  while (descendant && parent != descendant) {
    descendant = descendant.parentNode;
  }
  return descendant == parent;
};
goog.dom.compareNodeOrder = function(node1, node2) {
  if (node1 == node2) {
    return 0;
  }
  if (node1.compareDocumentPosition) {
    return node1.compareDocumentPosition(node2) & 2 ? 1 : -1;
  }
  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;
    }
  }
  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);
    }
  }
  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);
};
goog.dom.compareParentsDescendantNodeIe_ = function(textNode, node) {
  var parent = textNode.parentNode;
  if (parent == node) {
    return -1;
  }
  var sibling = node;
  while (sibling.parentNode != parent) {
    sibling = sibling.parentNode;
  }
  return goog.dom.compareSiblingOrder_(sibling, textNode);
};
goog.dom.compareSiblingOrder_ = function(node1, node2) {
  var s = node2;
  while (s = s.previousSibling) {
    if (s == node1) {
      return -1;
    }
  }
  return 1;
};
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++) {
    var ancestors = [];
    var node = arguments[i];
    while (node) {
      ancestors.unshift(node);
      node = node.parentNode;
    }
    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;
};
goog.dom.getOwnerDocument = function(node) {
  goog.asserts.assert(node, "Node cannot be null or undefined.");
  return node.nodeType == goog.dom.NodeType.DOCUMENT ? node : node.ownerDocument || node.document;
};
goog.dom.getFrameContentDocument = function(frame) {
  return frame.contentDocument || frame.contentWindow.document;
};
goog.dom.getFrameContentWindow = function(frame) {
  try {
    return frame.contentWindow || (frame.contentDocument ? goog.dom.getWindow(frame.contentDocument) : null);
  } catch (e) {
  }
  return null;
};
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) {
        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)));
      }
    }
  }
};
goog.dom.getOuterHtml = function(element) {
  goog.asserts.assert(element !== null, "goog.dom.getOuterHtml expects a non-null value for element");
  if ("outerHTML" in element) {
    return element.outerHTML;
  } else {
    var doc = goog.dom.getOwnerDocument(element);
    var div = goog.dom.createElement_(doc, goog.dom.TagName.DIV);
    div.appendChild(element.cloneNode(true));
    return div.innerHTML;
  }
};
goog.dom.findNode = function(root, p) {
  var rv = [];
  var found = goog.dom.findNodes_(root, p, rv, true);
  return found ? rv[0] : undefined;
};
goog.dom.findNodes = function(root, p) {
  var rv = [];
  goog.dom.findNodes_(root, p, rv, false);
  return rv;
};
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;
};
goog.dom.TAGS_TO_IGNORE_ = {"SCRIPT":1, "STYLE":1, "HEAD":1, "IFRAME":1, "OBJECT":1};
goog.dom.PREDEFINED_TAG_VALUES_ = {"IMG":" ", "BR":"\n"};
goog.dom.isFocusableTabIndex = function(element) {
  return goog.dom.hasSpecifiedTabIndex_(element) && goog.dom.isTabIndexFocusable_(element);
};
goog.dom.setFocusableTabIndex = function(element, enable) {
  if (enable) {
    element.tabIndex = 0;
  } else {
    element.tabIndex = -1;
    element.removeAttribute("tabIndex");
  }
};
goog.dom.isFocusable = function(element) {
  var focusable;
  if (goog.dom.nativelySupportsFocus_(element)) {
    focusable = !element.disabled && (!goog.dom.hasSpecifiedTabIndex_(element) || goog.dom.isTabIndexFocusable_(element));
  } else {
    focusable = goog.dom.isFocusableTabIndex(element);
  }
  return focusable && goog.userAgent.IE ? goog.dom.hasNonZeroBoundingRect_(element) : focusable;
};
goog.dom.hasSpecifiedTabIndex_ = function(element) {
  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("9")) {
    var attrNode = element.getAttributeNode("tabindex");
    return goog.isDefAndNotNull(attrNode) && attrNode.specified;
  } else {
    return element.hasAttribute("tabindex");
  }
};
goog.dom.isTabIndexFocusable_ = function(element) {
  var index = element.tabIndex;
  return goog.isNumber(index) && index >= 0 && index < 32768;
};
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;
};
goog.dom.hasNonZeroBoundingRect_ = function(element) {
  var rect;
  if (!goog.isFunction(element["getBoundingClientRect"]) || goog.userAgent.IE && element.parentElement == null) {
    rect = {"height":element.offsetHeight, "width":element.offsetWidth};
  } else {
    rect = element.getBoundingClientRect();
  }
  return goog.isDefAndNotNull(rect) && rect.height > 0 && rect.width > 0;
};
goog.dom.getTextContent = function(node) {
  var textContent;
  if (goog.dom.BrowserFeature.CAN_USE_INNER_TEXT && node !== null && "innerText" in node) {
    textContent = goog.string.canonicalizeNewlines(node.innerText);
  } else {
    var buf = [];
    goog.dom.getTextContent_(node, buf, true);
    textContent = buf.join("");
  }
  textContent = textContent.replace(/ \xAD /g, " ").replace(/\xAD/g, "");
  textContent = textContent.replace(/\u200B/g, "");
  if (!goog.dom.BrowserFeature.CAN_USE_INNER_TEXT) {
    textContent = textContent.replace(/ +/g, " ");
  }
  if (textContent != " ") {
    textContent = textContent.replace(/^\s*/, "");
  }
  return textContent;
};
goog.dom.getRawTextContent = function(node) {
  var buf = [];
  goog.dom.getTextContent_(node, buf, false);
  return buf.join("");
};
goog.dom.getTextContent_ = function(node, buf, normalizeWhitespace) {
  if (node.nodeName in goog.dom.TAGS_TO_IGNORE_) {
  } 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;
        }
      }
    }
  }
};
goog.dom.getNodeTextLength = function(node) {
  return goog.dom.getTextContent(node).length;
};
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;
  }
  return goog.string.trimLeft(buf.join("")).replace(/ +/g, " ").length;
};
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_) {
    } 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;
};
goog.dom.isNodeList = function(val) {
  if (val && typeof val.length == "number") {
    if (goog.isObject(val)) {
      return typeof val.item == "function" || typeof val.item == "string";
    } else {
      if (goog.isFunction(val)) {
        return typeof val.item == "function";
      }
    }
  }
  return false;
};
goog.dom.getAncestorByTagNameAndClass = function(element, opt_tag, opt_class, opt_maxSearchSteps) {
  if (!opt_tag && !opt_class) {
    return null;
  }
  var tagName = opt_tag ? String(opt_tag).toUpperCase() : null;
  return 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);
};
goog.dom.getAncestorByClass = function(element, className, opt_maxSearchSteps) {
  return goog.dom.getAncestorByTagNameAndClass(element, null, className, opt_maxSearchSteps);
};
goog.dom.getAncestor = function(element, matcher, opt_includeNode, opt_maxSearchSteps) {
  if (element && !opt_includeNode) {
    element = element.parentNode;
  }
  var steps = 0;
  while (element && (opt_maxSearchSteps == null || steps <= opt_maxSearchSteps)) {
    goog.asserts.assert(element.name != "parentNode");
    if (matcher(element)) {
      return element;
    }
    element = element.parentNode;
    steps++;
  }
  return null;
};
goog.dom.getActiveElement = function(doc) {
  try {
    return doc && doc.activeElement;
  } catch (e) {
  }
  return null;
};
goog.dom.getPixelRatio = function() {
  var win = goog.dom.getWindow();
  if (goog.isDef(win.devicePixelRatio)) {
    return win.devicePixelRatio;
  } else {
    if (win.matchMedia) {
      return goog.dom.matchesPixelRatio_(3) || goog.dom.matchesPixelRatio_(2) || goog.dom.matchesPixelRatio_(1.5) || goog.dom.matchesPixelRatio_(1) || .75;
    }
  }
  return 1;
};
goog.dom.matchesPixelRatio_ = function(pixelRatio) {
  var win = goog.dom.getWindow();
  var dpiPerDppx = 96;
  var query = "(min-resolution: " + pixelRatio + "dppx)," + "(min--moz-device-pixel-ratio: " + pixelRatio + ")," + "(min-resolution: " + pixelRatio * dpiPerDppx + "dpi)";
  return win.matchMedia(query).matches ? pixelRatio : 0;
};
goog.dom.getCanvasContext2D = function(canvas) {
  return canvas.getContext("2d");
};
goog.dom.DomHelper = function(opt_document) {
  this.document_ = opt_document || goog.global.document || document;
};
goog.dom.DomHelper.prototype.getDomHelper = goog.dom.getDomHelper;
goog.dom.DomHelper.prototype.setDocument = function(document) {
  this.document_ = document;
};
goog.dom.DomHelper.prototype.getDocument = function() {
  return this.document_;
};
goog.dom.DomHelper.prototype.getElement = function(element) {
  return goog.dom.getElementHelper_(this.document_, element);
};
goog.dom.DomHelper.prototype.getRequiredElement = function(id) {
  return goog.dom.getRequiredElementHelper_(this.document_, id);
};
goog.dom.DomHelper.prototype.$ = goog.dom.DomHelper.prototype.getElement;
goog.dom.DomHelper.prototype.getElementsByTagName = function(tagName, opt_parent) {
  var parent = opt_parent || this.document_;
  return parent.getElementsByTagName(String(tagName));
};
goog.dom.DomHelper.prototype.getElementsByTagNameAndClass = function(opt_tag, opt_class, opt_el) {
  return goog.dom.getElementsByTagNameAndClass_(this.document_, opt_tag, opt_class, opt_el);
};
goog.dom.DomHelper.prototype.getElementsByClass = function(className, opt_el) {
  var doc = opt_el || this.document_;
  return goog.dom.getElementsByClass(className, doc);
};
goog.dom.DomHelper.prototype.getElementByClass = function(className, opt_el) {
  var doc = opt_el || this.document_;
  return goog.dom.getElementByClass(className, doc);
};
goog.dom.DomHelper.prototype.getRequiredElementByClass = function(className, opt_root) {
  var root = opt_root || this.document_;
  return goog.dom.getRequiredElementByClass(className, root);
};
goog.dom.DomHelper.prototype.$$ = goog.dom.DomHelper.prototype.getElementsByTagNameAndClass;
goog.dom.DomHelper.prototype.setProperties = goog.dom.setProperties;
goog.dom.DomHelper.prototype.getViewportSize = function(opt_window) {
  return goog.dom.getViewportSize(opt_window || this.getWindow());
};
goog.dom.DomHelper.prototype.getDocumentHeight = function() {
  return goog.dom.getDocumentHeight_(this.getWindow());
};
goog.dom.Appendable;
goog.dom.DomHelper.prototype.createDom = function(tagName, opt_attributes, var_args) {
  return goog.dom.createDom_(this.document_, arguments);
};
goog.dom.DomHelper.prototype.$dom = goog.dom.DomHelper.prototype.createDom;
goog.dom.DomHelper.prototype.createElement = function(name) {
  return goog.dom.createElement_(this.document_, name);
};
goog.dom.DomHelper.prototype.createTextNode = function(content) {
  return this.document_.createTextNode(String(content));
};
goog.dom.DomHelper.prototype.createTable = function(rows, columns, opt_fillWithNbsp) {
  return goog.dom.createTable_(this.document_, rows, columns, !!opt_fillWithNbsp);
};
goog.dom.DomHelper.prototype.safeHtmlToNode = function(html) {
  return goog.dom.safeHtmlToNode_(this.document_, html);
};
goog.dom.DomHelper.prototype.isCss1CompatMode = function() {
  return goog.dom.isCss1CompatMode_(this.document_);
};
goog.dom.DomHelper.prototype.getWindow = function() {
  return goog.dom.getWindow_(this.document_);
};
goog.dom.DomHelper.prototype.getDocumentScrollElement = function() {
  return goog.dom.getDocumentScrollElement_(this.document_);
};
goog.dom.DomHelper.prototype.getDocumentScroll = function() {
  return goog.dom.getDocumentScroll_(this.document_);
};
goog.dom.DomHelper.prototype.getActiveElement = function(opt_doc) {
  return goog.dom.getActiveElement(opt_doc || this.document_);
};
goog.dom.DomHelper.prototype.appendChild = goog.dom.appendChild;
goog.dom.DomHelper.prototype.append = goog.dom.append;
goog.dom.DomHelper.prototype.canHaveChildren = goog.dom.canHaveChildren;
goog.dom.DomHelper.prototype.removeChildren = goog.dom.removeChildren;
goog.dom.DomHelper.prototype.insertSiblingBefore = goog.dom.insertSiblingBefore;
goog.dom.DomHelper.prototype.insertSiblingAfter = goog.dom.insertSiblingAfter;
goog.dom.DomHelper.prototype.insertChildAt = goog.dom.insertChildAt;
goog.dom.DomHelper.prototype.removeNode = goog.dom.removeNode;
goog.dom.DomHelper.prototype.replaceNode = goog.dom.replaceNode;
goog.dom.DomHelper.prototype.flattenElement = goog.dom.flattenElement;
goog.dom.DomHelper.prototype.getChildren = goog.dom.getChildren;
goog.dom.DomHelper.prototype.getFirstElementChild = goog.dom.getFirstElementChild;
goog.dom.DomHelper.prototype.getLastElementChild = goog.dom.getLastElementChild;
goog.dom.DomHelper.prototype.getNextElementSibling = goog.dom.getNextElementSibling;
goog.dom.DomHelper.prototype.getPreviousElementSibling = goog.dom.getPreviousElementSibling;
goog.dom.DomHelper.prototype.getNextNode = goog.dom.getNextNode;
goog.dom.DomHelper.prototype.getPreviousNode = goog.dom.getPreviousNode;
goog.dom.DomHelper.prototype.isNodeLike = goog.dom.isNodeLike;
goog.dom.DomHelper.prototype.isElement = goog.dom.isElement;
goog.dom.DomHelper.prototype.isWindow = goog.dom.isWindow;
goog.dom.DomHelper.prototype.getParentElement = goog.dom.getParentElement;
goog.dom.DomHelper.prototype.contains = goog.dom.contains;
goog.dom.DomHelper.prototype.compareNodeOrder = goog.dom.compareNodeOrder;
goog.dom.DomHelper.prototype.findCommonAncestor = goog.dom.findCommonAncestor;
goog.dom.DomHelper.prototype.getOwnerDocument = goog.dom.getOwnerDocument;
goog.dom.DomHelper.prototype.getFrameContentDocument = goog.dom.getFrameContentDocument;
goog.dom.DomHelper.prototype.getFrameContentWindow = goog.dom.getFrameContentWindow;
goog.dom.DomHelper.prototype.setTextContent = goog.dom.setTextContent;
goog.dom.DomHelper.prototype.getOuterHtml = goog.dom.getOuterHtml;
goog.dom.DomHelper.prototype.findNode = goog.dom.findNode;
goog.dom.DomHelper.prototype.findNodes = goog.dom.findNodes;
goog.dom.DomHelper.prototype.isFocusableTabIndex = goog.dom.isFocusableTabIndex;
goog.dom.DomHelper.prototype.setFocusableTabIndex = goog.dom.setFocusableTabIndex;
goog.dom.DomHelper.prototype.isFocusable = goog.dom.isFocusable;
goog.dom.DomHelper.prototype.getTextContent = goog.dom.getTextContent;
goog.dom.DomHelper.prototype.getNodeTextLength = goog.dom.getNodeTextLength;
goog.dom.DomHelper.prototype.getNodeTextOffset = goog.dom.getNodeTextOffset;
goog.dom.DomHelper.prototype.getNodeAtOffset = goog.dom.getNodeAtOffset;
goog.dom.DomHelper.prototype.isNodeList = goog.dom.isNodeList;
goog.dom.DomHelper.prototype.getAncestorByTagNameAndClass = goog.dom.getAncestorByTagNameAndClass;
goog.dom.DomHelper.prototype.getAncestorByClass = goog.dom.getAncestorByClass;
goog.dom.DomHelper.prototype.getAncestor = goog.dom.getAncestor;
goog.dom.DomHelper.prototype.getCanvasContext2D = goog.dom.getCanvasContext2D;
goog.provide("goog.dom.classlist");
goog.require("goog.array");
goog.define("goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST", false);
goog.dom.classlist.get = function(element) {
  if (goog.dom.classlist.ALWAYS_USE_DOM_TOKEN_LIST || element.classList) {
    return element.classList;
  }
  var className = element.className;
  return goog.isString(className) && className.match(/\S+/g) || [];
};
goog.dom.classlist.set = function(element, className) {
  element.className = className;
};
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);
};
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)) {
    element.className += element.className.length > 0 ? " " + className : className;
  }
};
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 = {};
  goog.array.forEach(goog.dom.classlist.get(element), function(className) {
    classMap[className] = true;
  });
  goog.array.forEach(classesToAdd, function(className) {
    classMap[className] = true;
  });
  element.className = "";
  for (var className in classMap) {
    element.className += element.className.length > 0 ? " " + className : className;
  }
};
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)) {
    element.className = goog.array.filter(goog.dom.classlist.get(element), function(c) {
      return c != className;
    }).join(" ");
  }
};
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;
  }
  element.className = goog.array.filter(goog.dom.classlist.get(element), function(className) {
    return !goog.array.contains(classesToRemove, className);
  }).join(" ");
};
goog.dom.classlist.enable = function(element, className, enabled) {
  if (enabled) {
    goog.dom.classlist.add(element, className);
  } else {
    goog.dom.classlist.remove(element, className);
  }
};
goog.dom.classlist.enableAll = function(element, classesToEnable, enabled) {
  var f = enabled ? goog.dom.classlist.addAll : goog.dom.classlist.removeAll;
  f(element, classesToEnable);
};
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;
};
goog.dom.classlist.toggle = function(element, className) {
  var add = !goog.dom.classlist.contains(element, className);
  goog.dom.classlist.enable(element, className, add);
  return add;
};
goog.dom.classlist.addRemove = function(element, classToRemove, classToAdd) {
  goog.dom.classlist.remove(element, classToRemove);
  goog.dom.classlist.add(element, classToAdd);
};
goog.provide("goog.dom.vendor");
goog.require("goog.string");
goog.require("goog.userAgent");
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;
};
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;
};
goog.dom.vendor.getPrefixedPropertyName = function(propertyName, opt_object) {
  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;
};
goog.dom.vendor.getPrefixedEventType = function(eventType) {
  var prefix = goog.dom.vendor.getVendorJsPrefix() || "";
  return (prefix + eventType).toLowerCase();
};
goog.provide("goog.html.legacyconversions");
goog.require("goog.html.SafeHtml");
goog.require("goog.html.SafeStyle");
goog.require("goog.html.SafeStyleSheet");
goog.require("goog.html.SafeUrl");
goog.require("goog.html.TrustedResourceUrl");
goog.html.legacyconversions.safeHtmlFromString = function(html) {
  goog.html.legacyconversions.reportCallback_();
  return goog.html.SafeHtml.createSafeHtmlSecurityPrivateDoNotAccessOrElse(html, null);
};
goog.html.legacyconversions.safeStyleFromString = function(style) {
  goog.html.legacyconversions.reportCallback_();
  return goog.html.SafeStyle.createSafeStyleSecurityPrivateDoNotAccessOrElse(style);
};
goog.html.legacyconversions.safeStyleSheetFromString = function(styleSheet) {
  goog.html.legacyconversions.reportCallback_();
  return goog.html.SafeStyleSheet.createSafeStyleSheetSecurityPrivateDoNotAccessOrElse(styleSheet);
};
goog.html.legacyconversions.safeUrlFromString = function(url) {
  goog.html.legacyconversions.reportCallback_();
  return goog.html.SafeUrl.createSafeUrlSecurityPrivateDoNotAccessOrElse(url);
};
goog.html.legacyconversions.trustedResourceUrlFromString = function(url) {
  goog.html.legacyconversions.reportCallback_();
  return goog.html.TrustedResourceUrl.createTrustedResourceUrlSecurityPrivateDoNotAccessOrElse(url);
};
goog.html.legacyconversions.reportCallback_ = goog.nullFunction;
goog.html.legacyconversions.setReportCallback = function(callback) {
  goog.html.legacyconversions.reportCallback_ = callback;
};
goog.provide("goog.math.Box");
goog.require("goog.asserts");
goog.require("goog.math.Coordinate");
goog.math.Box = function(top, right, bottom, left) {
  this.top = top;
  this.right = right;
  this.bottom = bottom;
  this.left = left;
};
goog.math.Box.boundingBox = function(var_args) {
  var box = new goog.math.Box(arguments[0].y, arguments[0].x, arguments[0].y, arguments[0].x);
  for (var i = 1; i < arguments.length; i++) {
    box.expandToIncludeCoordinate(arguments[i]);
  }
  return box;
};
goog.math.Box.prototype.getWidth = function() {
  return this.right - this.left;
};
goog.math.Box.prototype.getHeight = function() {
  return this.bottom - this.top;
};
goog.math.Box.prototype.clone = function() {
  return new goog.math.Box(this.top, this.right, this.bottom, this.left);
};
if (goog.DEBUG) {
  goog.math.Box.prototype.toString = function() {
    return "(" + this.top + "t, " + this.right + "r, " + this.bottom + "b, " + this.left + "l)";
  };
}
goog.math.Box.prototype.contains = function(other) {
  return goog.math.Box.contains(this, other);
};
goog.math.Box.prototype.expand = function(top, opt_right, opt_bottom, opt_left) {
  if (goog.isObject(top)) {
    this.top -= top.top;
    this.right += top.right;
    this.bottom += top.bottom;
    this.left -= top.left;
  } else {
    this.top -= top;
    this.right += Number(opt_right);
    this.bottom += Number(opt_bottom);
    this.left -= Number(opt_left);
  }
  return this;
};
goog.math.Box.prototype.expandToInclude = function(box) {
  this.left = Math.min(this.left, box.left);
  this.top = Math.min(this.top, box.top);
  this.right = Math.max(this.right, box.right);
  this.bottom = Math.max(this.bottom, box.bottom);
};
goog.math.Box.prototype.expandToIncludeCoordinate = function(coord) {
  this.top = Math.min(this.top, coord.y);
  this.right = Math.max(this.right, coord.x);
  this.bottom = Math.max(this.bottom, coord.y);
  this.left = Math.min(this.left, coord.x);
};
goog.math.Box.equals = function(a, b) {
  if (a == b) {
    return true;
  }
  if (!a || !b) {
    return false;
  }
  return a.top == b.top && a.right == b.right && a.bottom == b.bottom && a.left == b.left;
};
goog.math.Box.contains = function(box, other) {
  if (!box || !other) {
    return false;
  }
  if (other instanceof goog.math.Box) {
    return other.left >= box.left && other.right <= box.right && other.top >= box.top && other.bottom <= box.bottom;
  }
  return other.x >= box.left && other.x <= box.right && other.y >= box.top && other.y <= box.bottom;
};
goog.math.Box.relativePositionX = function(box, coord) {
  if (coord.x < box.left) {
    return coord.x - box.left;
  } else {
    if (coord.x > box.right) {
      return coord.x - box.right;
    }
  }
  return 0;
};
goog.math.Box.relativePositionY = function(box, coord) {
  if (coord.y < box.top) {
    return coord.y - box.top;
  } else {
    if (coord.y > box.bottom) {
      return coord.y - box.bottom;
    }
  }
  return 0;
};
goog.math.Box.distance = function(box, coord) {
  var x = goog.math.Box.relativePositionX(box, coord);
  var y = goog.math.Box.relativePositionY(box, coord);
  return Math.sqrt(x * x + y * y);
};
goog.math.Box.intersects = function(a, b) {
  return a.left <= b.right && b.left <= a.right && a.top <= b.bottom && b.top <= a.bottom;
};
goog.math.Box.intersectsWithPadding = function(a, b, padding) {
  return a.left <= b.right + padding && b.left <= a.right + padding && a.top <= b.bottom + padding && b.top <= a.bottom + padding;
};
goog.math.Box.prototype.ceil = function() {
  this.top = Math.ceil(this.top);
  this.right = Math.ceil(this.right);
  this.bottom = Math.ceil(this.bottom);
  this.left = Math.ceil(this.left);
  return this;
};
goog.math.Box.prototype.floor = function() {
  this.top = Math.floor(this.top);
  this.right = Math.floor(this.right);
  this.bottom = Math.floor(this.bottom);
  this.left = Math.floor(this.left);
  return this;
};
goog.math.Box.prototype.round = function() {
  this.top = Math.round(this.top);
  this.right = Math.round(this.right);
  this.bottom = Math.round(this.bottom);
  this.left = Math.round(this.left);
  return this;
};
goog.math.Box.prototype.translate = function(tx, opt_ty) {
  if (tx instanceof goog.math.Coordinate) {
    this.left += tx.x;
    this.right += tx.x;
    this.top += tx.y;
    this.bottom += tx.y;
  } else {
    goog.asserts.assertNumber(tx);
    this.left += tx;
    this.right += tx;
    if (goog.isNumber(opt_ty)) {
      this.top += opt_ty;
      this.bottom += opt_ty;
    }
  }
  return this;
};
goog.math.Box.prototype.scale = function(sx, opt_sy) {
  var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
  this.left *= sx;
  this.right *= sx;
  this.top *= sy;
  this.bottom *= sy;
  return this;
};
goog.provide("goog.math.IRect");
goog.math.IRect = function() {
};
goog.math.IRect.prototype.left;
goog.math.IRect.prototype.top;
goog.math.IRect.prototype.width;
goog.math.IRect.prototype.height;
goog.provide("goog.math.Rect");
goog.require("goog.asserts");
goog.require("goog.math.Box");
goog.require("goog.math.Coordinate");
goog.require("goog.math.IRect");
goog.require("goog.math.Size");
goog.math.Rect = function(x, y, w, h) {
  this.left = x;
  this.top = y;
  this.width = w;
  this.height = h;
};
goog.math.Rect.prototype.clone = function() {
  return new goog.math.Rect(this.left, this.top, this.width, this.height);
};
goog.math.Rect.prototype.toBox = function() {
  var right = this.left + this.width;
  var bottom = this.top + this.height;
  return new goog.math.Box(this.top, right, bottom, this.left);
};
goog.math.Rect.createFromPositionAndSize = function(position, size) {
  return new goog.math.Rect(position.x, position.y, size.width, size.height);
};
goog.math.Rect.createFromBox = function(box) {
  return new goog.math.Rect(box.left, box.top, box.right - box.left, box.bottom - box.top);
};
if (goog.DEBUG) {
  goog.math.Rect.prototype.toString = function() {
    return "(" + this.left + ", " + this.top + " - " + this.width + "w x " + this.height + "h)";
  };
}
goog.math.Rect.equals = function(a, b) {
  if (a == b) {
    return true;
  }
  if (!a || !b) {
    return false;
  }
  return a.left == b.left && a.width == b.width && a.top == b.top && a.height == b.height;
};
goog.math.Rect.prototype.intersection = function(rect) {
  var x0 = Math.max(this.left, rect.left);
  var x1 = Math.min(this.left + this.width, rect.left + rect.width);
  if (x0 <= x1) {
    var y0 = Math.max(this.top, rect.top);
    var y1 = Math.min(this.top + this.height, rect.top + rect.height);
    if (y0 <= y1) {
      this.left = x0;
      this.top = y0;
      this.width = x1 - x0;
      this.height = y1 - y0;
      return true;
    }
  }
  return false;
};
goog.math.Rect.intersection = function(a, b) {
  var x0 = Math.max(a.left, b.left);
  var x1 = Math.min(a.left + a.width, b.left + b.width);
  if (x0 <= x1) {
    var y0 = Math.max(a.top, b.top);
    var y1 = Math.min(a.top + a.height, b.top + b.height);
    if (y0 <= y1) {
      return new goog.math.Rect(x0, y0, x1 - x0, y1 - y0);
    }
  }
  return null;
};
goog.math.Rect.intersects = function(a, b) {
  return a.left <= b.left + b.width && b.left <= a.left + a.width && a.top <= b.top + b.height && b.top <= a.top + a.height;
};
goog.math.Rect.prototype.intersects = function(rect) {
  return goog.math.Rect.intersects(this, rect);
};
goog.math.Rect.difference = function(a, b) {
  var intersection = goog.math.Rect.intersection(a, b);
  if (!intersection || !intersection.height || !intersection.width) {
    return [a.clone()];
  }
  var result = [];
  var top = a.top;
  var height = a.height;
  var ar = a.left + a.width;
  var ab = a.top + a.height;
  var br = b.left + b.width;
  var bb = b.top + b.height;
  if (b.top > a.top) {
    result.push(new goog.math.Rect(a.left, a.top, a.width, b.top - a.top));
    top = b.top;
    height -= b.top - a.top;
  }
  if (bb < ab) {
    result.push(new goog.math.Rect(a.left, bb, a.width, ab - bb));
    height = bb - top;
  }
  if (b.left > a.left) {
    result.push(new goog.math.Rect(a.left, top, b.left - a.left, height));
  }
  if (br < ar) {
    result.push(new goog.math.Rect(br, top, ar - br, height));
  }
  return result;
};
goog.math.Rect.prototype.difference = function(rect) {
  return goog.math.Rect.difference(this, rect);
};
goog.math.Rect.prototype.boundingRect = function(rect) {
  var right = Math.max(this.left + this.width, rect.left + rect.width);
  var bottom = Math.max(this.top + this.height, rect.top + rect.height);
  this.left = Math.min(this.left, rect.left);
  this.top = Math.min(this.top, rect.top);
  this.width = right - this.left;
  this.height = bottom - this.top;
};
goog.math.Rect.boundingRect = function(a, b) {
  if (!a || !b) {
    return null;
  }
  var newRect = new goog.math.Rect(a.left, a.top, a.width, a.height);
  newRect.boundingRect(b);
  return newRect;
};
goog.math.Rect.prototype.contains = function(another) {
  if (another instanceof goog.math.Coordinate) {
    return another.x >= this.left && another.x <= this.left + this.width && another.y >= this.top && another.y <= this.top + this.height;
  } else {
    return this.left <= another.left && this.left + this.width >= another.left + another.width && this.top <= another.top && this.top + this.height >= another.top + another.height;
  }
};
goog.math.Rect.prototype.squaredDistance = function(point) {
  var dx = point.x < this.left ? this.left - point.x : Math.max(point.x - (this.left + this.width), 0);
  var dy = point.y < this.top ? this.top - point.y : Math.max(point.y - (this.top + this.height), 0);
  return dx * dx + dy * dy;
};
goog.math.Rect.prototype.distance = function(point) {
  return Math.sqrt(this.squaredDistance(point));
};
goog.math.Rect.prototype.getSize = function() {
  return new goog.math.Size(this.width, this.height);
};
goog.math.Rect.prototype.getTopLeft = function() {
  return new goog.math.Coordinate(this.left, this.top);
};
goog.math.Rect.prototype.getCenter = function() {
  return new goog.math.Coordinate(this.left + this.width / 2, this.top + this.height / 2);
};
goog.math.Rect.prototype.getBottomRight = function() {
  return new goog.math.Coordinate(this.left + this.width, this.top + this.height);
};
goog.math.Rect.prototype.ceil = function() {
  this.left = Math.ceil(this.left);
  this.top = Math.ceil(this.top);
  this.width = Math.ceil(this.width);
  this.height = Math.ceil(this.height);
  return this;
};
goog.math.Rect.prototype.floor = function() {
  this.left = Math.floor(this.left);
  this.top = Math.floor(this.top);
  this.width = Math.floor(this.width);
  this.height = Math.floor(this.height);
  return this;
};
goog.math.Rect.prototype.round = function() {
  this.left = Math.round(this.left);
  this.top = Math.round(this.top);
  this.width = Math.round(this.width);
  this.height = Math.round(this.height);
  return this;
};
goog.math.Rect.prototype.translate = function(tx, opt_ty) {
  if (tx instanceof goog.math.Coordinate) {
    this.left += tx.x;
    this.top += tx.y;
  } else {
    this.left += goog.asserts.assertNumber(tx);
    if (goog.isNumber(opt_ty)) {
      this.top += opt_ty;
    }
  }
  return this;
};
goog.math.Rect.prototype.scale = function(sx, opt_sy) {
  var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
  this.left *= sx;
  this.width *= sx;
  this.top *= sy;
  this.height *= sy;
  return this;
};
goog.provide("goog.style");
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.vendor");
goog.require("goog.html.SafeStyleSheet");
goog.require("goog.html.legacyconversions");
goog.require("goog.math.Box");
goog.require("goog.math.Coordinate");
goog.require("goog.math.Rect");
goog.require("goog.math.Size");
goog.require("goog.object");
goog.require("goog.reflect");
goog.require("goog.string");
goog.require("goog.userAgent");
goog.forwardDeclare("goog.events.Event");
goog.style.setStyle = function(element, style, opt_value) {
  if (goog.isString(style)) {
    goog.style.setStyle_(element, opt_value, style);
  } else {
    for (var key in style) {
      goog.style.setStyle_(element, style[key], key);
    }
  }
};
goog.style.setStyle_ = function(element, value, style) {
  var propertyName = goog.style.getVendorJsStyleName_(element, style);
  if (propertyName) {
    element.style[propertyName] = value;
  }
};
goog.style.styleNameCache_ = {};
goog.style.getVendorJsStyleName_ = function(element, style) {
  var propertyName = goog.style.styleNameCache_[style];
  if (!propertyName) {
    var camelStyle = goog.string.toCamelCase(style);
    propertyName = camelStyle;
    if (element.style[camelStyle] === undefined) {
      var prefixedStyle = goog.dom.vendor.getVendorJsPrefix() + goog.string.toTitleCase(camelStyle);
      if (element.style[prefixedStyle] !== undefined) {
        propertyName = prefixedStyle;
      }
    }
    goog.style.styleNameCache_[style] = propertyName;
  }
  return propertyName;
};
goog.style.getVendorStyleName_ = function(element, style) {
  var camelStyle = goog.string.toCamelCase(style);
  if (element.style[camelStyle] === undefined) {
    var prefixedStyle = goog.dom.vendor.getVendorJsPrefix() + goog.string.toTitleCase(camelStyle);
    if (element.style[prefixedStyle] !== undefined) {
      return goog.dom.vendor.getVendorPrefix() + "-" + style;
    }
  }
  return style;
};
goog.style.getStyle = function(element, property) {
  var styleValue = element.style[goog.string.toCamelCase(property)];
  if (typeof styleValue !== "undefined") {
    return styleValue;
  }
  return element.style[goog.style.getVendorJsStyleName_(element, property)] || "";
};
goog.style.getComputedStyle = function(element, property) {
  var doc = goog.dom.getOwnerDocument(element);
  if (doc.defaultView && doc.defaultView.getComputedStyle) {
    var styles = doc.defaultView.getComputedStyle(element, null);
    if (styles) {
      return styles[property] || styles.getPropertyValue(property) || "";
    }
  }
  return "";
};
goog.style.getCascadedStyle = function(element, style) {
  return element.currentStyle ? element.currentStyle[style] : null;
};
goog.style.getStyle_ = function(element, style) {
  return goog.style.getComputedStyle(element, style) || goog.style.getCascadedStyle(element, style) || element.style && element.style[style];
};
goog.style.getComputedBoxSizing = function(element) {
  return goog.style.getStyle_(element, "boxSizing") || goog.style.getStyle_(element, "MozBoxSizing") || goog.style.getStyle_(element, "WebkitBoxSizing") || null;
};
goog.style.getComputedPosition = function(element) {
  return goog.style.getStyle_(element, "position");
};
goog.style.getBackgroundColor = function(element) {
  return goog.style.getStyle_(element, "backgroundColor");
};
goog.style.getComputedOverflowX = function(element) {
  return goog.style.getStyle_(element, "overflowX");
};
goog.style.getComputedOverflowY = function(element) {
  return goog.style.getStyle_(element, "overflowY");
};
goog.style.getComputedZIndex = function(element) {
  return goog.style.getStyle_(element, "zIndex");
};
goog.style.getComputedTextAlign = function(element) {
  return goog.style.getStyle_(element, "textAlign");
};
goog.style.getComputedCursor = function(element) {
  return goog.style.getStyle_(element, "cursor");
};
goog.style.getComputedTransform = function(element) {
  var property = goog.style.getVendorStyleName_(element, "transform");
  return goog.style.getStyle_(element, property) || goog.style.getStyle_(element, "transform");
};
goog.style.setPosition = function(el, arg1, opt_arg2) {
  var x, y;
  if (arg1 instanceof goog.math.Coordinate) {
    x = arg1.x;
    y = arg1.y;
  } else {
    x = arg1;
    y = opt_arg2;
  }
  el.style.left = goog.style.getPixelStyleValue_(x, false);
  el.style.top = goog.style.getPixelStyleValue_(y, false);
};
goog.style.getPosition = function(element) {
  return new goog.math.Coordinate(element.offsetLeft, element.offsetTop);
};
goog.style.getClientViewportElement = function(opt_node) {
  var doc;
  if (opt_node) {
    doc = goog.dom.getOwnerDocument(opt_node);
  } else {
    doc = goog.dom.getDocument();
  }
  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) && !goog.dom.getDomHelper(doc).isCss1CompatMode()) {
    return doc.body;
  }
  return doc.documentElement;
};
goog.style.getViewportPageOffset = function(doc) {
  var body = doc.body;
  var documentElement = doc.documentElement;
  var scrollLeft = body.scrollLeft || documentElement.scrollLeft;
  var scrollTop = body.scrollTop || documentElement.scrollTop;
  return new goog.math.Coordinate(scrollLeft, scrollTop);
};
goog.style.getBoundingClientRect_ = function(el) {
  var rect;
  try {
    rect = el.getBoundingClientRect();
  } catch (e) {
    return {"left":0, "top":0, "right":0, "bottom":0};
  }
  if (goog.userAgent.IE && el.ownerDocument.body) {
    var doc = el.ownerDocument;
    rect.left -= doc.documentElement.clientLeft + doc.body.clientLeft;
    rect.top -= doc.documentElement.clientTop + doc.body.clientTop;
  }
  return rect;
};
goog.style.getOffsetParent = function(element) {
  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(8)) {
    goog.asserts.assert(element && "offsetParent" in element);
    return element.offsetParent;
  }
  var doc = goog.dom.getOwnerDocument(element);
  var positionStyle = goog.style.getStyle_(element, "position");
  var skipStatic = positionStyle == "fixed" || positionStyle == "absolute";
  for (var parent = element.parentNode; parent && parent != doc; parent = parent.parentNode) {
    if (parent.nodeType == goog.dom.NodeType.DOCUMENT_FRAGMENT && parent.host) {
      parent = parent.host;
    }
    positionStyle = goog.style.getStyle_(parent, "position");
    skipStatic = skipStatic && positionStyle == "static" && parent != doc.documentElement && parent != doc.body;
    if (!skipStatic && (parent.scrollWidth > parent.clientWidth || parent.scrollHeight > parent.clientHeight || positionStyle == "fixed" || positionStyle == "absolute" || positionStyle == "relative")) {
      return parent;
    }
  }
  return null;
};
goog.style.getVisibleRectForElement = function(element) {
  var visibleRect = new goog.math.Box(0, Infinity, Infinity, 0);
  var dom = goog.dom.getDomHelper(element);
  var body = dom.getDocument().body;
  var documentElement = dom.getDocument().documentElement;
  var scrollEl = dom.getDocumentScrollElement();
  for (var el = element; el = goog.style.getOffsetParent(el);) {
    if ((!goog.userAgent.IE || el.clientWidth != 0) && (!goog.userAgent.WEBKIT || el.clientHeight != 0 || el != body) && (el != body && el != documentElement && goog.style.getStyle_(el, "overflow") != "visible")) {
      var pos = goog.style.getPageOffset(el);
      var client = goog.style.getClientLeftTop(el);
      pos.x += client.x;
      pos.y += client.y;
      visibleRect.top = Math.max(visibleRect.top, pos.y);
      visibleRect.right = Math.min(visibleRect.right, pos.x + el.clientWidth);
      visibleRect.bottom = Math.min(visibleRect.bottom, pos.y + el.clientHeight);
      visibleRect.left = Math.max(visibleRect.left, pos.x);
    }
  }
  var scrollX = scrollEl.scrollLeft, scrollY = scrollEl.scrollTop;
  visibleRect.left = Math.max(visibleRect.left, scrollX);
  visibleRect.top = Math.max(visibleRect.top, scrollY);
  var winSize = dom.getViewportSize();
  visibleRect.right = Math.min(visibleRect.right, scrollX + winSize.width);
  visibleRect.bottom = Math.min(visibleRect.bottom, scrollY + winSize.height);
  return visibleRect.top >= 0 && visibleRect.left >= 0 && visibleRect.bottom > visibleRect.top && visibleRect.right > visibleRect.left ? visibleRect : null;
};
goog.style.getContainerOffsetToScrollInto = function(element, opt_container, opt_center) {
  var container = opt_container || goog.dom.getDocumentScrollElement();
  var elementPos = goog.style.getPageOffset(element);
  var containerPos = goog.style.getPageOffset(container);
  var containerBorder = goog.style.getBorderBox(container);
  if (container == goog.dom.getDocumentScrollElement()) {
    var relX = elementPos.x - container.scrollLeft;
    var relY = elementPos.y - container.scrollTop;
    if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(10)) {
      relX += containerBorder.left;
      relY += containerBorder.top;
    }
  } else {
    var relX = elementPos.x - containerPos.x - containerBorder.left;
    var relY = elementPos.y - containerPos.y - containerBorder.top;
  }
  var elementSize = goog.style.getSizeWithDisplay_(element);
  var spaceX = container.clientWidth - elementSize.width;
  var spaceY = container.clientHeight - elementSize.height;
  var scrollLeft = container.scrollLeft;
  var scrollTop = container.scrollTop;
  if (opt_center) {
    scrollLeft += relX - spaceX / 2;
    scrollTop += relY - spaceY / 2;
  } else {
    scrollLeft += Math.min(relX, Math.max(relX - spaceX, 0));
    scrollTop += Math.min(relY, Math.max(relY - spaceY, 0));
  }
  return new goog.math.Coordinate(scrollLeft, scrollTop);
};
goog.style.scrollIntoContainerView = function(element, opt_container, opt_center) {
  var container = opt_container || goog.dom.getDocumentScrollElement();
  var offset = goog.style.getContainerOffsetToScrollInto(element, container, opt_center);
  container.scrollLeft = offset.x;
  container.scrollTop = offset.y;
};
goog.style.getClientLeftTop = function(el) {
  return new goog.math.Coordinate(el.clientLeft, el.clientTop);
};
goog.style.getPageOffset = function(el) {
  var doc = goog.dom.getOwnerDocument(el);
  goog.asserts.assertObject(el, "Parameter is required");
  var pos = new goog.math.Coordinate(0, 0);
  var viewportElement = goog.style.getClientViewportElement(doc);
  if (el == viewportElement) {
    return pos;
  }
  var box = goog.style.getBoundingClientRect_(el);
  var scrollCoord = goog.dom.getDomHelper(doc).getDocumentScroll();
  pos.x = box.left + scrollCoord.x;
  pos.y = box.top + scrollCoord.y;
  return pos;
};
goog.style.getPageOffsetLeft = function(el) {
  return goog.style.getPageOffset(el).x;
};
goog.style.getPageOffsetTop = function(el) {
  return goog.style.getPageOffset(el).y;
};
goog.style.getFramedPageOffset = function(el, relativeWin) {
  var position = new goog.math.Coordinate(0, 0);
  var currentWin = goog.dom.getWindow(goog.dom.getOwnerDocument(el));
  if (!goog.reflect.canAccessProperty(currentWin, "parent")) {
    return position;
  }
  var currentEl = el;
  do {
    var offset = currentWin == relativeWin ? goog.style.getPageOffset(currentEl) : goog.style.getClientPositionForElement_(goog.asserts.assert(currentEl));
    position.x += offset.x;
    position.y += offset.y;
  } while (currentWin && currentWin != relativeWin && currentWin != currentWin.parent && (currentEl = currentWin.frameElement) && (currentWin = currentWin.parent));
  return position;
};
goog.style.translateRectForAnotherFrame = function(rect, origBase, newBase) {
  if (origBase.getDocument() != newBase.getDocument()) {
    var body = origBase.getDocument().body;
    var pos = goog.style.getFramedPageOffset(body, newBase.getWindow());
    pos = goog.math.Coordinate.difference(pos, goog.style.getPageOffset(body));
    if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9) && !origBase.isCss1CompatMode()) {
      pos = goog.math.Coordinate.difference(pos, origBase.getDocumentScroll());
    }
    rect.left += pos.x;
    rect.top += pos.y;
  }
};
goog.style.getRelativePosition = function(a, b) {
  var ap = goog.style.getClientPosition(a);
  var bp = goog.style.getClientPosition(b);
  return new goog.math.Coordinate(ap.x - bp.x, ap.y - bp.y);
};
goog.style.getClientPositionForElement_ = function(el) {
  var box = goog.style.getBoundingClientRect_(el);
  return new goog.math.Coordinate(box.left, box.top);
};
goog.style.getClientPosition = function(el) {
  goog.asserts.assert(el);
  if (el.nodeType == goog.dom.NodeType.ELEMENT) {
    return goog.style.getClientPositionForElement_(el);
  } else {
    var targetEvent = el.changedTouches ? el.changedTouches[0] : el;
    return new goog.math.Coordinate(targetEvent.clientX, targetEvent.clientY);
  }
};
goog.style.setPageOffset = function(el, x, opt_y) {
  var cur = goog.style.getPageOffset(el);
  if (x instanceof goog.math.Coordinate) {
    opt_y = x.y;
    x = x.x;
  }
  var dx = goog.asserts.assertNumber(x) - cur.x;
  var dy = Number(opt_y) - cur.y;
  goog.style.setPosition(el, el.offsetLeft + dx, el.offsetTop + dy);
};
goog.style.setSize = function(element, w, opt_h) {
  var h;
  if (w instanceof goog.math.Size) {
    h = w.height;
    w = w.width;
  } else {
    if (opt_h == undefined) {
      throw Error("missing height argument");
    }
    h = opt_h;
  }
  goog.style.setWidth(element, w);
  goog.style.setHeight(element, h);
};
goog.style.getPixelStyleValue_ = function(value, round) {
  if (typeof value == "number") {
    value = (round ? Math.round(value) : value) + "px";
  }
  return value;
};
goog.style.setHeight = function(element, height) {
  element.style.height = goog.style.getPixelStyleValue_(height, true);
};
goog.style.setWidth = function(element, width) {
  element.style.width = goog.style.getPixelStyleValue_(width, true);
};
goog.style.getSize = function(element) {
  return goog.style.evaluateWithTemporaryDisplay_(goog.style.getSizeWithDisplay_, element);
};
goog.style.evaluateWithTemporaryDisplay_ = function(fn, element) {
  if (goog.style.getStyle_(element, "display") != "none") {
    return fn(element);
  }
  var style = element.style;
  var originalDisplay = style.display;
  var originalVisibility = style.visibility;
  var originalPosition = style.position;
  style.visibility = "hidden";
  style.position = "absolute";
  style.display = "inline";
  var retVal = fn(element);
  style.display = originalDisplay;
  style.position = originalPosition;
  style.visibility = originalVisibility;
  return retVal;
};
goog.style.getSizeWithDisplay_ = function(element) {
  var offsetWidth = element.offsetWidth;
  var offsetHeight = element.offsetHeight;
  var webkitOffsetsZero = goog.userAgent.WEBKIT && !offsetWidth && !offsetHeight;
  if ((!goog.isDef(offsetWidth) || webkitOffsetsZero) && element.getBoundingClientRect) {
    var clientRect = goog.style.getBoundingClientRect_(element);
    return new goog.math.Size(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
  }
  return new goog.math.Size(offsetWidth, offsetHeight);
};
goog.style.getTransformedSize = function(element) {
  if (!element.getBoundingClientRect) {
    return null;
  }
  var clientRect = goog.style.evaluateWithTemporaryDisplay_(goog.style.getBoundingClientRect_, element);
  return new goog.math.Size(clientRect.right - clientRect.left, clientRect.bottom - clientRect.top);
};
goog.style.getBounds = function(element) {
  var o = goog.style.getPageOffset(element);
  var s = goog.style.getSize(element);
  return new goog.math.Rect(o.x, o.y, s.width, s.height);
};
goog.style.toCamelCase = function(selector) {
  return goog.string.toCamelCase(String(selector));
};
goog.style.toSelectorCase = function(selector) {
  return goog.string.toSelectorCase(selector);
};
goog.style.getOpacity = function(el) {
  goog.asserts.assert(el);
  var style = el.style;
  var result = "";
  if ("opacity" in style) {
    result = style.opacity;
  } else {
    if ("MozOpacity" in style) {
      result = style.MozOpacity;
    } else {
      if ("filter" in style) {
        var match = style.filter.match(/alpha\(opacity=([\d.]+)\)/);
        if (match) {
          result = String(match[1] / 100);
        }
      }
    }
  }
  return result == "" ? result : Number(result);
};
goog.style.setOpacity = function(el, alpha) {
  goog.asserts.assert(el);
  var style = el.style;
  if ("opacity" in style) {
    style.opacity = alpha;
  } else {
    if ("MozOpacity" in style) {
      style.MozOpacity = alpha;
    } else {
      if ("filter" in style) {
        if (alpha === "") {
          style.filter = "";
        } else {
          style.filter = "alpha(opacity=" + Number(alpha) * 100 + ")";
        }
      }
    }
  }
};
goog.style.setTransparentBackgroundImage = function(el, src) {
  var style = el.style;
  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("8")) {
    style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(" + 'src="' + src + '", sizingMethod="crop")';
  } else {
    style.backgroundImage = "url(" + src + ")";
    style.backgroundPosition = "top left";
    style.backgroundRepeat = "no-repeat";
  }
};
goog.style.clearTransparentBackgroundImage = function(el) {
  var style = el.style;
  if ("filter" in style) {
    style.filter = "";
  } else {
    style.backgroundImage = "none";
  }
};
goog.style.showElement = function(el, display) {
  goog.style.setElementShown(el, display);
};
goog.style.setElementShown = function(el, isShown) {
  el.style.display = isShown ? "" : "none";
};
goog.style.isElementShown = function(el) {
  return el.style.display != "none";
};
goog.style.installStyles = function(stylesString, opt_node) {
  return goog.style.installSafeStyleSheet(goog.html.legacyconversions.safeStyleSheetFromString(stylesString), opt_node);
};
goog.style.installSafeStyleSheet = function(safeStyleSheet, opt_node) {
  var dh = goog.dom.getDomHelper(opt_node);
  var styleSheet = null;
  var doc = dh.getDocument();
  if (goog.userAgent.IE && doc.createStyleSheet) {
    styleSheet = doc.createStyleSheet();
    goog.style.setSafeStyleSheet(styleSheet, safeStyleSheet);
  } else {
    var head = dh.getElementsByTagNameAndClass(goog.dom.TagName.HEAD)[0];
    if (!head) {
      var body = dh.getElementsByTagNameAndClass(goog.dom.TagName.BODY)[0];
      head = dh.createDom(goog.dom.TagName.HEAD);
      body.parentNode.insertBefore(head, body);
    }
    styleSheet = dh.createDom(goog.dom.TagName.STYLE);
    goog.style.setSafeStyleSheet(styleSheet, safeStyleSheet);
    dh.appendChild(head, styleSheet);
  }
  return styleSheet;
};
goog.style.uninstallStyles = function(styleSheet) {
  var node = styleSheet.ownerNode || styleSheet.owningElement || styleSheet;
  goog.dom.removeNode(node);
};
goog.style.setStyles = function(element, stylesString) {
  goog.style.setSafeStyleSheet(element, goog.html.legacyconversions.safeStyleSheetFromString(stylesString));
};
goog.style.setSafeStyleSheet = function(element, safeStyleSheet) {
  var stylesString = goog.html.SafeStyleSheet.unwrap(safeStyleSheet);
  if (goog.userAgent.IE && goog.isDef(element.cssText)) {
    element.cssText = stylesString;
  } else {
    element.innerHTML = stylesString;
  }
};
goog.style.setPreWrap = function(el) {
  var style = el.style;
  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("8")) {
    style.whiteSpace = "pre";
    style.wordWrap = "break-word";
  } else {
    if (goog.userAgent.GECKO) {
      style.whiteSpace = "-moz-pre-wrap";
    } else {
      style.whiteSpace = "pre-wrap";
    }
  }
};
goog.style.setInlineBlock = function(el) {
  var style = el.style;
  style.position = "relative";
  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("8")) {
    style.zoom = "1";
    style.display = "inline";
  } else {
    style.display = "inline-block";
  }
};
goog.style.isRightToLeft = function(el) {
  return "rtl" == goog.style.getStyle_(el, "direction");
};
goog.style.unselectableStyle_ = goog.userAgent.GECKO ? "MozUserSelect" : goog.userAgent.WEBKIT || goog.userAgent.EDGE ? "WebkitUserSelect" : null;
goog.style.isUnselectable = function(el) {
  if (goog.style.unselectableStyle_) {
    return el.style[goog.style.unselectableStyle_].toLowerCase() == "none";
  } else {
    if (goog.userAgent.IE || goog.userAgent.OPERA) {
      return el.getAttribute("unselectable") == "on";
    }
  }
  return false;
};
goog.style.setUnselectable = function(el, unselectable, opt_noRecurse) {
  var descendants = !opt_noRecurse ? el.getElementsByTagName("*") : null;
  var name = goog.style.unselectableStyle_;
  if (name) {
    var value = unselectable ? "none" : "";
    if (el.style) {
      el.style[name] = value;
    }
    if (descendants) {
      for (var i = 0, descendant; descendant = descendants[i]; i++) {
        if (descendant.style) {
          descendant.style[name] = value;
        }
      }
    }
  } else {
    if (goog.userAgent.IE || goog.userAgent.OPERA) {
      var value = unselectable ? "on" : "";
      el.setAttribute("unselectable", value);
      if (descendants) {
        for (var i = 0, descendant; descendant = descendants[i]; i++) {
          descendant.setAttribute("unselectable", value);
        }
      }
    }
  }
};
goog.style.getBorderBoxSize = function(element) {
  return new goog.math.Size(element.offsetWidth, element.offsetHeight);
};
goog.style.setBorderBoxSize = function(element, size) {
  var doc = goog.dom.getOwnerDocument(element);
  var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode();
  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("10") && (!isCss1CompatMode || !goog.userAgent.isVersionOrHigher("8"))) {
    var style = element.style;
    if (isCss1CompatMode) {
      var paddingBox = goog.style.getPaddingBox(element);
      var borderBox = goog.style.getBorderBox(element);
      style.pixelWidth = size.width - borderBox.left - paddingBox.left - paddingBox.right - borderBox.right;
      style.pixelHeight = size.height - borderBox.top - paddingBox.top - paddingBox.bottom - borderBox.bottom;
    } else {
      style.pixelWidth = size.width;
      style.pixelHeight = size.height;
    }
  } else {
    goog.style.setBoxSizingSize_(element, size, "border-box");
  }
};
goog.style.getContentBoxSize = function(element) {
  var doc = goog.dom.getOwnerDocument(element);
  var ieCurrentStyle = goog.userAgent.IE && element.currentStyle;
  if (ieCurrentStyle && goog.dom.getDomHelper(doc).isCss1CompatMode() && ieCurrentStyle.width != "auto" && ieCurrentStyle.height != "auto" && !ieCurrentStyle.boxSizing) {
    var width = goog.style.getIePixelValue_(element, ieCurrentStyle.width, "width", "pixelWidth");
    var height = goog.style.getIePixelValue_(element, ieCurrentStyle.height, "height", "pixelHeight");
    return new goog.math.Size(width, height);
  } else {
    var borderBoxSize = goog.style.getBorderBoxSize(element);
    var paddingBox = goog.style.getPaddingBox(element);
    var borderBox = goog.style.getBorderBox(element);
    return new goog.math.Size(borderBoxSize.width - borderBox.left - paddingBox.left - paddingBox.right - borderBox.right, borderBoxSize.height - borderBox.top - paddingBox.top - paddingBox.bottom - borderBox.bottom);
  }
};
goog.style.setContentBoxSize = function(element, size) {
  var doc = goog.dom.getOwnerDocument(element);
  var isCss1CompatMode = goog.dom.getDomHelper(doc).isCss1CompatMode();
  if (goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("10") && (!isCss1CompatMode || !goog.userAgent.isVersionOrHigher("8"))) {
    var style = element.style;
    if (isCss1CompatMode) {
      style.pixelWidth = size.width;
      style.pixelHeight = size.height;
    } else {
      var paddingBox = goog.style.getPaddingBox(element);
      var borderBox = goog.style.getBorderBox(element);
      style.pixelWidth = size.width + borderBox.left + paddingBox.left + paddingBox.right + borderBox.right;
      style.pixelHeight = size.height + borderBox.top + paddingBox.top + paddingBox.bottom + borderBox.bottom;
    }
  } else {
    goog.style.setBoxSizingSize_(element, size, "content-box");
  }
};
goog.style.setBoxSizingSize_ = function(element, size, boxSizing) {
  var style = element.style;
  if (goog.userAgent.GECKO) {
    style.MozBoxSizing = boxSizing;
  } else {
    if (goog.userAgent.WEBKIT) {
      style.WebkitBoxSizing = boxSizing;
    } else {
      style.boxSizing = boxSizing;
    }
  }
  style.width = Math.max(size.width, 0) + "px";
  style.height = Math.max(size.height, 0) + "px";
};
goog.style.getIePixelValue_ = function(element, value, name, pixelName) {
  if (/^\d+px?$/.test(value)) {
    return parseInt(value, 10);
  } else {
    var oldStyleValue = element.style[name];
    var oldRuntimeValue = element.runtimeStyle[name];
    element.runtimeStyle[name] = element.currentStyle[name];
    element.style[name] = value;
    var pixelValue = element.style[pixelName];
    element.style[name] = oldStyleValue;
    element.runtimeStyle[name] = oldRuntimeValue;
    return +pixelValue;
  }
};
goog.style.getIePixelDistance_ = function(element, propName) {
  var value = goog.style.getCascadedStyle(element, propName);
  return value ? goog.style.getIePixelValue_(element, value, "left", "pixelLeft") : 0;
};
goog.style.getBox_ = function(element, stylePrefix) {
  if (goog.userAgent.IE) {
    var left = goog.style.getIePixelDistance_(element, stylePrefix + "Left");
    var right = goog.style.getIePixelDistance_(element, stylePrefix + "Right");
    var top = goog.style.getIePixelDistance_(element, stylePrefix + "Top");
    var bottom = goog.style.getIePixelDistance_(element, stylePrefix + "Bottom");
    return new goog.math.Box(top, right, bottom, left);
  } else {
    var left = goog.style.getComputedStyle(element, stylePrefix + "Left");
    var right = goog.style.getComputedStyle(element, stylePrefix + "Right");
    var top = goog.style.getComputedStyle(element, stylePrefix + "Top");
    var bottom = goog.style.getComputedStyle(element, stylePrefix + "Bottom");
    return new goog.math.Box(parseFloat(top), parseFloat(right), parseFloat(bottom), parseFloat(left));
  }
};
goog.style.getPaddingBox = function(element) {
  return goog.style.getBox_(element, "padding");
};
goog.style.getMarginBox = function(element) {
  return goog.style.getBox_(element, "margin");
};
goog.style.ieBorderWidthKeywords_ = {"thin":2, "medium":4, "thick":6};
goog.style.getIePixelBorder_ = function(element, prop) {
  if (goog.style.getCascadedStyle(element, prop + "Style") == "none") {
    return 0;
  }
  var width = goog.style.getCascadedStyle(element, prop + "Width");
  if (width in goog.style.ieBorderWidthKeywords_) {
    return goog.style.ieBorderWidthKeywords_[width];
  }
  return goog.style.getIePixelValue_(element, width, "left", "pixelLeft");
};
goog.style.getBorderBox = function(element) {
  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
    var left = goog.style.getIePixelBorder_(element, "borderLeft");
    var right = goog.style.getIePixelBorder_(element, "borderRight");
    var top = goog.style.getIePixelBorder_(element, "borderTop");
    var bottom = goog.style.getIePixelBorder_(element, "borderBottom");
    return new goog.math.Box(top, right, bottom, left);
  } else {
    var left = goog.style.getComputedStyle(element, "borderLeftWidth");
    var right = goog.style.getComputedStyle(element, "borderRightWidth");
    var top = goog.style.getComputedStyle(element, "borderTopWidth");
    var bottom = goog.style.getComputedStyle(element, "borderBottomWidth");
    return new goog.math.Box(parseFloat(top), parseFloat(right), parseFloat(bottom), parseFloat(left));
  }
};
goog.style.getFontFamily = function(el) {
  var doc = goog.dom.getOwnerDocument(el);
  var font = "";
  if (doc.body.createTextRange && goog.dom.contains(doc, el)) {
    var range = doc.body.createTextRange();
    range.moveToElementText(el);
    try {
      font = range.queryCommandValue("FontName");
    } catch (e) {
      font = "";
    }
  }
  if (!font) {
    font = goog.style.getStyle_(el, "fontFamily");
  }
  var fontsArray = font.split(",");
  if (fontsArray.length > 1) {
    font = fontsArray[0];
  }
  return goog.string.stripQuotes(font, "\"'");
};
goog.style.lengthUnitRegex_ = /[^\d]+$/;
goog.style.getLengthUnits = function(value) {
  var units = value.match(goog.style.lengthUnitRegex_);
  return units && units[0] || null;
};
goog.style.ABSOLUTE_CSS_LENGTH_UNITS_ = {"cm":1, "in":1, "mm":1, "pc":1, "pt":1};
goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_ = {"em":1, "ex":1};
goog.style.getFontSize = function(el) {
  var fontSize = goog.style.getStyle_(el, "fontSize");
  var sizeUnits = goog.style.getLengthUnits(fontSize);
  if (fontSize && "px" == sizeUnits) {
    return parseInt(fontSize, 10);
  }
  if (goog.userAgent.IE) {
    if (String(sizeUnits) in goog.style.ABSOLUTE_CSS_LENGTH_UNITS_) {
      return goog.style.getIePixelValue_(el, fontSize, "left", "pixelLeft");
    } else {
      if (el.parentNode && el.parentNode.nodeType == goog.dom.NodeType.ELEMENT && String(sizeUnits) in goog.style.CONVERTIBLE_RELATIVE_CSS_UNITS_) {
        var parentElement = el.parentNode;
        var parentSize = goog.style.getStyle_(parentElement, "fontSize");
        return goog.style.getIePixelValue_(parentElement, fontSize == parentSize ? "1em" : fontSize, "left", "pixelLeft");
      }
    }
  }
  var sizeElement = goog.dom.createDom(goog.dom.TagName.SPAN, {"style":"visibility:hidden;position:absolute;" + "line-height:0;padding:0;margin:0;border:0;height:1em;"});
  goog.dom.appendChild(el, sizeElement);
  fontSize = sizeElement.offsetHeight;
  goog.dom.removeNode(sizeElement);
  return fontSize;
};
goog.style.parseStyleAttribute = function(value) {
  var result = {};
  goog.array.forEach(value.split(/\s*;\s*/), function(pair) {
    var keyValue = pair.match(/\s*([\w-]+)\s*\:(.+)/);
    if (keyValue) {
      var styleName = keyValue[1];
      var styleValue = goog.string.trim(keyValue[2]);
      result[goog.string.toCamelCase(styleName.toLowerCase())] = styleValue;
    }
  });
  return result;
};
goog.style.toStyleAttribute = function(obj) {
  var buffer = [];
  goog.object.forEach(obj, function(value, key) {
    buffer.push(goog.string.toSelectorCase(key), ":", value, ";");
  });
  return buffer.join("");
};
goog.style.setFloat = function(el, value) {
  el.style[goog.userAgent.IE ? "styleFloat" : "cssFloat"] = value;
};
goog.style.getFloat = function(el) {
  return el.style[goog.userAgent.IE ? "styleFloat" : "cssFloat"] || "";
};
goog.style.getScrollbarWidth = function(opt_className) {
  var outerDiv = goog.dom.createElement(goog.dom.TagName.DIV);
  if (opt_className) {
    outerDiv.className = opt_className;
  }
  outerDiv.style.cssText = "overflow:auto;" + "position:absolute;top:0;width:100px;height:100px";
  var innerDiv = goog.dom.createElement(goog.dom.TagName.DIV);
  goog.style.setSize(innerDiv, "200px", "200px");
  outerDiv.appendChild(innerDiv);
  goog.dom.appendChild(goog.dom.getDocument().body, outerDiv);
  var width = outerDiv.offsetWidth - outerDiv.clientWidth;
  goog.dom.removeNode(outerDiv);
  return width;
};
goog.style.MATRIX_TRANSLATION_REGEX_ = new RegExp("matrix\\([0-9\\.\\-]+, [0-9\\.\\-]+, " + "[0-9\\.\\-]+, [0-9\\.\\-]+, " + "([0-9\\.\\-]+)p?x?, ([0-9\\.\\-]+)p?x?\\)");
goog.style.getCssTranslation = function(element) {
  var transform = goog.style.getComputedTransform(element);
  if (!transform) {
    return new goog.math.Coordinate(0, 0);
  }
  var matches = transform.match(goog.style.MATRIX_TRANSLATION_REGEX_);
  if (!matches) {
    return new goog.math.Coordinate(0, 0);
  }
  return new goog.math.Coordinate(parseFloat(matches[1]), parseFloat(matches[2]));
};
goog.provide("goog.editor.Command");
goog.editor.Command = {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", DIR_LTR:"ltr", DIR_RTL:"rtl", IMAGE:"image", EDIT_HTML:"editHtml", UPDATE_LINK_BUBBLE:"updateLinkBubble", DEFAULT_TAG:"+defaultTag", CLEAR_LOREM:"clearlorem", UPDATE_LOREM:"updatelorem", USING_LOREM:"usinglorem", MODAL_LINK_EDITOR:"link"};
goog.provide("goog.debug.EntryPointMonitor");
goog.provide("goog.debug.entryPointRegistry");
goog.require("goog.asserts");
goog.debug.EntryPointMonitor = function() {
};
goog.debug.EntryPointMonitor.prototype.wrap;
goog.debug.EntryPointMonitor.prototype.unwrap;
goog.debug.entryPointRegistry.refList_ = [];
goog.debug.entryPointRegistry.monitors_ = [];
goog.debug.entryPointRegistry.monitorsMayExist_ = false;
goog.debug.entryPointRegistry.register = function(callback) {
  goog.debug.entryPointRegistry.refList_[goog.debug.entryPointRegistry.refList_.length] = callback;
  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]));
    }
  }
};
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);
};
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--;
};
goog.provide("goog.events.BrowserFeature");
goog.require("goog.userAgent");
goog.events.BrowserFeature = {HAS_W3C_BUTTON:!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9), HAS_W3C_EVENT_SUPPORT:!goog.userAgent.IE || goog.userAgent.isDocumentModeOrHigher(9), SET_KEY_CODE_TO_PREVENT_DEFAULT:goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("9"), HAS_NAVIGATOR_ONLINE_PROPERTY:!goog.userAgent.WEBKIT || goog.userAgent.isVersionOrHigher("528"), 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"), HTML5_NETWORK_EVENTS_FIRE_ON_BODY:goog.userAgent.GECKO && !goog.userAgent.isVersionOrHigher("8") || goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("9"), TOUCH_ENABLED:"ontouchstart" in goog.global || !!(goog.global["document"] && document.documentElement && "ontouchstart" in document.documentElement) || !!(goog.global["navigator"] && 
goog.global["navigator"]["msMaxTouchPoints"])};
goog.provide("goog.disposable.IDisposable");
goog.disposable.IDisposable = function() {
};
goog.disposable.IDisposable.prototype.dispose = goog.abstractMethod;
goog.disposable.IDisposable.prototype.isDisposed = goog.abstractMethod;
goog.provide("goog.Disposable");
goog.provide("goog.dispose");
goog.provide("goog.disposeAll");
goog.require("goog.disposable.IDisposable");
goog.Disposable = function() {
  this.creationStack;
  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;
  }
  this.disposed_ = this.disposed_;
  this.onDisposeCallbacks_ = this.onDisposeCallbacks_;
};
goog.Disposable.MonitoringMode = {OFF:0, PERMANENT:1, INTERACTIVE:2};
goog.define("goog.Disposable.MONITORING_MODE", 0);
goog.define("goog.Disposable.INCLUDE_STACK_ON_CREATION", true);
goog.Disposable.instances_ = {};
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;
};
goog.Disposable.clearUndisposedObjects = function() {
  goog.Disposable.instances_ = {};
};
goog.Disposable.prototype.disposed_ = false;
goog.Disposable.prototype.onDisposeCallbacks_;
goog.Disposable.prototype.isDisposed = function() {
  return this.disposed_;
};
goog.Disposable.prototype.getDisposed = goog.Disposable.prototype.isDisposed;
goog.Disposable.prototype.dispose = function() {
  if (!this.disposed_) {
    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];
    }
  }
};
goog.Disposable.prototype.registerDisposable = function(disposable) {
  this.addOnDisposeCallback(goog.partial(goog.dispose, disposable));
};
goog.Disposable.prototype.addOnDisposeCallback = function(callback, opt_scope) {
  if (this.disposed_) {
    goog.isDef(opt_scope) ? callback.call(opt_scope) : callback();
    return;
  }
  if (!this.onDisposeCallbacks_) {
    this.onDisposeCallbacks_ = [];
  }
  this.onDisposeCallbacks_.push(goog.isDef(opt_scope) ? goog.bind(callback, opt_scope) : callback);
};
goog.Disposable.prototype.disposeInternal = function() {
  if (this.onDisposeCallbacks_) {
    while (this.onDisposeCallbacks_.length) {
      this.onDisposeCallbacks_.shift()();
    }
  }
};
goog.Disposable.isDisposed = function(obj) {
  if (obj && typeof obj.isDisposed == "function") {
    return obj.isDisposed();
  }
  return false;
};
goog.dispose = function(obj) {
  if (obj && typeof obj.dispose == "function") {
    obj.dispose();
  }
};
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);
    }
  }
};
goog.provide("goog.events.EventId");
goog.events.EventId = function(eventId) {
  this.id = eventId;
};
goog.events.EventId.prototype.toString = function() {
  return this.id;
};
goog.provide("goog.events.Event");
goog.provide("goog.events.EventLike");
goog.require("goog.Disposable");
goog.require("goog.events.EventId");
goog.events.EventLike;
goog.events.Event = function(type, opt_target) {
  this.type = type instanceof goog.events.EventId ? String(type) : type;
  this.target = opt_target;
  this.currentTarget = this.target;
  this.propagationStopped_ = false;
  this.defaultPrevented = false;
  this.returnValue_ = true;
};
goog.events.Event.prototype.stopPropagation = function() {
  this.propagationStopped_ = true;
};
goog.events.Event.prototype.preventDefault = function() {
  this.defaultPrevented = true;
  this.returnValue_ = false;
};
goog.events.Event.stopPropagation = function(e) {
  e.stopPropagation();
};
goog.events.Event.preventDefault = function(e) {
  e.preventDefault();
};
goog.provide("goog.events.EventType");
goog.require("goog.userAgent");
goog.events.getVendorPrefixedName_ = function(eventName) {
  return goog.userAgent.WEBKIT ? "webkit" + eventName : goog.userAgent.OPERA ? "o" + eventName.toLowerCase() : eventName.toLowerCase();
};
goog.events.EventType = {CLICK:"click", RIGHTCLICK:"rightclick", DBLCLICK:"dblclick", MOUSEDOWN:"mousedown", MOUSEUP:"mouseup", MOUSEOVER:"mouseover", MOUSEOUT:"mouseout", MOUSEMOVE:"mousemove", MOUSEENTER:"mouseenter", MOUSELEAVE:"mouseleave", SELECTIONCHANGE:"selectionchange", SELECTSTART:"selectstart", WHEEL:"wheel", KEYPRESS:"keypress", KEYDOWN:"keydown", KEYUP:"keyup", BLUR:"blur", FOCUS:"focus", DEACTIVATE:"deactivate", FOCUSIN:goog.userAgent.IE ? "focusin" : "DOMFocusIn", FOCUSOUT:goog.userAgent.IE ? 
"focusout" : "DOMFocusOut", CHANGE:"change", RESET:"reset", SELECT:"select", SUBMIT:"submit", INPUT:"input", PROPERTYCHANGE:"propertychange", DRAGSTART:"dragstart", DRAG:"drag", DRAGENTER:"dragenter", DRAGOVER:"dragover", DRAGLEAVE:"dragleave", DROP:"drop", DRAGEND:"dragend", TOUCHSTART:"touchstart", TOUCHMOVE:"touchmove", TOUCHEND:"touchend", TOUCHCANCEL:"touchcancel", BEFOREUNLOAD:"beforeunload", CONSOLEMESSAGE:"consolemessage", CONTEXTMENU:"contextmenu", DEVICEMOTION:"devicemotion", DEVICEORIENTATION:"deviceorientation", 
DOMCONTENTLOADED:"DOMContentLoaded", ERROR:"error", HELP:"help", LOAD:"load", LOSECAPTURE:"losecapture", ORIENTATIONCHANGE:"orientationchange", READYSTATECHANGE:"readystatechange", RESIZE:"resize", SCROLL:"scroll", UNLOAD:"unload", CANPLAY:"canplay", CANPLAYTHROUGH:"canplaythrough", DURATIONCHANGE:"durationchange", EMPTIED:"emptied", ENDED:"ended", LOADEDDATA:"loadeddata", LOADEDMETADATA:"loadedmetadata", PAUSE:"pause", PLAY:"play", PLAYING:"playing", RATECHANGE:"ratechange", SEEKED:"seeked", SEEKING:"seeking", 
STALLED:"stalled", SUSPEND:"suspend", TIMEUPDATE:"timeupdate", VOLUMECHANGE:"volumechange", WAITING:"waiting", SOURCEOPEN:"sourceopen", SOURCEENDED:"sourceended", SOURCECLOSED:"sourceclosed", ABORT:"abort", UPDATE:"update", UPDATESTART:"updatestart", UPDATEEND:"updateend", HASHCHANGE:"hashchange", PAGEHIDE:"pagehide", PAGESHOW:"pageshow", POPSTATE:"popstate", COPY:"copy", PASTE:"paste", CUT:"cut", BEFORECOPY:"beforecopy", BEFORECUT:"beforecut", BEFOREPASTE:"beforepaste", ONLINE:"online", OFFLINE:"offline", 
MESSAGE:"message", CONNECT:"connect", INSTALL:"install", ACTIVATE:"activate", FETCH:"fetch", FOREIGNFETCH:"foreignfetch", MESSAGEERROR:"messageerror", STATECHANGE:"statechange", UPDATEFOUND:"updatefound", CONTROLLERCHANGE:"controllerchange", ANIMATIONSTART:goog.events.getVendorPrefixedName_("AnimationStart"), ANIMATIONEND:goog.events.getVendorPrefixedName_("AnimationEnd"), ANIMATIONITERATION:goog.events.getVendorPrefixedName_("AnimationIteration"), TRANSITIONEND:goog.events.getVendorPrefixedName_("TransitionEnd"), 
POINTERDOWN:"pointerdown", POINTERUP:"pointerup", POINTERCANCEL:"pointercancel", POINTERMOVE:"pointermove", POINTEROVER:"pointerover", POINTEROUT:"pointerout", POINTERENTER:"pointerenter", POINTERLEAVE:"pointerleave", GOTPOINTERCAPTURE:"gotpointercapture", LOSTPOINTERCAPTURE:"lostpointercapture", 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", TEXT:"text", TEXTINPUT:goog.userAgent.IE ? "textinput" : "textInput", COMPOSITIONSTART:"compositionstart", COMPOSITIONUPDATE:"compositionupdate", COMPOSITIONEND:"compositionend", 
BEFOREINPUT:"beforeinput", EXIT:"exit", LOADABORT:"loadabort", LOADCOMMIT:"loadcommit", LOADREDIRECT:"loadredirect", LOADSTART:"loadstart", LOADSTOP:"loadstop", RESPONSIVE:"responsive", SIZECHANGED:"sizechanged", UNRESPONSIVE:"unresponsive", VISIBILITYCHANGE:"visibilitychange", STORAGE:"storage", DOMSUBTREEMODIFIED:"DOMSubtreeModified", DOMNODEINSERTED:"DOMNodeInserted", DOMNODEREMOVED:"DOMNodeRemoved", DOMNODEREMOVEDFROMDOCUMENT:"DOMNodeRemovedFromDocument", DOMNODEINSERTEDINTODOCUMENT:"DOMNodeInsertedIntoDocument", 
DOMATTRMODIFIED:"DOMAttrModified", DOMCHARACTERDATAMODIFIED:"DOMCharacterDataModified", BEFOREPRINT:"beforeprint", AFTERPRINT:"afterprint"};
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");
goog.events.BrowserEvent = function(opt_e, opt_currentTarget) {
  goog.events.BrowserEvent.base(this, "constructor", opt_e ? opt_e.type : "");
  this.target = null;
  this.currentTarget = null;
  this.relatedTarget = null;
  this.offsetX = 0;
  this.offsetY = 0;
  this.clientX = 0;
  this.clientY = 0;
  this.screenX = 0;
  this.screenY = 0;
  this.button = 0;
  this.key = "";
  this.keyCode = 0;
  this.charCode = 0;
  this.ctrlKey = false;
  this.altKey = false;
  this.shiftKey = false;
  this.metaKey = false;
  this.state = null;
  this.platformModifierKey = false;
  this.event_ = null;
  if (opt_e) {
    this.init(opt_e, opt_currentTarget);
  }
};
goog.inherits(goog.events.BrowserEvent, goog.events.Event);
goog.events.BrowserEvent.MouseButton = {LEFT:0, MIDDLE:1, RIGHT:2};
goog.events.BrowserEvent.IEButtonMap = [1, 4, 2];
goog.events.BrowserEvent.prototype.init = function(e, opt_currentTarget) {
  var type = this.type = e.type;
  var relevantTouch = e.changedTouches ? e.changedTouches[0] : null;
  this.target = e.target || e.srcElement;
  this.currentTarget = opt_currentTarget;
  var relatedTarget = e.relatedTarget;
  if (relatedTarget) {
    if (goog.userAgent.GECKO) {
      if (!goog.reflect.canAccessProperty(relatedTarget, "nodeName")) {
        relatedTarget = null;
      }
    }
  } else {
    if (type == goog.events.EventType.MOUSEOVER) {
      relatedTarget = e.fromElement;
    } else {
      if (type == goog.events.EventType.MOUSEOUT) {
        relatedTarget = e.toElement;
      }
    }
  }
  this.relatedTarget = relatedTarget;
  if (!goog.isNull(relevantTouch)) {
    this.clientX = relevantTouch.clientX !== undefined ? relevantTouch.clientX : relevantTouch.pageX;
    this.clientY = relevantTouch.clientY !== undefined ? relevantTouch.clientY : relevantTouch.pageY;
    this.screenX = relevantTouch.screenX || 0;
    this.screenY = relevantTouch.screenY || 0;
  } else {
    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.key = e.key || "";
  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();
  }
};
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;
  }
};
goog.events.BrowserEvent.prototype.isMouseActionButton = function() {
  return this.isButton(goog.events.BrowserEvent.MouseButton.LEFT) && !(goog.userAgent.WEBKIT && goog.userAgent.MAC && this.ctrlKey);
};
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;
  }
};
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) {
      try {
        var VK_F1 = 112;
        var VK_F12 = 123;
        if (be.ctrlKey || be.keyCode >= VK_F1 && be.keyCode <= VK_F12) {
          be.keyCode = -1;
        }
      } catch (ex) {
      }
    }
  } else {
    be.preventDefault();
  }
};
goog.events.BrowserEvent.prototype.getBrowserEvent = function() {
  return this.event_;
};
goog.provide("goog.events.Listenable");
goog.provide("goog.events.ListenableKey");
goog.require("goog.events.EventId");
goog.forwardDeclare("goog.events.EventLike");
goog.forwardDeclare("goog.events.EventTarget");
goog.events.Listenable = function() {
};
goog.events.Listenable.IMPLEMENTED_BY_PROP = "closure_listenable_" + (Math.random() * 1e6 | 0);
goog.events.Listenable.addImplementation = function(cls) {
  cls.prototype[goog.events.Listenable.IMPLEMENTED_BY_PROP] = true;
};
goog.events.Listenable.isImplementedBy = function(obj) {
  return !!(obj && obj[goog.events.Listenable.IMPLEMENTED_BY_PROP]);
};
goog.events.Listenable.prototype.listen;
goog.events.Listenable.prototype.listenOnce;
goog.events.Listenable.prototype.unlisten;
goog.events.Listenable.prototype.unlistenByKey;
goog.events.Listenable.prototype.dispatchEvent;
goog.events.Listenable.prototype.removeAllListeners;
goog.events.Listenable.prototype.getParentEventTarget;
goog.events.Listenable.prototype.fireListeners;
goog.events.Listenable.prototype.getListeners;
goog.events.Listenable.prototype.getListener;
goog.events.Listenable.prototype.hasListener;
goog.events.ListenableKey = function() {
};
goog.events.ListenableKey.counter_ = 0;
goog.events.ListenableKey.reserveKey = function() {
  return ++goog.events.ListenableKey.counter_;
};
goog.events.ListenableKey.prototype.src;
goog.events.ListenableKey.prototype.type;
goog.events.ListenableKey.prototype.listener;
goog.events.ListenableKey.prototype.capture;
goog.events.ListenableKey.prototype.handler;
goog.events.ListenableKey.prototype.key;
goog.provide("goog.events.Listener");
goog.require("goog.events.ListenableKey");
goog.events.Listener = function(listener, proxy, src, type, capture, opt_handler) {
  if (goog.events.Listener.ENABLE_MONITORING) {
    this.creationStack = (new Error).stack;
  }
  this.listener = listener;
  this.proxy = proxy;
  this.src = src;
  this.type = type;
  this.capture = !!capture;
  this.handler = opt_handler;
  this.key = goog.events.ListenableKey.reserveKey();
  this.callOnce = false;
  this.removed = false;
};
goog.define("goog.events.Listener.ENABLE_MONITORING", false);
goog.events.Listener.prototype.creationStack;
goog.events.Listener.prototype.markAsRemoved = function() {
  this.removed = true;
  this.listener = null;
  this.proxy = null;
  this.src = null;
  this.handler = null;
};
goog.provide("goog.events.ListenerMap");
goog.require("goog.array");
goog.require("goog.events.Listener");
goog.require("goog.object");
goog.events.ListenerMap = function(src) {
  this.src = src;
  this.listeners = {};
  this.typeCount_ = 0;
};
goog.events.ListenerMap.prototype.getTypeCount = function() {
  return this.typeCount_;
};
goog.events.ListenerMap.prototype.getListenerCount = function() {
  var count = 0;
  for (var type in this.listeners) {
    count += this.listeners[type].length;
  }
  return count;
};
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) {
      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;
};
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;
};
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;
};
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;
};
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;
};
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;
};
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;
  });
};
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;
};
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");
goog.events.Key;
goog.events.ListenableType;
goog.events.LISTENER_MAP_PROP_ = "closure_lm_" + (Math.random() * 1e6 | 0);
goog.events.onString_ = "on";
goog.events.onStringMap_ = {};
goog.events.CaptureSimulationMode = {OFF_AND_FAIL:0, OFF_AND_SILENT:1, ON:2};
goog.define("goog.events.CAPTURE_SIMULATION_MODE", 2);
goog.events.listenerCountEstimate_ = 0;
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, listener, opt_capt, opt_handler);
  } else {
    return goog.events.listen_(src, type, listener, false, opt_capt, opt_handler);
  }
};
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 (listenerObj.proxy) {
    return listenerObj;
  }
  var proxy = goog.events.getProxy();
  listenerObj.proxy = proxy;
  proxy.src = src;
  proxy.listener = listenerObj;
  if (src.addEventListener) {
    src.addEventListener(type.toString(), proxy, capture);
  } else {
    if (src.attachEvent) {
      src.attachEvent(goog.events.getOnString_(type.toString()), proxy);
    } else {
      throw Error("addEventListener and attachEvent are unavailable.");
    }
  }
  goog.events.listenerCountEstimate_++;
  return listenerObj;
};
goog.events.getProxy = function() {
  var proxyCallbackFunction = goog.events.handleBrowserEvent_;
  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);
    if (!v) {
      return v;
    }
  };
  return f;
};
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, listener, opt_capt, opt_handler);
  } else {
    return goog.events.listen_(src, type, listener, true, opt_capt, opt_handler);
  }
};
goog.events.listenWithWrapper = function(src, wrapper, listener, opt_capt, opt_handler) {
  wrapper.listen(src, listener, opt_capt, opt_handler);
};
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, listener, opt_capt, opt_handler);
  }
  if (!src) {
    return false;
  }
  var capture = !!opt_capt;
  var listenerMap = goog.events.getListenerMap_(src);
  if (listenerMap) {
    var listenerObj = listenerMap.getListener(type, listener, capture, opt_handler);
    if (listenerObj) {
      return goog.events.unlistenByKey(listenerObj);
    }
  }
  return false;
};
goog.events.unlistenByKey = function(key) {
  if (goog.isNumber(key)) {
    return false;
  }
  var listener = 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_(src);
  if (listenerMap) {
    listenerMap.removeByKey(listener);
    if (listenerMap.getTypeCount() == 0) {
      listenerMap.src = null;
      src[goog.events.LISTENER_MAP_PROP_] = null;
    }
  } else {
    listener.markAsRemoved();
  }
  return true;
};
goog.events.unlistenWithWrapper = function(src, wrapper, listener, opt_capt, opt_handler) {
  wrapper.unlisten(src, listener, opt_capt, opt_handler);
};
goog.events.removeAll = function(obj, opt_type) {
  if (!obj) {
    return 0;
  }
  if (goog.events.Listenable.isImplementedBy(obj)) {
    return obj.removeAllListeners(opt_type);
  }
  var listenerMap = goog.events.getListenerMap_(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) {
      var listeners = listenerMap.listeners[type].concat();
      for (var i = 0; i < listeners.length; ++i) {
        if (goog.events.unlistenByKey(listeners[i])) {
          ++count;
        }
      }
    }
  }
  return count;
};
goog.events.getListeners = function(obj, type, capture) {
  if (goog.events.Listenable.isImplementedBy(obj)) {
    return obj.getListeners(type, capture);
  } else {
    if (!obj) {
      return [];
    }
    var listenerMap = goog.events.getListenerMap_(obj);
    return listenerMap ? listenerMap.getListeners(type, capture) : [];
  }
};
goog.events.getListener = function(src, type, listener, opt_capt, opt_handler) {
  type = 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) {
    return null;
  }
  var listenerMap = goog.events.getListenerMap_(src);
  if (listenerMap) {
    return listenerMap.getListener(type, listener, capture, opt_handler);
  }
  return null;
};
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_(obj);
  return !!listenerMap && listenerMap.hasListener(opt_type, opt_capture);
};
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");
};
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;
};
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);
};
goog.events.fireListeners_ = function(obj, type, capture, eventObject) {
  var retval = true;
  var listenerMap = goog.events.getListenerMap_(obj);
  if (listenerMap) {
    var listenerArray = listenerMap.listeners[type.toString()];
    if (listenerArray) {
      listenerArray = listenerArray.concat();
      for (var i = 0; i < listenerArray.length; i++) {
        var listener = listenerArray[i];
        if (listener && listener.capture == capture && !listener.removed) {
          var result = goog.events.fireListener(listener, eventObject);
          retval = retval && result !== false;
        }
      }
    }
  }
  return retval;
};
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);
};
goog.events.getTotalListenerCount = function() {
  return goog.events.listenerCountEstimate_;
};
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);
};
goog.events.protectBrowserEventEntryPoint = function(errorHandler) {
  goog.events.handleBrowserEvent_ = errorHandler.protectEntryPoint(goog.events.handleBrowserEvent_);
};
goog.events.handleBrowserEvent_ = function(listener, opt_evt) {
  if (listener.removed) {
    return true;
  }
  if (!goog.events.BrowserFeature.HAS_W3C_EVENT_SUPPORT) {
    var ieEvent = opt_evt || goog.getObjectByName("window.event");
    var evt = new goog.events.BrowserEvent(ieEvent, this);
    var retval = true;
    if (goog.events.CAPTURE_SIMULATION_MODE == goog.events.CaptureSimulationMode.ON) {
      if (!goog.events.isMarkedIeEvent_(ieEvent)) {
        goog.events.markIeEvent_(ieEvent);
        var ancestors = [];
        for (var parent = evt.currentTarget; parent; parent = parent.parentNode) {
          ancestors.push(parent);
        }
        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;
        }
        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;
  }
  return goog.events.fireListener(listener, new goog.events.BrowserEvent(opt_evt, this));
};
goog.events.markIeEvent_ = function(e) {
  var useReturnValue = false;
  if (e.keyCode == 0) {
    try {
      e.keyCode = -1;
      return;
    } catch (ex) {
      useReturnValue = true;
    }
  }
  if (useReturnValue || e.returnValue == undefined) {
    e.returnValue = true;
  }
};
goog.events.isMarkedIeEvent_ = function(e) {
  return e.keyCode < 0 || e.returnValue != undefined;
};
goog.events.uniqueIdCounter_ = 0;
goog.events.getUniqueId = function(identifier) {
  return identifier + "_" + goog.events.uniqueIdCounter_++;
};
goog.events.getListenerMap_ = function(src) {
  var listenerMap = src[goog.events.LISTENER_MAP_PROP_];
  return listenerMap instanceof goog.events.ListenerMap ? listenerMap : null;
};
goog.events.LISTENER_WRAPPER_PROP_ = "__closure_events_fn_" + (Math.random() * 1e9 >>> 0);
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_];
};
goog.debug.entryPointRegistry.register(function(transformer) {
  goog.events.handleBrowserEvent_ = transformer(goog.events.handleBrowserEvent_);
});
goog.provide("uno.api.celogger");
goog.require("goog.debug.Logger");
(function() {
  var celogger = uno && uno.api && (uno.api.celogger || {});
  var log = goog && goog.debug && (goog.debug.Logger.getLogger("uno.api.celogger") || {config:console.log.bind(console), info:console.log.bind(console)});
  celogger.wrap = function(EN) {
    celogger.EN = {setup:EN.setup.bind(EN), cleanup:EN.cleanup.bind(EN), execCommand:EN.execCommand.bind(EN), queryCommandEnabled:EN.queryCommandEnabled.bind(EN), queryCommandValue:EN.queryCommandValue.bind(EN), queryCommandState:EN.queryCommandState.bind(EN), notify:EN.notify.bind(EN)};
    EN.setup = function(opt) {
      var obj = typeof opt === "string" ? JSON.parse(opt) : opt;
      log.config("EN.setup(" + JSON.stringify(obj, null, 2) + ")");
      var result = celogger.EN.setup(opt);
      log.info("EN.setup returning: " + result);
      return result;
    };
    EN.cleanup = function() {
      log.info("EN.cleanup()");
      var result = celogger.EN.cleanup();
      log.info("EN.cleanup returning: " + result);
      return result;
    };
    EN.execCommand = function(command, value, options) {
      logCommand("EN.execCommand", command, value, options);
      var result = celogger.EN.execCommand(command, value, options);
      log.info("EN.execCommand '" + command + "' returning: " + result);
      return result;
    };
    EN.queryCommandEnabled = function(command, options) {
      logCommand("EN.queryCommandEnabled", command, options);
      var result = celogger.EN.queryCommandEnabled(command, options);
      log.info("EN.queryCommandEnabled '" + command + "' returning: " + result);
      return result;
    };
    EN.queryCommandValue = function(command, options) {
      logCommand("EN.queryCommandValue", command, options);
      var result = celogger.EN.queryCommandValue(command, options);
      log.info("EN.queryCommandValue '" + command + "' returning: " + result);
      return result;
    };
    EN.queryCommandState = function(command, options) {
      logCommand("EN.queryCommandState", command, options);
      var result = celogger.EN.queryCommandState(command, options);
      log.info("EN.queryCommandState '" + command + "' returning: " + result);
      return result;
    };
    EN.notify = function(name, info) {
      log.info("NOTIFICATION : " + name + (goog.isDef(info) ? " : " + JSON.stringify(info, null, 2) : ""));
      return celogger.EN.notify(name, info);
    };
  };
  function logCommand(method, command, value, options) {
    var message = method + "('" + command + "'";
    if (value === undefined) {
      message += options === undefined ? "" : ", undefined, " + options;
    } else {
      if (value && typeof value === "object") {
        value = JSON.stringify(value, null, 2);
      } else {
        if (typeof value === "string" && !/^[\{\[]/.test(value) && !/^(true|false|[\.0-9]+)$/.test(value)) {
          value = "'" + value.replace(/'/g, "\\'") + "'";
        }
      }
      if (options && typeof options === "object") {
        options = JSON.stringify(options, null, 2);
      }
      message += ", " + value + (options === undefined ? "" : ", " + options);
    }
    message += ")";
    log.info(message);
  }
})();
goog.provide("uno.Auth");
goog.require("goog.debug.Logger");
(function() {
  var log = goog.debug.Logger.getLogger("uno.Auth");
  var Auth = uno.Auth = function(options) {
    this.router = options.router;
    this.providers = {};
  };
  Auth.ERROR_CODE_NO_AUTH = 2001;
  Auth.ERROR_CODE_INVALID_AUTH = 2002;
  Auth.ERROR_CODE_NETWORK_ERROR = 2003;
  Auth.ERROR_CODE_UNKNOWN = 2004;
  Auth.prototype.getTokenAsync = function(providerName, refresh, askUserForPermission) {
    var provider = this.providers[providerName] || this.addProvider(providerName);
    if (refresh) {
      provider.token = null;
    }
    if (provider.token) {
      return Promise.resolve(provider.token);
    }
    if (provider.request) {
      return provider.request;
    }
    provider.request = this.router.toHostAsync("requestAuth", {serviceName:provider.name, refresh:!!refresh, askUserForPermission:!!askUserForPermission}).then(function(response) {
      provider.request = null;
      provider.token = response.token;
      provider.lastRefreshed = response.lastRefreshed;
      provider.lastErrorCode = provider.errorCode;
      provider.errorCode = response.errorCode;
      if (response.errorCode) {
        var err = new Error("Auth Error");
        err.provider = providerName;
        err.errorCode = response.errorCode;
        throw err;
      } else {
        return response.token;
      }
    }).catch(function(error) {
      provider.request = null;
      provider.errorCode = error.errorCode;
      throw error;
    });
    return provider.request;
  };
  Auth.prototype.getLastErrorCode = function(providerName) {
    var provider = this.providers[providerName];
    return provider && provider.lastErrorCode;
  };
  Auth.prototype.addProvider = function(name) {
    this.providers[name] = {name:name, request:null, token:null, lastErrorCode:null, errorCode:null, lastRefreshed:null};
    return this.providers[name];
  };
})();
goog.provide("uno.Cache");
goog.require("goog.debug.Logger");
(function() {
  var log = goog.debug.Logger.getLogger("uno.Cache");
  var Cache = uno.Cache = function(options) {
    this.router = options.router;
    this.diskEnabled = false;
    this.memCache = {};
  };
  Cache.prototype.readMem = function(key) {
    return this.memCache[key];
  };
  Cache.prototype.writeMem = function(key, value) {
    this.memCache[key] = value;
  };
  Cache.prototype.readDiskAsync = function(key) {
    if (this.diskEnabled) {
      return this.router.toHostAsync("getFromCache", {href:key}).then(function(result) {
        return result.data ? result.data.data || result.data : result.data;
      });
    }
    return Promise.resolve();
  };
  Cache.prototype.writeDisk = function(key, value) {
    if (this.diskEnabled) {
      this.router.toHostAsync("saveInCache", {href:key, data:value});
    }
  };
  Cache.prototype.write = function(key, value) {
    this.writeMem(key, value);
    this.writeDisk(key, value);
  };
  Cache.prototype.enableDisk = function() {
    this.diskEnabled = true;
  };
  Cache.prototype.disableDisk = function() {
    this.diskEnabled = false;
  };
})();
goog.provide("uno.debug");
(function() {
  window.__timers__ = [];
  window.start = function(name) {
    if (!DEBUG) {
      return;
    }
    console.log(pad(__timers__.length) + "%c [START TIMER] [%s]", "color: #aaa;", name);
    __timers__.push({name:name, time:performance.now()});
  };
  window.stop = function(name) {
    if (!DEBUG) {
      return;
    }
    var timer = __timers__.pop() || {};
    if (timer.name !== name) {
      console.warn('Timer name "' + name + '" did not match "' + timer.name + '"! Are you missing a call to start or stop?');
    }
    var duration = performance.now() - timer.time;
    var color = duration < 0.5 ? "#aaa" : duration < 50 ? "green" : duration < 500 ? "darkorange" : "red";
    console.log(pad(__timers__.length) + "%c [%c%s sec%c] [%s]", "color: " + color + ";", "color: " + color + ";font-weight: bold;", format(duration), "color: " + color + ";", timer.name);
  };
  function pad(depth) {
    var padding = "";
    for (var i = 0; i < depth; i++) {
      padding += "\t";
    }
    return padding;
  }
  function format(num) {
    var text = (num / 1000).toFixed(3);
    return text.length === 5 ? "  " + text : text.length === 6 ? " " + text : text;
  }
})();
goog.provide("goog.dom.classes");
goog.require("goog.array");
goog.dom.classes.set = function(element, className) {
  element.className = className;
};
goog.dom.classes.get = function(element) {
  var className = element.className;
  return goog.isString(className) && className.match(/\S+/g) || [];
};
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;
};
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;
};
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]);
    }
  }
};
goog.dom.classes.getDifference_ = function(arr1, arr2) {
  return goog.array.filter(arr1, function(item) {
    return !goog.array.contains(arr2, item);
  });
};
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;
};
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(" "));
};
goog.dom.classes.has = function(element, className) {
  return goog.array.contains(goog.dom.classes.get(element), className);
};
goog.dom.classes.enable = function(element, className, enabled) {
  if (enabled) {
    goog.dom.classes.add(element, className);
  } else {
    goog.dom.classes.remove(element, className);
  }
};
goog.dom.classes.toggle = function(element, className) {
  var add = !goog.dom.classes.has(element, className);
  goog.dom.classes.enable(element, className, add);
  return add;
};
goog.provide("goog.log");
goog.provide("goog.log.Level");
goog.provide("goog.log.LogRecord");
goog.provide("goog.log.Logger");
goog.require("goog.debug");
goog.require("goog.debug.LogManager");
goog.require("goog.debug.LogRecord");
goog.require("goog.debug.Logger");
goog.define("goog.log.ENABLED", goog.debug.LOGGING_ENABLED);
goog.log.ROOT_LOGGER_NAME = goog.debug.Logger.ROOT_LOGGER_NAME;
goog.log.Logger = goog.debug.Logger;
goog.log.Level = goog.debug.Logger.Level;
goog.log.LogRecord = goog.debug.LogRecord;
goog.log.getLogger = function(name, opt_level) {
  if (goog.log.ENABLED) {
    var logger = goog.debug.LogManager.getLogger(name);
    if (opt_level && logger) {
      logger.setLevel(opt_level);
    }
    return logger;
  } else {
    return null;
  }
};
goog.log.addHandler = function(logger, handler) {
  if (goog.log.ENABLED && logger) {
    logger.addHandler(handler);
  }
};
goog.log.removeHandler = function(logger, handler) {
  if (goog.log.ENABLED && logger) {
    return logger.removeHandler(handler);
  } else {
    return false;
  }
};
goog.log.log = function(logger, level, msg, opt_exception) {
  if (goog.log.ENABLED && logger) {
    logger.log(level, msg, opt_exception);
  }
};
goog.log.error = function(logger, msg, opt_exception) {
  if (goog.log.ENABLED && logger) {
    logger.severe(msg, opt_exception);
  }
};
goog.log.warning = function(logger, msg, opt_exception) {
  if (goog.log.ENABLED && logger) {
    logger.warning(msg, opt_exception);
  }
};
goog.log.info = function(logger, msg, opt_exception) {
  if (goog.log.ENABLED && logger) {
    logger.info(msg, opt_exception);
  }
};
goog.log.fine = function(logger, msg, opt_exception) {
  if (goog.log.ENABLED && logger) {
    logger.fine(msg, opt_exception);
  }
};
goog.provide("goog.dom.SavedRange");
goog.require("goog.Disposable");
goog.require("goog.log");
goog.dom.SavedRange = function() {
  goog.Disposable.call(this);
};
goog.inherits(goog.dom.SavedRange, goog.Disposable);
goog.dom.SavedRange.logger_ = goog.log.getLogger("goog.dom.SavedRange");
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;
};
goog.dom.SavedRange.prototype.restoreInternal = goog.abstractMethod;
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");
goog.dom.SavedCaretRange = function(range) {
  goog.dom.SavedRange.call(this);
  this.startCaretId_ = goog.string.createUniqueString();
  this.endCaretId_ = goog.string.createUniqueString();
  this.reversed_ = range.isReversed();
  this.dom_ = goog.dom.getDomHelper(range.getDocument());
  range.surroundWithNodes(this.createCaret_(true), this.createCaret_(false));
};
goog.inherits(goog.dom.SavedCaretRange, goog.dom.SavedRange);
goog.dom.SavedCaretRange.prototype.toAbstractRange = function() {
  var range = null;
  var startCaret = this.getCaret(true);
  var endCaret = this.getCaret(false);
  if (startCaret && endCaret) {
    range = goog.dom.Range.createFromNodes(startCaret, 0, endCaret, 0);
  }
  return range;
};
goog.dom.SavedCaretRange.prototype.getCaret = function(start) {
  return this.dom_.getElement(start ? this.startCaretId_ : this.endCaretId_);
};
goog.dom.SavedCaretRange.prototype.removeCarets = function(opt_range) {
  goog.dom.removeNode(this.getCaret(true));
  goog.dom.removeNode(this.getCaret(false));
  return opt_range;
};
goog.dom.SavedCaretRange.prototype.setRestorationDocument = function(doc) {
  this.dom_.setDocument(doc);
};
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) {
      if (this.reversed_) {
        anchorOffset--;
      } else {
        focusOffset--;
      }
    }
    range = goog.dom.Range.createFromNodes(anchorNode, anchorOffset, focusNode, focusOffset);
    range = this.removeCarets(range);
    range.select();
  } else {
    this.removeCarets();
  }
  return range;
};
goog.dom.SavedCaretRange.prototype.disposeInternal = function() {
  this.removeCarets();
  this.dom_ = null;
};
goog.dom.SavedCaretRange.prototype.createCaret_ = function(start) {
  return this.dom_.createDom(goog.dom.TagName.SPAN, {"id":start ? this.startCaretId_ : this.endCaretId_});
};
goog.dom.SavedCaretRange.CARET_REGEX = /<span\s+id="?goog_\d+"?><\/span>/ig;
goog.dom.SavedCaretRange.htmlEqual = function(str1, str2) {
  return str1 == str2 || str1.replace(goog.dom.SavedCaretRange.CARET_REGEX, "") == str2.replace(goog.dom.SavedCaretRange.CARET_REGEX, "");
};
goog.provide("goog.functions");
goog.functions.constant = function(retValue) {
  return function() {
    return retValue;
  };
};
goog.functions.FALSE = goog.functions.constant(false);
goog.functions.TRUE = goog.functions.constant(true);
goog.functions.NULL = goog.functions.constant(null);
goog.functions.identity = function(opt_returnValue, var_args) {
  return opt_returnValue;
};
goog.functions.error = function(message) {
  return function() {
    throw Error(message);
  };
};
goog.functions.fail = function(err) {
  return function() {
    throw err;
  };
};
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));
  };
};
goog.functions.nth = function(n) {
  return function() {
    return arguments[n];
  };
};
goog.functions.partialRight = function(fn, var_args) {
  var rightArgs = Array.prototype.slice.call(arguments, 1);
  return function() {
    var newArgs = Array.prototype.slice.call(arguments);
    newArgs.push.apply(newArgs, rightArgs);
    return fn.apply(this, newArgs);
  };
};
goog.functions.withReturnValue = function(f, retValue) {
  return goog.functions.sequence(f, goog.functions.constant(retValue));
};
goog.functions.equalTo = function(value, opt_useLooseComparison) {
  return function(other) {
    return opt_useLooseComparison ? value == other : value === other;
  };
};
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;
  };
};
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;
  };
};
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;
  };
};
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;
  };
};
goog.functions.not = function(f) {
  return function() {
    return !f.apply(this, arguments);
  };
};
goog.functions.create = function(constructor, var_args) {
  var temp = function() {
  };
  temp.prototype = constructor.prototype;
  var obj = new temp;
  constructor.apply(obj, Array.prototype.slice.call(arguments, 1));
  return obj;
};
goog.define("goog.functions.CACHE_RETURN_VALUE", true);
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;
  };
};
goog.functions.once = function(f) {
  var inner = f;
  return function() {
    if (inner) {
      var tmp = inner;
      inner = null;
      tmp();
    }
  };
};
goog.functions.debounce = function(f, interval, opt_scope) {
  var timeout = 0;
  return function(var_args) {
    goog.global.clearTimeout(timeout);
    var args = arguments;
    timeout = goog.global.setTimeout(function() {
      f.apply(opt_scope, args);
    }, interval);
  };
};
goog.functions.throttle = function(f, interval, opt_scope) {
  var timeout = 0;
  var shouldFire = false;
  var args = [];
  var handleTimeout = function() {
    timeout = 0;
    if (shouldFire) {
      shouldFire = false;
      fire();
    }
  };
  var fire = function() {
    timeout = goog.global.setTimeout(handleTimeout, interval);
    f.apply(opt_scope, args);
  };
  return function(var_args) {
    args = arguments;
    if (!timeout) {
      fire();
    } else {
      shouldFire = true;
    }
  };
};
goog.functions.rateLimit = function(f, interval, opt_scope) {
  var timeout = 0;
  var handleTimeout = function() {
    timeout = 0;
  };
  return function(var_args) {
    if (!timeout) {
      timeout = goog.global.setTimeout(handleTimeout, interval);
      f.apply(opt_scope, arguments);
    }
  };
};
goog.provide("goog.iter");
goog.provide("goog.iter.Iterable");
goog.provide("goog.iter.Iterator");
goog.provide("goog.iter.StopIteration");
goog.require("goog.array");
goog.require("goog.asserts");
goog.require("goog.functions");
goog.require("goog.math");
goog.iter.Iterable;
goog.iter.StopIteration = "StopIteration" in goog.global ? goog.global["StopIteration"] : {message:"StopIteration", stack:""};
goog.iter.Iterator = function() {
};
goog.iter.Iterator.prototype.next = function() {
  throw goog.iter.StopIteration;
};
goog.iter.Iterator.prototype.__iterator__ = function(opt_keys) {
  return this;
};
goog.iter.toIterator = function(iterable) {
  if (iterable instanceof goog.iter.Iterator) {
    return iterable;
  }
  if (typeof iterable.__iterator__ == "function") {
    return iterable.__iterator__(false);
  }
  if (goog.isArrayLike(iterable)) {
    var i = 0;
    var newIter = new goog.iter.Iterator;
    newIter.next = function() {
      while (true) {
        if (i >= iterable.length) {
          throw goog.iter.StopIteration;
        }
        if (!(i in iterable)) {
          i++;
          continue;
        }
        return iterable[i++];
      }
    };
    return newIter;
  }
  throw Error("Not implemented");
};
goog.iter.forEach = function(iterable, f, opt_obj) {
  if (goog.isArrayLike(iterable)) {
    try {
      goog.array.forEach(iterable, f, opt_obj);
    } catch (ex) {
      if (ex !== goog.iter.StopIteration) {
        throw ex;
      }
    }
  } else {
    iterable = goog.iter.toIterator(iterable);
    try {
      while (true) {
        f.call(opt_obj, iterable.next(), undefined, iterable);
      }
    } catch (ex$2) {
      if (ex$2 !== goog.iter.StopIteration) {
        throw ex$2;
      }
    }
  }
};
goog.iter.filter = function(iterable, f, opt_obj) {
  var iterator = goog.iter.toIterator(iterable);
  var newIter = new goog.iter.Iterator;
  newIter.next = function() {
    while (true) {
      var val = iterator.next();
      if (f.call(opt_obj, val, undefined, iterator)) {
        return val;
      }
    }
  };
  return newIter;
};
goog.iter.filterFalse = function(iterable, f, opt_obj) {
  return goog.iter.filter(iterable, goog.functions.not(f), opt_obj);
};
goog.iter.range = function(startOrStop, opt_stop, opt_step) {
  var start = 0;
  var stop = startOrStop;
  var step = opt_step || 1;
  if (arguments.length > 1) {
    start = startOrStop;
    stop = opt_stop;
  }
  if (step == 0) {
    throw Error("Range step argument must not be zero");
  }
  var newIter = new goog.iter.Iterator;
  newIter.next = function() {
    if (step > 0 && start >= stop || step < 0 && start <= stop) {
      throw goog.iter.StopIteration;
    }
    var rv = start;
    start += step;
    return rv;
  };
  return newIter;
};
goog.iter.join = function(iterable, deliminator) {
  return goog.iter.toArray(iterable).join(deliminator);
};
goog.iter.map = function(iterable, f, opt_obj) {
  var iterator = goog.iter.toIterator(iterable);
  var newIter = new goog.iter.Iterator;
  newIter.next = function() {
    var val = iterator.next();
    return f.call(opt_obj, val, undefined, iterator);
  };
  return newIter;
};
goog.iter.reduce = function(iterable, f, val, opt_obj) {
  var rval = val;
  goog.iter.forEach(iterable, function(val) {
    rval = f.call(opt_obj, rval, val);
  });
  return rval;
};
goog.iter.some = function(iterable, f, opt_obj) {
  iterable = goog.iter.toIterator(iterable);
  try {
    while (true) {
      if (f.call(opt_obj, iterable.next(), undefined, iterable)) {
        return true;
      }
    }
  } catch (ex) {
    if (ex !== goog.iter.StopIteration) {
      throw ex;
    }
  }
  return false;
};
goog.iter.every = function(iterable, f, opt_obj) {
  iterable = goog.iter.toIterator(iterable);
  try {
    while (true) {
      if (!f.call(opt_obj, iterable.next(), undefined, iterable)) {
        return false;
      }
    }
  } catch (ex) {
    if (ex !== goog.iter.StopIteration) {
      throw ex;
    }
  }
  return true;
};
goog.iter.chain = function(var_args) {
  return goog.iter.chainFromIterable(arguments);
};
goog.iter.chainFromIterable = function(iterable) {
  var iterator = goog.iter.toIterator(iterable);
  var iter = new goog.iter.Iterator;
  var current = null;
  iter.next = function() {
    while (true) {
      if (current == null) {
        var it = iterator.next();
        current = goog.iter.toIterator(it);
      }
      try {
        return current.next();
      } catch (ex) {
        if (ex !== goog.iter.StopIteration) {
          throw ex;
        }
        current = null;
      }
    }
  };
  return iter;
};
goog.iter.dropWhile = function(iterable, f, opt_obj) {
  var iterator = goog.iter.toIterator(iterable);
  var newIter = new goog.iter.Iterator;
  var dropping = true;
  newIter.next = function() {
    while (true) {
      var val = iterator.next();
      if (dropping && f.call(opt_obj, val, undefined, iterator)) {
        continue;
      } else {
        dropping = false;
      }
      return val;
    }
  };
  return newIter;
};
goog.iter.takeWhile = function(iterable, f, opt_obj) {
  var iterator = goog.iter.toIterator(iterable);
  var iter = new goog.iter.Iterator;
  iter.next = function() {
    var val = iterator.next();
    if (f.call(opt_obj, val, undefined, iterator)) {
      return val;
    }
    throw goog.iter.StopIteration;
  };
  return iter;
};
goog.iter.toArray = function(iterable) {
  if (goog.isArrayLike(iterable)) {
    return goog.array.toArray(iterable);
  }
  iterable = goog.iter.toIterator(iterable);
  var array = [];
  goog.iter.forEach(iterable, function(val) {
    array.push(val);
  });
  return array;
};
goog.iter.equals = function(iterable1, iterable2, opt_equalsFn) {
  var fillValue = {};
  var pairs = goog.iter.zipLongest(fillValue, iterable1, iterable2);
  var equalsFn = opt_equalsFn || goog.array.defaultCompareEquality;
  return goog.iter.every(pairs, function(pair) {
    return equalsFn(pair[0], pair[1]);
  });
};
goog.iter.nextOrValue = function(iterable, defaultValue) {
  try {
    return goog.iter.toIterator(iterable).next();
  } catch (e) {
    if (e != goog.iter.StopIteration) {
      throw e;
    }
    return defaultValue;
  }
};
goog.iter.product = function(var_args) {
  var someArrayEmpty = goog.array.some(arguments, function(arr) {
    return !arr.length;
  });
  if (someArrayEmpty || !arguments.length) {
    return new goog.iter.Iterator;
  }
  var iter = new goog.iter.Iterator;
  var arrays = arguments;
  var indicies = goog.array.repeat(0, arrays.length);
  iter.next = function() {
    if (indicies) {
      var retVal = goog.array.map(indicies, function(valueIndex, arrayIndex) {
        return arrays[arrayIndex][valueIndex];
      });
      for (var i = indicies.length - 1; i >= 0; i--) {
        goog.asserts.assert(indicies);
        if (indicies[i] < arrays[i].length - 1) {
          indicies[i]++;
          break;
        }
        if (i == 0) {
          indicies = null;
          break;
        }
        indicies[i] = 0;
      }
      return retVal;
    }
    throw goog.iter.StopIteration;
  };
  return iter;
};
goog.iter.cycle = function(iterable) {
  var baseIterator = goog.iter.toIterator(iterable);
  var cache = [];
  var cacheIndex = 0;
  var iter = new goog.iter.Iterator;
  var useCache = false;
  iter.next = function() {
    var returnElement = null;
    if (!useCache) {
      try {
        returnElement = baseIterator.next();
        cache.push(returnElement);
        return returnElement;
      } catch (e) {
        if (e != goog.iter.StopIteration || goog.array.isEmpty(cache)) {
          throw e;
        }
        useCache = true;
      }
    }
    returnElement = cache[cacheIndex];
    cacheIndex = (cacheIndex + 1) % cache.length;
    return returnElement;
  };
  return iter;
};
goog.iter.count = function(opt_start, opt_step) {
  var counter = opt_start || 0;
  var step = goog.isDef(opt_step) ? opt_step : 1;
  var iter = new goog.iter.Iterator;
  iter.next = function() {
    var returnValue = counter;
    counter += step;
    return returnValue;
  };
  return iter;
};
goog.iter.repeat = function(value) {
  var iter = new goog.iter.Iterator;
  iter.next = goog.functions.constant(value);
  return iter;
};
goog.iter.accumulate = function(iterable) {
  var iterator = goog.iter.toIterator(iterable);
  var total = 0;
  var iter = new goog.iter.Iterator;
  iter.next = function() {
    total += iterator.next();
    return total;
  };
  return iter;
};
goog.iter.zip = function(var_args) {
  var args = arguments;
  var iter = new goog.iter.Iterator;
  if (args.length > 0) {
    var iterators = goog.array.map(args, goog.iter.toIterator);
    iter.next = function() {
      var arr = goog.array.map(iterators, function(it) {
        return it.next();
      });
      return arr;
    };
  }
  return iter;
};
goog.iter.zipLongest = function(fillValue, var_args) {
  var args = goog.array.slice(arguments, 1);
  var iter = new goog.iter.Iterator;
  if (args.length > 0) {
    var iterators = goog.array.map(args, goog.iter.toIterator);
    iter.next = function() {
      var iteratorsHaveValues = false;
      var arr = goog.array.map(iterators, function(it) {
        var returnValue;
        try {
          returnValue = it.next();
          iteratorsHaveValues = true;
        } catch (ex) {
          if (ex !== goog.iter.StopIteration) {
            throw ex;
          }
          returnValue = fillValue;
        }
        return returnValue;
      });
      if (!iteratorsHaveValues) {
        throw goog.iter.StopIteration;
      }
      return arr;
    };
  }
  return iter;
};
goog.iter.compress = function(iterable, selectors) {
  var selectorIterator = goog.iter.toIterator(selectors);
  return goog.iter.filter(iterable, function() {
    return !!selectorIterator.next();
  });
};
goog.iter.GroupByIterator_ = function(iterable, opt_keyFunc) {
  this.iterator = goog.iter.toIterator(iterable);
  this.keyFunc = opt_keyFunc || goog.functions.identity;
  this.targetKey;
  this.currentKey;
  this.currentValue;
};
goog.inherits(goog.iter.GroupByIterator_, goog.iter.Iterator);
goog.iter.GroupByIterator_.prototype.next = function() {
  while (this.currentKey == this.targetKey) {
    this.currentValue = this.iterator.next();
    this.currentKey = this.keyFunc(this.currentValue);
  }
  this.targetKey = this.currentKey;
  return [this.currentKey, this.groupItems_(this.targetKey)];
};
goog.iter.GroupByIterator_.prototype.groupItems_ = function(targetKey) {
  var arr = [];
  while (this.currentKey == targetKey) {
    arr.push(this.currentValue);
    try {
      this.currentValue = this.iterator.next();
    } catch (ex) {
      if (ex !== goog.iter.StopIteration) {
        throw ex;
      }
      break;
    }
    this.currentKey = this.keyFunc(this.currentValue);
  }
  return arr;
};
goog.iter.groupBy = function(iterable, opt_keyFunc) {
  return new goog.iter.GroupByIterator_(iterable, opt_keyFunc);
};
goog.iter.starMap = function(iterable, f, opt_obj) {
  var iterator = goog.iter.toIterator(iterable);
  var iter = new goog.iter.Iterator;
  iter.next = function() {
    var args = goog.iter.toArray(iterator.next());
    return f.apply(opt_obj, goog.array.concat(args, undefined, iterator));
  };
  return iter;
};
goog.iter.tee = function(iterable, opt_num) {
  var iterator = goog.iter.toIterator(iterable);
  var num = goog.isNumber(opt_num) ? opt_num : 2;
  var buffers = goog.array.map(goog.array.range(num), function() {
    return [];
  });
  var addNextIteratorValueToBuffers = function() {
    var val = iterator.next();
    goog.array.forEach(buffers, function(buffer) {
      buffer.push(val);
    });
  };
  var createIterator = function(buffer) {
    var iter = new goog.iter.Iterator;
    iter.next = function() {
      if (goog.array.isEmpty(buffer)) {
        addNextIteratorValueToBuffers();
      }
      goog.asserts.assert(!goog.array.isEmpty(buffer));
      return buffer.shift();
    };
    return iter;
  };
  return goog.array.map(buffers, createIterator);
};
goog.iter.enumerate = function(iterable, opt_start) {
  return goog.iter.zip(goog.iter.count(opt_start), iterable);
};
goog.iter.limit = function(iterable, limitSize) {
  goog.asserts.assert(goog.math.isInt(limitSize) && limitSize >= 0);
  var iterator = goog.iter.toIterator(iterable);
  var iter = new goog.iter.Iterator;
  var remaining = limitSize;
  iter.next = function() {
    if (remaining-- > 0) {
      return iterator.next();
    }
    throw goog.iter.StopIteration;
  };
  return iter;
};
goog.iter.consume = function(iterable, count) {
  goog.asserts.assert(goog.math.isInt(count) && count >= 0);
  var iterator = goog.iter.toIterator(iterable);
  while (count-- > 0) {
    goog.iter.nextOrValue(iterator, null);
  }
  return iterator;
};
goog.iter.slice = function(iterable, start, opt_end) {
  goog.asserts.assert(goog.math.isInt(start) && start >= 0);
  var iterator = goog.iter.consume(iterable, start);
  if (goog.isNumber(opt_end)) {
    goog.asserts.assert(goog.math.isInt(opt_end) && opt_end >= start);
    iterator = goog.iter.limit(iterator, opt_end - start);
  }
  return iterator;
};
goog.iter.hasDuplicates_ = function(arr) {
  var deduped = [];
  goog.array.removeDuplicates(arr, deduped);
  return arr.length != deduped.length;
};
goog.iter.permutations = function(iterable, opt_length) {
  var elements = goog.iter.toArray(iterable);
  var length = goog.isNumber(opt_length) ? opt_length : elements.length;
  var sets = goog.array.repeat(elements, length);
  var product = goog.iter.product.apply(undefined, sets);
  return goog.iter.filter(product, function(arr) {
    return !goog.iter.hasDuplicates_(arr);
  });
};
goog.iter.combinations = function(iterable, length) {
  var elements = goog.iter.toArray(iterable);
  var indexes = goog.iter.range(elements.length);
  var indexIterator = goog.iter.permutations(indexes, length);
  var sortedIndexIterator = goog.iter.filter(indexIterator, function(arr) {
    return goog.array.isSorted(arr);
  });
  var iter = new goog.iter.Iterator;
  function getIndexFromElements(index) {
    return elements[index];
  }
  iter.next = function() {
    return goog.array.map(sortedIndexIterator.next(), getIndexFromElements);
  };
  return iter;
};
goog.iter.combinationsWithReplacement = function(iterable, length) {
  var elements = goog.iter.toArray(iterable);
  var indexes = goog.array.range(elements.length);
  var sets = goog.array.repeat(indexes, length);
  var indexIterator = goog.iter.product.apply(undefined, sets);
  var sortedIndexIterator = goog.iter.filter(indexIterator, function(arr) {
    return goog.array.isSorted(arr);
  });
  var iter = new goog.iter.Iterator;
  function getIndexFromElements(index) {
    return elements[index];
  }
  iter.next = function() {
    return goog.array.map(sortedIndexIterator.next(), getIndexFromElements);
  };
  return iter;
};
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");
goog.dom.TagWalkType = {START_TAG:1, OTHER:0, END_TAG:-1};
goog.dom.TagIterator = function(opt_node, opt_reversed, opt_unconstrained, opt_tagType, opt_depth) {
  this.reversed = !!opt_reversed;
  this.node = null;
  this.tagType = goog.dom.TagWalkType.OTHER;
  this.depth;
  this.started_ = false;
  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);
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 {
      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;
  }
};
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;
};
goog.dom.TagIterator.prototype.clone = function() {
  return new goog.dom.TagIterator(this.node, this.reversed, !this.constrained, this.tagType, this.depth);
};
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 = check * -1;
    this.depth += this.tagType * (this.reversed ? -1 : 1);
  }
};
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 = check * -1;
    this.depth += this.tagType * (this.reversed ? -1 : 1);
  }
};
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) {
      var child = this.reversed ? node.lastChild : node.firstChild;
      if (child) {
        this.setPosition(child);
      } else {
        this.setPosition(node, startType * -1);
      }
    } else {
      var sibling = this.reversed ? node.previousSibling : node.nextSibling;
      if (sibling) {
        this.setPosition(sibling);
      } else {
        this.setPosition(node.parentNode, startType * -1);
      }
    }
    this.depth += this.tagType * (this.reversed ? -1 : 1);
  } else {
    this.started_ = true;
  }
  node = this.node;
  if (!this.node) {
    throw goog.iter.StopIteration;
  }
  return node;
};
goog.dom.TagIterator.prototype.isStarted = function() {
  return this.started_;
};
goog.dom.TagIterator.prototype.isStartTag = function() {
  return this.tagType == goog.dom.TagWalkType.START_TAG;
};
goog.dom.TagIterator.prototype.isEndTag = function() {
  return this.tagType == goog.dom.TagWalkType.END_TAG;
};
goog.dom.TagIterator.prototype.isNonElement = function() {
  return this.tagType == goog.dom.TagWalkType.OTHER;
};
goog.dom.TagIterator.prototype.equals = function(other) {
  return other.node == this.node && (!this.node || other.tagType == this.tagType);
};
goog.dom.TagIterator.prototype.splice = function(var_args) {
  var node = this.node;
  this.restartTag();
  this.reversed = !this.reversed;
  goog.dom.TagIterator.prototype.next.call(this);
  this.reversed = !this.reversed;
  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);
};
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");
goog.dom.RangeType = {TEXT:"text", CONTROL:"control", MULTI:"mutli"};
goog.dom.AbstractRange = function() {
};
goog.dom.AbstractRange.getBrowserSelectionForWindow = function(win) {
  if (win.getSelection) {
    return win.getSelection();
  } else {
    var doc = win.document;
    var sel = doc.selection;
    if (sel) {
      try {
        var range = sel.createRange();
        if (range.parentElement) {
          if (range.parentElement().document != doc) {
            return null;
          }
        } else {
          if (!range.length || range.item(0).document != doc) {
            return null;
          }
        }
      } catch (e) {
        return null;
      }
      return sel;
    }
    return null;
  }
};
goog.dom.AbstractRange.isNativeControlRange = function(range) {
  return !!range && !!range.addElement;
};
goog.dom.AbstractRange.prototype.clone = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getType = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getBrowserRangeObject = goog.abstractMethod;
goog.dom.AbstractRange.prototype.setBrowserRangeObject = function(nativeRange) {
  return false;
};
goog.dom.AbstractRange.prototype.getTextRangeCount = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getTextRange = goog.abstractMethod;
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;
};
goog.dom.AbstractRange.prototype.getContainer = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getContainerElement = function() {
  var node = this.getContainer();
  return node.nodeType == goog.dom.NodeType.ELEMENT ? node : node.parentNode;
};
goog.dom.AbstractRange.prototype.getStartNode = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getStartOffset = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getStartPosition = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getEndNode = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getEndOffset = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getEndPosition = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getAnchorNode = function() {
  return this.isReversed() ? this.getEndNode() : this.getStartNode();
};
goog.dom.AbstractRange.prototype.getAnchorOffset = function() {
  return this.isReversed() ? this.getEndOffset() : this.getStartOffset();
};
goog.dom.AbstractRange.prototype.getFocusNode = function() {
  return this.isReversed() ? this.getStartNode() : this.getEndNode();
};
goog.dom.AbstractRange.prototype.getFocusOffset = function() {
  return this.isReversed() ? this.getStartOffset() : this.getEndOffset();
};
goog.dom.AbstractRange.prototype.isReversed = function() {
  return false;
};
goog.dom.AbstractRange.prototype.getDocument = function() {
  return goog.dom.getOwnerDocument(goog.userAgent.IE ? this.getContainer() : this.getStartNode());
};
goog.dom.AbstractRange.prototype.getWindow = function() {
  return goog.dom.getWindow(this.getDocument());
};
goog.dom.AbstractRange.prototype.containsRange = goog.abstractMethod;
goog.dom.AbstractRange.prototype.containsNode = goog.abstractMethod;
goog.dom.AbstractRange.prototype.isRangeInDocument = goog.abstractMethod;
goog.dom.AbstractRange.prototype.isCollapsed = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getText = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getHtmlFragment = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getValidHtml = goog.abstractMethod;
goog.dom.AbstractRange.prototype.getPastableHtml = goog.abstractMethod;
goog.dom.AbstractRange.prototype.__iterator__ = goog.abstractMethod;
goog.dom.AbstractRange.prototype.select = goog.abstractMethod;
goog.dom.AbstractRange.prototype.removeContents = goog.abstractMethod;
goog.dom.AbstractRange.prototype.insertNode = goog.abstractMethod;
goog.dom.AbstractRange.prototype.replaceContentsWithNode = function(node) {
  if (!this.isCollapsed()) {
    this.removeContents();
  }
  return this.insertNode(node, true);
};
goog.dom.AbstractRange.prototype.surroundWithNodes = goog.abstractMethod;
goog.dom.AbstractRange.prototype.saveUsingDom = goog.abstractMethod;
goog.dom.AbstractRange.prototype.saveUsingCarets = function() {
  return this.getStartNode() && this.getEndNode() ? new goog.dom.SavedCaretRange(this) : null;
};
goog.dom.AbstractRange.prototype.collapse = goog.abstractMethod;
goog.dom.RangeIterator = function(node, opt_reverse) {
  goog.dom.TagIterator.call(this, node, opt_reverse, true);
};
goog.inherits(goog.dom.RangeIterator, goog.dom.TagIterator);
goog.dom.RangeIterator.prototype.getStartTextOffset = goog.abstractMethod;
goog.dom.RangeIterator.prototype.getEndTextOffset = goog.abstractMethod;
goog.dom.RangeIterator.prototype.getStartNode = goog.abstractMethod;
goog.dom.RangeIterator.prototype.getEndNode = goog.abstractMethod;
goog.dom.RangeIterator.prototype.isLast = goog.abstractMethod;
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");
goog.dom.TextRangeIterator = function(startNode, startOffset, endNode, endOffset, opt_reverse) {
  this.startNode_ = null;
  this.endNode_ = null;
  this.startOffset_ = 0;
  this.endOffset_ = 0;
  var goNext;
  if (startNode) {
    this.startNode_ = startNode;
    this.startOffset_ = startOffset;
    this.endNode_ = endNode;
    this.endOffset_ = endOffset;
    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_ = 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 {
        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);
goog.dom.TextRangeIterator.prototype.getStartTextOffset = function() {
  return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 : this.node == this.startNode_ ? this.startOffset_ : 0;
};
goog.dom.TextRangeIterator.prototype.getEndTextOffset = function() {
  return this.node.nodeType != goog.dom.NodeType.TEXT ? -1 : this.node == this.endNode_ ? this.endOffset_ : this.node.nodeValue.length;
};
goog.dom.TextRangeIterator.prototype.getStartNode = function() {
  return this.startNode_;
};
goog.dom.TextRangeIterator.prototype.setStartNode = function(node) {
  if (!this.isStarted()) {
    this.setPosition(node);
  }
  this.startNode_ = node;
  this.startOffset_ = 0;
};
goog.dom.TextRangeIterator.prototype.getEndNode = function() {
  return this.endNode_;
};
goog.dom.TextRangeIterator.prototype.setEndNode = function(node) {
  this.endNode_ = node;
  this.endOffset_ = 0;
};
goog.dom.TextRangeIterator.prototype.isLast = function() {
  return this.isStarted() && this.node == this.endNode_ && (!this.endOffset_ || !this.isStartTag());
};
goog.dom.TextRangeIterator.prototype.next = function() {
  if (this.isLast()) {
    throw goog.iter.StopIteration;
  }
  return goog.dom.TextRangeIterator.superClass_.next.call(this);
};
goog.dom.TextRangeIterator.prototype.skipTag = function() {
  goog.dom.TextRangeIterator.superClass_.skipTag.apply(this);
  if (goog.dom.contains(this.node, this.endNode_)) {
    throw goog.iter.StopIteration;
  }
};
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);
};
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;
};
goog.provide("goog.dom.RangeEndpoint");
goog.dom.RangeEndpoint = {START:1, END:0};
goog.provide("goog.string.StringBuffer");
goog.string.StringBuffer = function(opt_a1, var_args) {
  if (opt_a1 != null) {
    this.append.apply(this, arguments);
  }
};
goog.string.StringBuffer.prototype.buffer_ = "";
goog.string.StringBuffer.prototype.set = function(s) {
  this.buffer_ = "" + s;
};
goog.string.StringBuffer.prototype.append = function(a1, opt_a2, var_args) {
  this.buffer_ += String(a1);
  if (opt_a2 != null) {
    for (var i = 1; i < arguments.length; i++) {
      this.buffer_ += arguments[i];
    }
  }
  return this;
};
goog.string.StringBuffer.prototype.clear = function() {
  this.buffer_ = "";
};
goog.string.StringBuffer.prototype.getLength = function() {
  return this.buffer_.length;
};
goog.string.StringBuffer.prototype.toString = function() {
  return this.buffer_;
};
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");
goog.dom.browserrange.AbstractRange = function() {
};
goog.dom.browserrange.AbstractRange.prototype.clone = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.getBrowserRange = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.getContainer = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.getStartNode = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.getStartOffset = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.getStartPosition = function() {
  return this.getPosition_(true);
};
goog.dom.browserrange.AbstractRange.prototype.getEndNode = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.getEndOffset = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.getEndPosition = function() {
  return this.getPosition_(false);
};
goog.dom.browserrange.AbstractRange.prototype.getPosition_ = function(start) {
  goog.asserts.assert(this.range_.getClientRects, "Getting selection coordinates is not supported.");
  var rects = this.range_.getClientRects();
  if (rects.length) {
    var r = start ? rects[0] : goog.array.peek(rects);
    return new goog.math.Coordinate(start ? r.left : r.right, start ? r.top : r.bottom);
  }
  return null;
};
goog.dom.browserrange.AbstractRange.prototype.compareBrowserRangeEndpoints = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.containsRange = function(abstractRange, opt_allowPartial) {
  var checkPartial = opt_allowPartial && !abstractRange.isCollapsed();
  var range = abstractRange.getBrowserRange();
  var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END;
  try {
    if (checkPartial) {
      return this.compareBrowserRangeEndpoints(range, end, start) >= 0 && this.compareBrowserRangeEndpoints(range, start, end) <= 0;
    } else {
      return this.compareBrowserRangeEndpoints(range, end, end) >= 0 && this.compareBrowserRangeEndpoints(range, start, start) <= 0;
    }
  } catch (e) {
    if (!goog.userAgent.IE) {
      throw e;
    }
    return false;
  }
};
goog.dom.browserrange.AbstractRange.prototype.containsNode = function(node, opt_allowPartial) {
  return this.containsRange(goog.dom.browserrange.createRangeFromNodeContents(node), opt_allowPartial);
};
goog.dom.browserrange.AbstractRange.prototype.isCollapsed = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.getText = goog.abstractMethod;
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) {
            output.append(html);
          } else {
            var index = html.lastIndexOf("<");
            output.append(index ? html.substr(0, index) : html);
          }
        }
      }
    }
  }, this);
  return output.toString();
};
goog.dom.browserrange.AbstractRange.prototype.getValidHtml = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.__iterator__ = function(opt_keys) {
  return new goog.dom.TextRangeIterator(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset());
};
goog.dom.browserrange.AbstractRange.prototype.select = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.removeContents = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.surroundContents = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.insertNode = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.surroundWithNodes = goog.abstractMethod;
goog.dom.browserrange.AbstractRange.prototype.collapse = goog.abstractMethod;
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");
goog.dom.browserrange.W3cRange = function(range) {
  this.range_ = range;
};
goog.inherits(goog.dom.browserrange.W3cRange, goog.dom.browserrange.AbstractRange);
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 {
    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) && goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
        leaf = tempNode;
      }
      nodeRange.setStart(leaf, 0);
      leaf = node;
      while ((tempNode = leaf.lastChild) && goog.dom.browserrange.canContainRangeEndpoint(tempNode)) {
        leaf = tempNode;
      }
      nodeRange.setEnd(leaf, leaf.nodeType == goog.dom.NodeType.ELEMENT ? leaf.childNodes.length : leaf.length);
    }
  }
  return nodeRange;
};
goog.dom.browserrange.W3cRange.getBrowserRangeForNodes = function(startNode, startOffset, endNode, endOffset) {
  var nodeRange = goog.dom.getOwnerDocument(startNode).createRange();
  nodeRange.setStart(startNode, startOffset);
  nodeRange.setEnd(endNode, endOffset);
  return nodeRange;
};
goog.dom.browserrange.W3cRange.createFromNodeContents = function(node) {
  return new goog.dom.browserrange.W3cRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node));
};
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));
};
goog.dom.browserrange.W3cRange.prototype.clone = function() {
  return new this.constructor(this.range_.cloneRange());
};
goog.dom.browserrange.W3cRange.prototype.getBrowserRange = function() {
  return this.range_;
};
goog.dom.browserrange.W3cRange.prototype.getContainer = function() {
  return this.range_.commonAncestorContainer;
};
goog.dom.browserrange.W3cRange.prototype.getStartNode = function() {
  return this.range_.startContainer;
};
goog.dom.browserrange.W3cRange.prototype.getStartOffset = function() {
  return this.range_.startOffset;
};
goog.dom.browserrange.W3cRange.prototype.getEndNode = function() {
  return this.range_.endContainer;
};
goog.dom.browserrange.W3cRange.prototype.getEndOffset = function() {
  return this.range_.endOffset;
};
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, range);
};
goog.dom.browserrange.W3cRange.prototype.isCollapsed = function() {
  return this.range_.collapsed;
};
goog.dom.browserrange.W3cRange.prototype.getText = function() {
  return this.range_.toString();
};
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, "<")) {
    return result;
  }
  var container = this.getContainer();
  container = container.nodeType == goog.dom.NodeType.ELEMENT ? container : container.parentNode;
  var html = goog.dom.getOuterHtml(container.cloneNode(false));
  return html.replace(">", ">" + result);
};
goog.dom.browserrange.W3cRange.prototype.select = function(reverse) {
  var win = goog.dom.getWindow(goog.dom.getOwnerDocument(this.getStartNode()));
  this.selectInternal(win.getSelection(), reverse);
};
goog.dom.browserrange.W3cRange.prototype.selectInternal = function(selection, reverse) {
  selection.removeAllRanges();
  selection.addRange(this.range_);
};
goog.dom.browserrange.W3cRange.prototype.removeContents = function() {
  var range = this.range_;
  range.extractContents();
  if (range.startContainer.hasChildNodes()) {
    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.EDGE_OR_IE) {
    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);
      range.setStart(startNode, startOffset);
      range.setEnd(endNode, endOffset);
    }
  }
};
goog.dom.browserrange.W3cRange.prototype.surroundContents = function(element) {
  this.range_.surroundContents(element);
  return element;
};
goog.dom.browserrange.W3cRange.prototype.insertNode = function(node, before) {
  var range = this.range_.cloneRange();
  range.collapse(before);
  range.insertNode(node);
  range.detach();
  return node;
};
goog.dom.browserrange.W3cRange.prototype.surroundWithNodes = function(startNode, endNode) {
  var win = goog.dom.getWindow(goog.dom.getOwnerDocument(this.getStartNode()));
  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) {
    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));
      }
    }
    goog.dom.Range.createFromNodes(sNode, sOffset, eNode, eOffset).select();
  }
};
goog.dom.browserrange.W3cRange.prototype.collapse = function(toStart) {
  this.range_.collapse(toStart);
};
goog.provide("goog.dom.browserrange.GeckoRange");
goog.require("goog.dom.browserrange.W3cRange");
goog.dom.browserrange.GeckoRange = function(range) {
  goog.dom.browserrange.W3cRange.call(this, range);
};
goog.inherits(goog.dom.browserrange.GeckoRange, goog.dom.browserrange.W3cRange);
goog.dom.browserrange.GeckoRange.createFromNodeContents = function(node) {
  return new goog.dom.browserrange.GeckoRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node));
};
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));
};
goog.dom.browserrange.GeckoRange.prototype.selectInternal = function(selection, reversed) {
  if (!reversed || this.isCollapsed()) {
    goog.dom.browserrange.GeckoRange.base(this, "selectInternal", selection, reversed);
  } else {
    selection.collapse(this.getEndNode(), this.getEndOffset());
    selection.extend(this.getStartNode(), this.getStartOffset());
  }
};
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");
goog.dom.browserrange.IeRange = function(range, doc) {
  this.parentNode_ = null;
  this.startNode_ = null;
  this.endNode_ = null;
  this.startOffset_ = -1;
  this.endOffset_ = -1;
  this.range_ = range;
  this.doc_ = doc;
};
goog.inherits(goog.dom.browserrange.IeRange, goog.dom.browserrange.AbstractRange);
goog.dom.browserrange.IeRange.logger_ = goog.log.getLogger("goog.dom.browserrange.IeRange");
goog.dom.browserrange.IeRange.getBrowserRangeForNode_ = function(node) {
  var nodeRange = goog.dom.getOwnerDocument(node).body.createTextRange();
  if (node.nodeType == goog.dom.NodeType.ELEMENT) {
    nodeRange.moveToElementText(node);
    if (goog.dom.browserrange.canContainRangeEndpoint(node) && !node.childNodes.length) {
      nodeRange.collapse(false);
    }
  } else {
    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) {
          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;
};
goog.dom.browserrange.IeRange.getBrowserRangeForNodes_ = function(startNode, startOffset, endNode, endOffset) {
  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);
  if (startOffset) {
    leftRange.move("character", startOffset);
  }
  if (startNode == endNode && startOffset == endOffset) {
    leftRange.collapse(true);
    return leftRange;
  }
  if (collapse) {
    leftRange.collapse(false);
  }
  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);
  }
  leftRange.setEndPoint("EndToEnd", rightRange);
  return leftRange;
};
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 {
    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;
};
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;
};
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;
};
goog.dom.browserrange.IeRange.prototype.getBrowserRange = function() {
  return this.range_;
};
goog.dom.browserrange.IeRange.prototype.clearCachedValues_ = function() {
  this.parentNode_ = this.startNode_ = this.endNode_ = null;
  this.startOffset_ = this.endOffset_ = -1;
};
goog.dom.browserrange.IeRange.prototype.getContainer = function() {
  if (!this.parentNode_) {
    var selectText = this.range_.text;
    var range = this.range_.duplicate();
    var rightTrimmedSelectText = selectText.replace(/ +$/, "");
    var numSpacesAtEnd = selectText.length - rightTrimmedSelectText.length;
    if (numSpacesAtEnd) {
      range.moveEnd("character", -numSpacesAtEnd);
    }
    var parent = range.parentElement();
    var htmlText = range.htmlText;
    var htmlTextLen = goog.string.stripNewlines(htmlText).length;
    if (this.isCollapsed() && htmlTextLen > 0) {
      return this.parentNode_ = parent;
    }
    while (htmlTextLen > goog.string.stripNewlines(parent.outerHTML).length) {
      parent = parent.parentNode;
    }
    while (parent.childNodes.length == 1 && parent.innerText == goog.dom.browserrange.IeRange.getNodeText_(parent.firstChild)) {
      if (!goog.dom.browserrange.canContainRangeEndpoint(parent.firstChild)) {
        break;
      }
      parent = parent.firstChild;
    }
    if (selectText.length == 0) {
      parent = this.findDeepestContainer_(parent);
    }
    this.parentNode_ = parent;
  }
  return this.parentNode_;
};
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;
      var isChildRangeErratic = childRange.htmlText != child.outerHTML;
      var isNativeInRangeErratic = this.isCollapsed() && isChildRangeErratic;
      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;
};
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_;
};
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_;
};
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_;
};
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_;
};
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);
};
goog.dom.browserrange.IeRange.prototype.getEndpointNode_ = function(endpoint, opt_node) {
  var node = opt_node || this.getContainer();
  if (!node || !node.firstChild) {
    return node;
  }
  var start = goog.dom.RangeEndpoint.START, end = goog.dom.RangeEndpoint.END;
  var isStartEndpoint = endpoint == start;
  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) {
      continue;
    }
    var ieRange = childRange.getBrowserRange();
    if (this.isCollapsed()) {
      if (!goog.dom.browserrange.canContainRangeEndpoint(child)) {
        if (this.compareBrowserRangeEndpoints(ieRange, start, start) == 0) {
          this.startOffset_ = this.endOffset_ = i;
          return node;
        }
      } else {
        if (childRange.containsRange(this)) {
          return this.getEndpointNode_(endpoint, child);
        }
      }
    } else {
      if (this.containsRange(childRange)) {
        if (!goog.dom.browserrange.canContainRangeEndpoint(child)) {
          if (isStartEndpoint) {
            this.startOffset_ = i;
          } else {
            this.endOffset_ = i + 1;
          }
          return node;
        }
        return this.getEndpointNode_(endpoint, child);
      } else {
        if (this.compareBrowserRangeEndpoints(ieRange, start, end) < 0 && this.compareBrowserRangeEndpoints(ieRange, end, start) > 0) {
          return this.getEndpointNode_(endpoint, child);
        }
      }
    }
  }
  return node;
};
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());
};
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) {
    var children = container.childNodes;
    var len = children.length;
    var edge = isStartEndpoint ? 0 : len - 1;
    var sign = isStartEndpoint ? 1 : -1;
    for (var i = edge; i >= 0 && i < len; i += sign) {
      var child = children[i];
      if (goog.dom.browserrange.canContainRangeEndpoint(child)) {
        continue;
      }
      var endPointCompare = this.compareNodeEndpoints_(child, endpoint, endpoint);
      if (endPointCompare == 0) {
        return isStartEndpoint ? i : i + 1;
      }
    }
    return i == -1 ? 0 : i;
  } else {
    var range = this.range_.duplicate();
    var nodeRange = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(container);
    range.setEndPoint(isStartEndpoint ? "EndToEnd" : "StartToStart", nodeRange);
    var rangeLength = range.text.length;
    return isStartEndpoint ? container.length - rangeLength : rangeLength;
  }
};
goog.dom.browserrange.IeRange.getNodeText_ = function(node) {
  return node.nodeType == goog.dom.NodeType.TEXT ? node.nodeValue : node.innerText;
};
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);
};
goog.dom.browserrange.IeRange.prototype.isCollapsed = function() {
  return this.range_.compareEndPoints("StartToEnd", this.range_) == 0;
};
goog.dom.browserrange.IeRange.prototype.getText = function() {
  return this.range_.text;
};
goog.dom.browserrange.IeRange.prototype.getValidHtml = function() {
  return this.range_.htmlText;
};
goog.dom.browserrange.IeRange.prototype.select = function(opt_reverse) {
  this.range_.select();
};
goog.dom.browserrange.IeRange.prototype.removeContents = function() {
  if (!this.isCollapsed() && this.range_.htmlText) {
    var startNode = this.getStartNode();
    var endNode = this.getEndNode();
    var oldText = this.range_.text;
    var clone = this.range_.duplicate();
    clone.moveStart("character", 1);
    clone.moveStart("character", -1);
    if (clone.text == oldText) {
      this.range_ = clone;
    }
    this.range_.text = "";
    this.clearCachedValues_();
    var newStartNode = this.getStartNode();
    var newStartOffset = this.getStartOffset();
    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);
        this.range_ = goog.dom.browserrange.IeRange.getBrowserRangeForNode_(newStartNode);
        this.range_.move("character", newStartOffset);
        this.clearCachedValues_();
      }
    } catch (e) {
    }
  }
};
goog.dom.browserrange.IeRange.getDomHelper_ = function(range) {
  return goog.dom.getDomHelper(range.parentElement());
};
goog.dom.browserrange.IeRange.pasteElement_ = function(range, element, opt_domHelper) {
  opt_domHelper = opt_domHelper || goog.dom.browserrange.IeRange.getDomHelper_(range);
  var id;
  var originalId = id = element.id;
  if (!id) {
    id = element.id = goog.string.createUniqueString();
  }
  range.pasteHTML(element.outerHTML);
  element = opt_domHelper.getElement(id);
  if (element) {
    if (!originalId) {
      element.removeAttribute("id");
    }
  }
  return element;
};
goog.dom.browserrange.IeRange.prototype.surroundContents = function(element) {
  goog.dom.removeNode(element);
  element.innerHTML = this.range_.htmlText;
  element = goog.dom.browserrange.IeRange.pasteElement_(this.range_, element);
  if (element) {
    this.range_.moveToElementText(element);
  }
  this.clearCachedValues_();
  return element;
};
goog.dom.browserrange.IeRange.insertNode_ = function(clone, node, before, opt_domHelper) {
  opt_domHelper = opt_domHelper || goog.dom.browserrange.IeRange.getDomHelper_(clone);
  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, node, opt_domHelper);
  if (isNonElement) {
    var newNonElement = node.firstChild;
    opt_domHelper.flattenElement(node);
    node = newNonElement;
  }
  return node;
};
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;
};
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_();
};
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_;
  }
};
goog.provide("goog.dom.browserrange.OperaRange");
goog.require("goog.dom.browserrange.W3cRange");
goog.dom.browserrange.OperaRange = function(range) {
  goog.dom.browserrange.W3cRange.call(this, range);
};
goog.inherits(goog.dom.browserrange.OperaRange, goog.dom.browserrange.W3cRange);
goog.dom.browserrange.OperaRange.createFromNodeContents = function(node) {
  return new goog.dom.browserrange.OperaRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node));
};
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));
};
goog.dom.browserrange.OperaRange.prototype.selectInternal = function(selection, reversed) {
  selection.collapse(this.getStartNode(), this.getStartOffset());
  if (this.getEndNode() != this.getStartNode() || this.getEndOffset() != this.getStartOffset()) {
    selection.extend(this.getEndNode(), this.getEndOffset());
  }
  if (selection.rangeCount == 0) {
    selection.addRange(this.range_);
  }
};
goog.provide("goog.dom.browserrange.WebKitRange");
goog.require("goog.dom.RangeEndpoint");
goog.require("goog.dom.browserrange.W3cRange");
goog.require("goog.userAgent");
goog.dom.browserrange.WebKitRange = function(range) {
  goog.dom.browserrange.W3cRange.call(this, range);
};
goog.inherits(goog.dom.browserrange.WebKitRange, goog.dom.browserrange.W3cRange);
goog.dom.browserrange.WebKitRange.createFromNodeContents = function(node) {
  return new goog.dom.browserrange.WebKitRange(goog.dom.browserrange.W3cRange.getBrowserRangeForNode(node));
};
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));
};
goog.dom.browserrange.WebKitRange.prototype.compareBrowserRangeEndpoints = function(range, thisEndpoint, otherEndpoint) {
  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 : thisEndpoint == goog.dom.RangeEndpoint.START ? goog.global["Range"].START_TO_END : goog.global["Range"].END_TO_END, range);
};
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());
  }
};
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");
goog.dom.browserrange.Error = {NOT_IMPLEMENTED:"Not Implemented"};
goog.dom.browserrange.createRange = function(range) {
  if (goog.dom.BrowserFeature.LEGACY_IE_RANGES) {
    return new goog.dom.browserrange.IeRange(range, goog.dom.getOwnerDocument(range.parentElement()));
  } else {
    if (goog.userAgent.WEBKIT) {
      return new goog.dom.browserrange.WebKitRange(range);
    } else {
      if (goog.userAgent.GECKO) {
        return new goog.dom.browserrange.GeckoRange(range);
      } else {
        if (goog.userAgent.OPERA) {
          return new goog.dom.browserrange.OperaRange(range);
        } else {
          return new goog.dom.browserrange.W3cRange(range);
        }
      }
    }
  }
};
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 {
          return goog.dom.browserrange.W3cRange.createFromNodeContents(node);
        }
      }
    }
  }
};
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 {
          return goog.dom.browserrange.W3cRange.createFromNodes(startNode, startOffset, endNode, endOffset);
        }
      }
    }
  }
};
goog.dom.browserrange.canContainRangeEndpoint = function(node) {
  return goog.dom.canHaveChildren(node) || node.nodeType == goog.dom.NodeType.TEXT;
};
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");
goog.dom.TextRange = function() {
  this.browserRangeWrapper_ = null;
  this.startNode_ = null;
  this.startOffset_ = null;
  this.endNode_ = null;
  this.endOffset_ = null;
  this.isReversed_ = false;
};
goog.inherits(goog.dom.TextRange, goog.dom.AbstractRange);
goog.dom.TextRange.createFromBrowserRange = function(range, opt_isReversed) {
  return goog.dom.TextRange.createFromBrowserRangeWrapper_(goog.dom.browserrange.createRange(range), opt_isReversed);
};
goog.dom.TextRange.createFromBrowserRangeWrapper_ = function(browserRange, opt_isReversed) {
  var range = new goog.dom.TextRange;
  range.browserRangeWrapper_ = browserRange;
  range.isReversed_ = !!opt_isReversed;
  return range;
};
goog.dom.TextRange.createFromNodeContents = function(node, opt_isReversed) {
  return goog.dom.TextRange.createFromBrowserRangeWrapper_(goog.dom.browserrange.createRangeFromNodeContents(node), opt_isReversed);
};
goog.dom.TextRange.createFromNodes = function(anchorNode, anchorOffset, focusNode, focusOffset) {
  var range = new goog.dom.TextRange;
  range.isReversed_ = goog.dom.Range.isReversed(anchorNode, anchorOffset, focusNode, focusOffset);
  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;
  }
  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;
};
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;
};
goog.dom.TextRange.prototype.getType = function() {
  return goog.dom.RangeType.TEXT;
};
goog.dom.TextRange.prototype.getBrowserRangeObject = function() {
  return this.getBrowserRangeWrapper_().getBrowserRange();
};
goog.dom.TextRange.prototype.setBrowserRangeObject = function(nativeRange) {
  if (goog.dom.AbstractRange.isNativeControlRange(nativeRange)) {
    return false;
  }
  this.browserRangeWrapper_ = goog.dom.browserrange.createRange(nativeRange);
  this.clearCachedValues_();
  return true;
};
goog.dom.TextRange.prototype.clearCachedValues_ = function() {
  this.startNode_ = this.startOffset_ = this.endNode_ = this.endOffset_ = null;
};
goog.dom.TextRange.prototype.getTextRangeCount = function() {
  return 1;
};
goog.dom.TextRange.prototype.getTextRange = function(i) {
  return this;
};
goog.dom.TextRange.prototype.getBrowserRangeWrapper_ = function() {
  return this.browserRangeWrapper_ || (this.browserRangeWrapper_ = goog.dom.browserrange.createRangeFromNodes(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset()));
};
goog.dom.TextRange.prototype.getContainer = function() {
  return this.getBrowserRangeWrapper_().getContainer();
};
goog.dom.TextRange.prototype.getStartNode = function() {
  return this.startNode_ || (this.startNode_ = this.getBrowserRangeWrapper_().getStartNode());
};
goog.dom.TextRange.prototype.getStartOffset = function() {
  return this.startOffset_ != null ? this.startOffset_ : this.startOffset_ = this.getBrowserRangeWrapper_().getStartOffset();
};
goog.dom.TextRange.prototype.getStartPosition = function() {
  return this.getBrowserRangeWrapper_().getStartPosition();
};
goog.dom.TextRange.prototype.getEndNode = function() {
  return this.endNode_ || (this.endNode_ = this.getBrowserRangeWrapper_().getEndNode());
};
goog.dom.TextRange.prototype.getEndOffset = function() {
  return this.endOffset_ != null ? this.endOffset_ : this.endOffset_ = this.getBrowserRangeWrapper_().getEndOffset();
};
goog.dom.TextRange.prototype.getEndPosition = function() {
  return this.getBrowserRangeWrapper_().getEndPosition();
};
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;
};
goog.dom.TextRange.prototype.isReversed = function() {
  return this.isReversed_;
};
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;
};
goog.dom.TextRange.prototype.containsNode = function(node, opt_allowPartial) {
  return this.containsRange(goog.dom.TextRange.createFromNodeContents(node), opt_allowPartial);
};
goog.dom.TextRange.isAttachedNode = function(node) {
  if (goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9)) {
    var returnValue = false;
    try {
      returnValue = node.parentNode;
    } catch (e) {
    }
    return !!returnValue;
  } else {
    return goog.dom.contains(node.ownerDocument.body, node);
  }
};
goog.dom.TextRange.prototype.isRangeInDocument = function() {
  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());
};
goog.dom.TextRange.prototype.isCollapsed = function() {
  return this.getBrowserRangeWrapper_().isCollapsed();
};
goog.dom.TextRange.prototype.getText = function() {
  return this.getBrowserRangeWrapper_().getText();
};
goog.dom.TextRange.prototype.getHtmlFragment = function() {
  return this.getBrowserRangeWrapper_().getHtmlFragment();
};
goog.dom.TextRange.prototype.getValidHtml = function() {
  return this.getBrowserRangeWrapper_().getValidHtml();
};
goog.dom.TextRange.prototype.getPastableHtml = function() {
  var html = this.getValidHtml();
  if (html.match(/^\s*<td\b/i)) {
    html = "<table><tbody><tr>" + html + "</tr></tbody></table>";
  } else {
    if (html.match(/^\s*<tr\b/i)) {
      html = "<table><tbody>" + html + "</tbody></table>";
    } else {
      if (html.match(/^\s*<tbody\b/i)) {
        html = "<table>" + html + "</table>";
      } else {
        if (html.match(/^\s*<li\b/i)) {
          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;
};
goog.dom.TextRange.prototype.__iterator__ = function(opt_keys) {
  return new goog.dom.TextRangeIterator(this.getStartNode(), this.getStartOffset(), this.getEndNode(), this.getEndOffset());
};
goog.dom.TextRange.prototype.select = function() {
  this.getBrowserRangeWrapper_().select(this.isReversed_);
};
goog.dom.TextRange.prototype.removeContents = function() {
  this.getBrowserRangeWrapper_().removeContents();
  this.clearCachedValues_();
};
goog.dom.TextRange.prototype.surroundContents = function(element) {
  var output = this.getBrowserRangeWrapper_().surroundContents(element);
  this.clearCachedValues_();
  return output;
};
goog.dom.TextRange.prototype.insertNode = function(node, before) {
  var output = this.getBrowserRangeWrapper_().insertNode(node, before);
  this.clearCachedValues_();
  return output;
};
goog.dom.TextRange.prototype.surroundWithNodes = function(startNode, endNode) {
  this.getBrowserRangeWrapper_().surroundWithNodes(startNode, endNode);
  this.clearCachedValues_();
};
goog.dom.TextRange.prototype.saveUsingDom = function() {
  return new goog.dom.DomSavedTextRange_(this);
};
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_;
  }
  this.isReversed_ = false;
};
goog.dom.DomSavedTextRange_ = function(range) {
  goog.dom.DomSavedTextRange_.base(this, "constructor");
  this.anchorNode_ = range.getAnchorNode();
  this.anchorOffset_ = range.getAnchorOffset();
  this.focusNode_ = range.getFocusNode();
  this.focusOffset_ = range.getFocusOffset();
};
goog.inherits(goog.dom.DomSavedTextRange_, goog.dom.SavedRange);
goog.dom.DomSavedTextRange_.prototype.restoreInternal = function() {
  return goog.dom.Range.createFromNodes(this.anchorNode_, this.anchorOffset_, this.focusNode_, this.focusOffset_);
};
goog.dom.DomSavedTextRange_.prototype.disposeInternal = function() {
  goog.dom.DomSavedTextRange_.superClass_.disposeInternal.call(this);
  this.anchorNode_ = null;
  this.focusNode_ = null;
};
goog.provide("goog.dom.AbstractMultiRange");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.dom.AbstractRange");
goog.require("goog.dom.TextRange");
goog.dom.AbstractMultiRange = function() {
};
goog.inherits(goog.dom.AbstractMultiRange, goog.dom.AbstractRange);
goog.dom.AbstractMultiRange.prototype.containsRange = function(otherRange, opt_allowPartial) {
  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);
    });
  });
};
goog.dom.AbstractMultiRange.prototype.containsNode = function(node, opt_allowPartial) {
  return this.containsRange(goog.dom.TextRange.createFromNodeContents(node), opt_allowPartial);
};
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;
};
goog.dom.AbstractMultiRange.prototype.surroundWithNodes = function(startNode, endNode) {
  this.insertNode(startNode, true);
  this.insertNode(endNode, false);
};
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");
goog.dom.ControlRange = function() {
  this.range_ = null;
  this.elements_ = null;
  this.sortedElements_ = null;
};
goog.inherits(goog.dom.ControlRange, goog.dom.AbstractMultiRange);
goog.dom.ControlRange.createFromBrowserRange = function(controlRange) {
  var range = new goog.dom.ControlRange;
  range.range_ = controlRange;
  return range;
};
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);
};
goog.dom.ControlRange.prototype.clearCachedValues_ = function() {
  this.elements_ = null;
  this.sortedElements_ = null;
};
goog.dom.ControlRange.prototype.clone = function() {
  return goog.dom.ControlRange.createFromElements.apply(this, this.getElements());
};
goog.dom.ControlRange.prototype.getType = function() {
  return goog.dom.RangeType.CONTROL;
};
goog.dom.ControlRange.prototype.getBrowserRangeObject = function() {
  return this.range_ || document.body.createControlRange();
};
goog.dom.ControlRange.prototype.setBrowserRangeObject = function(nativeRange) {
  if (!goog.dom.AbstractRange.isNativeControlRange(nativeRange)) {
    return false;
  }
  this.range_ = nativeRange;
  return true;
};
goog.dom.ControlRange.prototype.getTextRangeCount = function() {
  return this.range_ ? this.range_.length : 0;
};
goog.dom.ControlRange.prototype.getTextRange = function(i) {
  return goog.dom.TextRange.createFromNodeContents(this.range_.item(i));
};
goog.dom.ControlRange.prototype.getContainer = function() {
  return goog.dom.findCommonAncestor.apply(null, this.getElements());
};
goog.dom.ControlRange.prototype.getStartNode = function() {
  return this.getSortedElements()[0];
};
goog.dom.ControlRange.prototype.getStartOffset = function() {
  return 0;
};
goog.dom.ControlRange.prototype.getEndNode = function() {
  var sorted = this.getSortedElements();
  var startsLast = goog.array.peek(sorted);
  return goog.array.find(sorted, function(el) {
    return goog.dom.contains(el, startsLast);
  });
};
goog.dom.ControlRange.prototype.getEndOffset = function() {
  return this.getEndNode().childNodes.length;
};
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_;
};
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_;
};
goog.dom.ControlRange.prototype.isRangeInDocument = function() {
  var returnValue = false;
  try {
    returnValue = goog.array.every(this.getElements(), function(element) {
      return goog.userAgent.IE ? !!element.parentNode : goog.dom.contains(element.ownerDocument.body, element);
    });
  } catch (e) {
  }
  return returnValue;
};
goog.dom.ControlRange.prototype.isCollapsed = function() {
  return !this.range_ || !this.range_.length;
};
goog.dom.ControlRange.prototype.getText = function() {
  return "";
};
goog.dom.ControlRange.prototype.getHtmlFragment = function() {
  return goog.array.map(this.getSortedElements(), goog.dom.getOuterHtml).join("");
};
goog.dom.ControlRange.prototype.getValidHtml = function() {
  return this.getHtmlFragment();
};
goog.dom.ControlRange.prototype.getPastableHtml = goog.dom.ControlRange.prototype.getValidHtml;
goog.dom.ControlRange.prototype.__iterator__ = function(opt_keys) {
  return new goog.dom.ControlRangeIterator(this);
};
goog.dom.ControlRange.prototype.select = function() {
  if (this.range_) {
    this.range_.select();
  }
};
goog.dom.ControlRange.prototype.removeContents = function() {
  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);
  }
};
goog.dom.ControlRange.prototype.replaceContentsWithNode = function(node) {
  var result = this.insertNode(node, true);
  if (!this.isCollapsed()) {
    this.removeContents();
  }
  return result;
};
goog.dom.ControlRange.prototype.saveUsingDom = function() {
  return new goog.dom.DomSavedControlRange_(this);
};
goog.dom.ControlRange.prototype.collapse = function(toAnchor) {
  this.range_ = null;
  this.clearCachedValues_();
};
goog.dom.DomSavedControlRange_ = function(range) {
  this.elements_ = range.getElements();
};
goog.inherits(goog.dom.DomSavedControlRange_, goog.dom.SavedRange);
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);
};
goog.dom.DomSavedControlRange_.prototype.disposeInternal = function() {
  goog.dom.DomSavedControlRange_.superClass_.disposeInternal.call(this);
  delete this.elements_;
};
goog.dom.ControlRangeIterator = function(range) {
  this.startNode_ = null;
  this.endNode_ = null;
  this.elements_ = null;
  if (range) {
    this.elements_ = range.getSortedElements();
    this.startNode_ = this.elements_.shift();
    this.endNode_ = goog.array.peek(this.elements_) || this.startNode_;
  }
  goog.dom.ControlRangeIterator.base(this, "constructor", this.startNode_, false);
};
goog.inherits(goog.dom.ControlRangeIterator, goog.dom.RangeIterator);
goog.dom.ControlRangeIterator.prototype.getStartTextOffset = function() {
  return 0;
};
goog.dom.ControlRangeIterator.prototype.getEndTextOffset = function() {
  return 0;
};
goog.dom.ControlRangeIterator.prototype.getStartNode = function() {
  return this.startNode_;
};
goog.dom.ControlRangeIterator.prototype.getEndNode = function() {
  return this.endNode_;
};
goog.dom.ControlRangeIterator.prototype.isLast = function() {
  return !this.depth && !this.elements_.length;
};
goog.dom.ControlRangeIterator.prototype.next = function() {
  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;
    }
  }
  return goog.dom.ControlRangeIterator.superClass_.next.call(this);
};
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);
};
goog.dom.ControlRangeIterator.prototype.clone = function() {
  var copy = new goog.dom.ControlRangeIterator(null);
  copy.copyFrom(this);
  return copy;
};
goog.provide("goog.dom.MultiRange");
goog.provide("goog.dom.MultiRangeIterator");
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.TextRange");
goog.require("goog.iter");
goog.require("goog.iter.StopIteration");
goog.require("goog.log");
goog.dom.MultiRange = function() {
  this.logger_ = goog.log.getLogger("goog.dom.MultiRange");
  this.browserRanges_ = [];
  this.ranges_ = [];
  this.sortedRanges_ = null;
  this.container_ = null;
};
goog.inherits(goog.dom.MultiRange, goog.dom.AbstractMultiRange);
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;
};
goog.dom.MultiRange.createFromBrowserRanges = function(browserRanges) {
  var range = new goog.dom.MultiRange;
  range.browserRanges_ = goog.array.clone(browserRanges);
  return range;
};
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;
};
goog.dom.MultiRange.prototype.clearCachedValues_ = function() {
  this.ranges_ = [];
  this.sortedRanges_ = null;
  this.container_ = null;
};
goog.dom.MultiRange.prototype.clone = function() {
  return goog.dom.MultiRange.createFromBrowserRanges(this.browserRanges_);
};
goog.dom.MultiRange.prototype.getType = function() {
  return goog.dom.RangeType.MULTI;
};
goog.dom.MultiRange.prototype.getBrowserRangeObject = function() {
  if (this.browserRanges_.length > 1) {
    goog.log.warning(this.logger_, "getBrowserRangeObject called on MultiRange with more than 1 range");
  }
  return this.browserRanges_[0];
};
goog.dom.MultiRange.prototype.setBrowserRangeObject = function(nativeRange) {
  return false;
};
goog.dom.MultiRange.prototype.getTextRangeCount = function() {
  return this.browserRanges_.length;
};
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];
};
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_;
};
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_;
};
goog.dom.MultiRange.prototype.getStartNode = function() {
  return this.getSortedRanges()[0].getStartNode();
};
goog.dom.MultiRange.prototype.getStartOffset = function() {
  return this.getSortedRanges()[0].getStartOffset();
};
goog.dom.MultiRange.prototype.getEndNode = function() {
  return goog.array.peek(this.getSortedRanges()).getEndNode();
};
goog.dom.MultiRange.prototype.getEndOffset = function() {
  return goog.array.peek(this.getSortedRanges()).getEndOffset();
};
goog.dom.MultiRange.prototype.isRangeInDocument = function() {
  return goog.array.every(this.getTextRanges(), function(range) {
    return range.isRangeInDocument();
  });
};
goog.dom.MultiRange.prototype.isCollapsed = function() {
  return this.browserRanges_.length == 0 || this.browserRanges_.length == 1 && this.getTextRange(0).isCollapsed();
};
goog.dom.MultiRange.prototype.getText = function() {
  return goog.array.map(this.getTextRanges(), function(range) {
    return range.getText();
  }).join("");
};
goog.dom.MultiRange.prototype.getHtmlFragment = function() {
  return this.getValidHtml();
};
goog.dom.MultiRange.prototype.getValidHtml = function() {
  return goog.array.map(this.getTextRanges(), function(range) {
    return range.getValidHtml();
  }).join("");
};
goog.dom.MultiRange.prototype.getPastableHtml = function() {
  return this.getValidHtml();
};
goog.dom.MultiRange.prototype.__iterator__ = function(opt_keys) {
  return new goog.dom.MultiRangeIterator(this);
};
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());
  }
};
goog.dom.MultiRange.prototype.removeContents = function() {
  goog.array.forEach(this.getTextRanges(), function(range) {
    range.removeContents();
  });
};
goog.dom.MultiRange.prototype.saveUsingDom = function() {
  return new goog.dom.DomSavedMultiRange_(this);
};
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()];
  }
};
goog.dom.DomSavedMultiRange_ = function(range) {
  this.savedRanges_ = goog.array.map(range.getTextRanges(), function(range) {
    return range.saveUsingDom();
  });
};
goog.inherits(goog.dom.DomSavedMultiRange_, goog.dom.SavedRange);
goog.dom.DomSavedMultiRange_.prototype.restoreInternal = function() {
  var ranges = goog.array.map(this.savedRanges_, function(savedRange) {
    return savedRange.restore();
  });
  return goog.dom.MultiRange.createFromTextRanges(ranges);
};
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_;
};
goog.dom.MultiRangeIterator = function(range) {
  this.iterators_ = null;
  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);
goog.dom.MultiRangeIterator.prototype.getStartTextOffset = function() {
  return this.iterators_[this.currentIdx_].getStartTextOffset();
};
goog.dom.MultiRangeIterator.prototype.getEndTextOffset = function() {
  return this.iterators_[this.currentIdx_].getEndTextOffset();
};
goog.dom.MultiRangeIterator.prototype.getStartNode = function() {
  return this.iterators_[0].getStartNode();
};
goog.dom.MultiRangeIterator.prototype.getEndNode = function() {
  return goog.array.peek(this.iterators_).getEndNode();
};
goog.dom.MultiRangeIterator.prototype.isLast = function() {
  return this.iterators_[this.currentIdx_].isLast();
};
goog.dom.MultiRangeIterator.prototype.next = function() {
  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 {
      this.currentIdx_++;
      return this.next();
    }
  }
};
goog.dom.MultiRangeIterator.prototype.copyFrom = function(other) {
  this.iterators_ = goog.array.clone(other.iterators_);
  goog.dom.MultiRangeIterator.superClass_.copyFrom.call(this, other);
};
goog.dom.MultiRangeIterator.prototype.clone = function() {
  var copy = new goog.dom.MultiRangeIterator(null);
  copy.copyFrom(this);
  return copy;
};
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");
goog.dom.Range.createFromWindow = function(opt_win) {
  var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow(opt_win || window);
  return sel && goog.dom.Range.createFromBrowserSelection(sel);
};
goog.dom.Range.createFromBrowserSelection = function(selection) {
  var range;
  var isReversed = false;
  if (selection.createRange) {
    try {
      range = selection.createRange();
    } catch (e) {
      return null;
    }
  } else {
    if (selection.rangeCount) {
      if (selection.rangeCount > 1) {
        return goog.dom.MultiRange.createFromBrowserSelection(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);
};
goog.dom.Range.createFromBrowserRange = function(range, opt_isReversed) {
  return goog.dom.AbstractRange.isNativeControlRange(range) ? goog.dom.ControlRange.createFromBrowserRange(range) : goog.dom.TextRange.createFromBrowserRange(range, opt_isReversed);
};
goog.dom.Range.createFromNodeContents = function(node, opt_isReversed) {
  return goog.dom.TextRange.createFromNodeContents(node, opt_isReversed);
};
goog.dom.Range.createCaret = function(node, offset) {
  return goog.dom.TextRange.createFromNodes(node, offset, node, offset);
};
goog.dom.Range.createFromNodes = function(anchorNode, anchorOffset, focusNode, focusOffset) {
  return goog.dom.TextRange.createFromNodes(anchorNode, anchorOffset, focusNode, focusOffset);
};
goog.dom.Range.clearSelection = function(opt_win) {
  var sel = goog.dom.AbstractRange.getBrowserSelectionForWindow(opt_win || window);
  if (!sel) {
    return;
  }
  if (sel.empty) {
    try {
      sel.empty();
    } catch (e) {
    }
  } else {
    try {
      sel.removeAllRanges();
    } catch (e$3) {
    }
  }
};
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);
};
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)) {
        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)) {
        return false;
      }
    }
  }
  return (goog.dom.compareNodeOrder(anchorNode, focusNode) || anchorOffset - focusOffset) > 0;
};
goog.provide("goog.a11y.aria.Role");
goog.a11y.aria.Role = {ALERT:"alert", ALERTDIALOG:"alertdialog", APPLICATION:"application", ARTICLE:"article", BANNER:"banner", BUTTON:"button", CHECKBOX:"checkbox", COLUMNHEADER:"columnheader", COMBOBOX:"combobox", COMPLEMENTARY:"complementary", CONTENTINFO:"contentinfo", DEFINITION:"definition", DIALOG:"dialog", DIRECTORY:"directory", DOCUMENT:"document", FORM:"form", GRID:"grid", GRIDCELL:"gridcell", GROUP:"group", HEADING:"heading", IMG:"img", LINK:"link", LIST:"list", LISTBOX:"listbox", LISTITEM:"listitem", 
LOG:"log", MAIN:"main", MARQUEE:"marquee", MATH:"math", MENU:"menu", MENUBAR:"menubar", MENU_ITEM:"menuitem", MENU_ITEM_CHECKBOX:"menuitemcheckbox", MENU_ITEM_RADIO:"menuitemradio", NAVIGATION:"navigation", NOTE:"note", OPTION:"option", PRESENTATION:"presentation", PROGRESSBAR:"progressbar", RADIO:"radio", RADIOGROUP:"radiogroup", REGION:"region", ROW:"row", ROWGROUP:"rowgroup", ROWHEADER:"rowheader", SCROLLBAR:"scrollbar", SEARCH:"search", SEPARATOR:"separator", SLIDER:"slider", SPINBUTTON:"spinbutton", 
STATUS:"status", TAB:"tab", TAB_LIST:"tablist", TAB_PANEL:"tabpanel", TEXTBOX:"textbox", TEXTINFO:"textinfo", TIMER:"timer", TOOLBAR:"toolbar", TOOLTIP:"tooltip", TREE:"tree", TREEGRID:"treegrid", TREEITEM:"treeitem"};
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");
goog.a11y.aria.State = {ACTIVEDESCENDANT:"activedescendant", ATOMIC:"atomic", AUTOCOMPLETE:"autocomplete", BUSY:"busy", CHECKED:"checked", CONTROLS:"controls", DESCRIBEDBY:"describedby", DISABLED:"disabled", DROPEFFECT:"dropeffect", EXPANDED:"expanded", FLOWTO:"flowto", GRABBED:"grabbed", HASPOPUP:"haspopup", HIDDEN:"hidden", INVALID:"invalid", LABEL:"label", LABELLEDBY:"labelledby", LEVEL:"level", LIVE:"live", MULTILINE:"multiline", MULTISELECTABLE:"multiselectable", ORIENTATION:"orientation", OWNS:"owns", 
POSINSET:"posinset", PRESSED:"pressed", READONLY:"readonly", RELEVANT:"relevant", REQUIRED:"required", SELECTED:"selected", SETSIZE:"setsize", SORT:"sort", VALUEMAX:"valuemax", VALUEMIN:"valuemin", VALUENOW:"valuenow", VALUETEXT:"valuetext"};
goog.a11y.aria.AutoCompleteValues = {INLINE:"inline", LIST:"list", BOTH:"both", NONE:"none"};
goog.a11y.aria.DropEffectValues = {COPY:"copy", MOVE:"move", LINK:"link", EXECUTE:"execute", POPUP:"popup", NONE:"none"};
goog.a11y.aria.LivePriority = {OFF:"off", POLITE:"polite", ASSERTIVE:"assertive"};
goog.a11y.aria.OrientationValues = {VERTICAL:"vertical", HORIZONTAL:"horizontal"};
goog.a11y.aria.RelevantValues = {ADDITIONS:"additions", REMOVALS:"removals", TEXT:"text", ALL:"all"};
goog.a11y.aria.SortValues = {ASCENDING:"ascending", DESCENDING:"descending", NONE:"none", OTHER:"other"};
goog.a11y.aria.CheckedValues = {TRUE:"true", FALSE:"false", MIXED:"mixed", UNDEFINED:"undefined"};
goog.a11y.aria.ExpandedValues = {TRUE:"true", FALSE:"false", UNDEFINED:"undefined"};
goog.a11y.aria.GrabbedValues = {TRUE:"true", FALSE:"false", UNDEFINED:"undefined"};
goog.a11y.aria.InvalidValues = {FALSE:"false", TRUE:"true", GRAMMAR:"grammar", SPELLING:"spelling"};
goog.a11y.aria.PressedValues = {TRUE:"true", FALSE:"false", MIXED:"mixed", UNDEFINED:"undefined"};
goog.a11y.aria.SelectedValues = {TRUE:"true", FALSE:"false", UNDEFINED:"undefined"};
goog.provide("goog.a11y.aria.datatables");
goog.require("goog.a11y.aria.State");
goog.require("goog.object");
goog.a11y.aria.DefaultStateValueMap_;
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_;
};
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");
goog.a11y.aria.ARIA_PREFIX_ = "aria-";
goog.a11y.aria.ROLE_ATTRIBUTE_ = "role";
goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_ = goog.object.createSet([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]);
goog.a11y.aria.CONTAINER_ROLES_ = [goog.a11y.aria.Role.COMBOBOX, goog.a11y.aria.Role.GRID, goog.a11y.aria.Role.GROUP, goog.a11y.aria.Role.LISTBOX, goog.a11y.aria.Role.MENU, goog.a11y.aria.Role.MENUBAR, goog.a11y.aria.Role.RADIOGROUP, goog.a11y.aria.Role.ROW, goog.a11y.aria.Role.ROWGROUP, goog.a11y.aria.Role.TAB_LIST, goog.a11y.aria.Role.TEXTBOX, goog.a11y.aria.Role.TOOLBAR, goog.a11y.aria.Role.TREE, goog.a11y.aria.Role.TREEGRID];
goog.a11y.aria.setRole = function(element, roleName) {
  if (!roleName) {
    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);
  }
};
goog.a11y.aria.getRole = function(element) {
  var role = element.getAttribute(goog.a11y.aria.ROLE_ATTRIBUTE_);
  return role || null;
};
goog.a11y.aria.removeRole = function(element) {
  element.removeAttribute(goog.a11y.aria.ROLE_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();
    if (stateName in defaultValueMap) {
      element.setAttribute(attrStateName, defaultValueMap[stateName]);
    } else {
      element.removeAttribute(attrStateName);
    }
  } else {
    element.setAttribute(attrStateName, value);
  }
};
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, attr);
    return;
  }
  goog.a11y.aria.setState(el, attr, val == "true" ? "false" : "true");
};
goog.a11y.aria.removeState = function(element, stateName) {
  element.removeAttribute(goog.a11y.aria.getAriaAttributeName_(stateName));
};
goog.a11y.aria.getState = function(element, stateName) {
  var attr = element.getAttribute(goog.a11y.aria.getAriaAttributeName_(stateName));
  var isNullOrUndefined = attr == null || attr == undefined;
  return isNullOrUndefined ? "" : String(attr);
};
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);
};
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);
};
goog.a11y.aria.getLabel = function(element) {
  return goog.a11y.aria.getState(element, goog.a11y.aria.State.LABEL);
};
goog.a11y.aria.setLabel = function(element, label) {
  goog.a11y.aria.setState(element, goog.a11y.aria.State.LABEL, label);
};
goog.a11y.aria.assertRoleIsSetInternalUtil = function(element, allowedRoles) {
  if (goog.a11y.aria.TAGS_WITH_ASSUMED_ROLES_[element.tagName]) {
    return;
  }
  var elementRole = 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.");
};
goog.a11y.aria.getStateBoolean = function(element, stateName) {
  var attr = 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";
};
goog.a11y.aria.getStateNumber = function(element, stateName) {
  var attr = element.getAttribute(goog.a11y.aria.getAriaAttributeName_(stateName));
  goog.asserts.assert((attr == null || !isNaN(Number(attr))) && !goog.isBoolean(attr));
  return attr == null ? null : Number(attr);
};
goog.a11y.aria.getStateString = function(element, stateName) {
  var attr = element.getAttribute(goog.a11y.aria.getAriaAttributeName_(stateName));
  goog.asserts.assert((attr == null || goog.isString(attr)) && (attr == "" || isNaN(Number(attr))) && attr != "true" && attr != "false");
  return attr == null || attr == "" ? null : attr;
};
goog.a11y.aria.getStringArrayStateInternalUtil = function(element, stateName) {
  var attrValue = element.getAttribute(goog.a11y.aria.getAriaAttributeName_(stateName));
  return goog.a11y.aria.splitStringOnWhitespace_(attrValue);
};
goog.a11y.aria.hasState = function(element, stateName) {
  return element.hasAttribute(goog.a11y.aria.getAriaAttributeName_(stateName));
};
goog.a11y.aria.isContainerRole = function(element) {
  var role = goog.a11y.aria.getRole(element);
  return goog.array.contains(goog.a11y.aria.CONTAINER_ROLES_, role);
};
goog.a11y.aria.splitStringOnWhitespace_ = function(stringValue) {
  return stringValue ? stringValue.split(/\s+/) : [];
};
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;
};
goog.provide("goog.Thenable");
goog.forwardDeclare("goog.Promise");
goog.Thenable = function() {
};
goog.Thenable.prototype.then = function(opt_onFulfilled, opt_onRejected, opt_context) {
};
goog.Thenable.IMPLEMENTED_BY_PROP = "$goog_Thenable";
goog.Thenable.addImplementation = function(ctor) {
  ctor.prototype["then"] = ctor.prototype.then;
  if (COMPILED) {
    ctor.prototype[goog.Thenable.IMPLEMENTED_BY_PROP] = true;
  } else {
    ctor.prototype.$goog_Thenable = true;
  }
};
goog.Thenable.isImplementedBy = function(object) {
  if (!object) {
    return false;
  }
  try {
    if (COMPILED) {
      return !!object[goog.Thenable.IMPLEMENTED_BY_PROP];
    }
    return !!object.$goog_Thenable;
  } catch (e) {
    return false;
  }
};
goog.provide("goog.async.FreeList");
goog.async.FreeList = goog.defineClass(null, {constructor:function(create, reset, limit) {
  this.limit_ = limit;
  this.create_ = create;
  this.reset_ = reset;
  this.occupants_ = 0;
  this.head_ = null;
}, 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;
}, put:function(item) {
  this.reset_(item);
  if (this.occupants_ < this.limit_) {
    this.occupants_++;
    item.next = this.head_;
    this.head_ = item;
  }
}, occupants:function() {
  return this.occupants_;
}});
goog.provide("goog.async.WorkItem");
goog.provide("goog.async.WorkQueue");
goog.require("goog.asserts");
goog.require("goog.async.FreeList");
goog.async.WorkQueue = function() {
  this.workHead_ = null;
  this.workTail_ = null;
};
goog.define("goog.async.WorkQueue.DEFAULT_MAX_UNUSED", 100);
goog.async.WorkQueue.freelist_ = new goog.async.FreeList(function() {
  return new goog.async.WorkItem;
}, function(item) {
  item.reset();
}, goog.async.WorkQueue.DEFAULT_MAX_UNUSED);
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;
  }
};
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;
};
goog.async.WorkQueue.prototype.returnUnused = function(item) {
  goog.async.WorkQueue.freelist_.put(item);
};
goog.async.WorkQueue.prototype.getUnusedItem_ = function() {
  return goog.async.WorkQueue.freelist_.get();
};
goog.async.WorkItem = function() {
  this.fn = null;
  this.scope = null;
  this.next = null;
};
goog.async.WorkItem.prototype.set = function(fn, scope) {
  this.fn = fn;
  this.scope = scope;
  this.next = null;
};
goog.async.WorkItem.prototype.reset = function() {
  this.fn = null;
  this.scope = null;
  this.next = null;
};
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");
goog.async.throwException = function(exception) {
  goog.global.setTimeout(function() {
    throw exception;
  }, 0);
};
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);
  if (goog.isFunction(goog.global.setImmediate) && (opt_useSetImmediate || goog.async.nextTick.useSetImmediate_())) {
    goog.global.setImmediate(cb);
    return;
  }
  if (!goog.async.nextTick.setImmediate_) {
    goog.async.nextTick.setImmediate_ = goog.async.nextTick.getSetImmediateEmulator_();
  }
  goog.async.nextTick.setImmediate_(cb);
};
goog.async.nextTick.useSetImmediate_ = function() {
  if (!goog.global.Window || !goog.global.Window.prototype) {
    return true;
  }
  if (goog.labs.userAgent.browser.isEdge() || goog.global.Window.prototype.setImmediate != goog.global.setImmediate) {
    return true;
  }
  return false;
};
goog.async.nextTick.setImmediate_;
goog.async.nextTick.getSetImmediateEmulator_ = function() {
  var Channel = goog.global["MessageChannel"];
  if (typeof Channel === "undefined" && typeof window !== "undefined" && window.postMessage && window.addEventListener && !goog.labs.userAgent.engine.isPresto()) {
    Channel = function() {
      var iframe = document.createElement(String(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();
      var message = "callImmediate" + Math.random();
      var origin = win.location.protocol == "file:" ? "*" : win.location.protocol + "//" + win.location.host;
      var onmessage = goog.bind(function(e) {
        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()) {
    var channel = new Channel;
    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);
    };
  }
  if (typeof document !== "undefined" && "onreadystatechange" in document.createElement(String(goog.dom.TagName.SCRIPT))) {
    return function(cb) {
      var script = document.createElement(String(goog.dom.TagName.SCRIPT));
      script.onreadystatechange = function() {
        script.onreadystatechange = null;
        script.parentNode.removeChild(script);
        script = null;
        cb();
        cb = null;
      };
      document.documentElement.appendChild(script);
    };
  }
  return function(cb) {
    goog.global.setTimeout(cb, 0);
  };
};
goog.async.nextTick.wrapCallback_ = goog.functions.identity;
goog.debug.entryPointRegistry.register(function(transformer) {
  goog.async.nextTick.wrapCallback_ = transformer;
});
goog.provide("goog.async.run");
goog.require("goog.async.WorkQueue");
goog.require("goog.async.nextTick");
goog.require("goog.async.throwException");
goog.async.run = function(callback, opt_context) {
  if (!goog.async.run.schedule_) {
    goog.async.run.initializeRunner_();
  }
  if (!goog.async.run.workQueueScheduled_) {
    goog.async.run.schedule_();
    goog.async.run.workQueueScheduled_ = true;
  }
  goog.async.run.workQueue_.add(callback, opt_context);
};
goog.async.run.initializeRunner_ = function() {
  if (String(goog.global.Promise).indexOf("[native code]") != -1) {
    var promise = goog.global.Promise.resolve(undefined);
    goog.async.run.schedule_ = function() {
      promise.then(goog.async.run.processWorkQueue);
    };
  } else {
    goog.async.run.schedule_ = function() {
      goog.async.nextTick(goog.async.run.processWorkQueue);
    };
  }
};
goog.async.run.forceNextTick = function(opt_realSetTimeout) {
  goog.async.run.schedule_ = function() {
    goog.async.nextTick(goog.async.run.processWorkQueue);
    if (opt_realSetTimeout) {
      opt_realSetTimeout(goog.async.run.processWorkQueue);
    }
  };
};
goog.async.run.schedule_;
goog.async.run.workQueueScheduled_ = false;
goog.async.run.workQueue_ = new goog.async.WorkQueue;
if (goog.DEBUG) {
  goog.async.run.resetQueue = function() {
    goog.async.run.workQueueScheduled_ = false;
    goog.async.run.workQueue_ = new goog.async.WorkQueue;
  };
}
goog.async.run.processWorkQueue = function() {
  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);
  }
  goog.async.run.workQueueScheduled_ = false;
};
goog.provide("goog.promise.Resolver");
goog.promise.Resolver = function() {
};
goog.promise.Resolver.prototype.promise;
goog.promise.Resolver.prototype.resolve;
goog.promise.Resolver.prototype.reject;
goog.provide("goog.Promise");
goog.require("goog.Thenable");
goog.require("goog.asserts");
goog.require("goog.async.FreeList");
goog.require("goog.async.run");
goog.require("goog.async.throwException");
goog.require("goog.debug.Error");
goog.require("goog.promise.Resolver");
goog.Promise = function(resolver, opt_context) {
  this.state_ = goog.Promise.State_.PENDING;
  this.result_ = undefined;
  this.parent_ = null;
  this.callbackEntries_ = null;
  this.callbackEntriesTail_ = null;
  this.executing_ = false;
  if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
    this.unhandledRejectionId_ = 0;
  } else {
    if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
      this.hadUnhandledRejection_ = false;
    }
  }
  if (goog.Promise.LONG_STACK_TRACES) {
    this.stack_ = [];
    this.addStackTrace_(new Error("created"));
    this.currentStep_ = 0;
  }
  if (resolver != goog.nullFunction) {
    try {
      var self = this;
      resolver.call(opt_context, function(value) {
        self.resolve_(goog.Promise.State_.FULFILLED, value);
      }, function(reason) {
        if (goog.DEBUG && !(reason instanceof goog.Promise.CancellationError)) {
          try {
            if (reason instanceof Error) {
              throw reason;
            } else {
              throw new Error("Promise rejected.");
            }
          } catch (e) {
          }
        }
        self.resolve_(goog.Promise.State_.REJECTED, reason);
      });
    } catch (e) {
      this.resolve_(goog.Promise.State_.REJECTED, e);
    }
  }
};
goog.define("goog.Promise.LONG_STACK_TRACES", false);
goog.define("goog.Promise.UNHANDLED_REJECTION_DELAY", 0);
goog.Promise.State_ = {PENDING:0, BLOCKED:1, FULFILLED:2, REJECTED:3};
goog.Promise.CallbackEntry_ = function() {
  this.child = null;
  this.onFulfilled = null;
  this.onRejected = null;
  this.context = null;
  this.next = null;
  this.always = false;
};
goog.Promise.CallbackEntry_.prototype.reset = function() {
  this.child = null;
  this.onFulfilled = null;
  this.onRejected = null;
  this.context = null;
  this.always = false;
};
goog.define("goog.Promise.DEFAULT_MAX_UNUSED", 100);
goog.Promise.freelist_ = new goog.async.FreeList(function() {
  return new goog.Promise.CallbackEntry_;
}, function(item) {
  item.reset();
}, goog.Promise.DEFAULT_MAX_UNUSED);
goog.Promise.getCallbackEntry_ = function(onFulfilled, onRejected, context) {
  var entry = goog.Promise.freelist_.get();
  entry.onFulfilled = onFulfilled;
  entry.onRejected = onRejected;
  entry.context = context;
  return entry;
};
goog.Promise.returnEntry_ = function(entry) {
  goog.Promise.freelist_.put(entry);
};
goog.Promise.resolve = function(opt_value) {
  if (opt_value instanceof goog.Promise) {
    return opt_value;
  }
  var promise = new goog.Promise(goog.nullFunction);
  promise.resolve_(goog.Promise.State_.FULFILLED, opt_value);
  return promise;
};
goog.Promise.reject = function(opt_reason) {
  return new goog.Promise(function(resolve, reject) {
    reject(opt_reason);
  });
};
goog.Promise.resolveThen_ = function(value, onFulfilled, onRejected) {
  var isThenable = goog.Promise.maybeThen_(value, onFulfilled, onRejected, null);
  if (!isThenable) {
    goog.async.run(goog.partial(onFulfilled, value));
  }
};
goog.Promise.race = function(promises) {
  return new goog.Promise(function(resolve, reject) {
    if (!promises.length) {
      resolve(undefined);
    }
    for (var i = 0, promise; i < promises.length; i++) {
      promise = promises[i];
      goog.Promise.resolveThen_(promise, resolve, reject);
    }
  });
};
goog.Promise.all = function(promises) {
  return new goog.Promise(function(resolve, reject) {
    var toFulfill = promises.length;
    var values = [];
    if (!toFulfill) {
      resolve(values);
      return;
    }
    var onFulfill = function(index, value) {
      toFulfill--;
      values[index] = value;
      if (toFulfill == 0) {
        resolve(values);
      }
    };
    var onReject = function(reason) {
      reject(reason);
    };
    for (var i = 0, promise; i < promises.length; i++) {
      promise = promises[i];
      goog.Promise.resolveThen_(promise, goog.partial(onFulfill, i), onReject);
    }
  });
};
goog.Promise.allSettled = function(promises) {
  return new goog.Promise(function(resolve, reject) {
    var toSettle = promises.length;
    var results = [];
    if (!toSettle) {
      resolve(results);
      return;
    }
    var onSettled = function(index, fulfilled, result) {
      toSettle--;
      results[index] = fulfilled ? {fulfilled:true, value:result} : {fulfilled:false, reason:result};
      if (toSettle == 0) {
        resolve(results);
      }
    };
    for (var i = 0, promise; i < promises.length; i++) {
      promise = promises[i];
      goog.Promise.resolveThen_(promise, goog.partial(onSettled, i, true), goog.partial(onSettled, i, false));
    }
  });
};
goog.Promise.firstFulfilled = function(promises) {
  return new goog.Promise(function(resolve, reject) {
    var toReject = promises.length;
    var reasons = [];
    if (!toReject) {
      resolve(undefined);
      return;
    }
    var onFulfill = function(value) {
      resolve(value);
    };
    var onReject = function(index, reason) {
      toReject--;
      reasons[index] = reason;
      if (toReject == 0) {
        reject(reasons);
      }
    };
    for (var i = 0, promise; i < promises.length; i++) {
      promise = promises[i];
      goog.Promise.resolveThen_(promise, onFulfill, goog.partial(onReject, i));
    }
  });
};
goog.Promise.withResolver = function() {
  var resolve, reject;
  var promise = new goog.Promise(function(rs, rj) {
    resolve = rs;
    reject = rj;
  });
  return new goog.Promise.Resolver_(promise, resolve, reject);
};
goog.Promise.prototype.then = function(opt_onFulfilled, opt_onRejected, opt_context) {
  if (opt_onFulfilled != null) {
    goog.asserts.assertFunction(opt_onFulfilled, "opt_onFulfilled should be a function.");
  }
  if (opt_onRejected != null) {
    goog.asserts.assertFunction(opt_onRejected, "opt_onRejected should be a function. Did you pass opt_context " + "as the second argument instead of the third?");
  }
  if (goog.Promise.LONG_STACK_TRACES) {
    this.addStackTrace_(new Error("then"));
  }
  return this.addChildPromise_(goog.isFunction(opt_onFulfilled) ? opt_onFulfilled : null, goog.isFunction(opt_onRejected) ? opt_onRejected : null, opt_context);
};
goog.Thenable.addImplementation(goog.Promise);
goog.Promise.prototype.thenVoid = function(opt_onFulfilled, opt_onRejected, opt_context) {
  if (opt_onFulfilled != null) {
    goog.asserts.assertFunction(opt_onFulfilled, "opt_onFulfilled should be a function.");
  }
  if (opt_onRejected != null) {
    goog.asserts.assertFunction(opt_onRejected, "opt_onRejected should be a function. Did you pass opt_context " + "as the second argument instead of the third?");
  }
  if (goog.Promise.LONG_STACK_TRACES) {
    this.addStackTrace_(new Error("then"));
  }
  this.addCallbackEntry_(goog.Promise.getCallbackEntry_(opt_onFulfilled || goog.nullFunction, opt_onRejected || null, opt_context));
};
goog.Promise.prototype.thenAlways = function(onSettled, opt_context) {
  if (goog.Promise.LONG_STACK_TRACES) {
    this.addStackTrace_(new Error("thenAlways"));
  }
  var entry = goog.Promise.getCallbackEntry_(onSettled, onSettled, opt_context);
  entry.always = true;
  this.addCallbackEntry_(entry);
  return this;
};
goog.Promise.prototype.thenCatch = function(onRejected, opt_context) {
  if (goog.Promise.LONG_STACK_TRACES) {
    this.addStackTrace_(new Error("thenCatch"));
  }
  return this.addChildPromise_(null, onRejected, opt_context);
};
goog.Promise.prototype.cancel = function(opt_message) {
  if (this.state_ == goog.Promise.State_.PENDING) {
    goog.async.run(function() {
      var err = new goog.Promise.CancellationError(opt_message);
      this.cancelInternal_(err);
    }, this);
  }
};
goog.Promise.prototype.cancelInternal_ = function(err) {
  if (this.state_ == goog.Promise.State_.PENDING) {
    if (this.parent_) {
      this.parent_.cancelChild_(this, err);
      this.parent_ = null;
    } else {
      this.resolve_(goog.Promise.State_.REJECTED, err);
    }
  }
};
goog.Promise.prototype.cancelChild_ = function(childPromise, err) {
  if (!this.callbackEntries_) {
    return;
  }
  var childCount = 0;
  var childEntry = null;
  var beforeChildEntry = null;
  for (var entry = this.callbackEntries_; entry; entry = entry.next) {
    if (!entry.always) {
      childCount++;
      if (entry.child == childPromise) {
        childEntry = entry;
      }
      if (childEntry && childCount > 1) {
        break;
      }
    }
    if (!childEntry) {
      beforeChildEntry = entry;
    }
  }
  if (childEntry) {
    if (this.state_ == goog.Promise.State_.PENDING && childCount == 1) {
      this.cancelInternal_(err);
    } else {
      if (beforeChildEntry) {
        this.removeEntryAfter_(beforeChildEntry);
      } else {
        this.popEntry_();
      }
      this.executeCallback_(childEntry, goog.Promise.State_.REJECTED, err);
    }
  }
};
goog.Promise.prototype.addCallbackEntry_ = function(callbackEntry) {
  if (!this.hasEntry_() && (this.state_ == goog.Promise.State_.FULFILLED || this.state_ == goog.Promise.State_.REJECTED)) {
    this.scheduleCallbacks_();
  }
  this.queueEntry_(callbackEntry);
};
goog.Promise.prototype.addChildPromise_ = function(onFulfilled, onRejected, opt_context) {
  var callbackEntry = goog.Promise.getCallbackEntry_(null, null, null);
  callbackEntry.child = new goog.Promise(function(resolve, reject) {
    callbackEntry.onFulfilled = onFulfilled ? function(value) {
      try {
        var result = onFulfilled.call(opt_context, value);
        resolve(result);
      } catch (err$4) {
        reject(err$4);
      }
    } : resolve;
    callbackEntry.onRejected = onRejected ? function(reason) {
      try {
        var result = onRejected.call(opt_context, reason);
        if (!goog.isDef(result) && reason instanceof goog.Promise.CancellationError) {
          reject(reason);
        } else {
          resolve(result);
        }
      } catch (err$5) {
        reject(err$5);
      }
    } : reject;
  });
  callbackEntry.child.parent_ = this;
  this.addCallbackEntry_(callbackEntry);
  return callbackEntry.child;
};
goog.Promise.prototype.unblockAndFulfill_ = function(value) {
  goog.asserts.assert(this.state_ == goog.Promise.State_.BLOCKED);
  this.state_ = goog.Promise.State_.PENDING;
  this.resolve_(goog.Promise.State_.FULFILLED, value);
};
goog.Promise.prototype.unblockAndReject_ = function(reason) {
  goog.asserts.assert(this.state_ == goog.Promise.State_.BLOCKED);
  this.state_ = goog.Promise.State_.PENDING;
  this.resolve_(goog.Promise.State_.REJECTED, reason);
};
goog.Promise.prototype.resolve_ = function(state, x) {
  if (this.state_ != goog.Promise.State_.PENDING) {
    return;
  }
  if (this === x) {
    state = goog.Promise.State_.REJECTED;
    x = new TypeError("Promise cannot resolve to itself");
  }
  this.state_ = goog.Promise.State_.BLOCKED;
  var isThenable = goog.Promise.maybeThen_(x, this.unblockAndFulfill_, this.unblockAndReject_, this);
  if (isThenable) {
    return;
  }
  this.result_ = x;
  this.state_ = state;
  this.parent_ = null;
  this.scheduleCallbacks_();
  if (state == goog.Promise.State_.REJECTED && !(x instanceof goog.Promise.CancellationError)) {
    goog.Promise.addUnhandledRejection_(this, x);
  }
};
goog.Promise.maybeThen_ = function(value, onFulfilled, onRejected, context) {
  if (value instanceof goog.Promise) {
    value.thenVoid(onFulfilled, onRejected, context);
    return true;
  } else {
    if (goog.Thenable.isImplementedBy(value)) {
      value = value;
      value.then(onFulfilled, onRejected, context);
      return true;
    } else {
      if (goog.isObject(value)) {
        try {
          var then = value["then"];
          if (goog.isFunction(then)) {
            goog.Promise.tryThen_(value, then, onFulfilled, onRejected, context);
            return true;
          }
        } catch (e) {
          onRejected.call(context, e);
          return true;
        }
      }
    }
  }
  return false;
};
goog.Promise.tryThen_ = function(thenable, then, onFulfilled, onRejected, context) {
  var called = false;
  var resolve = function(value) {
    if (!called) {
      called = true;
      onFulfilled.call(context, value);
    }
  };
  var reject = function(reason) {
    if (!called) {
      called = true;
      onRejected.call(context, reason);
    }
  };
  try {
    then.call(thenable, resolve, reject);
  } catch (e) {
    reject(e);
  }
};
goog.Promise.prototype.scheduleCallbacks_ = function() {
  if (!this.executing_) {
    this.executing_ = true;
    goog.async.run(this.executeCallbacks_, this);
  }
};
goog.Promise.prototype.hasEntry_ = function() {
  return !!this.callbackEntries_;
};
goog.Promise.prototype.queueEntry_ = function(entry) {
  goog.asserts.assert(entry.onFulfilled != null);
  if (this.callbackEntriesTail_) {
    this.callbackEntriesTail_.next = entry;
    this.callbackEntriesTail_ = entry;
  } else {
    this.callbackEntries_ = entry;
    this.callbackEntriesTail_ = entry;
  }
};
goog.Promise.prototype.popEntry_ = function() {
  var entry = null;
  if (this.callbackEntries_) {
    entry = this.callbackEntries_;
    this.callbackEntries_ = entry.next;
    entry.next = null;
  }
  if (!this.callbackEntries_) {
    this.callbackEntriesTail_ = null;
  }
  if (entry != null) {
    goog.asserts.assert(entry.onFulfilled != null);
  }
  return entry;
};
goog.Promise.prototype.removeEntryAfter_ = function(previous) {
  goog.asserts.assert(this.callbackEntries_);
  goog.asserts.assert(previous != null);
  if (previous.next == this.callbackEntriesTail_) {
    this.callbackEntriesTail_ = previous;
  }
  previous.next = previous.next.next;
};
goog.Promise.prototype.executeCallbacks_ = function() {
  var entry = null;
  while (entry = this.popEntry_()) {
    if (goog.Promise.LONG_STACK_TRACES) {
      this.currentStep_++;
    }
    this.executeCallback_(entry, this.state_, this.result_);
  }
  this.executing_ = false;
};
goog.Promise.prototype.executeCallback_ = function(callbackEntry, state, result) {
  if (state == goog.Promise.State_.REJECTED && callbackEntry.onRejected && !callbackEntry.always) {
    this.removeUnhandledRejection_();
  }
  if (callbackEntry.child) {
    callbackEntry.child.parent_ = null;
    goog.Promise.invokeCallback_(callbackEntry, state, result);
  } else {
    try {
      callbackEntry.always ? callbackEntry.onFulfilled.call(callbackEntry.context) : goog.Promise.invokeCallback_(callbackEntry, state, result);
    } catch (err$6) {
      goog.Promise.handleRejection_.call(null, err$6);
    }
  }
  goog.Promise.returnEntry_(callbackEntry);
};
goog.Promise.invokeCallback_ = function(callbackEntry, state, result) {
  if (state == goog.Promise.State_.FULFILLED) {
    callbackEntry.onFulfilled.call(callbackEntry.context, result);
  } else {
    if (callbackEntry.onRejected) {
      callbackEntry.onRejected.call(callbackEntry.context, result);
    }
  }
};
goog.Promise.prototype.addStackTrace_ = function(err) {
  if (goog.Promise.LONG_STACK_TRACES && goog.isString(err.stack)) {
    var trace = err.stack.split("\n", 4)[3];
    var message = err.message;
    message += Array(11 - message.length).join(" ");
    this.stack_.push(message + trace);
  }
};
goog.Promise.prototype.appendLongStack_ = function(err) {
  if (goog.Promise.LONG_STACK_TRACES && err && goog.isString(err.stack) && this.stack_.length) {
    var longTrace = ["Promise trace:"];
    for (var promise = this; promise; promise = promise.parent_) {
      for (var i = this.currentStep_; i >= 0; i--) {
        longTrace.push(promise.stack_[i]);
      }
      longTrace.push("Value: " + "[" + (promise.state_ == goog.Promise.State_.REJECTED ? "REJECTED" : "FULFILLED") + "] " + "<" + String(promise.result_) + ">");
    }
    err.stack += "\n\n" + longTrace.join("\n");
  }
};
goog.Promise.prototype.removeUnhandledRejection_ = function() {
  if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
    for (var p = this; p && p.unhandledRejectionId_; p = p.parent_) {
      goog.global.clearTimeout(p.unhandledRejectionId_);
      p.unhandledRejectionId_ = 0;
    }
  } else {
    if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
      for (var p = this; p && p.hadUnhandledRejection_; p = p.parent_) {
        p.hadUnhandledRejection_ = false;
      }
    }
  }
};
goog.Promise.addUnhandledRejection_ = function(promise, reason) {
  if (goog.Promise.UNHANDLED_REJECTION_DELAY > 0) {
    promise.unhandledRejectionId_ = goog.global.setTimeout(function() {
      promise.appendLongStack_(reason);
      goog.Promise.handleRejection_.call(null, reason);
    }, goog.Promise.UNHANDLED_REJECTION_DELAY);
  } else {
    if (goog.Promise.UNHANDLED_REJECTION_DELAY == 0) {
      promise.hadUnhandledRejection_ = true;
      goog.async.run(function() {
        if (promise.hadUnhandledRejection_) {
          promise.appendLongStack_(reason);
          goog.Promise.handleRejection_.call(null, reason);
        }
      });
    }
  }
};
goog.Promise.handleRejection_ = goog.async.throwException;
goog.Promise.setUnhandledRejectionHandler = function(handler) {
  goog.Promise.handleRejection_ = handler;
};
goog.Promise.CancellationError = function(opt_message) {
  goog.Promise.CancellationError.base(this, "constructor", opt_message);
};
goog.inherits(goog.Promise.CancellationError, goog.debug.Error);
goog.Promise.CancellationError.prototype.name = "cancel";
goog.Promise.Resolver_ = function(promise, resolve, reject) {
  this.promise = promise;
  this.resolve = resolve;
  this.reject = reject;
};
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");
goog.events.EventTarget = function() {
  goog.Disposable.call(this);
  this.eventTargetListeners_ = new goog.events.ListenerMap(this);
  this.actualEventTarget_ = this;
  this.parentEventTarget_ = null;
};
goog.inherits(goog.events.EventTarget, goog.Disposable);
goog.events.Listenable.addImplementation(goog.events.EventTarget);
goog.events.EventTarget.MAX_ANCESTORS_ = 1000;
goog.events.EventTarget.prototype.getParentEventTarget = function() {
  return this.parentEventTarget_;
};
goog.events.EventTarget.prototype.setParentEventTarget = function(parent) {
  this.parentEventTarget_ = parent;
};
goog.events.EventTarget.prototype.addEventListener = function(type, handler, opt_capture, opt_handlerScope) {
  goog.events.listen(this, type, handler, opt_capture, opt_handlerScope);
};
goog.events.EventTarget.prototype.removeEventListener = function(type, handler, opt_capture, opt_handlerScope) {
  goog.events.unlisten(this, type, handler, opt_capture, opt_handlerScope);
};
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);
};
goog.events.EventTarget.prototype.disposeInternal = function() {
  goog.events.EventTarget.superClass_.disposeInternal.call(this);
  this.removeAllListeners();
  this.parentEventTarget_ = null;
};
goog.events.EventTarget.prototype.listen = function(type, listener, opt_useCapture, opt_listenerScope) {
  this.assertInitialized_();
  return this.eventTargetListeners_.add(String(type), listener, false, opt_useCapture, opt_listenerScope);
};
goog.events.EventTarget.prototype.listenOnce = function(type, listener, opt_useCapture, opt_listenerScope) {
  return this.eventTargetListeners_.add(String(type), listener, true, opt_useCapture, opt_listenerScope);
};
goog.events.EventTarget.prototype.unlisten = function(type, listener, opt_useCapture, opt_listenerScope) {
  return this.eventTargetListeners_.remove(String(type), listener, opt_useCapture, opt_listenerScope);
};
goog.events.EventTarget.prototype.unlistenByKey = function(key) {
  return this.eventTargetListeners_.removeByKey(key);
};
goog.events.EventTarget.prototype.removeAllListeners = function(opt_type) {
  if (!this.eventTargetListeners_) {
    return 0;
  }
  return this.eventTargetListeners_.removeAll(opt_type);
};
goog.events.EventTarget.prototype.fireListeners = function(type, capture, eventObject) {
  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];
    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;
};
goog.events.EventTarget.prototype.getListeners = function(type, capture) {
  return this.eventTargetListeners_.getListeners(String(type), capture);
};
goog.events.EventTarget.prototype.getListener = function(type, listener, capture, opt_listenerScope) {
  return this.eventTargetListeners_.getListener(String(type), listener, capture, opt_listenerScope);
};
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);
};
goog.events.EventTarget.prototype.setTargetForTesting = function(target) {
  this.actualEventTarget_ = target;
};
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?");
};
goog.events.EventTarget.dispatchEventInternal_ = function(target, e, opt_ancestorsTree) {
  var type = e.type || e;
  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;
  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;
    }
  }
  if (!e.propagationStopped_) {
    currentTarget = e.currentTarget = target;
    rv = currentTarget.fireListeners(type, true, e) && rv;
    if (!e.propagationStopped_) {
      rv = currentTarget.fireListeners(type, false, e) && rv;
    }
  }
  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;
};
goog.provide("goog.Timer");
goog.require("goog.Promise");
goog.require("goog.events.EventTarget");
goog.Timer = function(opt_interval, opt_timerObject) {
  goog.events.EventTarget.call(this);
  this.interval_ = opt_interval || 1;
  this.timerObject_ = opt_timerObject || goog.Timer.defaultTimerObject;
  this.boundTick_ = goog.bind(this.tick_, this);
  this.last_ = goog.now();
};
goog.inherits(goog.Timer, goog.events.EventTarget);
goog.Timer.MAX_TIMEOUT_ = 2147483647;
goog.Timer.INVALID_TIMEOUT_ID_ = -1;
goog.Timer.prototype.enabled = false;
goog.Timer.defaultTimerObject = goog.global;
goog.Timer.intervalScale = 0.8;
goog.Timer.prototype.timer_ = null;
goog.Timer.prototype.getInterval = function() {
  return this.interval_;
};
goog.Timer.prototype.setInterval = function(interval) {
  this.interval_ = interval;
  if (this.timer_ && this.enabled) {
    this.stop();
    this.start();
  } else {
    if (this.timer_) {
      this.stop();
    }
  }
};
goog.Timer.prototype.tick_ = function() {
  if (this.enabled) {
    var elapsed = goog.now() - this.last_;
    if (elapsed > 0 && elapsed < this.interval_ * goog.Timer.intervalScale) {
      this.timer_ = this.timerObject_.setTimeout(this.boundTick_, this.interval_ - elapsed);
      return;
    }
    if (this.timer_) {
      this.timerObject_.clearTimeout(this.timer_);
      this.timer_ = null;
    }
    this.dispatchTick();
    if (this.enabled) {
      this.timer_ = this.timerObject_.setTimeout(this.boundTick_, this.interval_);
      this.last_ = goog.now();
    }
  }
};
goog.Timer.prototype.dispatchTick = function() {
  this.dispatchEvent(goog.Timer.TICK);
};
goog.Timer.prototype.start = function() {
  this.enabled = true;
  if (!this.timer_) {
    this.timer_ = this.timerObject_.setTimeout(this.boundTick_, this.interval_);
    this.last_ = goog.now();
  }
};
goog.Timer.prototype.stop = function() {
  this.enabled = false;
  if (this.timer_) {
    this.timerObject_.clearTimeout(this.timer_);
    this.timer_ = null;
  }
};
goog.Timer.prototype.disposeInternal = function() {
  goog.Timer.superClass_.disposeInternal.call(this);
  this.stop();
  delete this.timerObject_;
};
goog.Timer.TICK = "tick";
goog.Timer.callOnce = function(listener, opt_delay, opt_handler) {
  if (goog.isFunction(listener)) {
    if (opt_handler) {
      listener = goog.bind(listener, opt_handler);
    }
  } else {
    if (listener && typeof listener.handleEvent == "function") {
      listener = goog.bind(listener.handleEvent, listener);
    } else {
      throw Error("Invalid listener argument");
    }
  }
  if (Number(opt_delay) > goog.Timer.MAX_TIMEOUT_) {
    return goog.Timer.INVALID_TIMEOUT_ID_;
  } else {
    return goog.Timer.defaultTimerObject.setTimeout(listener, opt_delay || 0);
  }
};
goog.Timer.clear = function(timerId) {
  goog.Timer.defaultTimerObject.clearTimeout(timerId);
};
goog.Timer.promise = function(delay, opt_result) {
  var timerKey = null;
  return (new goog.Promise(function(resolve, reject) {
    timerKey = goog.Timer.callOnce(function() {
      resolve(opt_result);
    }, delay);
    if (timerKey == goog.Timer.INVALID_TIMEOUT_ID_) {
      reject(new Error("Failed to schedule timer."));
    }
  })).thenCatch(function(error) {
    goog.Timer.clear(timerKey);
    throw error;
  });
};
goog.provide("goog.Delay");
goog.provide("goog.async.Delay");
goog.require("goog.Disposable");
goog.require("goog.Timer");
goog.async.Delay = function(listener, opt_interval, opt_handler) {
  goog.async.Delay.base(this, "constructor");
  this.listener_ = listener;
  this.interval_ = opt_interval || 0;
  this.handler_ = opt_handler;
  this.callback_ = goog.bind(this.doAction_, this);
};
goog.inherits(goog.async.Delay, goog.Disposable);
goog.Delay = goog.async.Delay;
goog.async.Delay.prototype.id_ = 0;
goog.async.Delay.prototype.disposeInternal = function() {
  goog.async.Delay.base(this, "disposeInternal");
  this.stop();
  delete this.listener_;
  delete this.handler_;
};
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_);
};
goog.async.Delay.prototype.startIfNotActive = function(opt_interval) {
  if (!this.isActive()) {
    this.start(opt_interval);
  }
};
goog.async.Delay.prototype.stop = function() {
  if (this.isActive()) {
    goog.Timer.clear(this.id_);
  }
  this.id_ = 0;
};
goog.async.Delay.prototype.fire = function() {
  this.stop();
  this.doAction_();
};
goog.async.Delay.prototype.fireIfActive = function() {
  if (this.isActive()) {
    this.fire();
  }
};
goog.async.Delay.prototype.isActive = function() {
  return this.id_ != 0;
};
goog.async.Delay.prototype.doAction_ = function() {
  this.id_ = 0;
  if (this.listener_) {
    this.listener_.call(this.handler_);
  }
};
goog.provide("goog.editor.defines");
goog.define("goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3", false);
goog.provide("goog.userAgent.product");
goog.require("goog.labs.userAgent.browser");
goog.require("goog.labs.userAgent.platform");
goog.require("goog.userAgent");
goog.define("goog.userAgent.product.ASSUME_FIREFOX", false);
goog.define("goog.userAgent.product.ASSUME_IPHONE", false);
goog.define("goog.userAgent.product.ASSUME_IPAD", false);
goog.define("goog.userAgent.product.ASSUME_ANDROID", false);
goog.define("goog.userAgent.product.ASSUME_CHROME", false);
goog.define("goog.userAgent.product.ASSUME_SAFARI", false);
goog.userAgent.product.PRODUCT_KNOWN_ = goog.userAgent.ASSUME_IE || goog.userAgent.ASSUME_EDGE || goog.userAgent.ASSUME_OPERA || goog.userAgent.product.ASSUME_FIREFOX || goog.userAgent.product.ASSUME_IPHONE || goog.userAgent.product.ASSUME_IPAD || goog.userAgent.product.ASSUME_ANDROID || goog.userAgent.product.ASSUME_CHROME || goog.userAgent.product.ASSUME_SAFARI;
goog.userAgent.product.OPERA = goog.userAgent.OPERA;
goog.userAgent.product.IE = goog.userAgent.IE;
goog.userAgent.product.EDGE = goog.userAgent.EDGE;
goog.userAgent.product.FIREFOX = goog.userAgent.product.PRODUCT_KNOWN_ ? goog.userAgent.product.ASSUME_FIREFOX : goog.labs.userAgent.browser.isFirefox();
goog.userAgent.product.isIphoneOrIpod_ = function() {
  return goog.labs.userAgent.platform.isIphone() || goog.labs.userAgent.platform.isIpod();
};
goog.userAgent.product.IPHONE = goog.userAgent.product.PRODUCT_KNOWN_ ? goog.userAgent.product.ASSUME_IPHONE : goog.userAgent.product.isIphoneOrIpod_();
goog.userAgent.product.IPAD = goog.userAgent.product.PRODUCT_KNOWN_ ? goog.userAgent.product.ASSUME_IPAD : goog.labs.userAgent.platform.isIpad();
goog.userAgent.product.ANDROID = goog.userAgent.product.PRODUCT_KNOWN_ ? goog.userAgent.product.ASSUME_ANDROID : goog.labs.userAgent.browser.isAndroidBrowser();
goog.userAgent.product.CHROME = goog.userAgent.product.PRODUCT_KNOWN_ ? goog.userAgent.product.ASSUME_CHROME : goog.labs.userAgent.browser.isChrome();
goog.userAgent.product.isSafariDesktop_ = function() {
  return goog.labs.userAgent.browser.isSafari() && !goog.labs.userAgent.platform.isIos();
};
goog.userAgent.product.SAFARI = goog.userAgent.product.PRODUCT_KNOWN_ ? goog.userAgent.product.ASSUME_SAFARI : goog.userAgent.product.isSafariDesktop_();
goog.provide("goog.userAgent.product.isVersion");
goog.require("goog.labs.userAgent.platform");
goog.require("goog.string");
goog.require("goog.userAgent");
goog.require("goog.userAgent.product");
goog.userAgent.product.determineVersion_ = function() {
  if (goog.userAgent.product.FIREFOX) {
    return goog.userAgent.product.getFirstRegExpGroup_(/Firefox\/([0-9.]+)/);
  }
  if (goog.userAgent.product.IE || goog.userAgent.product.EDGE || goog.userAgent.product.OPERA) {
    return goog.userAgent.VERSION;
  }
  if (goog.userAgent.product.CHROME) {
    if (goog.labs.userAgent.platform.isIos()) {
      return goog.userAgent.product.getFirstRegExpGroup_(/CriOS\/([0-9.]+)/);
    }
    return goog.userAgent.product.getFirstRegExpGroup_(/Chrome\/([0-9.]+)/);
  }
  if (goog.userAgent.product.SAFARI && !goog.labs.userAgent.platform.isIos()) {
    return goog.userAgent.product.getFirstRegExpGroup_(/Version\/([0-9.]+)/);
  }
  if (goog.userAgent.product.IPHONE || goog.userAgent.product.IPAD) {
    var arr = goog.userAgent.product.execRegExp_(/Version\/(\S+).*Mobile\/(\S+)/);
    if (arr) {
      return arr[1] + "." + arr[2];
    }
  } else {
    if (goog.userAgent.product.ANDROID) {
      var version = goog.userAgent.product.getFirstRegExpGroup_(/Android\s+([0-9.]+)/);
      if (version) {
        return version;
      }
      return goog.userAgent.product.getFirstRegExpGroup_(/Version\/([0-9.]+)/);
    }
  }
  return "";
};
goog.userAgent.product.getFirstRegExpGroup_ = function(re) {
  var arr = goog.userAgent.product.execRegExp_(re);
  return arr ? arr[1] : "";
};
goog.userAgent.product.execRegExp_ = function(re) {
  return re.exec(goog.userAgent.getUserAgentString());
};
goog.userAgent.product.VERSION = goog.userAgent.product.determineVersion_();
goog.userAgent.product.isVersion = function(version) {
  return goog.string.compareVersions(goog.userAgent.product.VERSION, version) >= 0;
};
goog.provide("goog.editor.BrowserFeature");
goog.require("goog.editor.defines");
goog.require("goog.labs.userAgent.browser");
goog.require("goog.userAgent");
goog.require("goog.userAgent.product");
goog.require("goog.userAgent.product.isVersion");
goog.editor.BrowserFeature = {HAS_IE_RANGES:goog.userAgent.IE && !goog.userAgent.isDocumentModeOrHigher(9), HAS_W3C_RANGES:goog.userAgent.GECKO || goog.userAgent.WEBKIT || goog.userAgent.OPERA || goog.userAgent.EDGE || goog.userAgent.IE && goog.userAgent.isDocumentModeOrHigher(9), HAS_CONTENT_EDITABLE:goog.userAgent.IE || goog.userAgent.WEBKIT || goog.userAgent.OPERA || goog.userAgent.EDGE || goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 && goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher("1.9"), 
USE_MUTATION_EVENTS:goog.userAgent.GECKO, HAS_DOM_SUBTREE_MODIFIED_EVENT:goog.userAgent.WEBKIT || goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3 && goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher("1.9"), HAS_DOCUMENT_INDEPENDENT_NODES:goog.userAgent.GECKO, PUTS_CURSOR_BEFORE_FIRST_BLOCK_ELEMENT_ON_FOCUS:goog.userAgent.GECKO, CLEARS_SELECTION_WHEN_FOCUS_LEAVES:goog.userAgent.IE || goog.userAgent.WEBKIT || goog.userAgent.OPERA, HAS_UNSELECTABLE_STYLE:goog.userAgent.GECKO || goog.userAgent.WEBKIT, 
FORMAT_BLOCK_WORKS_FOR_BLOCKQUOTES:goog.userAgent.GECKO || goog.userAgent.WEBKIT || goog.userAgent.OPERA, CREATES_MULTIPLE_BLOCKQUOTES:goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher("534.16") || goog.userAgent.OPERA, WRAPS_BLOCKQUOTE_IN_DIVS:goog.userAgent.OPERA, PREFERS_READY_STATE_CHANGE_EVENT:goog.userAgent.IE, TAB_FIRES_KEYPRESS:!goog.userAgent.IE, NEEDS_99_WIDTH_IN_STANDARDS_MODE:goog.userAgent.IE, USE_DOCUMENT_FOR_KEY_EVENTS:goog.userAgent.GECKO && !goog.editor.defines.USE_CONTENTEDITABLE_IN_FIREFOX_3, 
SHOWS_CUSTOM_ATTRS_IN_INNER_HTML:goog.userAgent.IE, COLLAPSES_EMPTY_NODES:goog.userAgent.GECKO || goog.userAgent.WEBKIT || goog.userAgent.OPERA, CONVERT_TO_B_AND_I_TAGS:goog.userAgent.GECKO || goog.userAgent.OPERA, TABS_THROUGH_IMAGES:goog.userAgent.IE, UNESCAPES_URLS_WITHOUT_ASKING:goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("7.0"), HAS_STYLE_WITH_CSS:goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher("1.8") || goog.userAgent.WEBKIT || goog.userAgent.OPERA, FOLLOWS_EDITABLE_LINKS:goog.userAgent.WEBKIT || 
goog.userAgent.IE && goog.userAgent.isVersionOrHigher("9"), HAS_ACTIVE_ELEMENT:goog.userAgent.IE || goog.userAgent.EDGE || goog.userAgent.OPERA || goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher("1.9"), HAS_SET_CAPTURE:goog.userAgent.IE, EATS_EMPTY_BACKGROUND_COLOR:goog.userAgent.GECKO || goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher("527"), SUPPORTS_FOCUSIN:goog.userAgent.IE || goog.userAgent.OPERA, SELECTS_IMAGES_ON_CLICK:goog.userAgent.IE || goog.userAgent.OPERA, MOVES_STYLE_TO_HEAD:goog.userAgent.WEBKIT, 
COLLAPSES_SELECTION_ONMOUSEDOWN:false, CARET_INSIDE_SELECTION:goog.userAgent.OPERA, FOCUSES_EDITABLE_BODY_ON_HTML_CLICK:true, USES_KEYDOWN:goog.userAgent.IE || goog.userAgent.EDGE || goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher("525"), ADDS_NBSPS_IN_REMOVE_FORMAT:goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher("531"), GETS_STUCK_IN_LINKS:goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher("528"), NORMALIZE_CORRUPTS_EMPTY_TEXT_NODES:goog.userAgent.GECKO && goog.userAgent.isVersionOrHigher("1.9") || 
goog.userAgent.IE || goog.userAgent.EDGE || goog.userAgent.OPERA || goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher("531"), NORMALIZE_CORRUPTS_ALL_TEXT_NODES:goog.userAgent.IE, NESTS_SUBSCRIPT_SUPERSCRIPT:goog.userAgent.IE || goog.userAgent.EDGE || goog.userAgent.GECKO || goog.userAgent.OPERA, 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, DOESNT_OVERRIDE_FONT_SIZE_IN_STYLE_ATTR:!goog.userAgent.WEBKIT && !goog.userAgent.EDGE, 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") || 
goog.userAgent.OPERA && goog.labs.userAgent.browser.isVersionOrHigher("15") || goog.userAgent.EDGE, SUPPORTS_OPERA_DEFAULTBLOCK_COMMAND:goog.userAgent.OPERA && goog.userAgent.isVersionOrHigher("11.10"), SUPPORTS_FILE_PASTING:goog.userAgent.product.CHROME && goog.userAgent.product.isVersion("12")};
goog.provide("goog.editor.Plugin");
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");
goog.editor.Plugin = function() {
  goog.events.EventTarget.call(this);
  this.enabled_ = this.activeOnUneditableFields();
  this.fieldObject = null;
  this.autoDispose_ = true;
  this.logger = goog.log.getLogger("goog.editor.Plugin");
};
goog.inherits(goog.editor.Plugin, goog.events.EventTarget);
goog.editor.Plugin.prototype.getFieldDomHelper = function() {
  return this.getFieldObject() && this.getFieldObject().getEditableDomHelper();
};
goog.editor.Plugin.prototype.getFieldObject = function() {
  return this.fieldObject;
};
goog.editor.Plugin.prototype.setFieldObject = function(fieldObject) {
  this.fieldObject = fieldObject;
};
goog.editor.Plugin.prototype.registerFieldObject = function(fieldObject) {
  this.setFieldObject(fieldObject);
};
goog.editor.Plugin.prototype.unregisterFieldObject = function(fieldObj) {
  if (this.getFieldObject()) {
    this.disable(this.getFieldObject());
    this.setFieldObject(null);
  }
};
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.");
  }
};
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.");
  }
};
goog.editor.Plugin.prototype.isEnabled = function(fieldObject) {
  return this.getFieldObject() == fieldObject ? this.enabled_ : false;
};
goog.editor.Plugin.prototype.setAutoDispose = function(autoDispose) {
  this.autoDispose_ = autoDispose;
};
goog.editor.Plugin.prototype.isAutoDispose = function() {
  return this.autoDispose_;
};
goog.editor.Plugin.prototype.activeOnUneditableFields = goog.functions.FALSE;
goog.editor.Plugin.prototype.isSilentCommand = goog.functions.FALSE;
goog.editor.Plugin.prototype.disposeInternal = function() {
  if (this.getFieldObject()) {
    this.unregisterFieldObject(this.getFieldObject());
  }
  goog.editor.Plugin.superClass_.disposeInternal.call(this);
};
goog.editor.Plugin.prototype.getTrogClassId;
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};
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}));
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);
goog.editor.Plugin.prototype.handleKeyDown;
goog.editor.Plugin.prototype.handleKeyPress;
goog.editor.Plugin.prototype.handleKeyUp;
goog.editor.Plugin.prototype.handleSelectionChange;
goog.editor.Plugin.prototype.handleKeyboardShortcut;
goog.editor.Plugin.prototype.execCommand = function(command, var_args) {
  var silent = this.isSilentCommand(command);
  if (!silent) {
    if (goog.userAgent.GECKO) {
      this.getFieldObject().stopChangeEvents(true, true);
    }
    this.getFieldObject().dispatchBeforeChange();
  }
  try {
    var result = this.execCommandInternal.apply(this, arguments);
  } finally {
    if (!silent) {
      this.getFieldObject().dispatchChange();
      this.getFieldObject().dispatchSelectionChangeEvent();
    }
  }
  return result;
};
goog.editor.Plugin.prototype.execCommandInternal;
goog.editor.Plugin.prototype.queryCommandValue;
goog.editor.Plugin.prototype.prepareContentsHtml;
goog.editor.Plugin.prototype.cleanContentsDom;
goog.editor.Plugin.prototype.cleanContentsHtml;
goog.editor.Plugin.prototype.isSupportedCommand = function(command) {
  return false;
};
goog.editor.Plugin.prototype.saveScrollPosition = function() {
  if (this.getFieldObject() && goog.userAgent.EDGE) {
    var win = this.getFieldObject().getEditableDomHelper().getWindow();
    return win.scrollTo.bind(win, win.scrollX, win.scrollY);
  }
  return function() {
  };
};
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");
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 || {};
};
goog.editor.icontent.FieldStyleInfo = function(wrapper, css) {
  this.wrapper_ = wrapper;
  this.css_ = css;
};
goog.editor.icontent.useStandardsModeIframes_ = false;
goog.editor.icontent.forceStandardsModeIframes = function() {
  goog.editor.icontent.useStandardsModeIframes_ = true;
};
goog.editor.icontent.getInitialIframeContent_ = function(info, bodyHtml, style) {
  var html = [];
  if (info.blended_ && info.standards_ || goog.editor.icontent.useStandardsModeIframes_) {
    html.push("<!DOCTYPE HTML>");
  }
  html.push('<html style="background:none transparent;min-width:0;');
  if (info.blended_) {
    html.push("height:", info.fixedHeight_ ? "100%" : "auto");
  }
  html.push('">');
  html.push("<head><style>");
  if (style && style.css_) {
    html.push(style.css_);
  }
  if (goog.userAgent.GECKO && info.standards_) {
    html.push(" img {-moz-force-broken-image-icon: 1;}");
  }
  html.push("</style></head>");
  html.push('<body g_editable="true" hidefocus="true" ');
  if (goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE) {
    html.push("contentEditable ");
  }
  html.push('class="editable ');
  html.push('" id="', info.fieldId_, '" style="min-width:0;');
  if (goog.userAgent.GECKO && info.blended_) {
    html.push(";width:100%;border:0;margin:0;background:none transparent;", ";height:", info.standards_ ? "100%" : "auto");
    if (info.fixedHeight_) {
      html.push(";overflow:auto");
    } else {
      html.push(";overflow-y:hidden;overflow-x:auto");
    }
  }
  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("");
};
goog.editor.icontent.writeNormalInitialBlendedIframe = function(info, bodyHtml, style, iframe) {
  if (info.blended_) {
    var field = style.wrapper_;
    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);
};
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();
};
goog.editor.icontent.writeHttpsInitialIframe = function(info, doc, bodyHtml) {
  var body = doc.body;
  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;
};
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");
goog.dom.iter.SiblingIterator = function(node, opt_includeNode, opt_reverse) {
  this.node_ = node;
  this.reverse_ = !!opt_reverse;
  if (node && !opt_includeNode) {
    this.next();
  }
};
goog.inherits(goog.dom.iter.SiblingIterator, goog.iter.Iterator);
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;
};
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);
goog.dom.iter.AncestorIterator = function(node, opt_includeNode) {
  this.node_ = node;
  if (node && !opt_includeNode) {
    this.next();
  }
};
goog.inherits(goog.dom.iter.AncestorIterator, goog.iter.Iterator);
goog.dom.iter.AncestorIterator.prototype.next = function() {
  var node = this.node_;
  if (!node) {
    throw goog.iter.StopIteration;
  }
  this.node_ = node.parentNode;
  return node;
};
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");
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);
goog.editor.node.NON_EMPTY_TAGS_ = goog.object.createSet(goog.dom.TagName.IMG, goog.dom.TagName.IFRAME, goog.dom.TagName.EMBED);
goog.editor.node.isStandardsMode = function(node) {
  return goog.dom.getDomHelper(node).isCss1CompatMode();
};
goog.editor.node.getRightMostLeaf = function(parent) {
  var temp;
  while (temp = goog.editor.node.getLastChild(parent)) {
    parent = temp;
  }
  return parent;
};
goog.editor.node.getLeftMostLeaf = function(parent) {
  var temp;
  while (temp = goog.editor.node.getFirstChild(parent)) {
    parent = temp;
  }
  return parent;
};
goog.editor.node.getFirstChild = function(parent) {
  return goog.editor.node.getChildHelper_(parent, false);
};
goog.editor.node.getLastChild = function(parent) {
  return goog.editor.node.getChildHelper_(parent, true);
};
goog.editor.node.getPreviousSibling = function(sibling) {
  return goog.editor.node.getFirstValue_(goog.iter.filter(new goog.dom.iter.SiblingIterator(sibling, false, true), goog.editor.node.isImportant));
};
goog.editor.node.getNextSibling = function(sibling) {
  return goog.editor.node.getFirstValue_(goog.iter.filter(new goog.dom.iter.SiblingIterator(sibling), goog.editor.node.isImportant));
};
goog.editor.node.getChildHelper_ = function(parent, isReversed) {
  return !parent || parent.nodeType != goog.dom.NodeType.ELEMENT ? null : goog.editor.node.getFirstValue_(goog.iter.filter(new goog.dom.iter.ChildIterator(parent, isReversed), goog.editor.node.isImportant));
};
goog.editor.node.getFirstValue_ = function(iterator) {
  try {
    return iterator.next();
  } catch (e) {
    return null;
  }
};
goog.editor.node.isImportant = function(node) {
  return node.nodeType == goog.dom.NodeType.ELEMENT || node.nodeType == goog.dom.NodeType.TEXT && !goog.editor.node.isAllNonNbspWhiteSpace(node);
};
goog.editor.node.isAllNonNbspWhiteSpace = function(textNode) {
  return goog.string.isBreakingWhitespace(textNode.nodeValue);
};
goog.editor.node.isEmpty = function(node, opt_prohibitSingleNbsp) {
  var nodeData = goog.dom.getRawTextContent(node);
  if (node.getElementsByTagName) {
    node = node;
    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);
};
goog.editor.node.getLength = function(node) {
  return node.length || node.childNodes.length;
};
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;
};
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;
};
goog.editor.node.isBlockTag = function(node) {
  return !!goog.editor.node.BLOCK_TAG_NAMES_[node.tagName];
};
goog.editor.node.skipEmptyTextNodes = function(node) {
  while (node && node.nodeType == goog.dom.NodeType.TEXT && !node.nodeValue) {
    node = node.nextSibling;
  }
  return node;
};
goog.editor.node.isEditableContainer = function(element) {
  return element.getAttribute && element.getAttribute("g_editable") == "true";
};
goog.editor.node.isEditable = function(node) {
  return !!goog.dom.getAncestor(node, goog.editor.node.isEditableContainer);
};
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;
};
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 opt_secondHalf;
};
goog.editor.node.getSecondHalfOfNode_ = function(node, startNode, firstChild) {
  var secondHalf = node.cloneNode(false);
  while (startNode.nextSibling) {
    goog.dom.appendChild(secondHalf, startNode.nextSibling);
  }
  if (firstChild) {
    secondHalf.insertBefore(firstChild, secondHalf.firstChild);
  }
  return secondHalf;
};
goog.editor.node.transferChildren = function(newNode, oldNode) {
  goog.dom.append(newNode, oldNode.childNodes);
};
goog.editor.node.replaceInnerHtml = function(node, html) {
  if (goog.userAgent.IE) {
    goog.dom.removeChildren(node);
  }
  node.innerHTML = html;
};
goog.provide("goog.events.EventHandler");
goog.require("goog.Disposable");
goog.require("goog.events");
goog.require("goog.object");
goog.forwardDeclare("goog.events.EventWrapper");
goog.events.EventHandler = function(opt_scope) {
  goog.Disposable.call(this);
  this.handler_ = opt_scope;
  this.keys_ = {};
};
goog.inherits(goog.events.EventHandler, goog.Disposable);
goog.events.EventHandler.typeArray_ = [];
goog.events.EventHandler.prototype.listen = function(src, type, opt_fn, opt_capture) {
  var self = this;
  return self.listen_(src, type, opt_fn, opt_capture);
};
goog.events.EventHandler.prototype.listenWithScope = function(src, type, fn, capture, scope) {
  var self = this;
  return self.listen_(src, type, fn, capture, scope);
};
goog.events.EventHandler.prototype.listen_ = function(src, type, opt_fn, opt_capture, opt_scope) {
  var self = this;
  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 || self.handleEvent, opt_capture || false, opt_scope || self.handler_ || self);
    if (!listenerObj) {
      return self;
    }
    var key = listenerObj.key;
    self.keys_[key] = listenerObj;
  }
  return self;
};
goog.events.EventHandler.prototype.listenOnce = function(src, type, opt_fn, opt_capture) {
  var self = this;
  return self.listenOnce_(src, type, opt_fn, opt_capture);
};
goog.events.EventHandler.prototype.listenOnceWithScope = function(src, type, fn, capture, scope) {
  var self = this;
  return self.listenOnce_(src, type, fn, capture, scope);
};
goog.events.EventHandler.prototype.listenOnce_ = function(src, type, opt_fn, opt_capture, opt_scope) {
  var self = this;
  if (goog.isArray(type)) {
    for (var i = 0; i < type.length; i++) {
      self.listenOnce_(src, type[i], opt_fn, opt_capture, opt_scope);
    }
  } else {
    var listenerObj = goog.events.listenOnce(src, type, opt_fn || self.handleEvent, opt_capture, opt_scope || self.handler_ || self);
    if (!listenerObj) {
      return self;
    }
    var key = listenerObj.key;
    self.keys_[key] = listenerObj;
  }
  return self;
};
goog.events.EventHandler.prototype.listenWithWrapper = function(src, wrapper, listener, opt_capt) {
  var self = this;
  return self.listenWithWrapper_(src, wrapper, listener, opt_capt);
};
goog.events.EventHandler.prototype.listenWithWrapperAndScope = function(src, wrapper, listener, capture, scope) {
  var self = this;
  return self.listenWithWrapper_(src, wrapper, listener, capture, scope);
};
goog.events.EventHandler.prototype.listenWithWrapper_ = function(src, wrapper, listener, opt_capt, opt_scope) {
  var self = this;
  wrapper.listen(src, listener, opt_capt, opt_scope || self.handler_ || self, self);
  return self;
};
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;
};
goog.events.EventHandler.prototype.unlisten = function(src, type, opt_fn, opt_capture, opt_scope) {
  var self = this;
  if (goog.isArray(type)) {
    for (var i = 0; i < type.length; i++) {
      self.unlisten(src, type[i], opt_fn, opt_capture, opt_scope);
    }
  } else {
    var listener = goog.events.getListener(src, type, opt_fn || self.handleEvent, opt_capture, opt_scope || self.handler_ || self);
    if (listener) {
      goog.events.unlistenByKey(listener);
      delete self.keys_[listener.key];
    }
  }
  return self;
};
goog.events.EventHandler.prototype.unlistenWithWrapper = function(src, wrapper, listener, opt_capt, opt_scope) {
  var self = this;
  wrapper.unlisten(src, listener, opt_capt, opt_scope || self.handler_ || self, self);
  return self;
};
goog.events.EventHandler.prototype.removeAll = function() {
  goog.object.forEach(this.keys_, function(listenerObj, key) {
    if (this.keys_.hasOwnProperty(key)) {
      goog.events.unlistenByKey(listenerObj);
    }
  }, this);
  this.keys_ = {};
};
goog.events.EventHandler.prototype.disposeInternal = function() {
  goog.events.EventHandler.superClass_.disposeInternal.call(this);
  this.removeAll();
};
goog.events.EventHandler.prototype.handleEvent = function(e) {
  throw Error("EventHandler.handleEvent not implemented");
};
goog.provide("goog.editor.style");
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.editor.BrowserFeature");
goog.require("goog.events.EventHandler");
goog.require("goog.events.EventType");
goog.require("goog.object");
goog.require("goog.style");
goog.require("goog.userAgent");
goog.editor.style.getComputedOrCascadedStyle_ = function(node, stylePropertyName) {
  if (node.nodeType != goog.dom.NodeType.ELEMENT) {
    return null;
  }
  return goog.userAgent.IE ? goog.style.getCascadedStyle(node, stylePropertyName) : goog.style.getComputedStyle(node, stylePropertyName);
};
goog.editor.style.isDisplayBlock = function(node) {
  return goog.editor.style.getComputedOrCascadedStyle_(node, "display") == "block";
};
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));
};
goog.editor.style.getContainer = function(node) {
  return goog.dom.getAncestor(node, goog.editor.style.isContainer, true);
};
goog.editor.style.SELECTABLE_INPUT_TYPES_ = goog.object.createSet("text", "file", "url");
goog.editor.style.cancelMouseDownHelper_ = function(e) {
  var targetTagName = e.target.tagName;
  if (targetTagName != goog.dom.TagName.TEXTAREA && targetTagName != goog.dom.TagName.INPUT) {
    e.preventDefault();
  }
};
goog.editor.style.makeUnselectable = function(element, eventHandler) {
  if (goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE) {
    eventHandler.listen(element, goog.events.EventType.MOUSEDOWN, goog.editor.style.cancelMouseDownHelper_, true);
  }
  goog.style.setUnselectable(element, true);
  var inputs = goog.dom.getElementsByTagName(goog.dom.TagName.INPUT, goog.asserts.assert(element));
  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(goog.dom.getElementsByTagName(goog.dom.TagName.TEXTAREA, goog.asserts.assert(element)), goog.editor.style.makeSelectable);
};
goog.editor.style.makeSelectable = function(element) {
  goog.style.setUnselectable(element, false);
  if (goog.editor.BrowserFeature.HAS_UNSELECTABLE_STYLE) {
    var child = element;
    var current = 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 = current.parentNode;
    }
  }
};
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");
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) {
      return range.clone();
    } else {
      if (hasStart) {
        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) {
          return goog.dom.Range.createFromNodes(goog.editor.node.getLeftMostLeaf(el), 0, range.getEndNode(), range.getEndOffset());
        }
      }
    }
  }
  return null;
};
goog.editor.range.expand = function(range, opt_stopNode) {
  var expandedRange = goog.editor.range.expandEndPointToContainer_(range, goog.dom.RangeEndpoint.START, opt_stopNode);
  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 (startNode == endNode) {
    while (endNode != opt_stopNode && startOffset == 0 && endOffset == goog.editor.node.getLength(endNode)) {
      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);
};
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();
  while (node != container && node != opt_stopNode) {
    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);
};
goog.editor.range.selectNodeStart = function(node) {
  goog.dom.Range.createCaret(goog.editor.node.getLeftMostLeaf(node), 0).select();
};
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;
};
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();
  }
};
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;
  }
};
goog.editor.range.normalizeNode = function(node) {
  if (goog.userAgent.IE) {
    goog.editor.range.normalizeNodeIe_(node);
  } else {
    node.normalize();
  }
};
goog.editor.range.rangePreservingNormalize = function(node, range) {
  if (range) {
    var rangeFactory = goog.editor.range.normalize(range);
    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;
  }
};
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());
};
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) {
      anchorPoint.node = anchorPreviousSibling.nextSibling;
      if (!anchorPoint.node) {
        anchorPoint = goog.editor.range.Point.getPointAtEndOfNode(anchorPreviousSibling);
      }
    }
    if (!focusPoint.node && focusPreviousSibling) {
      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);
  };
};
goog.editor.range.normalizePoint_ = function(point) {
  var previous;
  if (point.node.nodeType == goog.dom.NodeType.TEXT) {
    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;
};
goog.editor.range.isEditable = function(range) {
  var rangeContainer = range.getContainerElement();
  var rangeContainerIsOutsideRange = range.getStartNode() != rangeContainer.parentElement;
  return rangeContainerIsOutsideRange && goog.editor.node.isEditableContainer(rangeContainer) || goog.editor.node.isEditable(rangeContainer);
};
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;
  });
};
goog.editor.range.Point = function(node, offset) {
  this.node = node;
  this.offset = offset;
};
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));
};
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);
};
goog.editor.range.Point.isTerminalElement_ = function(node) {
  return node.nodeType == goog.dom.NodeType.ELEMENT && !goog.dom.canHaveChildren(node);
};
goog.editor.range.Point.getPointAtEndOfNode = function(node) {
  return new goog.editor.range.Point(node, goog.editor.node.getLength(node));
};
goog.editor.range.saveUsingNormalizedCarets = function(range) {
  return new goog.editor.range.NormalizedCaretRange_(range);
};
goog.editor.range.NormalizedCaretRange_ = function(range) {
  goog.dom.SavedCaretRange.call(this, range);
};
goog.inherits(goog.editor.range.NormalizedCaretRange_, goog.dom.SavedCaretRange);
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);
    }
  }
};
goog.provide("goog.events.KeyCodes");
goog.require("goog.userAgent");
goog.forwardDeclare("goog.events.BrowserEvent");
goog.events.KeyCodes = {WIN_KEY_FF_LINUX:0, MAC_ENTER:3, BACKSPACE:8, TAB:9, NUM_CENTER:12, ENTER:13, SHIFT:16, CTRL:17, ALT:18, PAUSE:19, CAPS_LOCK:20, ESC:27, SPACE:32, PAGE_UP:33, PAGE_DOWN:34, END:35, HOME:36, LEFT:37, UP:38, RIGHT:39, DOWN:40, PLUS_SIGN:43, PRINT_SCREEN:44, INSERT:45, DELETE:46, ZERO:48, ONE:49, TWO:50, THREE:51, FOUR:52, FIVE:53, SIX:54, SEVEN:55, EIGHT:56, NINE:57, FF_SEMICOLON:59, FF_EQUALS:61, FF_DASH:173, QUESTION_MARK:63, AT_SIGN:64, 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_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, 
FIRST_MEDIA_KEY:166, LAST_MEDIA_KEY:183, SEMICOLON:186, DASH:189, EQUALS:187, COMMA:188, PERIOD:190, SLASH:191, APOSTROPHE:192, TILDE:192, SINGLE_QUOTE:222, OPEN_SQUARE_BRACKET:219, BACKSLASH:220, CLOSE_SQUARE_BRACKET:221, WIN_KEY:224, MAC_FF_META:224, MAC_WK_CMD_LEFT:91, MAC_WK_CMD_RIGHT:93, WIN_IME:229, VK_NONAME:252, PHANTOM:255};
goog.events.KeyCodes.isTextModifyingKeyEvent = function(e) {
  if (e.altKey && !e.ctrlKey || e.metaKey || e.keyCode >= goog.events.KeyCodes.F1 && e.keyCode <= goog.events.KeyCodes.F12) {
    return false;
  }
  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;
  }
};
goog.events.KeyCodes.firesKeyPressEvent = function(keyCode, opt_heldKeyCode, opt_shiftKey, opt_ctrlKey, opt_altKey, opt_metaKey) {
  if (!goog.userAgent.IE && !goog.userAgent.EDGE && !(goog.userAgent.WEBKIT && goog.userAgent.isVersionOrHigher("525"))) {
    return true;
  }
  if (goog.userAgent.MAC && opt_altKey) {
    return goog.events.KeyCodes.isCharacterKey(keyCode);
  }
  if (opt_altKey && !opt_ctrlKey) {
    return false;
  }
  if (goog.isNumber(opt_heldKeyCode)) {
    opt_heldKeyCode = goog.events.KeyCodes.normalizeKeyCode(opt_heldKeyCode);
  }
  var heldKeyIsModifier = opt_heldKeyCode == goog.events.KeyCodes.CTRL || opt_heldKeyCode == goog.events.KeyCodes.ALT || goog.userAgent.MAC && opt_heldKeyCode == goog.events.KeyCodes.META;
  var modifiedShiftKey = opt_heldKeyCode == goog.events.KeyCodes.SHIFT && (opt_ctrlKey || opt_metaKey);
  if ((!opt_shiftKey || goog.userAgent.MAC) && heldKeyIsModifier || goog.userAgent.MAC && modifiedShiftKey) {
    return false;
  }
  if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && 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;
    }
  }
  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 || goog.userAgent.EDGE);
  }
  return goog.events.KeyCodes.isCharacterKey(keyCode);
};
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;
  }
  if ((goog.userAgent.WEBKIT || goog.userAgent.EDGE) && keyCode == 0) {
    return true;
  }
  switch(keyCode) {
    case goog.events.KeyCodes.SPACE:
    case goog.events.KeyCodes.PLUS_SIGN:
    case goog.events.KeyCodes.QUESTION_MARK:
    case goog.events.KeyCodes.AT_SIGN:
    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;
  }
};
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;
    }
  }
};
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;
  }
};
goog.events.KeyCodes.normalizeMacWebKitKeyCode = function(keyCode) {
  switch(keyCode) {
    case goog.events.KeyCodes.MAC_WK_CMD_RIGHT:
      return goog.events.KeyCodes.META;
    default:
      return keyCode;
  }
};
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.dom.classlist");
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.html.SafeHtml");
goog.require("goog.html.legacyconversions");
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");
goog.editor.Field = function(id, opt_doc) {
  goog.events.EventTarget.call(this);
  this.id = id;
  this.hashCode_ = id;
  this.editableDomHelper = null;
  this.plugins_ = {};
  this.indexedPlugins_ = {};
  for (var op in goog.editor.Plugin.OPCODE) {
    this.indexedPlugins_[op] = [];
  }
  this.cssStyles = "";
  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);
  }
  this.eventRegister = new goog.events.EventHandler(this);
  this.wrappers_ = [];
  this.loadState_ = goog.editor.Field.LoadState_.UNEDITABLE;
  var doc = opt_doc || document;
  this.originalDomHelper = goog.dom.getDomHelper(doc);
  this.originalElement = this.originalDomHelper.getElement(this.id);
  this.followLinkInNewWindow_ = goog.editor.BrowserFeature.FOLLOWS_EDITABLE_LINKS;
  this.appWindow_ = this.originalDomHelper.getWindow();
};
goog.inherits(goog.editor.Field, goog.events.EventTarget);
goog.editor.Field.prototype.field = null;
goog.editor.Field.prototype.logger = goog.log.getLogger("goog.editor.Field");
goog.editor.Field.EventType = {COMMAND_VALUE_CHANGE:"cvc", LOAD:"load", UNLOAD:"unload", BEFORECHANGE:"beforechange", CHANGE:"change", DELAYEDCHANGE:"delayedchange", BEFOREFOCUS:"beforefocus", FOCUS:"focus", BLUR:"blur", BEFORETAB:"beforetab", IFRAME_RESIZED:"ifrsz", BEFORESELECTIONCHANGE:"beforeselectionchange", SELECTIONCHANGE:"selectionchange"};
goog.editor.Field.LoadState_ = {UNEDITABLE:0, LOADING:1, EDITABLE:2};
goog.editor.Field.DEBOUNCE_TIME_MS_ = 500;
goog.editor.Field.activeFieldId_ = null;
goog.editor.Field.prototype.inModalMode_ = false;
goog.editor.Field.prototype.appWindow_;
goog.editor.Field.prototype.selectionChangeTarget_;
goog.editor.Field.prototype.useWindowMouseUp_ = false;
goog.editor.Field.prototype.waitingForMouseUp_ = false;
goog.editor.Field.setActiveFieldId = function(fieldId) {
  goog.editor.Field.activeFieldId_ = fieldId;
};
goog.editor.Field.getActiveFieldId = function() {
  return goog.editor.Field.activeFieldId_;
};
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;
};
goog.editor.Field.prototype.inModalMode = function() {
  return this.inModalMode_;
};
goog.editor.Field.prototype.setModalMode = function(inModalMode) {
  this.inModalMode_ = inModalMode;
};
goog.editor.Field.prototype.getHashCode = function() {
  return this.hashCode_;
};
goog.editor.Field.prototype.getElement = function() {
  return this.field;
};
goog.editor.Field.prototype.getOriginalElement = function() {
  return this.originalElement;
};
goog.editor.Field.prototype.addListener = function(type, listener, opt_capture, opt_handler) {
  var elem = this.getElement();
  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);
  }
};
goog.editor.Field.prototype.getPluginByClassId = function(classId) {
  return this.plugins_[classId];
};
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;
  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);
  if (this.isLoaded()) {
    plugin.enable(this);
  }
};
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);
};
goog.editor.Field.prototype.setInitialStyle = function(cssText) {
  this.cssText = cssText;
};
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;
  }
};
goog.editor.Field.prototype.isModified = function(opt_useIsEverModified) {
  return opt_useIsEverModified ? this.isEverModified_ : this.isModified_;
};
goog.editor.Field.CHANGE_FREQUENCY = 15;
goog.editor.Field.DELAYED_CHANGE_FREQUENCY = 250;
goog.editor.Field.prototype.usesIframe = goog.functions.TRUE;
goog.editor.Field.prototype.isFixedHeight = goog.functions.TRUE;
goog.editor.Field.prototype.shouldRefocusOnInputMobileSafari = goog.functions.FALSE;
goog.editor.Field.KEYS_CAUSING_CHANGES_ = {46:true, 8:true};
if (!goog.userAgent.IE) {
  goog.editor.Field.KEYS_CAUSING_CHANGES_[9] = true;
}
goog.editor.Field.CTRL_KEYS_CAUSING_CHANGES_ = {86:true, 88:true};
if (goog.userAgent.WINDOWS && !goog.userAgent.GECKO) {
  goog.editor.Field.KEYS_CAUSING_CHANGES_[229] = true;
}
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));
};
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;
};
goog.editor.Field.prototype.setAppWindow = function(appWindow) {
  this.appWindow_ = appWindow;
};
goog.editor.Field.prototype.getAppWindow = function() {
  return this.appWindow_;
};
goog.editor.Field.prototype.setBaseZindex = function(zindex) {
  this.baseZindex_ = zindex;
};
goog.editor.Field.prototype.getBaseZindex = function() {
  return this.baseZindex_ || 0;
};
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);
};
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;
};
goog.editor.Field.prototype.setupChangeListeners_ = function() {
  if ((goog.userAgent.product.IPHONE || goog.userAgent.product.IPAD) && this.usesIframe() && this.shouldRefocusOnInputMobileSafari()) {
    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()) {
    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) {
    this.setupMutationEventHandlersGecko();
  } else {
    this.addListener(["beforecut", "beforepaste", "drop", "dragend"], this.dispatchBeforeChange);
    this.addListener(["cut", "paste"], goog.functions.lock(this.dispatchChange));
    this.addListener("drop", this.handleDrop_);
  }
  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_);
  }
};
goog.editor.Field.SELECTION_CHANGE_FREQUENCY_ = 250;
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) {
    }
    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$7) {
    }
    delete this.boundFocusListenerOpera_;
    delete this.boundBlurListenerOpera_;
  }
  if (this.changeTimerGecko_) {
    this.changeTimerGecko_.stop();
  }
  this.delayedChangeTimer_.stop();
};
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);
};
goog.editor.Field.prototype.attachWrapper = function(wrapper) {
  this.wrappers_.push(wrapper);
};
goog.editor.Field.prototype.removeAllWrappers = function() {
  var wrapper;
  while (wrapper = this.wrappers_.pop()) {
    wrapper.dispose();
  }
};
goog.editor.Field.prototype.setFollowLinkInNewWindow = function(followLinkInNewWindow) {
  this.followLinkInNewWindow_ = followLinkInNewWindow;
};
goog.editor.Field.MUTATION_EVENTS_GECKO = ["DOMNodeInserted", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMNodeInsertedIntoDocument", "DOMCharacterDataModified"];
goog.editor.Field.prototype.setupMutationEventHandlersGecko = function() {
  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);
    this.eventRegister.listen(doc, "DOMAttrModified", goog.bind(this.handleDomAttrChange, this, this.handleMutationEventGecko_), true);
  }
};
goog.editor.Field.prototype.handleBeforeChangeKeyEvent_ = function(e) {
  var block = e.keyCode == goog.events.KeyCodes.TAB && !this.dispatchBeforeTab_(e) || 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 {
    this.gotGeneratingKey_ = e.charCode || goog.editor.Field.isGeneratingKey_(e, goog.userAgent.GECKO);
    if (this.gotGeneratingKey_) {
      this.dispatchBeforeChange();
    }
  }
  return true;
};
goog.editor.Field.SELECTION_CHANGE_KEYCODES = {8:1, 9:1, 13:1, 33:1, 34:1, 35:1, 36:1, 37:1, 38:1, 39:1, 40:1, 46:1};
goog.editor.Field.CTRL_KEYS_CAUSING_SELECTION_CHANGES_ = {65:true, 86:true, 88:true};
goog.editor.Field.POTENTIAL_SHORTCUT_KEYCODES_ = {8:1, 9:1, 13:1, 27:1, 33:1, 34:1, 37:1, 38:1, 39:1, 40:1};
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) {
    var plugin = plugins[i];
    if ((plugin.isEnabled(this) || goog.editor.Plugin.IRREPRESSIBLE_OPS[op]) && plugin[goog.editor.Plugin.OPCODE[op]].apply(plugin, argList)) {
      return true;
    }
  }
  return false;
};
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);
    }
  }
};
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];
};
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);
};
goog.editor.Field.prototype.getInjectableContents = function(contents, styles) {
  return this.reduceOp_(goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, contents || "", styles);
};
goog.editor.Field.prototype.handleKeyDown_ = function(e) {
  if (goog.userAgent.MAC && e.keyCode == goog.events.KeyCodes.A) {
    this.maybeStartSelectionChangeTimer_(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);
  }
};
goog.editor.Field.prototype.handleKeyPress_ = function(e) {
  if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
    if (!this.handleBeforeChangeKeyEvent_(e)) {
      return;
    }
  } else {
    this.gotGeneratingKey_ = true;
    this.dispatchBeforeChange();
  }
  if (!this.invokeShortCircuitingOp_(goog.editor.Plugin.Op.KEYPRESS, e) && !goog.editor.BrowserFeature.USES_KEYDOWN) {
    this.handleKeyboardShortcut_(e);
  }
};
goog.editor.Field.prototype.handleKeyUp_ = function(e) {
  if (!goog.editor.BrowserFeature.USE_MUTATION_EVENTS && (this.gotGeneratingKey_ || goog.editor.Field.isSpecialGeneratingKey_(e))) {
    this.handleChange();
  }
  this.invokeShortCircuitingOp_(goog.editor.Plugin.Op.KEYUP, e);
  this.maybeStartSelectionChangeTimer_(e);
};
goog.editor.Field.prototype.maybeStartSelectionChangeTimer_ = function(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.dispatchEvent(goog.editor.Field.EventType.BEFORESELECTIONCHANGE);
    this.selectionChangeTimer_.start();
  }
};
goog.editor.Field.prototype.handleKeyboardShortcut_ = function(e) {
  if (e.altKey) {
    return;
  }
  var isModifierPressed = goog.userAgent.MAC ? e.metaKey : e.ctrlKey;
  if (isModifierPressed || goog.editor.Field.POTENTIAL_SHORTCUT_KEYCODES_[e.keyCode]) {
    var key = e.charCode || e.keyCode;
    if (key == 17) {
      return;
    }
    var stringKey = String.fromCharCode(key).toLowerCase();
    if (goog.userAgent.MAC && goog.userAgent.GECKO && stringKey == "`" && e.getBrowserEvent().key == " ") {
      stringKey = " ";
    }
    if (e.keyCode == goog.events.KeyCodes.BACKSLASH) {
      stringKey = "\\";
    }
    if (this.invokeShortCircuitingOp_(goog.editor.Plugin.Op.SHORTCUT, e, stringKey, isModifierPressed)) {
      e.preventDefault();
    }
  }
};
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) {
    var plugin = plugins[i];
    if (plugin.isEnabled(this) && plugin.isSupportedCommand(command)) {
      result = plugin.execCommand.apply(plugin, args);
      break;
    }
  }
  return result;
};
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;
  }
};
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;
};
goog.editor.Field.prototype.handleDomAttrChange = function(handler, browserEvent) {
  if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
    return;
  }
  var e = browserEvent.getBrowserEvent();
  try {
    if (e.originalTarget.prefix || e.originalTarget.nodeName == "scrollbar") {
      return;
    }
  } catch (ex1) {
    return;
  }
  if (e.prevValue == e.newValue) {
    return;
  }
  handler.call(this, e);
};
goog.editor.Field.prototype.handleMutationEventGecko_ = function(e) {
  if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
    return;
  }
  e = e.getBrowserEvent ? e.getBrowserEvent() : e;
  if (e.target.firebugIgnore) {
    return;
  }
  this.isModified_ = true;
  this.isEverModified_ = true;
  this.changeTimerGecko_.start();
};
goog.editor.Field.prototype.handleDrop_ = function(e) {
  if (goog.userAgent.IE) {
    this.execCommand(goog.editor.Command.CLEAR_LOREM, true);
  }
  if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
    this.dispatchFocusAndBeforeFocus_();
  }
  this.dispatchChange();
};
goog.editor.Field.prototype.getEditableIframe = function() {
  var dh;
  if (this.usesIframe() && (dh = this.getEditableDomHelper())) {
    var win = dh.getWindow();
    return win && win.frameElement;
  }
  return null;
};
goog.editor.Field.prototype.getEditableDomHelper = function() {
  return this.editableDomHelper;
};
goog.editor.Field.prototype.getRange = function() {
  var win = this.editableDomHelper && this.editableDomHelper.getWindow();
  return win && goog.dom.Range.createFromWindow(win);
};
goog.editor.Field.prototype.dispatchSelectionChangeEvent = function(opt_e, opt_target) {
  if (this.isEventStopped(goog.editor.Field.EventType.SELECTIONCHANGE)) {
    return;
  }
  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);
};
goog.editor.Field.prototype.handleSelectionChangeTimer_ = function() {
  var t = this.selectionChangeTarget_;
  this.selectionChangeTarget_ = null;
  this.dispatchSelectionChangeEvent(undefined, t);
};
goog.editor.Field.prototype.dispatchBeforeChange = function() {
  if (this.isEventStopped(goog.editor.Field.EventType.BEFORECHANGE)) {
    return;
  }
  this.dispatchEvent(goog.editor.Field.EventType.BEFORECHANGE);
};
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});
};
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);
  }
};
goog.editor.Field.prototype.startChangeEvents = function(opt_fireChange, opt_fireDelayedChange) {
  if (!opt_fireChange && this.changeTimerGecko_) {
    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_();
  }
};
goog.editor.Field.prototype.stopEvent = function(eventType) {
  this.stoppedEvents_[eventType] = 1;
};
goog.editor.Field.prototype.startEvent = function(eventType) {
  this.stoppedEvents_[eventType] = 0;
};
goog.editor.Field.prototype.debounceEvent = function(eventType) {
  this.debouncedEvents_[eventType] = goog.now();
};
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_;
};
goog.editor.Field.prototype.manipulateDom = function(func, opt_preventDelayedChange, opt_handler) {
  this.stopChangeEvents(true, true);
  try {
    func.call(opt_handler);
  } finally {
    if (this.isLoaded()) {
      if (opt_preventDelayedChange) {
        this.startEvent(goog.editor.Field.EventType.CHANGE);
        this.handleChange();
        this.startEvent(goog.editor.Field.EventType.DELAYEDCHANGE);
      } else {
        this.dispatchChange();
      }
    }
  }
};
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);
  }
};
goog.editor.Field.prototype.dispatchChange = function(opt_noDelay) {
  this.startChangeEvents(true, opt_noDelay);
};
goog.editor.Field.prototype.handleChange = function() {
  if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
    return;
  }
  if (this.changeTimerGecko_) {
    this.changeTimerGecko_.stop();
  }
  this.isModified_ = true;
  this.isEverModified_ = true;
  if (this.isEventStopped(goog.editor.Field.EventType.DELAYEDCHANGE)) {
    return;
  }
  this.delayedChangeTimer_.start();
};
goog.editor.Field.prototype.dispatchDelayedChange_ = function() {
  if (this.isEventStopped(goog.editor.Field.EventType.DELAYEDCHANGE)) {
    return;
  }
  this.delayedChangeTimer_.stop();
  this.isModified_ = false;
  this.dispatchEvent(goog.editor.Field.EventType.DELAYEDCHANGE);
};
goog.editor.Field.prototype.clearDelayedChange = function() {
  if (this.changeTimerGecko_) {
    this.changeTimerGecko_.fireIfActive();
  }
  this.delayedChangeTimer_.fireIfActive();
};
goog.editor.Field.prototype.dispatchFocusAndBeforeFocus_ = function() {
  this.dispatchBeforeFocus_();
  this.dispatchFocus_();
};
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);
};
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) {
    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();
  }
};
goog.editor.Field.prototype.dispatchBlur = function() {
  if (this.isEventStopped(goog.editor.Field.EventType.BLUR)) {
    return;
  }
  if (goog.editor.Field.getActiveFieldId() == this.id) {
    goog.editor.Field.setActiveFieldId(null);
  }
  this.isSelectionEditable_ = false;
  this.dispatchEvent(goog.editor.Field.EventType.BLUR);
};
goog.editor.Field.prototype.isSelectionEditable = function() {
  return this.isSelectionEditable_;
};
goog.editor.Field.cancelLinkClick_ = function(e) {
  if (goog.dom.getAncestorByTagNameAndClass(e.target, goog.dom.TagName.A)) {
    e.preventDefault();
  }
};
goog.editor.Field.prototype.handleMouseDown_ = function(e) {
  goog.editor.Field.setActiveFieldId(this.id);
  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;
};
goog.editor.Field.prototype.handleDragStart_ = function(e) {
  this.waitingForMouseUp_ = false;
};
goog.editor.Field.prototype.handleMouseUp_ = function(e) {
  if (this.useWindowMouseUp_ && !this.waitingForMouseUp_) {
    return;
  }
  this.waitingForMouseUp_ = false;
  this.dispatchEvent(goog.editor.Field.EventType.BEFORESELECTIONCHANGE);
  this.dispatchSelectionChangeEvent(e);
  if (goog.userAgent.IE) {
    this.selectionChangeTarget_ = e.target;
    this.selectionChangeTimer_.start();
  }
};
goog.editor.Field.prototype.getCleanContents = function() {
  if (this.queryCommandValue(goog.editor.Command.USING_LOREM)) {
    return goog.string.Unicode.NBSP;
  }
  if (!this.isLoaded()) {
    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();
  this.invokeOp_(goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM, fieldCopy);
  return this.reduceOp_(goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML, fieldCopy.innerHTML);
};
goog.editor.Field.prototype.getFieldCopy = function() {
  var field = this.getElement();
  var fieldCopy = field.cloneNode(false);
  var html = field.innerHTML;
  if (goog.userAgent.IE && html.match(/^\s*<script/i)) {
    html = goog.string.Unicode.NBSP + html;
  }
  fieldCopy.innerHTML = html;
  return fieldCopy;
};
goog.editor.Field.prototype.setHtml = function(addParas, html, opt_dontFireDelayedChange, opt_applyLorem) {
  var safeHtml = html ? goog.html.legacyconversions.safeHtmlFromString(html) : null;
  this.setSafeHtml(addParas, safeHtml, opt_dontFireDelayedChange, opt_applyLorem);
};
goog.editor.Field.prototype.setSafeHtml = function(addParas, html, opt_dontFireDelayedChange, opt_applyLorem) {
  if (this.isLoading()) {
    goog.log.error(this.logger, "Can't set html while loading Trogedit");
    return;
  }
  if (opt_applyLorem) {
    this.execCommand(goog.editor.Command.CLEAR_LOREM);
  }
  if (html && addParas) {
    html = goog.html.SafeHtml.create("p", {}, html);
  }
  if (opt_dontFireDelayedChange) {
    this.stopChangeEvents(false, true);
  }
  this.setInnerHtml_(html);
  if (opt_applyLorem) {
    this.execCommand(goog.editor.Command.UPDATE_LOREM);
  }
  if (this.isLoaded()) {
    if (opt_dontFireDelayedChange) {
      if (goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
        this.changeTimerGecko_.fireIfActive();
      }
      this.startChangeEvents();
    } else {
      this.dispatchChange();
    }
  }
};
goog.editor.Field.prototype.setInnerHtml_ = function(html) {
  var field = this.getElement();
  if (field) {
    if (this.usesIframe() && goog.editor.BrowserFeature.MOVES_STYLE_TO_HEAD) {
      var heads = goog.dom.getElementsByTagName(goog.dom.TagName.HEAD, goog.asserts.assert(field.ownerDocument));
      for (var i = heads.length - 1; i >= 1; --i) {
        heads[i].parentNode.removeChild(heads[i]);
      }
    }
  } else {
    field = this.getOriginalElement();
  }
  if (field) {
    this.injectContents(html && goog.html.SafeHtml.unwrap(html), field);
  }
};
goog.editor.Field.prototype.turnOnDesignModeGecko = function() {
  var doc = this.getEditableDomHelper().getDocument();
  doc.designMode = "on";
  if (goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS) {
    doc.execCommand("styleWithCSS", false, false);
  }
};
goog.editor.Field.prototype.installStyles = function() {
  if (this.cssStyles && this.shouldLoadAsynchronously()) {
    goog.style.installSafeStyleSheet(goog.html.legacyconversions.safeStyleSheetFromString(this.cssStyles), this.getElement());
  }
};
goog.editor.Field.prototype.dispatchLoadEvent_ = function() {
  this.getElement();
  this.installStyles();
  this.startChangeEvents();
  goog.log.info(this.logger, "Dispatching load " + this.id);
  this.dispatchEvent(goog.editor.Field.EventType.LOAD);
};
goog.editor.Field.prototype.isUneditable = function() {
  return this.loadState_ == goog.editor.Field.LoadState_.UNEDITABLE;
};
goog.editor.Field.prototype.isLoaded = function() {
  return this.loadState_ == goog.editor.Field.LoadState_.EDITABLE;
};
goog.editor.Field.prototype.isLoading = function() {
  return this.loadState_ == goog.editor.Field.LoadState_.LOADING;
};
goog.editor.Field.prototype.focus = function() {
  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE && this.usesIframe()) {
    this.getEditableDomHelper().getWindow().focus();
  } else {
    if (goog.userAgent.OPERA) {
      var scrollX = this.appWindow_.pageXOffset;
      var scrollY = this.appWindow_.pageYOffset;
    }
    this.getElement().focus();
    if (goog.userAgent.OPERA) {
      this.appWindow_.scrollTo(scrollX, scrollY);
    }
  }
};
goog.editor.Field.prototype.focusAndPlaceCursorAtStart = function() {
  if (goog.editor.BrowserFeature.HAS_IE_RANGES || !goog.userAgent.GECKO) {
    this.placeCursorAtStart();
  }
  this.focus();
};
goog.editor.Field.prototype.placeCursorAtStart = function() {
  this.placeCursorAtStartOrEnd_(true);
};
goog.editor.Field.prototype.placeCursorAtEnd = function() {
  this.placeCursorAtStartOrEnd_(false);
};
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) {
      goog.dom.Range.createCaret(field, 0).select();
    } else {
      goog.editor.range.placeCursorNextTo(cursorPosition, isStart);
    }
    this.dispatchSelectionChangeEvent();
  }
};
goog.editor.Field.prototype.restoreSavedRange = function(opt_range) {
  if (opt_range) {
    opt_range.restore();
  }
  this.focus();
};
goog.editor.Field.prototype.makeEditable = function(opt_iframeSrc) {
  this.loadState_ = goog.editor.Field.LoadState_.LOADING;
  var field = this.getOriginalElement();
  this.nodeName = field.nodeName;
  this.savedClassName_ = field.className;
  this.setInitialStyle(field.style.cssText);
  goog.dom.classlist.add(field, "editable");
  this.makeEditableInternal(opt_iframeSrc);
};
goog.editor.Field.prototype.makeEditableInternal = function(opt_iframeSrc) {
  this.makeIframeField_(opt_iframeSrc);
};
goog.editor.Field.prototype.handleFieldLoad = function() {
  if (goog.userAgent.IE) {
    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_();
  for (var classId in this.plugins_) {
    this.plugins_[classId].enable(this);
  }
};
goog.editor.Field.prototype.makeUneditable = function(opt_skipRestore) {
  if (this.isUneditable()) {
    throw Error("makeUneditable: Field is already uneditable");
  }
  this.clearDelayedChange();
  this.selectionChangeTimer_.fireIfActive();
  this.execCommand(goog.editor.Command.CLEAR_LOREM);
  var html = null;
  if (!opt_skipRestore && this.getElement()) {
    html = this.getCleanContents();
  }
  this.clearFieldLoadListener_();
  var field = this.getOriginalElement();
  if (goog.editor.Field.getActiveFieldId() == field.id) {
    goog.editor.Field.setActiveFieldId(null);
  }
  this.clearListeners();
  if (goog.isString(html)) {
    goog.editor.node.replaceInnerHtml(field, html);
    this.resetOriginalElemProperties();
  }
  this.restoreDom();
  this.tearDownFieldObject_();
  if (goog.userAgent.WEBKIT) {
    field.blur();
  }
  this.execCommand(goog.editor.Command.UPDATE_LOREM);
  this.dispatchEvent(goog.editor.Field.EventType.UNLOAD);
};
goog.editor.Field.prototype.restoreDom = function() {
  var field = this.getOriginalElement();
  if (field) {
    var iframe = this.getEditableIframe();
    if (iframe) {
      goog.dom.replaceNode(field, iframe);
    }
  }
};
goog.editor.Field.prototype.shouldLoadAsynchronously = function() {
  if (!goog.isDef(this.isHttps_)) {
    this.isHttps_ = false;
    if (goog.userAgent.IE && this.usesIframe()) {
      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_;
};
goog.editor.Field.prototype.makeIframeField_ = function(opt_iframeSrc) {
  var field = this.getOriginalElement();
  if (field) {
    var html = field.innerHTML;
    var styles = {};
    html = this.reduceOp_(goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, html, styles);
    var iframe = this.originalDomHelper.createDom(goog.dom.TagName.IFRAME, this.getIframeAttributes());
    if (this.shouldLoadAsynchronously()) {
      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);
    if (!this.shouldLoadAsynchronously()) {
      this.iframeFieldLoadHandler(iframe, html, styles);
    }
  }
};
goog.editor.Field.prototype.attachIframe = function(iframe) {
  var field = this.getOriginalElement();
  iframe.className = field.className;
  iframe.id = field.id;
  goog.dom.replaceNode(iframe, field);
};
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);
};
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);
  }
};
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);
  var body = doc.body;
  this.setupFieldObject(body);
  if (!goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE && this.usesIframe()) {
    this.turnOnDesignModeGecko();
  }
  this.handleFieldLoad();
};
goog.editor.Field.prototype.clearFieldLoadListener_ = function() {
  if (this.fieldLoadListenerKey_) {
    goog.events.unlistenByKey(this.fieldLoadListenerKey_);
    this.fieldLoadListenerKey_ = null;
  }
};
goog.editor.Field.prototype.getIframeAttributes = function() {
  var iframeStyle = "padding:0;" + this.getOriginalElement().style.cssText;
  if (!goog.string.endsWith(iframeStyle, ";")) {
    iframeStyle += ";";
  }
  iframeStyle += "background-color:white;";
  if (goog.userAgent.IE) {
    iframeStyle += "overflow:visible;";
  }
  return {"frameBorder":0, "style":iframeStyle};
};
goog.provide("goog.cssom");
goog.provide("goog.cssom.CssRuleType");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.dom.TagName");
goog.cssom.CssRuleType = {STYLE:1, IMPORT:3, MEDIA:4, FONT_FACE:5, PAGE:6, NAMESPACE:7};
goog.cssom.getAllCssText = function(opt_styleSheet) {
  var styleSheet = opt_styleSheet || document.styleSheets;
  return goog.cssom.getAllCss_(styleSheet, true);
};
goog.cssom.getAllCssStyleRules = function(opt_styleSheet) {
  var styleSheet = opt_styleSheet || document.styleSheets;
  return goog.cssom.getAllCss_(styleSheet, false);
};
goog.cssom.getCssRulesFromStyleSheet = function(styleSheet) {
  var cssRuleList = null;
  try {
    cssRuleList = styleSheet.cssRules || styleSheet.rules;
  } catch (e) {
    if (e.code == 15) {
      e.styleSheet = styleSheet;
      throw e;
    }
  }
  return cssRuleList;
};
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;
  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) {
      for (var i = 0, n = styleSheet.length; i < n; i++) {
        goog.array.extend(styleSheetsOutput, goog.cssom.getAllCssStyleSheets(styleSheet[i]));
      }
    } else {
      var cssRuleList = goog.cssom.getCssRulesFromStyleSheet(styleSheet);
      if (cssRuleList && cssRuleList.length) {
        for (var i = 0, n = cssRuleList.length, cssRule; i < n; i++) {
          cssRule = cssRuleList[i];
          if (cssRule.styleSheet) {
            goog.array.extend(styleSheetsOutput, goog.cssom.getAllCssStyleSheets(cssRule.styleSheet));
          }
        }
      }
    }
  }
  if ((styleSheet.type || styleSheet.rules || styleSheet.cssRules) && (!styleSheet.disabled || includeDisabled)) {
    styleSheetsOutput.push(styleSheet);
  }
  return styleSheetsOutput;
};
goog.cssom.getCssTextFromCssRule = function(cssRule) {
  var cssText = "";
  if (cssRule.cssText) {
    cssText = cssRule.cssText;
  } else {
    if (cssRule.style && cssRule.style.cssText && cssRule.selectorText) {
      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;
};
goog.cssom.getCssRuleIndexInParentStyleSheet = function(cssRule, opt_parentStyleSheet) {
  if (cssRule.style && cssRule.style["-closure-rule-index"]) {
    return cssRule.style["-closure-rule-index"];
  }
  var parentStyleSheet = opt_parentStyleSheet || goog.cssom.getParentStyleSheet(cssRule);
  if (!parentStyleSheet) {
    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;
};
goog.cssom.getParentStyleSheet = function(cssRule) {
  return cssRule.parentStyleSheet || cssRule.style && cssRule.style["-closure-parent-stylesheet"];
};
goog.cssom.replaceCssRule = function(cssRule, cssText, opt_parentStyleSheet, opt_index) {
  var parentStyleSheet = opt_parentStyleSheet || goog.cssom.getParentStyleSheet(cssRule);
  if (parentStyleSheet) {
    var index = Number(opt_index) >= 0 ? Number(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.");
  }
};
goog.cssom.addCssRule = function(cssStyleSheet, cssText, opt_index) {
  var index = opt_index;
  if (index == undefined || index < 0) {
    var rules = goog.cssom.getCssRulesFromStyleSheet(cssStyleSheet);
    index = rules.length;
  }
  if (cssStyleSheet.insertRule) {
    cssStyleSheet.insertRule(cssText, index);
  } else {
    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.");
    }
  }
};
goog.cssom.removeCssRule = function(cssStyleSheet, index) {
  if (cssStyleSheet.deleteRule) {
    cssStyleSheet.deleteRule(index);
  } else {
    cssStyleSheet.removeRule(index);
  }
};
goog.cssom.addCssText = function(cssText, opt_domHelper) {
  var domHelper = opt_domHelper || goog.dom.getDomHelper();
  var document = domHelper.getDocument();
  var cssNode = domHelper.createElement(goog.dom.TagName.STYLE);
  cssNode.type = "text/css";
  var head = domHelper.getElementsByTagName(goog.dom.TagName.HEAD)[0];
  head.appendChild(cssNode);
  if (cssNode.styleSheet) {
    cssNode.styleSheet.cssText = cssText;
  } else {
    var cssTextNode = document.createTextNode(cssText);
    cssNode.appendChild(cssTextNode);
  }
  return cssNode;
};
goog.cssom.getFileNameFromStyleSheet = function(styleSheet) {
  var href = styleSheet.href;
  if (!href) {
    return null;
  }
  var matches = /([^\/\?]+)[^\/]*$/.exec(href);
  var filename = matches[1];
  return filename;
};
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) {
      var ruleIndex = 0;
      for (var j = 0, n = cssRuleList.length, cssRule; j < n; j++) {
        cssRule = cssRuleList[j];
        if (isTextOutput && !cssRule.href) {
          var res = goog.cssom.getCssTextFromCssRule(cssRule);
          cssOut.push(res);
        } else {
          if (!cssRule.href) {
            if (cssRule.style) {
              if (!cssRule.parentStyleSheet) {
                cssRule.style["-closure-parent-stylesheet"] = styleSheet;
              }
              cssRule.style["-closure-rule-index"] = isTextOutput ? undefined : ruleIndex;
            }
            cssOut.push(cssRule);
          }
        }
        if (!isTextOutput) {
          ruleIndex++;
        }
      }
    }
  }
  return isTextOutput ? cssOut.join(" ") : cssOut;
};
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");
goog.cssom.iframe.style.selectorPartAnchorRegex_ = /a(:(link|visited|active|hover))?/;
goog.cssom.iframe.style.SELECTOR_DELIMITER_ = ",";
goog.cssom.iframe.style.SELECTOR_PART_DELIMITER_ = " ";
goog.cssom.iframe.style.DECLARATION_START_DELIMITER_ = "{";
goog.cssom.iframe.style.DECLARATION_END_DELIMITER_ = "}\n";
goog.cssom.iframe.style.CssRuleSet_ = function() {
  this.declarationText = "";
  this.selectors = [];
};
goog.cssom.iframe.style.CssRuleSet_.prototype.initializeFromCssRule = function(cssRule) {
  var ruleStyle = cssRule.style;
  if (!ruleStyle) {
    return false;
  }
  var selector;
  var declarations = "";
  if (ruleStyle && (selector = cssRule.selectorText) && (declarations = ruleStyle.cssText)) {
    if (goog.userAgent.IE) {
      declarations += "/* */";
    }
  } else {
    if (cssRule.cssText) {
      var cssSelectorMatch = /([^\{]+)\{/;
      var endTagMatch = /\}[^\}]*$/g;
      selector = cssSelectorMatch.exec(cssRule.cssText)[1];
      declarations = cssRule.cssText.replace(cssSelectorMatch, "").replace(endTagMatch, "");
    }
  }
  if (selector) {
    this.setSelectorsFromString(selector);
    this.declarationText = declarations;
    return true;
  }
  return false;
};
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));
    }
  }
};
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;
};
goog.cssom.iframe.style.CssRuleSet_.prototype.setDeclarationTextFromObject = function(sourceObject, opt_important) {
  var stringParts = [];
  for (var prop in sourceObject) {
    var value = sourceObject[prop];
    if (value) {
      stringParts.push(prop, ":", value, opt_important ? " !important" : "", ";");
    }
  }
  this.declarationText = stringParts.join("");
};
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")) {
      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_);
};
goog.cssom.iframe.style.colorImportantReplaceRegex_ = /(^|;|{)\s*color:([^;]+);/g;
goog.cssom.iframe.style.makeColorRuleImportant_ = function(cssText) {
  return cssText.replace(goog.cssom.iframe.style.colorImportantReplaceRegex_, "$1 color: $2 ! important; ");
};
goog.cssom.iframe.style.CssSelector_ = function(opt_selectorString) {
  this.ancestryMatchCache_ = {};
  if (opt_selectorString) {
    this.setPartsFromString_(opt_selectorString);
  }
};
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;
    }
    var part = new goog.cssom.iframe.style.CssSelectorPart_(selectorPartStrings[i]);
    parts.push(part);
  }
  this.parts = parts;
};
goog.cssom.iframe.style.CssSelector_.prototype.matchElementAncestry = function(elementAncestry) {
  var ancestryUid = elementAncestry.uid;
  if (this.ancestryMatchCache_[ancestryUid]) {
    return this.ancestryMatchCache_[ancestryUid];
  }
  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;
};
goog.cssom.iframe.style.CssSelectorPart_ = function(selectorPartString) {
  var cacheEntry = goog.cssom.iframe.style.CssSelectorPart_.instances_[selectorPartString];
  if (cacheEntry) {
    return cacheEntry;
  }
  var identifiers;
  if (selectorPartString.match(/[#\.]/)) {
    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;
};
goog.cssom.iframe.style.CssSelectorPart_.instances_ = {};
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;
};
goog.cssom.iframe.style.NodeAncestry_ = function(el) {
  var node = el;
  var nodeUid = goog.getUid(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);
  this.nodes = nodes;
  this.uid = goog.getUid(this);
  goog.cssom.iframe.style.NodeAncestry_.instances_[nodeUid] = this;
};
goog.cssom.iframe.style.NodeAncestry_.instances_ = {};
goog.cssom.iframe.style.resetDomCache = function() {
  goog.cssom.iframe.style.NodeAncestry_.instances_ = {};
};
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;
};
goog.cssom.iframe.style.ruleSetCache_ = {};
goog.cssom.iframe.style.ruleSetCache_.ruleSetCache_ = {};
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);
};
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);
  }
  var ruleSets = cache[docUid];
  var ruleSetsCopy = [];
  for (var i = 0; i < ruleSets.length; i++) {
    ruleSetsCopy.push(ruleSets[i].clone());
  }
  return ruleSetsCopy;
};
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"];
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"];
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;
    var ruleCount = selectors.length;
    for (var j = 0; j < ruleCount; j++) {
      var selector = selectors[j];
      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) {
          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) {
            selectorCopy = new goog.cssom.iframe.style.CssSelector_;
            selectorCopy.parts = [bodySelectorPart, selectorParts[lastSelectorPartIndex]];
            selectors.push(selectorCopy);
          }
        }
      }
    }
  }
  var defaultPropertiesRuleSet = new goog.cssom.iframe.style.CssRuleSet_;
  var computedStyle = goog.cssom.iframe.style.getComputedStyleObject_(element);
  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")];
  var bodyProperties = {position:"relative", top:"0", left:"0", right:"auto", display:"block", visibility:"visible"};
  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"])) {
    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);
  var ruleSetStrings = [];
  ruleCount = ruleSets.length;
  for (i = 0; i < ruleCount; i++) {
    ruleSets[i].writeToArray(ruleSetStrings);
  }
  return ruleSetStrings.join("");
};
goog.cssom.iframe.style.isTransparentValue_ = function(colorValue) {
  return colorValue == "transparent" || colorValue == "rgba(0, 0, 0, 0)";
};
goog.cssom.iframe.style.getComputedStyleObject_ = function(element) {
  return element.currentStyle || goog.dom.getOwnerDocument(element).defaultView.getComputedStyle(element, "") || {};
};
goog.cssom.iframe.style.valueWithUnitsRegEx_ = /^(-?)([0-9]+)([a-z]*|%)/;
goog.cssom.iframe.style.getBackgroundXYValues_ = function(styleObject) {
  if (styleObject["backgroundPositionY"]) {
    return [styleObject["backgroundPositionX"], styleObject["backgroundPositionY"]];
  } else {
    return (styleObject["backgroundPosition"] || "0 0").split(" ");
  }
};
goog.cssom.iframe.style.getBackgroundContext = function(element) {
  var propertyValues = {"backgroundImage":"none"};
  var ancestor = element;
  var currentIframeWindow;
  while ((ancestor = ancestor.parentNode) && ancestor.nodeType == goog.dom.NodeType.ELEMENT) {
    var computedStyle = goog.cssom.iframe.style.getComputedStyleObject_(ancestor);
    var backgroundColorValue = computedStyle["backgroundColor"];
    if (!goog.cssom.iframe.style.isTransparentValue_(backgroundColorValue)) {
      propertyValues["backgroundColor"] = backgroundColorValue;
    }
    if (computedStyle["backgroundImage"] && computedStyle["backgroundImage"] != "none") {
      propertyValues["backgroundImage"] = computedStyle["backgroundImage"];
      propertyValues["backgroundRepeat"] = computedStyle["backgroundRepeat"];
      var relativePosition;
      if (currentIframeWindow) {
        relativePosition = goog.style.getFramedPageOffset(element, currentIframeWindow);
        var frameElement = currentIframeWindow.frameElement;
        var iframeRelativePosition = goog.style.getRelativePosition(frameElement, 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, ancestor);
      }
      var backgroundXYValues = goog.cssom.iframe.style.getBackgroundXYValues_(computedStyle);
      for (var i = 0; i < 2; i++) {
        var positionValue = backgroundXYValues[i];
        var coordinate = i == 0 ? "X" : "Y";
        var positionProperty = "backgroundPosition" + coordinate;
        var positionValueParts = goog.cssom.iframe.style.valueWithUnitsRegEx_.exec(positionValue);
        if (positionValueParts) {
          var value = parseInt(positionValueParts[1] + positionValueParts[2], 10);
          var units = positionValueParts[3];
          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(ancestor.parentNode);
        ancestor = currentIframeWindow.frameElement;
        if (!ancestor) {
          break;
        }
      } catch (e) {
        break;
      }
    }
  }
  return propertyValues;
};
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.legacyconversions");
goog.require("goog.html.uncheckedconversions");
goog.require("goog.log");
goog.require("goog.string.Const");
goog.require("goog.style");
goog.editor.SeamlessField = function(id, opt_doc) {
  goog.editor.Field.call(this, id, opt_doc);
};
goog.inherits(goog.editor.SeamlessField, goog.editor.Field);
goog.editor.SeamlessField.prototype.logger = goog.log.getLogger("goog.editor.SeamlessField");
goog.editor.SeamlessField.prototype.listenForDragOverEventKey_;
goog.editor.SeamlessField.prototype.listenForIframeLoadEventKey_;
goog.editor.SeamlessField.prototype.setMinHeight = function(height) {
  if (height == this.minHeight_) {
    return;
  }
  this.minHeight_ = height;
  if (this.usesIframe()) {
    this.doFieldSizingGecko();
  }
};
goog.editor.SeamlessField.prototype.isFixedHeight_ = false;
goog.editor.SeamlessField.prototype.isFixedHeightOverridden_ = false;
goog.editor.SeamlessField.prototype.isFixedHeight = function() {
  return this.isFixedHeight_;
};
goog.editor.SeamlessField.prototype.overrideFixedHeight = function(newVal) {
  this.isFixedHeight_ = newVal;
  this.isFixedHeightOverridden_ = true;
};
goog.editor.SeamlessField.prototype.autoDetectFixedHeight_ = function() {
  if (!this.isFixedHeightOverridden_) {
    var originalElement = this.getOriginalElement();
    if (originalElement) {
      this.isFixedHeight_ = goog.style.getComputedOverflowY(originalElement) == "auto";
    }
  }
};
goog.editor.SeamlessField.prototype.handleOuterDocChange_ = function() {
  if (this.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
    return;
  }
  this.sizeIframeToWrapperGecko_();
};
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);
    }
  }
};
goog.editor.SeamlessField.prototype.getIframeBodyHeightGecko_ = function() {
  var ifr = this.getEditableIframe();
  var body = ifr.contentDocument.body;
  var htmlElement = body.parentNode;
  if (parseInt(goog.style.getStyle(ifr, "height"), 10) === 0) {
    goog.style.setStyle(ifr, "height", 1 + "px");
  }
  var fieldHeight;
  if (goog.editor.node.isStandardsMode(body)) {
    fieldHeight = htmlElement.offsetHeight;
  } else {
    fieldHeight = htmlElement.scrollHeight;
    if (htmlElement.clientHeight != htmlElement.offsetHeight) {
      fieldHeight += goog.editor.SeamlessField.getScrollbarWidth_();
    }
  }
  return fieldHeight;
};
goog.editor.SeamlessField.getScrollbarWidth_ = function() {
  return goog.editor.SeamlessField.scrollbarWidth_ || (goog.editor.SeamlessField.scrollbarWidth_ = goog.style.getScrollbarWidth());
};
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);
    }
  }
};
goog.editor.SeamlessField.prototype.doFieldSizingGecko = function() {
  if (this.getElement()) {
    this.sizeIframeToWrapperGecko_();
    if (!this.isFixedHeight()) {
      this.sizeIframeToBodyHeightGecko_();
    }
  }
};
goog.editor.SeamlessField.prototype.acquireSizeIframeLockGecko_ = function() {
  if (this.sizeIframeLock_) {
    return false;
  }
  return this.sizeIframeLock_ = true;
};
goog.editor.SeamlessField.prototype.releaseSizeIframeLockGecko_ = function() {
  this.sizeIframeLock_ = false;
};
goog.editor.SeamlessField.prototype.iframeableCss_ = "";
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_;
};
goog.editor.SeamlessField.prototype.setIframeableCss = function(iframeableCss) {
  this.iframeableCss_ = iframeableCss;
};
goog.editor.SeamlessField.haveInstalledCss_ = false;
goog.editor.SeamlessField.prototype.inheritBlendedCSS = function() {
  if (!this.usesIframe()) {
    return;
  }
  var field = this.getElement();
  var head = goog.dom.getDomHelper(field).getElementsByTagNameAndClass(goog.dom.TagName.HEAD)[0];
  if (head) {
    goog.dom.removeChildren(head);
  }
  var newCSS = this.getIframeableCss(true);
  goog.style.installSafeStyleSheet(goog.html.legacyconversions.safeStyleSheetFromString(newCSS), field);
};
goog.editor.SeamlessField.prototype.usesIframe = function() {
  return !goog.editor.BrowserFeature.HAS_CONTENT_EDITABLE;
};
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);
    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);
  }
};
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_();
  }
};
goog.editor.SeamlessField.prototype.dispatchBlur = function() {
  if (this.isEventStopped(goog.editor.Field.EventType.BLUR)) {
    return;
  }
  goog.editor.SeamlessField.superClass_.dispatchBlur.call(this);
  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() {
      if (!dragging) {
        if (this.editableDomHelper) {
          var rng = this.getRange();
          var iframeWindow = this.editableDomHelper.getWindow();
          goog.dom.Range.clearSelection(iframeWindow);
          if (rng) {
            rng.collapse(true);
            rng.select();
          }
        }
      }
    }, this), 0);
  }
};
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");
};
goog.editor.SeamlessField.prototype.installStyles = function() {
  if (!this.usesIframe()) {
    if (!goog.editor.SeamlessField.haveInstalledCss_) {
      if (this.cssStyles) {
        goog.style.installSafeStyleSheet(goog.html.legacyconversions.safeStyleSheetFromString(this.cssStyles), this.getElement());
      }
      goog.editor.SeamlessField.haveInstalledCss_ = true;
    }
  }
};
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();
    }
  }
};
goog.editor.SeamlessField.prototype.handleFieldLoad = function() {
  if (this.usesIframe()) {
    var self = this;
    goog.global.setTimeout(function() {
      self.doFieldSizingGecko();
    }, 0);
  }
  goog.editor.SeamlessField.superClass_.handleFieldLoad.call(this);
};
goog.editor.SeamlessField.prototype.getIframeAttributes = function() {
  return {"frameBorder":0, "style":"padding:0;"};
};
goog.editor.SeamlessField.prototype.attachIframe = function(iframe) {
  this.autoDetectFixedHeight_();
  var field = this.getOriginalElement();
  var dh = goog.dom.getDomHelper(field);
  var oldWidth = field.style.width;
  var oldHeight = field.style.height;
  goog.style.setStyle(field, "visibility", "hidden");
  var startDiv = dh.createDom(goog.dom.TagName.DIV, {"style":"height:0;clear:both", "innerHTML":"&nbsp;"});
  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 = "&nbsp;";
    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);
  if (goog.editor.node.isStandardsMode(field)) {
    this.originalFieldLineHeight_ = field.style.lineHeight;
    goog.style.setStyle(field, "lineHeight", "0");
  }
  goog.editor.node.replaceInnerHtml(field, html);
  goog.style.setSize(iframe, width, height);
  goog.style.setSize(field, oldWidth, oldHeight);
  goog.style.setStyle(field, "visibility", "");
  goog.dom.appendChild(field, iframe);
  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();
    }
  }
};
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");
};
goog.editor.SeamlessField.prototype.writeIframeContent = function(iframe, innerHtml, extraStyles) {
  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");
};
goog.editor.SeamlessField.prototype.restoreDom = function() {
  if (this.usesIframe()) {
    goog.dom.removeNode(this.getEditableIframe());
  }
};
goog.editor.SeamlessField.prototype.clearListeners = function() {
  goog.events.unlistenByKey(this.listenForDragOverEventKey_);
  goog.events.unlistenByKey(this.listenForIframeLoadEventKey_);
  goog.editor.SeamlessField.base(this, "clearListeners");
};
goog.provide("goog.uri.utils");
goog.provide("goog.uri.utils.ComponentIndex");
goog.provide("goog.uri.utils.QueryArray");
goog.provide("goog.uri.utils.QueryValue");
goog.provide("goog.uri.utils.StandardQueryParam");
goog.require("goog.array");
goog.require("goog.asserts");
goog.require("goog.string");
goog.uri.utils.CharCode_ = {AMPERSAND:38, EQUAL:61, HASH:35, QUESTION:63};
goog.uri.utils.buildFromEncodedParts = function(opt_scheme, opt_userInfo, opt_domain, opt_port, opt_path, opt_queryData, opt_fragment) {
  var out = "";
  if (opt_scheme) {
    out += opt_scheme + ":";
  }
  if (opt_domain) {
    out += "//";
    if (opt_userInfo) {
      out += opt_userInfo + "@";
    }
    out += opt_domain;
    if (opt_port) {
      out += ":" + opt_port;
    }
  }
  if (opt_path) {
    out += opt_path;
  }
  if (opt_queryData) {
    out += "?" + opt_queryData;
  }
  if (opt_fragment) {
    out += "#" + opt_fragment;
  }
  return out;
};
goog.uri.utils.splitRe_ = new RegExp("^" + "(?:" + "([^:/?#.]+)" + ":)?" + "(?://" + "(?:([^/?#]*)@)?" + "([^/#?]*?)" + "(?::([0-9]+))?" + "(?=[/#?]|$)" + ")?" + "([^?#]+)?" + "(?:\\?([^#]*))?" + "(?:#([\\s\\S]*))?" + "$");
goog.uri.utils.ComponentIndex = {SCHEME:1, USER_INFO:2, DOMAIN:3, PORT:4, PATH:5, QUERY_DATA:6, FRAGMENT:7};
goog.uri.utils.split = function(uri) {
  return uri.match(goog.uri.utils.splitRe_);
};
goog.uri.utils.decodeIfPossible_ = function(uri, opt_preserveReserved) {
  if (!uri) {
    return uri;
  }
  return opt_preserveReserved ? decodeURI(uri) : decodeURIComponent(uri);
};
goog.uri.utils.getComponentByIndex_ = function(componentIndex, uri) {
  return goog.uri.utils.split(uri)[componentIndex] || null;
};
goog.uri.utils.getScheme = function(uri) {
  return goog.uri.utils.getComponentByIndex_(goog.uri.utils.ComponentIndex.SCHEME, uri);
};
goog.uri.utils.getEffectiveScheme = function(uri) {
  var scheme = goog.uri.utils.getScheme(uri);
  if (!scheme && goog.global.self && goog.global.self.location) {
    var protocol = goog.global.self.location.protocol;
    scheme = protocol.substr(0, protocol.length - 1);
  }
  return scheme ? scheme.toLowerCase() : "";
};
goog.uri.utils.getUserInfoEncoded = function(uri) {
  return goog.uri.utils.getComponentByIndex_(goog.uri.utils.ComponentIndex.USER_INFO, uri);
};
goog.uri.utils.getUserInfo = function(uri) {
  return goog.uri.utils.decodeIfPossible_(goog.uri.utils.getUserInfoEncoded(uri));
};
goog.uri.utils.getDomainEncoded = function(uri) {
  return goog.uri.utils.getComponentByIndex_(goog.uri.utils.ComponentIndex.DOMAIN, uri);
};
goog.uri.utils.getDomain = function(uri) {
  return goog.uri.utils.decodeIfPossible_(goog.uri.utils.getDomainEncoded(uri), true);
};
goog.uri.utils.getPort = function(uri) {
  return Number(goog.uri.utils.getComponentByIndex_(goog.uri.utils.ComponentIndex.PORT, uri)) || null;
};
goog.uri.utils.getPathEncoded = function(uri) {
  return goog.uri.utils.getComponentByIndex_(goog.uri.utils.ComponentIndex.PATH, uri);
};
goog.uri.utils.getPath = function(uri) {
  return goog.uri.utils.decodeIfPossible_(goog.uri.utils.getPathEncoded(uri), true);
};
goog.uri.utils.getQueryData = function(uri) {
  return goog.uri.utils.getComponentByIndex_(goog.uri.utils.ComponentIndex.QUERY_DATA, uri);
};
goog.uri.utils.getFragmentEncoded = function(uri) {
  var hashIndex = uri.indexOf("#");
  return hashIndex < 0 ? null : uri.substr(hashIndex + 1);
};
goog.uri.utils.setFragmentEncoded = function(uri, fragment) {
  return goog.uri.utils.removeFragment(uri) + (fragment ? "#" + fragment : "");
};
goog.uri.utils.getFragment = function(uri) {
  return goog.uri.utils.decodeIfPossible_(goog.uri.utils.getFragmentEncoded(uri));
};
goog.uri.utils.getHost = function(uri) {
  var pieces = goog.uri.utils.split(uri);
  return goog.uri.utils.buildFromEncodedParts(pieces[goog.uri.utils.ComponentIndex.SCHEME], pieces[goog.uri.utils.ComponentIndex.USER_INFO], pieces[goog.uri.utils.ComponentIndex.DOMAIN], pieces[goog.uri.utils.ComponentIndex.PORT]);
};
goog.uri.utils.getOrigin = function(uri) {
  var pieces = goog.uri.utils.split(uri);
  return goog.uri.utils.buildFromEncodedParts(pieces[goog.uri.utils.ComponentIndex.SCHEME], null, pieces[goog.uri.utils.ComponentIndex.DOMAIN], pieces[goog.uri.utils.ComponentIndex.PORT]);
};
goog.uri.utils.getPathAndAfter = function(uri) {
  var pieces = goog.uri.utils.split(uri);
  return goog.uri.utils.buildFromEncodedParts(null, null, null, null, pieces[goog.uri.utils.ComponentIndex.PATH], pieces[goog.uri.utils.ComponentIndex.QUERY_DATA], pieces[goog.uri.utils.ComponentIndex.FRAGMENT]);
};
goog.uri.utils.removeFragment = function(uri) {
  var hashIndex = uri.indexOf("#");
  return hashIndex < 0 ? uri : uri.substr(0, hashIndex);
};
goog.uri.utils.haveSameDomain = function(uri1, uri2) {
  var pieces1 = goog.uri.utils.split(uri1);
  var pieces2 = goog.uri.utils.split(uri2);
  return pieces1[goog.uri.utils.ComponentIndex.DOMAIN] == pieces2[goog.uri.utils.ComponentIndex.DOMAIN] && pieces1[goog.uri.utils.ComponentIndex.SCHEME] == pieces2[goog.uri.utils.ComponentIndex.SCHEME] && pieces1[goog.uri.utils.ComponentIndex.PORT] == pieces2[goog.uri.utils.ComponentIndex.PORT];
};
goog.uri.utils.assertNoFragmentsOrQueries_ = function(uri) {
  goog.asserts.assert(uri.indexOf("#") < 0 && uri.indexOf("?") < 0, "goog.uri.utils: Fragment or query identifiers are not supported: [%s]", uri);
};
goog.uri.utils.QueryValue;
goog.uri.utils.QueryArray;
goog.uri.utils.parseQueryData = function(encodedQuery, callback) {
  if (!encodedQuery) {
    return;
  }
  var pairs = encodedQuery.split("&");
  for (var i = 0; i < pairs.length; i++) {
    var indexOfEquals = pairs[i].indexOf("=");
    var name = null;
    var value = null;
    if (indexOfEquals >= 0) {
      name = pairs[i].substring(0, indexOfEquals);
      value = pairs[i].substring(indexOfEquals + 1);
    } else {
      name = pairs[i];
    }
    callback(name, value ? goog.string.urlDecode(value) : "");
  }
};
goog.uri.utils.splitQueryData_ = function(uri) {
  var hashIndex = uri.indexOf("#");
  if (hashIndex < 0) {
    hashIndex = uri.length;
  }
  var questionIndex = uri.indexOf("?");
  var queryData;
  if (questionIndex < 0 || questionIndex > hashIndex) {
    questionIndex = hashIndex;
    queryData = "";
  } else {
    queryData = uri.substring(questionIndex + 1, hashIndex);
  }
  return [uri.substr(0, questionIndex), queryData, uri.substr(hashIndex)];
};
goog.uri.utils.joinQueryData_ = function(parts) {
  return parts[0] + (parts[1] ? "?" + parts[1] : "") + parts[2];
};
goog.uri.utils.appendQueryData_ = function(queryData, newData) {
  if (!newData) {
    return queryData;
  }
  return queryData ? queryData + "&" + newData : newData;
};
goog.uri.utils.appendQueryDataToUri_ = function(uri, queryData) {
  if (!queryData) {
    return uri;
  }
  var parts = goog.uri.utils.splitQueryData_(uri);
  parts[1] = goog.uri.utils.appendQueryData_(parts[1], queryData);
  return goog.uri.utils.joinQueryData_(parts);
};
goog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) {
  goog.asserts.assertString(key);
  if (goog.isArray(value)) {
    goog.asserts.assertArray(value);
    for (var j = 0; j < value.length; j++) {
      goog.uri.utils.appendKeyValuePairs_(key, String(value[j]), pairs);
    }
  } else {
    if (value != null) {
      pairs.push(key + (value === "" ? "" : "=" + goog.string.urlEncode(value)));
    }
  }
};
goog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) {
  goog.asserts.assert(Math.max(keysAndValues.length - (opt_startIndex || 0), 0) % 2 == 0, "goog.uri.utils: Key/value lists must be even in length.");
  var params = [];
  for (var i = opt_startIndex || 0; i < keysAndValues.length; i += 2) {
    var key = keysAndValues[i];
    goog.uri.utils.appendKeyValuePairs_(key, keysAndValues[i + 1], params);
  }
  return params.join("&");
};
goog.uri.utils.buildQueryDataFromMap = function(map) {
  var params = [];
  for (var key in map) {
    goog.uri.utils.appendKeyValuePairs_(key, map[key], params);
  }
  return params.join("&");
};
goog.uri.utils.appendParams = function(uri, var_args) {
  var queryData = arguments.length == 2 ? goog.uri.utils.buildQueryData(arguments[1], 0) : goog.uri.utils.buildQueryData(arguments, 1);
  return goog.uri.utils.appendQueryDataToUri_(uri, queryData);
};
goog.uri.utils.appendParamsFromMap = function(uri, map) {
  var queryData = goog.uri.utils.buildQueryDataFromMap(map);
  return goog.uri.utils.appendQueryDataToUri_(uri, queryData);
};
goog.uri.utils.appendParam = function(uri, key, opt_value) {
  var value = goog.isDefAndNotNull(opt_value) ? "=" + goog.string.urlEncode(opt_value) : "";
  return goog.uri.utils.appendQueryDataToUri_(uri, key + value);
};
goog.uri.utils.findParam_ = function(uri, startIndex, keyEncoded, hashOrEndIndex) {
  var index = startIndex;
  var keyLength = keyEncoded.length;
  while ((index = uri.indexOf(keyEncoded, index)) >= 0 && index < hashOrEndIndex) {
    var precedingChar = uri.charCodeAt(index - 1);
    if (precedingChar == goog.uri.utils.CharCode_.AMPERSAND || precedingChar == goog.uri.utils.CharCode_.QUESTION) {
      var followingChar = uri.charCodeAt(index + keyLength);
      if (!followingChar || followingChar == goog.uri.utils.CharCode_.EQUAL || followingChar == goog.uri.utils.CharCode_.AMPERSAND || followingChar == goog.uri.utils.CharCode_.HASH) {
        return index;
      }
    }
    index += keyLength + 1;
  }
  return -1;
};
goog.uri.utils.hashOrEndRe_ = /#|$/;
goog.uri.utils.hasParam = function(uri, keyEncoded) {
  return goog.uri.utils.findParam_(uri, 0, keyEncoded, uri.search(goog.uri.utils.hashOrEndRe_)) >= 0;
};
goog.uri.utils.getParamValue = function(uri, keyEncoded) {
  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
  var foundIndex = goog.uri.utils.findParam_(uri, 0, keyEncoded, hashOrEndIndex);
  if (foundIndex < 0) {
    return null;
  } else {
    var endPosition = uri.indexOf("&", foundIndex);
    if (endPosition < 0 || endPosition > hashOrEndIndex) {
      endPosition = hashOrEndIndex;
    }
    foundIndex += keyEncoded.length + 1;
    return goog.string.urlDecode(uri.substr(foundIndex, endPosition - foundIndex));
  }
};
goog.uri.utils.getParamValues = function(uri, keyEncoded) {
  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
  var position = 0;
  var foundIndex;
  var result = [];
  while ((foundIndex = goog.uri.utils.findParam_(uri, position, keyEncoded, hashOrEndIndex)) >= 0) {
    position = uri.indexOf("&", foundIndex);
    if (position < 0 || position > hashOrEndIndex) {
      position = hashOrEndIndex;
    }
    foundIndex += keyEncoded.length + 1;
    result.push(goog.string.urlDecode(uri.substr(foundIndex, position - foundIndex)));
  }
  return result;
};
goog.uri.utils.trailingQueryPunctuationRe_ = /[?&]($|#)/;
goog.uri.utils.removeParam = function(uri, keyEncoded) {
  var hashOrEndIndex = uri.search(goog.uri.utils.hashOrEndRe_);
  var position = 0;
  var foundIndex;
  var buffer = [];
  while ((foundIndex = goog.uri.utils.findParam_(uri, position, keyEncoded, hashOrEndIndex)) >= 0) {
    buffer.push(uri.substring(position, foundIndex));
    position = Math.min(uri.indexOf("&", foundIndex) + 1 || hashOrEndIndex, hashOrEndIndex);
  }
  buffer.push(uri.substr(position));
  return buffer.join("").replace(goog.uri.utils.trailingQueryPunctuationRe_, "$1");
};
goog.uri.utils.setParam = function(uri, keyEncoded, value) {
  return goog.uri.utils.appendParam(goog.uri.utils.removeParam(uri, keyEncoded), keyEncoded, value);
};
goog.uri.utils.setParamsFromMap = function(uri, params) {
  var parts = goog.uri.utils.splitQueryData_(uri);
  var queryData = parts[1];
  var buffer = [];
  if (queryData) {
    goog.array.forEach(queryData.split("&"), function(pair) {
      var indexOfEquals = pair.indexOf("=");
      var name = indexOfEquals >= 0 ? pair.substr(0, indexOfEquals) : pair;
      if (!params.hasOwnProperty(name)) {
        buffer.push(pair);
      }
    });
  }
  parts[1] = goog.uri.utils.appendQueryData_(buffer.join("&"), goog.uri.utils.buildQueryDataFromMap(params));
  return goog.uri.utils.joinQueryData_(parts);
};
goog.uri.utils.appendPath = function(baseUri, path) {
  goog.uri.utils.assertNoFragmentsOrQueries_(baseUri);
  if (goog.string.endsWith(baseUri, "/")) {
    baseUri = baseUri.substr(0, baseUri.length - 1);
  }
  if (goog.string.startsWith(path, "/")) {
    path = path.substr(1);
  }
  return goog.string.buildString(baseUri, "/", path);
};
goog.uri.utils.setPath = function(uri, path) {
  if (!goog.string.startsWith(path, "/")) {
    path = "/" + path;
  }
  var parts = goog.uri.utils.split(uri);
  return goog.uri.utils.buildFromEncodedParts(parts[goog.uri.utils.ComponentIndex.SCHEME], parts[goog.uri.utils.ComponentIndex.USER_INFO], parts[goog.uri.utils.ComponentIndex.DOMAIN], parts[goog.uri.utils.ComponentIndex.PORT], path, parts[goog.uri.utils.ComponentIndex.QUERY_DATA], parts[goog.uri.utils.ComponentIndex.FRAGMENT]);
};
goog.uri.utils.StandardQueryParam = {RANDOM:"zx"};
goog.uri.utils.makeUnique = function(uri) {
  return goog.uri.utils.setParam(uri, goog.uri.utils.StandardQueryParam.RANDOM, goog.string.getRandomString());
};
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.Field");
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");
goog.editor.Link = function(anchor, isNew) {
  this.anchor_ = anchor;
  this.isNew_ = isNew;
  this.extraAnchors_ = [];
};
goog.editor.Link.prototype.getAnchor = function() {
  return this.anchor_;
};
goog.editor.Link.prototype.getExtraAnchors = function() {
  return this.extraAnchors_;
};
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_;
};
goog.editor.Link.prototype.isNew = function() {
  return this.isNew_;
};
goog.editor.Link.prototype.initializeUrl = function(url) {
  this.getAnchor().href = url;
};
goog.editor.Link.prototype.removeLink = function() {
  goog.dom.flattenElement(this.anchor_);
  this.anchor_ = null;
  while (this.extraAnchors_.length) {
    goog.dom.flattenElement(this.extraAnchors_.pop());
  }
};
goog.editor.Link.prototype.setTextAndUrl = function(newText, newUrl) {
  var anchor = this.getAnchor();
  anchor.href = newUrl;
  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));
    }
    this.currentText_ = null;
  }
  this.isNew_ = false;
};
goog.editor.Link.prototype.placeCursorRightOf = function() {
  var anchor = this.getAnchor();
  if (goog.editor.BrowserFeature.GETS_STUCK_IN_LINKS) {
    var spaceNode;
    var nextSibling = anchor.nextSibling;
    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 {
      var dh = goog.dom.getDomHelper(anchor);
      spaceNode = dh.createTextNode(goog.string.Unicode.NBSP);
      goog.dom.insertSiblingAfter(spaceNode, anchor);
    }
    var range = goog.dom.Range.createCaret(spaceNode, 1);
    range.select();
  } else {
    goog.editor.range.placeCursorNextTo(anchor, false);
  }
};
goog.editor.Link.prototype.updateLinkDisplay_ = function(field, url) {
  this.initializeUrl(url);
  this.placeCursorRightOf();
  field.execCommand(goog.editor.Command.UPDATE_LINK_BUBBLE);
};
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;
};
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);
  }
};
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;
};
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;
};
goog.editor.Link.isLikelyUrl = function(str) {
  if (/\s/.test(str)) {
    return false;
  }
  if (goog.editor.Link.isLikelyEmailAddress(str)) {
    return false;
  }
  var addedScheme = false;
  if (!/^[^:\/?#.]+:/.test(str)) {
    str = "http://" + str;
    addedScheme = true;
  }
  var parts = goog.uri.utils.split(str);
  var scheme = parts[goog.uri.utils.ComponentIndex.SCHEME];
  if (goog.array.indexOf(["mailto", "aim"], scheme) != -1) {
    return true;
  }
  var domain = parts[goog.uri.utils.ComponentIndex.DOMAIN];
  if (!domain || addedScheme && domain.indexOf(".") == -1 || /[^\w\d\-\u0100-\uffff.%]/.test(domain)) {
    return false;
  }
  var path = parts[goog.uri.utils.ComponentIndex.PATH];
  return !path || path.indexOf("/") == 0;
};
goog.editor.Link.LIKELY_EMAIL_ADDRESS_ = new RegExp("^" + "[\\w-]+(\\.[\\w-]+)*" + "\\@" + "([\\w-]+\\.)+" + "(\\d+|\\w\\w+)$", "i");
goog.editor.Link.isLikelyEmailAddress = function(str) {
  return goog.editor.Link.LIKELY_EMAIL_ADDRESS_.test(str);
};
goog.editor.Link.isMailto = function(url) {
  return !!url && goog.string.startsWith(url, "mailto:");
};
goog.provide("goog.ui.editor.messages");
goog.require("goog.html.uncheckedconversions");
goog.require("goog.string.Const");
goog.ui.editor.messages.MSG_LINK_CAPTION = goog.getMsg("Link");
goog.ui.editor.messages.MSG_EDIT_LINK = goog.getMsg("Edit Link");
goog.ui.editor.messages.MSG_TEXT_TO_DISPLAY = goog.getMsg("Text to display:");
goog.ui.editor.messages.MSG_LINK_TO = goog.getMsg("Link to:");
goog.ui.editor.messages.MSG_ON_THE_WEB = goog.getMsg("Web address");
goog.ui.editor.messages.MSG_ON_THE_WEB_TIP = goog.getMsg("Link to a page or file somewhere else on the web");
goog.ui.editor.messages.MSG_TEST_THIS_LINK = goog.getMsg("Test this link");
goog.ui.editor.messages.MSG_TR_LINK_EXPLANATION = goog.getMsg("{$startBold}Not sure what to put in the box?{$endBold} " + "First, find the page on the web that you want to " + "link to. (A {$searchEngineLink}search engine{$endLink} " + "might be useful.) Then, copy the web address from " + "the box in your browser's address bar, and paste it into " + "the box above.", {"startBold":"<b>", "endBold":"</b>", "searchEngineLink":"<a href='http://www.google.com/' target='_new'>", "endLink":"</a>"});
goog.ui.editor.messages.getTrLinkExplanationSafeHtml = function() {
  return goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract(goog.string.Const.from("Parameterless translation"), goog.ui.editor.messages.MSG_TR_LINK_EXPLANATION);
};
goog.ui.editor.messages.MSG_WHAT_URL = goog.getMsg("To what URL should this link go?");
goog.ui.editor.messages.MSG_EMAIL_ADDRESS = goog.getMsg("Email address");
goog.ui.editor.messages.MSG_EMAIL_ADDRESS_TIP = goog.getMsg("Link to an email address");
goog.ui.editor.messages.MSG_INVALID_EMAIL = goog.getMsg("Invalid email address");
goog.ui.editor.messages.MSG_WHAT_EMAIL = goog.getMsg("To what email address should this link?");
goog.ui.editor.messages.MSG_EMAIL_EXPLANATION = goog.getMsg("{$preb}Be careful.{$postb} " + "Remember that any time you include an email address on a web page, " + "nasty spammers can find it too.", {"preb":"<b>", "postb":"</b>"});
goog.ui.editor.messages.getEmailExplanationSafeHtml = function() {
  return goog.html.uncheckedconversions.safeHtmlFromStringKnownToSatisfyTypeContract(goog.string.Const.from("Parameterless translation"), goog.ui.editor.messages.MSG_EMAIL_EXPLANATION);
};
goog.ui.editor.messages.MSG_OPEN_IN_NEW_WINDOW = goog.getMsg("Open this link in a new window");
goog.ui.editor.messages.MSG_IMAGE_CAPTION = goog.getMsg("Image");
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");
goog.editor.plugins.BasicTextFormatter = function() {
  goog.editor.Plugin.call(this);
};
goog.inherits(goog.editor.plugins.BasicTextFormatter, goog.editor.Plugin);
goog.editor.plugins.BasicTextFormatter.prototype.getTrogClassId = function() {
  return "BTF";
};
goog.editor.plugins.BasicTextFormatter.prototype.logger = goog.log.getLogger("goog.editor.plugins.BasicTextFormatter");
goog.editor.plugins.BasicTextFormatter.COMMAND = {LINK:"+link", CREATE_LINK:"+createLink", 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"};
goog.editor.plugins.BasicTextFormatter.SUPPORTED_COMMANDS_ = goog.object.transpose(goog.editor.plugins.BasicTextFormatter.COMMAND);
goog.editor.plugins.BasicTextFormatter.prototype.isSupportedCommand = function(command) {
  return command in goog.editor.plugins.BasicTextFormatter.SUPPORTED_COMMANDS_;
};
goog.editor.plugins.BasicTextFormatter.SILENT_COMMANDS_ = [goog.editor.plugins.BasicTextFormatter.COMMAND.CREATE_LINK];
goog.editor.plugins.BasicTextFormatter.prototype.isSilentCommand = function(command) {
  return goog.array.contains(goog.editor.plugins.BasicTextFormatter.SILENT_COMMANDS_, command);
};
goog.editor.plugins.BasicTextFormatter.prototype.getRange_ = function() {
  return this.getFieldObject().getRange();
};
goog.editor.plugins.BasicTextFormatter.prototype.getDocument_ = function() {
  return this.getFieldDomHelper().getDocument();
};
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:
      if (!goog.isNull(opt_arg)) {
        if (goog.editor.BrowserFeature.EATS_EMPTY_BACKGROUND_COLOR) {
          this.applyBgColorManually_(opt_arg);
        } else {
          if (goog.userAgent.OPERA) {
            this.execCommandHelper_("hiliteColor", opt_arg);
          } else {
            this.execCommandHelper_(command, opt_arg);
          }
        }
      }
      break;
    case goog.editor.plugins.BasicTextFormatter.COMMAND.CREATE_LINK:
      result = this.createLink_(arguments[1], arguments[2], arguments[3]);
      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) {
        opt_arg = "<" + opt_arg + ">";
      }
      if (command == goog.editor.plugins.BasicTextFormatter.COMMAND.FONT_COLOR && goog.isNull(opt_arg)) {
        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 = !this.getDocument_().queryCommandEnabled("outdent");
              } else {
                styleWithCss = true;
              }
            }
          }
        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)) {
            needsFormatBlockDiv = this.getFieldObject().queryCommandValue(goog.editor.Command.DEFAULT_TAG) != goog.dom.TagName.P;
          } else {
            if (!goog.editor.BrowserFeature.CAN_LISTIFY_BR) {
              this.convertBreaksToDivs_();
            }
          }
          if (goog.userAgent.GECKO && goog.editor.BrowserFeature.FORGETS_FORMATTING_WHEN_LISTIFYING && !this.queryCommandValue(command)) {
            hasDummySelection |= this.beforeInsertListGecko_();
          }
        case goog.editor.plugins.BasicTextFormatter.COMMAND.FORMAT_BLOCK:
          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.applySubscriptSuperscriptWorkarounds_(command);
          }
          break;
        case goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE:
        case goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD:
        case goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC:
          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:
          styleWithCss = goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && goog.userAgent.GECKO;
      }this.execCommandHelper_(command, opt_arg, preserveDir, !!styleWithCss);
      if (hasDummySelection) {
        this.getDocument_().execCommand("Delete", false, true);
      }
      if (needsFormatBlockDiv) {
        this.getDocument_().execCommand("FormatBlock", false, "<div>");
      }
  }
  if (goog.userAgent.GECKO && !this.getFieldObject().inModalMode()) {
    this.focusField_();
  }
  return result;
};
goog.editor.plugins.BasicTextFormatter.prototype.focusField_ = function() {
  this.getFieldDomHelper().getWindow().focus();
};
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:
      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:
      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:
      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:
      return this.queryCommandStateInternal_(this.getDocument_(), command, styleWithCss);
  }
};
goog.editor.plugins.BasicTextFormatter.prototype.prepareContentsHtml = function(html) {
  if (goog.editor.BrowserFeature.COLLAPSES_EMPTY_NODES && html.match(/^\s*<script/i)) {
    html = "&nbsp;" + html;
  }
  if (goog.editor.BrowserFeature.CONVERT_TO_B_AND_I_TAGS) {
    html = html.replace(/<(\/?)strong([^\w])/gi, "<$1b$2");
    html = html.replace(/<(\/?)em([^\w])/gi, "<$1i$2");
  }
  return html;
};
goog.editor.plugins.BasicTextFormatter.prototype.cleanContentsDom = function(fieldCopy) {
  var images = goog.dom.getElementsByTagName(goog.dom.TagName.IMG, fieldCopy);
  for (var i = 0, image; image = images[i]; i++) {
    if (goog.editor.BrowserFeature.SHOWS_CUSTOM_ATTRS_IN_INNER_HTML) {
      image.removeAttribute("tabIndex");
      image.removeAttribute("tabIndexSet");
      goog.removeUid(image);
      image.oldTabIndex;
      if (image.oldTabIndex) {
        image.tabIndex = image.oldTabIndex;
      }
    }
  }
};
goog.editor.plugins.BasicTextFormatter.prototype.cleanContentsHtml = function(html) {
  if (goog.editor.BrowserFeature.MOVES_STYLE_TO_HEAD) {
    var heads = this.getFieldObject().getEditableDomHelper().getElementsByTagNameAndClass(goog.dom.TagName.HEAD);
    var stylesHtmlArr = [];
    var numHeads = heads.length;
    for (var i = 1; i < numHeads; ++i) {
      var styles = goog.dom.getElementsByTagName(goog.dom.TagName.STYLE, heads[i]);
      var numStyles = styles.length;
      for (var j = 0; j < numStyles; ++j) {
        stylesHtmlArr.push(styles[j].outerHTML);
      }
    }
    return stylesHtmlArr.join("") + html;
  }
  return html;
};
goog.editor.plugins.BasicTextFormatter.prototype.handleKeyboardShortcut = function(e, key, isModifierPressed) {
  if (!isModifierPressed) {
    return false;
  }
  var command;
  switch(key) {
    case "b":
      command = goog.editor.plugins.BasicTextFormatter.COMMAND.BOLD;
      break;
    case "i":
      command = goog.editor.plugins.BasicTextFormatter.COMMAND.ITALIC;
      break;
    case "u":
      command = goog.editor.plugins.BasicTextFormatter.COMMAND.UNDERLINE;
      break;
    case "s":
      return true;
  }
  if (command) {
    this.getFieldObject().execCommand(command);
    return true;
  }
  return false;
};
goog.editor.plugins.BasicTextFormatter.BR_REGEXP_ = goog.userAgent.IE ? /<br([^\/>]*)\/?>/gi : /<br([^\/>]*)\/?>(?!<\/(div|p)>)/gi;
goog.editor.plugins.BasicTextFormatter.prototype.convertBreaksToDivs_ = function() {
  if (!goog.userAgent.IE && !goog.userAgent.OPERA) {
    return false;
  }
  var range = this.getRange_();
  var parent = range.getContainerElement();
  var doc = this.getDocument_();
  var dom = this.getFieldDomHelper();
  goog.editor.plugins.BasicTextFormatter.BR_REGEXP_.lastIndex = 0;
  if (goog.editor.plugins.BasicTextFormatter.BR_REGEXP_.test(parent.innerHTML)) {
    var savedRange = range.saveUsingCarets();
    if (parent.tagName == goog.dom.TagName.P) {
      goog.editor.plugins.BasicTextFormatter.convertParagraphToDiv_(parent, true);
    } else {
      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(goog.dom.getElementsByTagName(goog.dom.TagName.P, parent));
      goog.iter.forEach(paragraphs, function(paragraph) {
        if (paragraph.getAttribute(attribute) == value) {
          paragraph.removeAttribute(attribute);
          if (goog.string.isBreakingWhitespace(goog.dom.getTextContent(paragraph))) {
            var child = goog.userAgent.IE ? doc.createTextNode(goog.string.Unicode.NBSP) : dom.createElement(goog.dom.TagName.BR);
            paragraph.appendChild(child);
          }
          goog.editor.plugins.BasicTextFormatter.convertParagraphToDiv_(paragraph);
        }
      });
    }
    savedRange.restore();
    return true;
  }
  return false;
};
goog.editor.plugins.BasicTextFormatter.convertParagraphToDiv_ = function(paragraph, opt_convertBrs) {
  if (!goog.userAgent.IE && !goog.userAgent.OPERA) {
    return;
  }
  var outerHTML = paragraph.outerHTML.replace(/<(\/?)p/gi, "<$1div");
  if (opt_convertBrs) {
    outerHTML = outerHTML.replace(goog.editor.plugins.BasicTextFormatter.BR_REGEXP_, "</div><div$1>");
  }
  if (goog.userAgent.OPERA && !/<\/div>$/i.test(outerHTML)) {
    outerHTML += "</div>";
  }
  paragraph.outerHTML = outerHTML;
};
goog.editor.plugins.BasicTextFormatter.convertToRealExecCommand_ = function(command) {
  return command.indexOf("+") == 0 ? command.substring(1) : command;
};
goog.editor.plugins.BasicTextFormatter.prototype.justify_ = function(command) {
  this.execCommandHelper_(command, null, false, true);
  if (goog.userAgent.GECKO) {
    this.execCommandHelper_(command, null, false, true);
  }
  if (!(goog.editor.BrowserFeature.HAS_STYLE_WITH_CSS && goog.userAgent.GECKO)) {
    goog.iter.forEach(this.getFieldObject().getRange(), goog.editor.plugins.BasicTextFormatter.convertContainerToTextAlign_);
  }
};
goog.editor.plugins.BasicTextFormatter.convertContainerToTextAlign_ = function(node) {
  var container = goog.editor.style.getContainer(node);
  if (container.align) {
    container.style.textAlign = container.align;
    container.removeAttribute("align");
  }
};
goog.editor.plugins.BasicTextFormatter.prototype.execCommandHelper_ = function(command, opt_value, opt_preserveDir, opt_styleWithCss) {
  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) {
    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)) {
    if (goog.userAgent.WEBKIT && !goog.userAgent.isVersionOrHigher(534)) {
      this.fixSafariLists_();
    }
    if (goog.userAgent.IE) {
      this.fixIELists_();
      if (nbsp) {
        goog.dom.removeNode(nbsp);
      }
    }
  }
  if (endDiv) {
    goog.dom.removeNode(endDiv);
  }
  if (dir) {
    this.getFieldObject().execCommand(dir);
  }
};
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()) {
    textNode = this.getFieldDomHelper().createTextNode(needsSpaceInTextNode ? " " : "");
    var containerNode = range.getStartNode();
    parentTag = containerNode.nodeType == goog.dom.NodeType.ELEMENT ? containerNode : containerNode.parentNode;
    if (parentTag.innerHTML == "") {
      parentTag.style.textIndent = "-10000px";
      parentTag.appendChild(textNode);
    } else {
      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) {
    if (needsSpaceInTextNode) {
      textNode.data = "";
    }
    parentTag.style.textIndent = "";
  }
};
goog.editor.plugins.BasicTextFormatter.prototype.toggleLink_ = function(opt_target) {
  if (!this.getFieldObject().isSelectionEditable()) {
    this.focusField_();
  }
  var range = this.getRange_();
  var parent = range && range.getContainerElement();
  var link = 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;
};
goog.editor.plugins.BasicTextFormatter.prototype.createLink_ = function(range, url, opt_target) {
  var anchor = null;
  var anchors = [];
  var parent = range && range.getContainerElement();
  if (parent && parent.tagName == goog.dom.TagName.IMG) {
    return null;
  }
  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) {
        textRange.pasteHTML("<a id='newLink'></a>");
        anchor = this.getFieldDomHelper().getElement("newLink");
        anchor.removeAttribute("id");
      }
    }
  } else {
    var uniqueId = goog.string.createUniqueString();
    this.execCommandHelper_("CreateLink", uniqueId);
    var setHrefAndLink = function(element, index, arr) {
      if (goog.string.endsWith(element.href, uniqueId)) {
        anchors.push(element);
      }
    };
    goog.array.forEach(goog.dom.getElementsByTagName(goog.dom.TagName.A, this.getFieldObject().getElement()), 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(anchor, url, opt_target, anchors);
};
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};
goog.editor.plugins.BasicTextFormatter.blockquoteHatingCommandsIE_ = {"insertOrderedList":1, "insertUnorderedList":1};
goog.editor.plugins.BasicTextFormatter.prototype.applySubscriptSuperscriptWorkarounds_ = function(command) {
  if (!this.queryCommandValue(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);
    if (!this.queryCommandValue(oppositeCommand)) {
      this.getDocument_().execCommand(oppositeExecCommand, false, null);
    }
    this.getDocument_().execCommand(oppositeExecCommand, false, null);
  }
};
goog.editor.plugins.BasicTextFormatter.prototype.removeFontSizeFromStyleAttrs_ = function() {
  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", "");
    if (goog.userAgent.GECKO && node.style.length == 0 && node.getAttribute("style") != null) {
      node.removeAttribute("style");
    }
  });
};
goog.editor.plugins.BasicTextFormatter.prototype.applyExecCommandIEFixes_ = function(command) {
  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);
      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)) {
            range = goog.dom.Range.createFromNodes(range.getStartNode(), range.getStartOffset(), endDiv, 0);
          }
        }
        range.select();
      }
    }
  }
  var fieldObject = this.getFieldObject();
  if (!fieldObject.usesIframe() && !endDiv) {
    if (command in goog.editor.plugins.BasicTextFormatter.brokenExecCommandsIE_) {
      var field = fieldObject.getElement();
      if (range && range.isCollapsed() && !goog.dom.getFirstElementChild(field)) {
        var selection = range.getTextRange(0).getBrowserRangeObject();
        var testRange = selection.duplicate();
        testRange.moveToElementText(field);
        testRange.collapse(false);
        if (testRange.isEqual(selection)) {
          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;
};
goog.editor.plugins.BasicTextFormatter.prototype.cleanUpSafariHeadings_ = function() {
  goog.iter.forEach(this.getRange_(), function(node) {
    if (node.className == "Apple-style-span") {
      node.style.fontSize = "";
      node.style.fontWeight = "";
    }
  });
};
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) {
      if (!previousList) {
        previousList = true;
        return;
      }
      var previousElementSibling = goog.dom.getPreviousElementSibling(node);
      if (!previousElementSibling) {
        return;
      }
      var range = node.ownerDocument.createRange();
      range.setStartAfter(previousElementSibling);
      range.setEndBefore(node);
      if (!goog.string.isEmptyOrWhitespace(range.toString())) {
        return;
      }
      if (previousElementSibling.nodeName == node.nodeName) {
        while (previousElementSibling.lastChild) {
          node.insertBefore(previousElementSibling.lastChild, node.firstChild);
        }
        previousElementSibling.parentNode.removeChild(previousElementSibling);
      }
    }
  });
};
goog.editor.plugins.BasicTextFormatter.orderedListTypes_ = {1:1, "a":1, "A":1, "i":1, "I":1};
goog.editor.plugins.BasicTextFormatter.unorderedListTypes_ = {"disc":1, "circle":1, "square":1};
goog.editor.plugins.BasicTextFormatter.prototype.fixIELists_ = function() {
  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) {
    container = container.parentNode;
  }
  if (!container) {
    return;
  }
  var lists = goog.array.toArray(goog.dom.getElementsByTagName(goog.dom.TagName.UL, container));
  goog.array.extend(lists, goog.array.toArray(goog.dom.getElementsByTagName(goog.dom.TagName.OL, container)));
  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 = "";
      }
    }
  });
};
goog.editor.plugins.BasicTextFormatter.brokenExecCommandsSafari_ = {"justifyCenter":1, "justifyFull":1, "justifyRight":1, "justifyLeft":1, "formatBlock":1};
goog.editor.plugins.BasicTextFormatter.hangingExecCommandWebkit_ = {"insertOrderedList":1, "insertUnorderedList":1};
goog.editor.plugins.BasicTextFormatter.prototype.applyExecCommandSafariFixes_ = function(command) {
  var div;
  if (goog.editor.plugins.BasicTextFormatter.brokenExecCommandsSafari_[command]) {
    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]) {
    var field = this.getFieldObject().getElement();
    div = this.getFieldDomHelper().createDom(goog.dom.TagName.DIV, {"style":"height: 0"}, "x");
    field.insertBefore(div, field.firstChild);
  }
  return div;
};
goog.editor.plugins.BasicTextFormatter.prototype.applyExecCommandGeckoFixes_ = function(command) {
  if (goog.userAgent.isVersionOrHigher("1.9") && command.toLowerCase() == "formatblock") {
    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) {
        var browserRange = range.getBrowserRangeObject();
        browserRange.setStart(childNode, 0);
        browserRange.setEnd(childNode, 0);
      }
    }
  }
};
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;
  });
};
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;
  }
  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;
};
goog.editor.plugins.BasicTextFormatter.getSelectionBlockState_ = function(range) {
  var tagName = null;
  goog.iter.forEach(range, function(node, ignore, it) {
    if (!it.isEndTag()) {
      var container = goog.editor.style.getContainer(node);
      var thisTagName = container.tagName;
      tagName = tagName || thisTagName;
      if (tagName != thisTagName) {
        tagName = null;
        throw goog.iter.StopIteration;
      }
      it.skipTag();
    }
  });
  return tagName;
};
goog.editor.plugins.BasicTextFormatter.SUPPORTED_JUSTIFICATIONS_ = {"center":1, "justify":1, "right":1, "left":1};
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) {
    bidiPlugin.getSelectionAlignment;
    return alignment == bidiPlugin.getSelectionAlignment();
  } else {
    var range = this.getRange_();
    if (!range) {
      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];
      var container = goog.editor.style.getContainer(current);
      if (alignment != goog.editor.plugins.BasicTextFormatter.getNodeJustification_(container)) {
        return false;
      }
    }
    return true;
  }
};
goog.editor.plugins.BasicTextFormatter.getNodeJustification_ = function(element) {
  var value = goog.style.getComputedTextAlign(element);
  value = value.replace(/^-(moz|webkit)-/, "");
  if (!goog.editor.plugins.BasicTextFormatter.SUPPORTED_JUSTIFICATIONS_[value]) {
    value = element.align || "left";
  }
  return value;
};
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);
};
goog.editor.plugins.BasicTextFormatter.prototype.queryCommandStateInternal_ = function(queryObject, command, opt_styleWithCss) {
  return this.queryCommandHelper_(true, queryObject, command, opt_styleWithCss);
};
goog.editor.plugins.BasicTextFormatter.prototype.queryCommandValueInternal_ = function(queryObject, command, opt_styleWithCss) {
  return this.queryCommandHelper_(false, queryObject, command, opt_styleWithCss);
};
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_();
    doc.execCommand("styleWithCSS", false, true);
  }
  var ret = isGetQueryCommandState ? queryObject.queryCommandState(command) : queryObject.queryCommandValue(command);
  if (opt_styleWithCss) {
    doc.execCommand("styleWithCSS", false, false);
  }
  return ret;
};
goog.provide("goog.dom.NodeOffset");
goog.require("goog.Disposable");
goog.require("goog.dom.TagName");
goog.dom.NodeOffset = function(node, baseNode) {
  goog.Disposable.call(this);
  this.offsetStack_ = [];
  this.nameStack_ = [];
  while (node && node.nodeName != goog.dom.TagName.BODY && node != baseNode) {
    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);
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");
};
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]];
    if (!curNode || curNode.nodeName != name) {
      return null;
    }
  }
  return curNode;
};
goog.dom.NodeOffset.prototype.disposeInternal = function() {
  delete this.offsetStack_;
  delete this.nameStack_;
};
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");
goog.editor.plugins.Blockquote = function(requiresClassNameToSplit, opt_className) {
  goog.editor.Plugin.call(this);
  this.requiresClassNameToSplit_ = requiresClassNameToSplit;
  this.className_ = opt_className || goog.getCssName("tr_bq");
};
goog.inherits(goog.editor.plugins.Blockquote, goog.editor.Plugin);
goog.editor.plugins.Blockquote.SPLIT_COMMAND = "+splitBlockquote";
goog.editor.plugins.Blockquote.CLASS_ID = "Blockquote";
goog.editor.plugins.Blockquote.prototype.logger = goog.log.getLogger("goog.editor.plugins.Blockquote");
goog.editor.plugins.Blockquote.prototype.getTrogClassId = function() {
  return goog.editor.plugins.Blockquote.CLASS_ID;
};
goog.editor.plugins.Blockquote.prototype.isSilentCommand = goog.functions.TRUE;
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(node, this.className_);
};
goog.editor.plugins.Blockquote.prototype.isSetupBlockquote = function(node) {
  return node.tagName == goog.dom.TagName.BLOCKQUOTE && goog.dom.classlist.contains(node, this.className_);
};
goog.editor.plugins.Blockquote.prototype.isUnsetupBlockquote = function(node) {
  return node.tagName == goog.dom.TagName.BLOCKQUOTE && !this.isSetupBlockquote(node);
};
goog.editor.plugins.Blockquote.prototype.getBlockquoteClassName = function() {
  return this.className_;
};
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);
};
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]);
    }
  }
};
goog.editor.plugins.Blockquote.prototype.isSupportedCommand = function(command) {
  return command == goog.editor.plugins.Blockquote.SPLIT_COMMAND;
};
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_(pos);
  }
};
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;
  if (quoteNode) {
    if (cursorNode.nodeType == goog.dom.NodeType.TEXT) {
      if (anchorPos.offset == cursorNode.length) {
        var siblingNode = cursorNode.nextSibling;
        if (siblingNode && siblingNode.tagName == goog.dom.TagName.BR) {
          cursorNode = siblingNode;
          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) {
        secondHalf = cursorNode.nextSibling;
      } else {
        insertTextNode = true;
      }
    }
  } else {
    if (this.isSetupBlockquote(cursorNode)) {
      quoteNode = cursorNode;
      insertTextNode = true;
    }
  }
  if (insertTextNode) {
    cursorNode = this.insertEmptyTextNodeBeforeRange_();
    secondHalf = this.insertEmptyTextNodeBeforeRange_();
  }
  if (!quoteNode) {
    return false;
  }
  secondHalf = goog.editor.node.splitDomTreeAt(cursorNode, secondHalf, quoteNode);
  goog.dom.insertSiblingAfter(secondHalf, quoteNode);
  var dh = this.getFieldDomHelper();
  var tagToInsert = this.getFieldObject().queryCommandValue(goog.editor.Command.DEFAULT_TAG) || goog.dom.TagName.DIV;
  var container = dh.createElement(tagToInsert);
  container.innerHTML = "&nbsp;";
  quoteNode.parentNode.insertBefore(container, secondHalf);
  dh.getWindow().getSelection().collapse(container, 0);
  if (textNodeToRemove) {
    goog.editor.plugins.Blockquote.findAndRemoveSingleChildAncestor_(textNodeToRemove, secondHalf);
  }
  goog.editor.plugins.Blockquote.removeAllWhiteSpaceNodes_([quoteNode, secondHalf]);
  return true;
};
goog.editor.plugins.Blockquote.prototype.insertEmptyTextNodeBeforeRange_ = function() {
  var range = this.getFieldObject().getRange();
  var node = this.getFieldDomHelper().createTextNode("");
  range.insertNode(node, true);
  return node;
};
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);
  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);
  var tagToInsert = this.getFieldObject().queryCommandValue(goog.editor.Command.DEFAULT_TAG) || goog.dom.TagName.DIV;
  var div = dh.createElement(tagToInsert);
  quoteNode.parentNode.insertBefore(div, secondHalf);
  div.innerHTML = "&nbsp;";
  var range = dh.getDocument().selection.createRange();
  range.moveToElementText(splitNode);
  range.move("character", 2);
  range.select();
  goog.dom.removeChildren(div);
  range.pasteHTML("");
  goog.editor.plugins.Blockquote.findAndRemoveSingleChildAncestor_(clone, secondHalf);
  goog.editor.plugins.Blockquote.removeAllWhiteSpaceNodes_([quoteNode, secondHalf]);
  return true;
};
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");
goog.editor.plugins.EnterHandler = function() {
  goog.editor.Plugin.call(this);
};
goog.inherits(goog.editor.plugins.EnterHandler, goog.editor.Plugin);
goog.editor.plugins.EnterHandler.prototype.tag = goog.dom.TagName.DIV;
goog.editor.plugins.EnterHandler.prototype.getTrogClassId = function() {
  return "EnterHandler";
};
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);
  }
};
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;
};
goog.editor.plugins.EnterHandler.prototype.getNonCollapsingBlankHtml = goog.functions.constant("<br>");
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();
    e.stopPropagation();
  }
};
goog.editor.plugins.EnterHandler.prototype.processParagraphTagsInternal = function(e, split) {
  if (goog.userAgent.IE || goog.userAgent.OPERA) {
    this.ensureBlockIeOpera(goog.dom.TagName.DIV);
  } else {
    if (!split && goog.userAgent.WEBKIT) {
      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 (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();
    }
  }
};
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;
};
goog.editor.plugins.EnterHandler.prototype.handleDeleteGecko = function(e) {
  this.deleteBrGecko(e);
};
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) {
        var previousSibling = goog.editor.node.getPreviousSibling(nextNode);
        var nextSibling = nextNode.nextSibling;
        container.removeChild(nextNode);
        e.preventDefault();
        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();
          }
        }
      }
    }
  }
};
goog.editor.plugins.EnterHandler.prototype.handleKeyPress = function(e) {
  if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) {
    return false;
  }
  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) {
          this.handleEnterGecko_(e);
        }
      } else {
        this.getFieldObject().dispatchBeforeChange();
        var cursorPosition = this.deleteCursorSelection_();
        var split = !!this.getFieldObject().execCommand(goog.editor.plugins.Blockquote.SPLIT_COMMAND, cursorPosition);
        if (split) {
          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;
};
goog.editor.plugins.EnterHandler.prototype.handleKeyUp = function(e) {
  if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) {
    return false;
  }
  this.handleKeyUpInternal(e);
  return false;
};
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);
  }
};
goog.editor.plugins.EnterHandler.prototype.handleEnterGecko_ = function(e) {
  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) {
    e.preventDefault();
    e.stopPropagation();
  }
  this.releasePositionObject_(cursorPosition);
  if (!handled) {
    this.handleEnterAtCursorGeckoInternal(e, wasCollapsed, range);
  }
};
goog.editor.plugins.EnterHandler.prototype.handleEnterWebkitInternal = goog.nullFunction;
goog.editor.plugins.EnterHandler.prototype.handleEnterAtCursorGeckoInternal = goog.nullFunction;
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);
goog.editor.plugins.EnterHandler.isBrElem = function(node) {
  return goog.editor.node.isEmpty(node) && goog.dom.getElementsByTagName(goog.dom.TagName.BR, node).length == 1;
};
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) {
    var nodeName = container.nodeName;
    if (nodeName == tag || goog.editor.plugins.EnterHandler.DO_NOT_ENSURE_BLOCK_NODES_[nodeName] && !(opt_keyUp && goog.editor.plugins.EnterHandler.isBrElem(container))) {
      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)) {
    var needsHelp = false;
    range = range.getBrowserRangeObject();
    var range2 = range.duplicate();
    range2.moveEnd("character", 1);
    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();
  }
};
goog.editor.plugins.EnterHandler.prototype.deleteCursorSelection_ = function() {
  return goog.editor.BrowserFeature.HAS_W3C_RANGES ? this.deleteCursorSelectionW3C_() : this.deleteCursorSelectionIE_();
};
goog.editor.plugins.EnterHandler.prototype.releasePositionObject_ = function(position) {
  if (!goog.editor.BrowserFeature.HAS_W3C_RANGES) {
    position.removeNode(true);
  }
};
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;
};
goog.editor.plugins.EnterHandler.prototype.deleteCursorSelectionW3C_ = function() {
  var range = this.getFieldObject().getRange();
  if (range && !range.isCollapsed()) {
    var shouldDelete = true;
    if (goog.userAgent.OPERA) {
      var startNode = range.getStartNode();
      var startOffset = range.getStartOffset();
      if (startNode == range.getEndNode() && startNode.lastChild && startNode.lastChild.tagName == goog.dom.TagName.BR && startOffset == startNode.childNodes.length - 1) {
        shouldDelete = false;
      }
    }
    if (shouldDelete) {
      goog.editor.plugins.EnterHandler.deleteW3cRange_(range);
    }
  }
  return goog.editor.range.getDeepEndPoint(range, true);
};
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();
    var isInOneContainer = goog.editor.plugins.EnterHandler.isInOneContainerW3c_(range);
    var isPartialEnd = !isInOneContainer && goog.editor.plugins.EnterHandler.isPartialEndW3c_(range);
    range.removeContents();
    var node = nodeOffset.findTargetNode(baseNode);
    if (node) {
      range = goog.dom.Range.createCaret(node, rangeOffset);
    } else {
      range = goog.dom.Range.createCaret(baseNode, baseNode.childNodes.length);
      reselect = false;
    }
    range.select();
    if (isInOneContainer) {
      var container = goog.editor.style.getContainer(range.getStartNode());
      if (goog.editor.node.isEmpty(container, true)) {
        var html = "&nbsp;";
        if (goog.userAgent.OPERA && container.tagName == goog.dom.TagName.LI) {
          html = "<br>";
        }
        goog.editor.node.replaceInnerHtml(container, html);
        goog.editor.range.selectNodeStart(container.firstChild);
        reselect = false;
      }
    }
    if (isPartialEnd) {
      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) {
      range = goog.dom.Range.createCaret(nodeOffset.findTargetNode(baseNode), rangeOffset);
      range.select();
    }
  }
  return range;
};
goog.editor.plugins.EnterHandler.isInOneContainerW3c_ = function(range) {
  var startContainer = range.getStartNode();
  if (goog.editor.style.isContainer(startContainer)) {
    startContainer = startContainer.childNodes[range.getStartOffset()] || startContainer;
  }
  startContainer = goog.editor.style.getContainer(startContainer);
  var endContainer = range.getEndNode();
  if (goog.editor.style.isContainer(endContainer)) {
    endContainer = endContainer.childNodes[range.getEndOffset()] || endContainer;
  }
  endContainer = goog.editor.style.getContainer(endContainer);
  return startContainer == endContainer;
};
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];
    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);
};
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");
goog.editor.plugins.RemoveFormatting = function() {
  goog.editor.Plugin.call(this);
  this.optRemoveFormattingFunc_ = null;
  this.keyboardShortcutKey_ = " ";
};
goog.inherits(goog.editor.plugins.RemoveFormatting, goog.editor.Plugin);
goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND = "+removeFormat";
goog.editor.plugins.RemoveFormatting.BLOCK_RE_ = /^(DIV|TR|LI|BLOCKQUOTE|H\d|PRE|XMP)/;
goog.editor.plugins.RemoveFormatting.appendNewline_ = function(sb) {
  sb.push("<br>");
};
goog.editor.plugins.RemoveFormatting.createRangeDelimitedByRanges_ = function(startRange, endRange) {
  return goog.dom.Range.createFromNodes(startRange.getStartNode(), startRange.getStartOffset(), endRange.getEndNode(), endRange.getEndOffset());
};
goog.editor.plugins.RemoveFormatting.prototype.getTrogClassId = function() {
  return "RemoveFormatting";
};
goog.editor.plugins.RemoveFormatting.prototype.isSupportedCommand = function(command) {
  return command == goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND;
};
goog.editor.plugins.RemoveFormatting.prototype.execCommandInternal = function(command, var_args) {
  if (command == goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND) {
    this.removeFormatting_();
  }
};
goog.editor.plugins.RemoveFormatting.prototype.handleKeyboardShortcut = function(e, key, isModifierPressed) {
  if (!isModifierPressed) {
    return false;
  }
  if (e.metaKey && e.ctrlKey) {
    return false;
  }
  if (e.shiftKey) {
    return false;
  }
  if (key == this.keyboardShortcutKey_) {
    this.getFieldObject().execCommand(goog.editor.plugins.RemoveFormatting.REMOVE_FORMATTING_COMMAND);
    return true;
  }
  return false;
};
goog.editor.plugins.RemoveFormatting.prototype.setKeyboardShortcutKey = function(key) {
  this.keyboardShortcutKey_ = key;
};
goog.editor.plugins.RemoveFormatting.prototype.removeFormatting_ = function() {
  var range = this.getFieldObject().getRange();
  if (range.isCollapsed()) {
    return;
  }
  var convFunc = this.optRemoveFormattingFunc_ || goog.bind(this.removeFormattingWorker_, this);
  this.convertSelectedHtmlText_(convFunc);
  var doc = this.getFieldDomHelper().getDocument();
  doc.execCommand("RemoveFormat", false, undefined);
  if (goog.editor.BrowserFeature.ADDS_NBSPS_IN_REMOVE_FORMAT) {
    this.convertSelectedHtmlText_(function(text) {
      var nbspRegExp = goog.userAgent.isVersionOrHigher("528") ? /&nbsp;/g : /\u00A0/g;
      return text.replace(nbspRegExp, " ");
    });
  }
};
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;
};
goog.editor.plugins.RemoveFormatting.prototype.pasteHtml_ = function(html) {
  var range = this.getFieldObject().getRange();
  var dh = this.getFieldDomHelper();
  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) {
    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;
      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 (dummySpan) {
      goog.dom.removeNode(dummySpan);
    }
  } else {
    if (goog.editor.BrowserFeature.HAS_W3C_RANGES) {
      dh.getDocument().execCommand("insertImage", false, dummyNodeId);
      var dummyImageNodePattern = new RegExp("<[^<]*" + dummyNodeId + "[^>]*>");
      var parent = this.getFieldObject().getRange().getContainerElement();
      if (parent.nodeType == goog.dom.NodeType.TEXT) {
        parent = parent.parentNode;
      }
      while (!dummyImageNodePattern.test(parent.innerHTML)) {
        parent = parent.parentNode;
      }
      if (goog.userAgent.GECKO) {
        goog.editor.node.replaceInnerHtml(parent, parent.innerHTML.replace(dummyImageNodePattern, html.replace(/\$/g, "$$$$")));
      } 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;
          if (tag == goog.dom.TagName.TD || tag == goog.dom.TagName.TR || tag == goog.dom.TagName.TH) {
            break;
          }
          goog.dom.insertSiblingAfter(dummySpan, parent);
          goog.dom.removeNode(parent);
        }
        goog.editor.node.replaceInnerHtml(parent, parent.innerHTML.replace(new RegExp(dummySpanText, "i"), html.replace(/\$/g, "$$$$")));
      }
    }
  }
  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);
};
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) {
    div.appendChild(textRange.cloneContents());
  } else {
    if (goog.editor.BrowserFeature.HAS_IE_RANGES) {
      var rngText = range.getText();
      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;
      if (textRange.queryCommandValue("formatBlock") == "Formatted") {
        htmlText = goog.string.newLineToBr(textRange.htmlText);
      }
      div.innerHTML = htmlText;
    }
  }
  return div.innerHTML;
};
goog.editor.plugins.RemoveFormatting.prototype.adjustRangeForTables_ = function(range, startInTable, endInTable) {
  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();
  if (startInTable) {
    var textNode = dh.createTextNode("");
    goog.dom.insertSiblingAfter(textNode, startInTable);
    startNode = textNode;
    startOffset = 0;
  }
  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;
};
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;
  }
};
goog.editor.plugins.RemoveFormatting.prototype.restoreCaretsFromCave_ = function() {
  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;
  }
};
goog.editor.plugins.RemoveFormatting.prototype.convertSelectedHtmlText_ = function(convertFunc) {
  var range = this.getFieldObject().getRange();
  if (range.getTextRangeCount() > 1) {
    return;
  }
  if (goog.userAgent.GECKO || goog.userAgent.EDGE) {
    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) {
        return;
      }
      var savedCaretRange = this.adjustRangeForTables_(range, startInTable, endInTable);
      if (!startInTable) {
        this.putCaretInCave_(savedCaretRange, true);
      }
      if (!endInTable) {
        this.putCaretInCave_(savedCaretRange, false);
      }
      range = this.getFieldObject().getRange();
      expandedRange = goog.editor.range.expand(range, this.getFieldObject().getElement());
    }
    expandedRange.select();
    range = expandedRange;
  }
  var text = this.getHtmlText_(range);
  this.pasteHtml_(convertFunc(text));
  if ((goog.userAgent.GECKO || goog.userAgent.EDGE) && savedCaretRange) {
    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();
  }
};
goog.editor.plugins.RemoveFormatting.prototype.removeFormattingWorker_ = function(html) {
  var el = goog.dom.createElement(goog.dom.TagName.DIV);
  el.innerHTML = html;
  var sb = [];
  var stack = [el.childNodes, 0];
  var preTagStack = [];
  var preTagLevel = 0;
  var tableStack = [];
  var tableLevel = 0;
  for (var sp = 0; sp >= 0; sp -= 2) {
    var changedLevel = false;
    while (tableLevel > 0 && sp <= tableStack[tableLevel - 1]) {
      tableLevel--;
      changedLevel = true;
    }
    if (changedLevel) {
      goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    }
    changedLevel = false;
    while (preTagLevel > 0 && sp <= preTagStack[preTagLevel - 1]) {
      preTagLevel--;
      changedLevel = true;
    }
    if (changedLevel) {
      goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
    }
    var nodeList = stack[sp];
    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;
      }
      switch(nodeName) {
        case "#text":
          var nodeValue = preTagLevel > 0 ? node.nodeValue : goog.string.stripNewlines(node.nodeValue);
          nodeValue = goog.string.htmlEscape(nodeValue);
          sb.push(nodeValue);
          continue;
        case String(goog.dom.TagName.P):
          goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
          goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
          break;
        case String(goog.dom.TagName.BR):
          goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
          continue;
        case String(goog.dom.TagName.TABLE):
          goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
          tableStack[tableLevel++] = sp;
          break;
        case String(goog.dom.TagName.PRE):
        case "XMP":
          preTagStack[preTagLevel++] = sp;
          break;
        case String(goog.dom.TagName.STYLE):
        case String(goog.dom.TagName.SCRIPT):
        case String(goog.dom.TagName.SELECT):
          continue;
        case String(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;
          } else {
            break;
          }
        case String(goog.dom.TagName.IMG):
          sb.push("<img src='");
          sb.push(node.src);
          sb.push("'");
          if (node.border == "0") {
            sb.push(" border='0'");
          }
          sb.push(">");
          continue;
        case String(goog.dom.TagName.TD):
          if (node.previousSibling) {
            sb.push(" ");
          }
          break;
        case String(goog.dom.TagName.TR):
          if (node.previousSibling) {
            goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
          }
          break;
        case String(goog.dom.TagName.DIV):
          var parent = node.parentNode;
          if (parent.firstChild == node && goog.editor.plugins.RemoveFormatting.BLOCK_RE_.test(parent.tagName)) {
            break;
          }
        default:
          if (goog.editor.plugins.RemoveFormatting.BLOCK_RE_.test(nodeName)) {
            goog.editor.plugins.RemoveFormatting.appendNewline_(sb);
          }
      }
      var children = node.childNodes;
      if (children.length > 0) {
        stack[sp++] = nodeList;
        stack[sp++] = numNodesProcessed;
        nodeList = children;
        numNodesProcessed = 0;
      }
    }
  }
  return goog.string.normalizeSpaces(sb.join(""));
};
goog.editor.plugins.RemoveFormatting.prototype.getValueForNode = function(node) {
  return null;
};
goog.editor.plugins.RemoveFormatting.prototype.setRemoveFormattingFunc = function(removeFormattingFunc) {
  this.optRemoveFormattingFunc_ = removeFormattingFunc;
};
goog.provide("goog.editor.plugins.AbstractTabHandler");
goog.require("goog.editor.Plugin");
goog.require("goog.events.KeyCodes");
goog.require("goog.userAgent");
goog.editor.plugins.AbstractTabHandler = function() {
  goog.editor.Plugin.call(this);
};
goog.inherits(goog.editor.plugins.AbstractTabHandler, goog.editor.Plugin);
goog.editor.plugins.AbstractTabHandler.prototype.getTrogClassId = goog.abstractMethod;
goog.editor.plugins.AbstractTabHandler.prototype.handleKeyboardShortcut = function(e, key, isModifierPressed) {
  if (goog.userAgent.GECKO && this.getFieldObject().inModalMode()) {
    return false;
  }
  if (e.keyCode == goog.events.KeyCodes.TAB && !e.metaKey && !e.ctrlKey) {
    return this.handleTabKey(e);
  }
  return false;
};
goog.editor.plugins.AbstractTabHandler.prototype.handleTabKey = goog.abstractMethod;
goog.provide("goog.editor.plugins.SpacesTabHandler");
goog.require("goog.dom.TagName");
goog.require("goog.editor.plugins.AbstractTabHandler");
goog.require("goog.editor.range");
goog.editor.plugins.SpacesTabHandler = function() {
  goog.editor.plugins.AbstractTabHandler.call(this);
};
goog.inherits(goog.editor.plugins.SpacesTabHandler, goog.editor.plugins.AbstractTabHandler);
goog.editor.plugins.SpacesTabHandler.prototype.getTrogClassId = function() {
  return "SpacesTabHandler";
};
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)) {
    if (!e.shiftKey) {
      this.getFieldObject().stopChangeEvents(true, true);
      if (!range.isCollapsed()) {
        dh.getDocument().execCommand("delete", false, null);
        range = this.getFieldObject().getRange();
      }
      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;
};
goog.provide("goog.editor.Table");
goog.provide("goog.editor.TableCell");
goog.provide("goog.editor.TableRow");
goog.require("goog.asserts");
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");
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();
};
goog.editor.Table.prototype.logger_ = goog.log.getLogger("goog.editor.Table");
goog.editor.Table.prototype.refresh = function() {
  var rows = this.rows = [];
  var tbody = goog.dom.getElementsByTagName(goog.dom.TagName.TBODY, goog.asserts.assert(this.element))[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;
    for (var cellNum = 0, td; td = tds[cellNum]; cellNum++) {
      while (existingRow && existingRow.columns[columnNum]) {
        columnNum++;
      }
      var cell = new goog.editor.TableCell(td, rowNum, columnNum);
      for (var i = 0; i < cell.rowSpan; i++) {
        var cellRowNum = rowNum + i;
        var cellRow = rows[cellRowNum];
        if (!cellRow) {
          rows.push(cellRow = new goog.editor.TableRow(trs[cellRowNum], cellRowNum));
        }
        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;
    }
  }
};
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;
};
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) {
    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;
};
goog.editor.Table.prototype.insertColumn = function(opt_colIndex) {
  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();
      newTd.style.width = goog.editor.Table.OPTIMUM_EMPTY_CELL_WIDTH + "px";
      this.insertCellElement(newTd, rowNum, colIndex);
      newTds.push(newTd);
    }
  }
  this.refresh();
  return newTds;
};
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) {
        this.insertCellElement(cell.element, rowIndex + 1, cell.startCol);
      }
    }
  }
  row.element.parentNode.removeChild(row.element);
  this.refresh();
};
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);
    }
    i += cell.rowSpan - 1;
  }
  this.refresh();
};
goog.editor.Table.prototype.mergeCells = function(startRowIndex, startColIndex, endRowIndex, endColIndex) {
  var cells = [];
  var cell;
  if (startRowIndex == endRowIndex && startColIndex == endColIndex) {
    goog.log.warning(this.logger_, "Can't merge single cell");
    return false;
  }
  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;
      }
      cells.push(cell);
    }
  }
  var targetCell = cells[0];
  var targetTd = targetCell.element;
  var doc = this.dom_.getDocument();
  for (var i = 1; cell = cells[i]; i++) {
    var td = cell.element;
    if (!td.parentNode || td == targetTd) {
      continue;
    }
    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) {
    targetTd.removeAttribute("width");
    targetTd.style.width = null;
  }
  this.refresh();
  return true;
};
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;
};
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);
};
goog.editor.Table.prototype.createEmptyTd = function() {
  return this.dom_.createDom(goog.dom.TagName.TD, {}, goog.string.Unicode.NBSP);
};
goog.editor.TableRow = function(trElement, rowIndex) {
  this.index = rowIndex;
  this.element = trElement;
  this.columns = [];
};
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_();
};
goog.editor.TableCell.prototype.updateCoordinates_ = function() {
  this.endCol = this.startCol + this.colSpan - 1;
  this.endRow = this.startRow + this.rowSpan - 1;
};
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_();
  }
};
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_();
  }
};
goog.editor.Table.OPTIMUM_EMPTY_CELL_WIDTH = 60;
goog.editor.Table.OPTIMUM_MAX_NEW_TABLE_WIDTH = 600;
goog.editor.Table.DEFAULT_BORDER_COLOR = "#888";
goog.editor.Table.createDomTable = function(doc, columns, rows, opt_tableStyle) {
  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;
  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 = goog.dom.getElementsByTagName(goog.dom.TagName.TD, tableElement);
  for (var i = 0, td; td = tds[i]; i++) {
    td.style.width = cellWidth + "px";
  }
  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;
};
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");
goog.editor.plugins.TableEditor = function() {
  goog.editor.plugins.TableEditor.base(this, "constructor");
  this.isTableEditableFunctions_ = [];
  this.isUserEditableTableBound_ = goog.bind(this.isUserEditableTable_, this);
};
goog.inherits(goog.editor.plugins.TableEditor, goog.editor.Plugin);
goog.editor.plugins.TableEditor.prototype.getTrogClassId = function() {
  return String(goog.getUid(this.constructor));
};
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"};
goog.editor.plugins.TableEditor.SUPPORTED_COMMANDS_ = goog.object.transpose(goog.editor.plugins.TableEditor.COMMAND);
goog.editor.plugins.TableEditor.prototype.isSupportedCommand = function(command) {
  return command in goog.editor.plugins.TableEditor.SUPPORTED_COMMANDS_;
};
goog.editor.plugins.TableEditor.prototype.enable = function(fieldObject) {
  goog.editor.plugins.TableEditor.base(this, "enable", fieldObject);
  if (goog.userAgent.GECKO) {
    var doc = this.getFieldDomHelper().getDocument();
    doc.execCommand("enableObjectResizing", false, "true");
  }
};
goog.editor.plugins.TableEditor.prototype.getCurrentTable_ = function() {
  var selectedElement = this.getFieldObject().getRange().getContainer();
  return this.getAncestorTable_(selectedElement);
};
goog.editor.plugins.TableEditor.prototype.getAncestorTable_ = function(node) {
  var ancestor = goog.dom.getAncestor(node, this.isUserEditableTableBound_, true);
  if (goog.editor.node.isEditable(ancestor)) {
    return ancestor;
  } else {
    return null;
  }
};
goog.editor.plugins.TableEditor.prototype.queryCommandValue = function(command) {
  if (command == goog.editor.plugins.TableEditor.COMMAND.TABLE) {
    return !!this.getCurrentTable_();
  }
};
goog.editor.plugins.TableEditor.prototype.execCommandInternal = function(command, opt_arg) {
  var result = null;
  var cursorCell = null;
  var range = this.getFieldObject().getRange();
  if (command == goog.editor.plugins.TableEditor.COMMAND.TABLE) {
    if (!goog.editor.range.isEditable(range)) {
      return null;
    }
    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);
    if (!goog.userAgent.IE) {
      cursorCell = goog.dom.getElementsByTagName(goog.dom.TagName.TD, table)[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) {
          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) {
          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) {
          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) {
          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;
};
goog.editor.plugins.TableEditor.prototype.isUserEditableTable_ = function(element) {
  if (element.tagName != goog.dom.TagName.TABLE) {
    return false;
  }
  return goog.array.every(this.isTableEditableFunctions_, function(func) {
    return func(element);
  });
};
goog.editor.plugins.TableEditor.prototype.addIsTableEditableFunction = function(func) {
  goog.array.insert(this.isTableEditableFunctions_, func);
};
goog.editor.plugins.TableEditor.CellSelection_ = function(range, getParentTableFunction) {
  this.cells_ = [];
  var selectionContainer = range.getContainerElement();
  var elementInSelection = function(node) {
    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);
  if (!parentTable.rows.length || !parentTable.rows[0].columns.length) {
    return;
  }
  for (var i = 0, row; row = parentTable.rows[i]; i++) {
    for (var j = 0, cell; cell = row.columns[j]; j++) {
      if (elementInSelection(cell.element)) {
        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;
};
goog.editor.plugins.TableEditor.CellSelection_.prototype.getTable = function() {
  return this.parentTable_;
};
goog.editor.plugins.TableEditor.CellSelection_.prototype.getFirstRowIndex = function() {
  return this.firstRowIndex_;
};
goog.editor.plugins.TableEditor.CellSelection_.prototype.getLastRowIndex = function() {
  return this.lastRowIndex_;
};
goog.editor.plugins.TableEditor.CellSelection_.prototype.getFirstColumnIndex = function() {
  return this.firstColIndex_;
};
goog.editor.plugins.TableEditor.CellSelection_.prototype.getLastColumnIndex = function() {
  return this.lastColIndex_;
};
goog.editor.plugins.TableEditor.CellSelection_.prototype.getCells = function() {
  return this.cells_;
};
goog.editor.plugins.TableEditor.CellSelection_.prototype.isRectangle = function() {
  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);
};
goog.editor.plugins.TableEditor.CellSelection_.prototype.containsSingleCell = function() {
  var cellCount = this.cells_.length;
  return cellCount > 0 && this.cells_[0] == this.cells_[cellCount - 1];
};
goog.provide("goog.debug.RelativeTimeProvider");
goog.debug.RelativeTimeProvider = function() {
  this.relativeTimeStart_ = goog.now();
};
goog.debug.RelativeTimeProvider.defaultInstance_ = new goog.debug.RelativeTimeProvider;
goog.debug.RelativeTimeProvider.prototype.set = function(timeStamp) {
  this.relativeTimeStart_ = timeStamp;
};
goog.debug.RelativeTimeProvider.prototype.reset = function() {
  this.set(goog.now());
};
goog.debug.RelativeTimeProvider.prototype.get = function() {
  return this.relativeTimeStart_;
};
goog.debug.RelativeTimeProvider.getDefaultInstance = function() {
  return goog.debug.RelativeTimeProvider.defaultInstance_;
};
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");
goog.require("goog.html.SafeUrl");
goog.require("goog.html.uncheckedconversions");
goog.require("goog.string.Const");
goog.debug.Formatter = function(opt_prefix) {
  this.prefix_ = opt_prefix || "";
  this.startTimeProvider_ = goog.debug.RelativeTimeProvider.getDefaultInstance();
};
goog.debug.Formatter.prototype.appendNewline = true;
goog.debug.Formatter.prototype.showAbsoluteTime = true;
goog.debug.Formatter.prototype.showRelativeTime = true;
goog.debug.Formatter.prototype.showLoggerName = true;
goog.debug.Formatter.prototype.showExceptionText = false;
goog.debug.Formatter.prototype.showSeverityLevel = false;
goog.debug.Formatter.prototype.formatRecord = goog.abstractMethod;
goog.debug.Formatter.prototype.formatRecordAsHtml = goog.abstractMethod;
goog.debug.Formatter.prototype.setStartTimeProvider = function(provider) {
  this.startTimeProvider_ = provider;
};
goog.debug.Formatter.prototype.getStartTimeProvider = function() {
  return this.startTimeProvider_;
};
goog.debug.Formatter.prototype.resetRelativeTimeStart = function() {
  this.startTimeProvider_.reset();
};
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));
};
goog.debug.Formatter.getTwoDigitString_ = function(n) {
  if (n < 10) {
    return "0" + n;
  }
  return String(n);
};
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;
};
goog.debug.HtmlFormatter = function(opt_prefix) {
  goog.debug.Formatter.call(this, opt_prefix);
};
goog.inherits(goog.debug.HtmlFormatter, goog.debug.Formatter);
goog.debug.HtmlFormatter.exposeException = function(err, fn) {
  var html = goog.debug.HtmlFormatter.exposeExceptionAsHtml(err, fn);
  return goog.html.SafeHtml.unwrap(html);
};
goog.debug.HtmlFormatter.exposeExceptionAsHtml = function(err, fn) {
  try {
    var e = goog.debug.normalizeErrorObject(err);
    var viewSourceUrl = goog.debug.HtmlFormatter.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(fn) + "-> "));
    return error;
  } catch (e2) {
    return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces("Exception trying to expose exception! You win, we lose. " + e2);
  }
};
goog.debug.HtmlFormatter.createViewSourceUrl_ = function(fileName) {
  if (!goog.isDefAndNotNull(fileName)) {
    fileName = "";
  }
  if (!/^https?:\/\//i.test(fileName)) {
    return goog.html.SafeUrl.fromConstant(goog.string.Const.from("sanitizedviewsrc"));
  }
  var sanitizedFileName = goog.html.SafeUrl.sanitize(fileName);
  return goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract(goog.string.Const.from("view-source scheme plus HTTP/HTTPS URL"), "view-source:" + goog.html.SafeUrl.unwrap(sanitizedFileName));
};
goog.debug.HtmlFormatter.prototype.showExceptionText = true;
goog.debug.HtmlFormatter.prototype.formatRecord = function(logRecord) {
  if (!logRecord) {
    return "";
  }
  return this.formatRecordAsHtml(logRecord).getTypedStringValue();
};
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;
  }
  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(""));
  var exceptionHtml = goog.html.SafeHtml.EMPTY;
  if (this.showExceptionText && logRecord.getException()) {
    exceptionHtml = goog.html.SafeHtml.concat(goog.html.SafeHtml.BR, goog.debug.HtmlFormatter.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));
  var html;
  if (this.appendNewline) {
    html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml, goog.html.SafeHtml.BR);
  } else {
    html = goog.html.SafeHtml.concat(fullPrefixHtml, recordAndExceptionHtml);
  }
  return html;
};
goog.debug.TextFormatter = function(opt_prefix) {
  goog.debug.Formatter.call(this, opt_prefix);
};
goog.inherits(goog.debug.TextFormatter, goog.debug.Formatter);
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("");
};
goog.debug.TextFormatter.prototype.formatRecordAsHtml = function(logRecord) {
  return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces(goog.debug.TextFormatter.prototype.formatRecord(logRecord));
};
goog.provide("goog.debug.Console");
goog.require("goog.debug.LogManager");
goog.require("goog.debug.Logger");
goog.require("goog.debug.TextFormatter");
goog.debug.Console = function() {
  this.publishHandler_ = goog.bind(this.addLogRecord, this);
  this.formatter_ = new goog.debug.TextFormatter;
  this.formatter_.showAbsoluteTime = false;
  this.formatter_.showExceptionText = false;
  this.formatter_.appendNewline = false;
  this.isCapturing_ = false;
  this.logBuffer_ = "";
  this.filteredLoggers_ = {};
};
goog.debug.Console.prototype.getFormatter = function() {
  return this.formatter_;
};
goog.debug.Console.prototype.setCapturing = function(capturing) {
  if (capturing == this.isCapturing_) {
    return;
  }
  var rootLogger = goog.debug.LogManager.getRoot();
  if (capturing) {
    rootLogger.addHandler(this.publishHandler_);
  } else {
    rootLogger.removeHandler(this.publishHandler_);
    this.logBuffer = "";
  }
  this.isCapturing_ = capturing;
};
goog.debug.Console.prototype.addLogRecord = function(logRecord) {
  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;
  }
};
goog.debug.Console.prototype.addFilter = function(loggerName) {
  this.filteredLoggers_[loggerName] = true;
};
goog.debug.Console.prototype.removeFilter = function(loggerName) {
  delete this.filteredLoggers_[loggerName];
};
goog.debug.Console.instance = null;
goog.debug.Console.console_ = goog.global["console"];
goog.debug.Console.setConsole = function(console) {
  goog.debug.Console.console_ = console;
};
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);
  }
};
goog.debug.Console.show = function() {
  alert(goog.debug.Console.instance.logBuffer_);
};
goog.debug.Console.logToConsole_ = function(console, fnName, record) {
  if (console[fnName]) {
    console[fnName](record);
  } else {
    console.log(record);
  }
};
goog.provide("uno.ConsoleLogger");
goog.require("goog.debug.Console");
(function() {
  var ConsoleLogger = uno.ConsoleLogger = function(opt) {
    goog.debug.Console.call(this);
    this.cache = [];
    this.cachingEnabled = true;
    this.maxEntries = null;
    this.configure(opt);
  };
  goog.inherits(uno.ConsoleLogger, goog.debug.Console);
  ConsoleLogger.prototype.configure = function(opt) {
    opt = opt || {};
    if (typeof opt.cachingEnabled !== "undefined") {
      this.cachingEnabled = !!opt.cachingEnabled;
    }
    this.maxEntries = opt.maxEntries;
    if (!this.cachingEnabled) {
      this.clear();
    }
    if (this.maxEntries != null && this.cache.length > this.maxEntries) {
      this.cache = this.cache.slice(this.cache.length - this.maxEntries);
    }
  };
  ConsoleLogger.prototype.addLogRecord = function(logRecord) {
    if (this.filteredLoggers_[logRecord.getLoggerName()]) {
      return;
    }
    logRecord.formattedText = this.formatter_.formatRecord(logRecord);
    var level = logRecord.getLevel();
    var formattedText = logRecord.formattedText;
    this.print(level, formattedText);
    if (this.cachingEnabled) {
      if (this.maxEntries != null && this.maxEntries <= this.cache.length) {
        this.cache.shift();
      }
    }
  };
  ConsoleLogger.prototype.print = function(level, formattedText) {
    var console = goog.debug.Console.console_;
    if (console) {
      switch(level) {
        case goog.debug.Logger.Level.SHOUT:
          goog.debug.Console.logToConsole_(console, "info", formattedText);
          break;
        case goog.debug.Logger.Level.SEVERE:
          goog.debug.Console.logToConsole_(console, "error", formattedText);
          break;
        case goog.debug.Logger.Level.WARNING:
          goog.debug.Console.logToConsole_(console, "warn", formattedText);
          break;
        default:
          goog.debug.Console.logToConsole_(console, "debug", formattedText);
          break;
      }
    }
  };
  ConsoleLogger.prototype.dump = function() {
    var me = this;
    this.cache.forEach(function(record) {
      me.print(record.level, record.formattedText);
    });
  };
  ConsoleLogger.prototype.clear = function() {
    this.cache = [];
  };
})();
goog.provide("uno.defs");
(function() {
  uno.defs = {unicode:{ZERO_WIDTH_SPACE:"\u200b", NBSP:"\u00a0"}, containers:{EDITOR_BODY_SELECTOR:"en-note"}, classes:{RESOURCE_CLASS:"en-media", MODULE_CLASS:"en-module"}, tags:{BLOCK:"div", BOLD:"b", ITALIC:"i", STRIKETHROUGH:"s", UNDERLINE:"u", TT:"tt"}, objects:{OBJECT_PLACEHOLDER_CLASS:"en-object-placeholder"}, crypto:{CRYPT_CLASS:"en-crypt", CRYPT_HIDDEN_CLASS:"en-crypt-placeholder", CRYPT_VISIBLE_CLASS:"en-crypt-revealed"}, format:{CLIPBOARD:"clipboard", ENML:"enml", CLIENT_HTML:"client_html"}, 
  image:{TRANSPARENT_IMAGE_DATA_URL:"data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"}, regex:{CODEBLOCK:"```", BULLETED_LIST:"^\u200b*\\s*\\*", HORIZONTAL_RULE:"^\u200b*\\s*[\\*\\-\\=]{3}[\\s\\*\\-\\=]*", INVALID_HTML_CHARS:"[\x00\u0001-\b\u000e-\u001f\u007f-\u009f\ufdd0-\ufdef\x0B\ufffe\uffff]|[\u0001-\u0010][\ufffe-\uffff]", NUMBERED_LIST:"^\u200b*\\s*[0-9]+\\.", SIMPLE_EMAIL:"[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,4}", TABLE:"^\u200b*\\s*(\\[\\s*\\]){2,}([xX][0-9]+)?", 
  TODO:"^\u200b*\\[[\\sxX]?\\]", WORD_CHARACTER:"[A-Za-z\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2183\u2184\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005\u3006\u3031-\u3035\u303b\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6e5\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]+", 
  SIMPLE_URL:"(?:" + "(?:(?:https?://|ftp://|www\\.)\\S+)" + "|" + "(?:[a-z0-9\\-\\.]+\\.(?:com|net|edu|org))" + ")" + "(?:" + "(?:\\:|/|#|\\?)\\S*|\\b" + ")", WEB_URL:"" + "(?:(?:https?|ftp)://)" + "(?:\\S+(?::\\S*)?@)?" + "(" + "(?:" + ("(?!(?:10|127)(?:\\.\\d{1,3}){3})" + "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))") + 
  "|" + ("(?:(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)" + "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]-*)*[a-z\\u00a1-\\uffff0-9]+)*" + "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))") + ")" + ")" + "(?::\\d{2,5})?" + "(?:/\\S*)?", EMAIL:"\\S+@\\S+\\.\\S+"}, nbsp:{CHARACTER_SEQUENCE:"\u00a0"}, highlight:{COLOR:"rgb(255, 250, 165)", LEGACY_IOS:"rgb(255, 204, 102)", LEGACY_CLEARLY:"rgb(246, 238, 150)", regex:/rgb\(255, 204, 102\)|rgb\(255, 250, 165\)|rgb\(246, 238, 150\)/, LEGACY_STYLE:"-evernote-highlighted", 
  STYLE:"-evernote-highlight"}, table:{FIXED_WIDTH:792, CELL_LINE_HEIGHT:20, CELL_MIN_WIDTH:48, CELL_WIDTH:130, CELL_PADDING:8, CELL_HTML:"<div><br></div>", BORDER_COLOR:"rgb(204, 204, 204)"}, codeblock:{style:'box-sizing: border-box; padding: 8px; font-family: Monaco, Menlo, Consolas, "Courier New", monospace; font-size: 12px; color: rgb(51, 51, 51); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; background-color: rgb(251, 250, 248); border: 1px solid rgba(0, 0, 0, 0.14902); background-position: initial initial; background-repeat: initial initial;'}, 
  bitfields:{NODE_SHOW_ALL:-1, NODE_SHOW_TEXT:4, NODE_FILTER_ACCEPT:1, NODE_FILTER_REJECT:2, NODE_ATTRIBUTE_NODE:2, NODE_TEXT_NODE:3, NODE_CDATA_SECTION_NODE:4, NODE_ENTITY_REFERENCE_NODE:5, NODE_ENTITY_NODE:6, NODE_PROCESSING_INSTRUCTION_NODE:7, NODE_COMMENT_NODE:8, NODE_DOCUMENT_NODE:9, NODE_DOCUMENT_TYPE_NODE:10, NODE_DOCUMENT_FRAGMENT_NODE:11, NODE_NOTATION_NODE:12, NODE_DOCUMENT_POSITION_PRECEDING:2, NODE_DOCUMENT_POSITION_FOLLOWING:4, NODE_DOCUMENT_POSITION_CONTAINS:8, NODE_DOCUMENT_POSITION_CONTAINED_BY:16}, 
  tab:{CHARACTER_SEQUENCE:"\u00a0\u00a0\u00a0\u00a0"}, blockElements:{p:true, h1:true, h2:true, h3:true, h4:true, h5:true, h6:true, pre:true, hr:true, br:true, li:true, div:true, table:true, tr:true, head:true, body:true}, edam:{TITLE_LEN_MAX:255}, paragraph:{indent:40}};
})();
goog.provide("uno.env");
goog.require("goog.userAgent");
(function() {
  var ua = goog.userAgent;
  var env = uno.env;
  env.getClient = function() {
    if (ua.MAC) {
      return "mac";
    } else {
      if (ua.WINDOWS) {
        return "win";
      } else {
        if (ua.ANDROID) {
          return "android";
        } else {
          if (ua.IOS) {
            return "ios";
          } else {
            return "web";
          }
        }
      }
    }
  };
})();
goog.provide("uno.EditorMultiRange");
goog.require("goog.debug.Logger");
goog.require("goog.dom.MultiRange");
(function() {
  var log = goog.debug.Logger.getLogger("uno.EditorMultiRange");
  var EditorMultiRange = uno.EditorMultiRange = function(editor) {
    this.invoking_ = false;
    this.invokedRangeIndex_ = -1;
    this.editor_ = editor;
  };
  goog.inherits(uno.EditorMultiRange, goog.dom.MultiRange);
  EditorMultiRange.Mode = {NONE:0, FIRST:1, ALL:2};
  EditorMultiRange.prototype.addTextRange = function(textRange) {
    if (this.findTextRangeIndex_(textRange) === -1) {
      this.browserRanges_.push(textRange.getBrowserRangeObject());
      this.clearCachedValues_();
    }
  };
  EditorMultiRange.prototype.removeTextRange = function(textRange) {
    var index = this.findTextRangeIndex_(textRange);
    if (index > -1) {
      this.browserRanges_.splice(index, 1);
      this.clearCachedValues_();
    }
  };
  EditorMultiRange.prototype.toggleTextRange = function(textRange, flag) {
    var index = this.findTextRangeIndex_(textRange);
    if (index === -1 && (flag || flag === undefined)) {
      this.browserRanges_.push(textRange.getBrowserRangeObject());
      this.clearCachedValues_();
    } else {
      if (index > -1 && !flag) {
        this.browserRanges_.splice(index, 1);
        this.clearCachedValues_();
      }
    }
  };
  EditorMultiRange.prototype.containsTextRange = function(textRange) {
    return this.findTextRangeIndex_(textRange) > -1;
  };
  EditorMultiRange.prototype.findTextRangeIndex_ = function(textRange) {
    if (!textRange) {
      return -1;
    }
    var wrapper = textRange.getBrowserRangeWrapper_();
    var start = goog.dom.RangeEndpoint.START;
    var end = goog.dom.RangeEndpoint.END;
    try {
      for (var i = 0, l = this.browserRanges_.length; i < l; i++) {
        var range = this.browserRanges_[i];
        if (wrapper.compareBrowserRangeEndpoints(range, end, end) >= 0 && wrapper.compareBrowserRangeEndpoints(range, start, start) <= 0) {
          return i;
        }
      }
    } catch (err$8) {
      this.clear();
      log.warning(err$8.stack || err$8);
    }
    return -1;
  };
  EditorMultiRange.prototype.isEmpty = function() {
    return !this.getTextRangeCount();
  };
  EditorMultiRange.prototype.isInvoking = function() {
    return this.invoking_;
  };
  EditorMultiRange.prototype.isLastInvokedRange = function() {
    return this.invokedRangeIndex_ >= this.browserRanges_.length - 1;
  };
  EditorMultiRange.prototype.isFirstInvokedRange = function() {
    return this.invokedRangeIndex_ === 0;
  };
  EditorMultiRange.prototype.clear = function() {
    this.browserRanges_ = [];
    this.clearCachedValues_();
  };
  EditorMultiRange.prototype.invoke = function(mode, fn, context) {
    var retVal = null;
    try {
      if (mode !== EditorMultiRange.Mode.NONE && !this.isEmpty()) {
        var originalRange = this.editor_.getRange();
        var iterFn = mode === EditorMultiRange.Mode.ALL ? goog.array.forEach : goog.array.some;
        this.invoking_ = true;
        iterFn(this.getTextRanges(), function(range, index) {
          this.currentInvokeRangeIndex_ = index;
          range.select();
          var result = fn.call(context || this.editor_);
          if (!retVal && result) {
            retVal = result;
          }
          return result;
        }, this);
        if (originalRange) {
          originalRange.select();
        }
        this.currentInvokeRangeIndex_ = -1;
        setTimeout(function() {
          this.invoking_ = false;
        }.bind(this));
        return !!retVal;
      }
      return !!fn.call(context || this.editor_);
    } catch (err$9) {
      log.severe(err$9.stack || err$9);
      return false;
    }
  };
})();
goog.provide("uno.BasePlugin");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Plugin");
goog.require("uno.EditorMultiRange");
(function() {
  var Plugin = goog.editor.Plugin;
  var BasePlugin = uno.BasePlugin = function(trogClassId) {
    Plugin.call(this);
    this.trogClassId = trogClassId;
    this.client = null;
    this.multiRangeMode = uno.EditorMultiRange.Mode.FIRST;
    this.strictMode = false;
  };
  goog.inherits(BasePlugin, Plugin);
  BasePlugin.prototype.getTrogClassId = function() {
    return this.trogClassId;
  };
  BasePlugin.prototype.registerFieldObject = function(fieldObject) {
    Plugin.prototype.registerFieldObject.call(this, fieldObject);
    var me = this;
    var id = this.getTrogClassId();
    var namespace = goog.getObjectByName(id.toLowerCase());
    if (namespace) {
      this.client = namespace[fieldObject.config.client] || namespace.generic || {};
      Object.keys(this.client).forEach(function(key) {
        if (typeof me.client[key] === "function") {
          me.client[key] = me.client[key].bind(me);
        }
      });
    }
    this.editor = this.getFieldObject();
    this.setParentEventTarget(this.editor);
  };
  BasePlugin.prototype.unregisterFieldObject = function(fieldObject) {
    Plugin.prototype.unregisterFieldObject.call(this, fieldObject);
    this.editor = null;
  };
})();
goog.provide("uno.util.objects");
goog.require("goog.object");
(function() {
  var objects = uno.util.objects;
  objects.mergeOptions = function(options, defaultOptions) {
    var parsedOptions = goog.object.clone(options || {});
    goog.object.extend(defaultOptions, parsedOptions);
    return defaultOptions;
  };
  objects.valueOrDefault = function(val, defaultVal) {
    if (typeof val === "undefined") {
      return defaultVal;
    }
    return val;
  };
})();
goog.provide("uno.util.tools");
goog.require("goog.dom");
(function() {
  var util = uno.util;
  util.tools.getContainer = function() {
    var container = document.querySelector("en-tools");
    if (!container) {
      container = document.createElement("en-tools");
      document.body.appendChild(container);
    }
    return container;
  };
  util.tools.query = function(selector) {
    var container = util.tools.getContainer();
    return container.querySelector(selector);
  };
  util.tools.append = function(node) {
    var container = util.tools.getContainer();
    container.appendChild(node);
    return node;
  };
  util.tools.preloadImages = function() {
    if (!util.tools.query("en-preload")) {
      util.tools.append(goog.dom.createDom("en-preload", {class:"en-preload"}));
    }
  };
})();
goog.provide("uno.commands.Accentuate");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.objects");
goog.require("uno.util.tools");
(function() {
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.commands.Accentuate");
  var Accentuate = uno.commands.Accentuate = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Accentuate, uno.BasePlugin);
  Accentuate.CONTAINER_CLASSNAME = "accentuate-container";
  Accentuate.BOX_CLASSNAME = "en-find-result";
  Accentuate.BOX_ACTIVE_CLASSNAME = "en-find-result-active";
  Accentuate.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Accentuate.prototype.isSupportedCommand = function(command) {
    return command === "accentuate";
  };
  Accentuate.prototype.execCommand = function(command, rawOptions) {
    var options = util.objects.mergeOptions(rawOptions, {boxes:[], selectedBoxIndex:-1, scrollToSelectedBox:true, clearFirst:false, clearOnClickSelector:"en-note"});
    var accentuateContainer = document.querySelector("." + Accentuate.CONTAINER_CLASSNAME);
    if (options.clearFirst && accentuateContainer) {
      accentuateContainer.innerHTML = "";
    }
    if (!accentuateContainer) {
      var toolsContainer = util.tools.getContainer();
      accentuateContainer = goog.dom.createDom("div", {class:Accentuate.CONTAINER_CLASSNAME});
      toolsContainer.appendChild(accentuateContainer);
    }
    var boxes = options.boxes;
    var currentIndex = accentuateContainer.querySelectorAll("." + Accentuate.BOX_CLASSNAME).length;
    for (var i = 0; i < boxes.length; i++) {
      var match = boxes[i];
      for (var j = 0; j < match.length; j++) {
        var item = match[j];
        var box = goog.dom.createDom("div", {id:Accentuate.BOX_CLASSNAME + currentIndex, class:Accentuate.BOX_CLASSNAME, style:createStyle({position:"absolute", top:item.top + "px", left:item.left + "px", width:item.width + "px", height:item.height + "px"})});
        currentIndex++;
        accentuateContainer.appendChild(box);
      }
    }
    var newActiveBox = accentuateContainer.querySelector("#" + Accentuate.BOX_CLASSNAME + options.selectedBoxIndex);
    if (newActiveBox) {
      var oldActiveBox = accentuateContainer.querySelector("." + Accentuate.BOX_ACTIVE_CLASSNAME);
      if (oldActiveBox) {
        goog.dom.classlist.remove(oldActiveBox, Accentuate.BOX_ACTIVE_CLASSNAME);
      }
      goog.dom.classlist.add(newActiveBox, Accentuate.BOX_ACTIVE_CLASSNAME);
      if (options.scrollToSelectedBox) {
        newActiveBox.scrollIntoView();
      }
    }
    return true;
  };
  function createStyle(style) {
    var finalStyle = "";
    for (var key in style) {
      if (style.hasOwnProperty(key)) {
        finalStyle += key + ":" + style[key] + ";";
      }
    }
    return finalStyle;
  }
})();
goog.provide("uno.commands.Active");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Active");
  var Active = uno.commands.Active = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Active, uno.BasePlugin);
  Active.prototype.isSupportedCommand = function(command) {
    return command === "active";
  };
  Active.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Active.prototype.execCommand = function(command, makeActive) {
    if (makeActive === "true") {
      makeActive = true;
    } else {
      if (makeActive === "false") {
        makeActive = false;
      }
    }
    if (this.editor.readOnly === makeActive) {
      this.editor.readOnly = !makeActive;
      if (makeActive) {
        this.editor.enterEditMode(false);
      } else {
        this.editor.leaveEditMode();
      }
    }
    return true;
  };
  Active.prototype.queryCommandValue = function() {
    return !this.editor.readOnly;
  };
})();
goog.provide("goog.crypt");
goog.require("goog.array");
goog.require("goog.asserts");
goog.crypt.stringToByteArray = function(str) {
  var output = [], p = 0;
  for (var i = 0; i < str.length; i++) {
    var c = str.charCodeAt(i);
    while (c > 255) {
      output[p++] = c & 255;
      c >>= 8;
    }
    output[p++] = c;
  }
  return output;
};
goog.crypt.byteArrayToString = function(bytes) {
  var CHUNK_SIZE = 8192;
  if (bytes.length <= CHUNK_SIZE) {
    return String.fromCharCode.apply(null, bytes);
  }
  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;
};
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("");
};
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;
};
goog.crypt.stringToUtf8ByteArray = function(str) {
  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 {
        if ((c & 64512) == 55296 && i + 1 < str.length && (str.charCodeAt(i + 1) & 64512) == 56320) {
          c = 65536 + ((c & 1023) << 10) + (str.charCodeAt(++i) & 1023);
          out[p++] = c >> 18 | 240;
          out[p++] = c >> 12 & 63 | 128;
          out[p++] = c >> 6 & 63 | 128;
          out[p++] = c & 63 | 128;
        } else {
          out[p++] = c >> 12 | 224;
          out[p++] = c >> 6 & 63 | 128;
          out[p++] = c & 63 | 128;
        }
      }
    }
  }
  return out;
};
goog.crypt.utf8ByteArrayToString = function(bytes) {
  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 {
        if (c1 > 239 && c1 < 365) {
          var c2 = bytes[pos++];
          var c3 = bytes[pos++];
          var c4 = bytes[pos++];
          var u = ((c1 & 7) << 18 | (c2 & 63) << 12 | (c3 & 63) << 6 | c4 & 63) - 65536;
          out[c++] = String.fromCharCode(55296 + (u >> 10));
          out[c++] = String.fromCharCode(56320 + (u & 1023));
        } else {
          var c2 = bytes[pos++];
          var c3 = bytes[pos++];
          out[c++] = String.fromCharCode((c1 & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
        }
      }
    }
  }
  return out.join("");
};
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;
};
goog.provide("goog.crypt.Hash");
goog.crypt.Hash = function() {
  this.blockSize = -1;
};
goog.crypt.Hash.prototype.reset = goog.abstractMethod;
goog.crypt.Hash.prototype.update = goog.abstractMethod;
goog.crypt.Hash.prototype.digest = goog.abstractMethod;
goog.provide("goog.crypt.Md5");
goog.require("goog.crypt.Hash");
goog.crypt.Md5 = function() {
  goog.crypt.Md5.base(this, "constructor");
  this.blockSize = 512 / 8;
  this.chain_ = new Array(4);
  this.block_ = new Array(this.blockSize);
  this.blockLength_ = 0;
  this.totalLength_ = 0;
  this.reset();
};
goog.inherits(goog.crypt.Md5, goog.crypt.Hash);
goog.crypt.Md5.prototype.reset = function() {
  this.chain_[0] = 1732584193;
  this.chain_[1] = 4023233417;
  this.chain_[2] = 2562383102;
  this.chain_[3] = 271733878;
  this.blockLength_ = 0;
  this.totalLength_ = 0;
};
goog.crypt.Md5.prototype.compress_ = function(buf, opt_offset) {
  if (!opt_offset) {
    opt_offset = 0;
  }
  var X = new Array(16);
  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;
  sum = A + (D ^ B & (C ^ D)) + X[0] + 3614090360 & 4294967295;
  A = B + (sum << 7 & 4294967295 | sum >>> 25);
  sum = D + (C ^ A & (B ^ C)) + X[1] + 3905402710 & 4294967295;
  D = A + (sum << 12 & 4294967295 | sum >>> 20);
  sum = C + (B ^ D & (A ^ B)) + X[2] + 606105819 & 4294967295;
  C = D + (sum << 17 & 4294967295 | sum >>> 15);
  sum = B + (A ^ C & (D ^ A)) + X[3] + 3250441966 & 4294967295;
  B = C + (sum << 22 & 4294967295 | sum >>> 10);
  sum = A + (D ^ B & (C ^ D)) + X[4] + 4118548399 & 4294967295;
  A = B + (sum << 7 & 4294967295 | sum >>> 25);
  sum = D + (C ^ A & (B ^ C)) + X[5] + 1200080426 & 4294967295;
  D = A + (sum << 12 & 4294967295 | sum >>> 20);
  sum = C + (B ^ D & (A ^ B)) + X[6] + 2821735955 & 4294967295;
  C = D + (sum << 17 & 4294967295 | sum >>> 15);
  sum = B + (A ^ C & (D ^ A)) + X[7] + 4249261313 & 4294967295;
  B = C + (sum << 22 & 4294967295 | sum >>> 10);
  sum = A + (D ^ B & (C ^ D)) + X[8] + 1770035416 & 4294967295;
  A = B + (sum << 7 & 4294967295 | sum >>> 25);
  sum = D + (C ^ A & (B ^ C)) + X[9] + 2336552879 & 4294967295;
  D = A + (sum << 12 & 4294967295 | sum >>> 20);
  sum = C + (B ^ D & (A ^ B)) + X[10] + 4294925233 & 4294967295;
  C = D + (sum << 17 & 4294967295 | sum >>> 15);
  sum = B + (A ^ C & (D ^ A)) + X[11] + 2304563134 & 4294967295;
  B = C + (sum << 22 & 4294967295 | sum >>> 10);
  sum = A + (D ^ B & (C ^ D)) + X[12] + 1804603682 & 4294967295;
  A = B + (sum << 7 & 4294967295 | sum >>> 25);
  sum = D + (C ^ A & (B ^ C)) + X[13] + 4254626195 & 4294967295;
  D = A + (sum << 12 & 4294967295 | sum >>> 20);
  sum = C + (B ^ D & (A ^ B)) + X[14] + 2792965006 & 4294967295;
  C = D + (sum << 17 & 4294967295 | sum >>> 15);
  sum = B + (A ^ C & (D ^ A)) + X[15] + 1236535329 & 4294967295;
  B = C + (sum << 22 & 4294967295 | sum >>> 10);
  sum = A + (C ^ D & (B ^ C)) + X[1] + 4129170786 & 4294967295;
  A = B + (sum << 5 & 4294967295 | sum >>> 27);
  sum = D + (B ^ C & (A ^ B)) + X[6] + 3225465664 & 4294967295;
  D = A + (sum << 9 & 4294967295 | sum >>> 23);
  sum = C + (A ^ B & (D ^ A)) + X[11] + 643717713 & 4294967295;
  C = D + (sum << 14 & 4294967295 | sum >>> 18);
  sum = B + (D ^ A & (C ^ D)) + X[0] + 3921069994 & 4294967295;
  B = C + (sum << 20 & 4294967295 | sum >>> 12);
  sum = A + (C ^ D & (B ^ C)) + X[5] + 3593408605 & 4294967295;
  A = B + (sum << 5 & 4294967295 | sum >>> 27);
  sum = D + (B ^ C & (A ^ B)) + X[10] + 38016083 & 4294967295;
  D = A + (sum << 9 & 4294967295 | sum >>> 23);
  sum = C + (A ^ B & (D ^ A)) + X[15] + 3634488961 & 4294967295;
  C = D + (sum << 14 & 4294967295 | sum >>> 18);
  sum = B + (D ^ A & (C ^ D)) + X[4] + 3889429448 & 4294967295;
  B = C + (sum << 20 & 4294967295 | sum >>> 12);
  sum = A + (C ^ D & (B ^ C)) + X[9] + 568446438 & 4294967295;
  A = B + (sum << 5 & 4294967295 | sum >>> 27);
  sum = D + (B ^ C & (A ^ B)) + X[14] + 3275163606 & 4294967295;
  D = A + (sum << 9 & 4294967295 | sum >>> 23);
  sum = C + (A ^ B & (D ^ A)) + X[3] + 4107603335 & 4294967295;
  C = D + (sum << 14 & 4294967295 | sum >>> 18);
  sum = B + (D ^ A & (C ^ D)) + X[8] + 1163531501 & 4294967295;
  B = C + (sum << 20 & 4294967295 | sum >>> 12);
  sum = A + (C ^ D & (B ^ C)) + X[13] + 2850285829 & 4294967295;
  A = B + (sum << 5 & 4294967295 | sum >>> 27);
  sum = D + (B ^ C & (A ^ B)) + X[2] + 4243563512 & 4294967295;
  D = A + (sum << 9 & 4294967295 | sum >>> 23);
  sum = C + (A ^ B & (D ^ A)) + X[7] + 1735328473 & 4294967295;
  C = D + (sum << 14 & 4294967295 | sum >>> 18);
  sum = B + (D ^ A & (C ^ D)) + X[12] + 2368359562 & 4294967295;
  B = C + (sum << 20 & 4294967295 | sum >>> 12);
  sum = A + (B ^ C ^ D) + X[5] + 4294588738 & 4294967295;
  A = B + (sum << 4 & 4294967295 | sum >>> 28);
  sum = D + (A ^ B ^ C) + X[8] + 2272392833 & 4294967295;
  D = A + (sum << 11 & 4294967295 | sum >>> 21);
  sum = C + (D ^ A ^ B) + X[11] + 1839030562 & 4294967295;
  C = D + (sum << 16 & 4294967295 | sum >>> 16);
  sum = B + (C ^ D ^ A) + X[14] + 4259657740 & 4294967295;
  B = C + (sum << 23 & 4294967295 | sum >>> 9);
  sum = A + (B ^ C ^ D) + X[1] + 2763975236 & 4294967295;
  A = B + (sum << 4 & 4294967295 | sum >>> 28);
  sum = D + (A ^ B ^ C) + X[4] + 1272893353 & 4294967295;
  D = A + (sum << 11 & 4294967295 | sum >>> 21);
  sum = C + (D ^ A ^ B) + X[7] + 4139469664 & 4294967295;
  C = D + (sum << 16 & 4294967295 | sum >>> 16);
  sum = B + (C ^ D ^ A) + X[10] + 3200236656 & 4294967295;
  B = C + (sum << 23 & 4294967295 | sum >>> 9);
  sum = A + (B ^ C ^ D) + X[13] + 681279174 & 4294967295;
  A = B + (sum << 4 & 4294967295 | sum >>> 28);
  sum = D + (A ^ B ^ C) + X[0] + 3936430074 & 4294967295;
  D = A + (sum << 11 & 4294967295 | sum >>> 21);
  sum = C + (D ^ A ^ B) + X[3] + 3572445317 & 4294967295;
  C = D + (sum << 16 & 4294967295 | sum >>> 16);
  sum = B + (C ^ D ^ A) + X[6] + 76029189 & 4294967295;
  B = C + (sum << 23 & 4294967295 | sum >>> 9);
  sum = A + (B ^ C ^ D) + X[9] + 3654602809 & 4294967295;
  A = B + (sum << 4 & 4294967295 | sum >>> 28);
  sum = D + (A ^ B ^ C) + X[12] + 3873151461 & 4294967295;
  D = A + (sum << 11 & 4294967295 | sum >>> 21);
  sum = C + (D ^ A ^ B) + X[15] + 530742520 & 4294967295;
  C = D + (sum << 16 & 4294967295 | sum >>> 16);
  sum = B + (C ^ D ^ A) + X[2] + 3299628645 & 4294967295;
  B = C + (sum << 23 & 4294967295 | sum >>> 9);
  sum = A + (C ^ (B | ~D)) + X[0] + 4096336452 & 4294967295;
  A = B + (sum << 6 & 4294967295 | sum >>> 26);
  sum = D + (B ^ (A | ~C)) + X[7] + 1126891415 & 4294967295;
  D = A + (sum << 10 & 4294967295 | sum >>> 22);
  sum = C + (A ^ (D | ~B)) + X[14] + 2878612391 & 4294967295;
  C = D + (sum << 15 & 4294967295 | sum >>> 17);
  sum = B + (D ^ (C | ~A)) + X[5] + 4237533241 & 4294967295;
  B = C + (sum << 21 & 4294967295 | sum >>> 11);
  sum = A + (C ^ (B | ~D)) + X[12] + 1700485571 & 4294967295;
  A = B + (sum << 6 & 4294967295 | sum >>> 26);
  sum = D + (B ^ (A | ~C)) + X[3] + 2399980690 & 4294967295;
  D = A + (sum << 10 & 4294967295 | sum >>> 22);
  sum = C + (A ^ (D | ~B)) + X[10] + 4293915773 & 4294967295;
  C = D + (sum << 15 & 4294967295 | sum >>> 17);
  sum = B + (D ^ (C | ~A)) + X[1] + 2240044497 & 4294967295;
  B = C + (sum << 21 & 4294967295 | sum >>> 11);
  sum = A + (C ^ (B | ~D)) + X[8] + 1873313359 & 4294967295;
  A = B + (sum << 6 & 4294967295 | sum >>> 26);
  sum = D + (B ^ (A | ~C)) + X[15] + 4264355552 & 4294967295;
  D = A + (sum << 10 & 4294967295 | sum >>> 22);
  sum = C + (A ^ (D | ~B)) + X[6] + 2734768916 & 4294967295;
  C = D + (sum << 15 & 4294967295 | sum >>> 17);
  sum = B + (D ^ (C | ~A)) + X[13] + 1309151649 & 4294967295;
  B = C + (sum << 21 & 4294967295 | sum >>> 11);
  sum = A + (C ^ (B | ~D)) + X[4] + 4149444226 & 4294967295;
  A = B + (sum << 6 & 4294967295 | sum >>> 26);
  sum = D + (B ^ (A | ~C)) + X[11] + 3174756917 & 4294967295;
  D = A + (sum << 10 & 4294967295 | sum >>> 22);
  sum = C + (A ^ (D | ~B)) + X[2] + 718787259 & 4294967295;
  C = D + (sum << 15 & 4294967295 | sum >>> 17);
  sum = B + (D ^ (C | ~A)) + X[9] + 3951481745 & 4294967295;
  B = C + (sum << 21 & 4294967295 | sum >>> 11);
  this.chain_[0] = this.chain_[0] + A & 4294967295;
  this.chain_[1] = this.chain_[1] + B & 4294967295;
  this.chain_[2] = this.chain_[2] + C & 4294967295;
  this.chain_[3] = this.chain_[3] + D & 4294967295;
};
goog.crypt.Md5.prototype.update = function(bytes, opt_length) {
  if (!goog.isDef(opt_length)) {
    opt_length = bytes.length;
  }
  var lengthMinusBlock = opt_length - this.blockSize;
  var block = this.block_;
  var blockLength = this.blockLength_;
  var i = 0;
  while (i < opt_length) {
    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;
          break;
        }
      }
    } else {
      while (i < opt_length) {
        block[blockLength++] = bytes[i++];
        if (blockLength == this.blockSize) {
          this.compress_(block);
          blockLength = 0;
          break;
        }
      }
    }
  }
  this.blockLength_ = blockLength;
  this.totalLength_ += opt_length;
};
goog.crypt.Md5.prototype.digest = function() {
  var pad = new Array((this.blockLength_ < 56 ? this.blockSize : this.blockSize * 2) - this.blockLength_);
  pad[0] = 128;
  for (var i = 1; i < pad.length - 8; ++i) {
    pad[i] = 0;
  }
  var totalBits = this.totalLength_ * 8;
  for (var i = pad.length - 8; i < pad.length; ++i) {
    pad[i] = totalBits & 255;
    totalBits /= 256;
  }
  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 & 255;
    }
  }
  return digest;
};
goog.provide("uno.util.zoomscale");
goog.require("uno.defs");
(function() {
  var util = uno.util;
  var note = null;
  util.zoomscale.getZoom = function() {
    if (!note) {
      note = document.querySelector(uno.defs.containers.EDITOR_BODY_SELECTOR);
    }
    var zoom = parseFloat(note.style.zoom);
    return isNaN(zoom) ? 1.0 : zoom;
  };
  util.zoomscale.normalizeRect = function(rect) {
    var zoom = uno.util.zoomscale.getZoom();
    if (rect && zoom && zoom !== 1.0) {
      var b = {};
      if (rect.left) {
        b.left = rect.left * zoom;
      }
      if (rect.right) {
        b.right = rect.right * zoom;
      }
      if (rect.top) {
        b.top = rect.top * zoom;
      }
      if (rect.bottom) {
        b.bottom = rect.bottom * zoom;
      }
      if (rect.width) {
        b.width = rect.width * zoom;
      }
      if (rect.height) {
        b.height = rect.height * zoom;
      }
      return b;
    }
    return rect;
  };
})();
goog.provide("uno.util.todo.generic");
(function() {
  var util = uno.util;
  var generic = util.todo.generic;
  generic.tryToInsertTodo = function(editor) {
    editor.execCommand("insertparagraph");
    editor.execCommand("inserttodo");
    return true;
  };
  generic.findTodosInClientHtml = function() {
    return [];
  };
  generic.convertTodoToClientElement = function() {
  };
})();
goog.provide("uno.util.todo.mac");
goog.require("goog.dom");
goog.require("goog.dom.classes");
goog.require("uno.util.todo.generic");
(function() {
  var mac = uno.util.todo.mac;
  var util = uno.util;
  mac.tryToInsertTodo = function(editor) {
    return util.todo.generic.tryToInsertTodo(editor);
  };
  mac.findTodosInClientHtml = function(frag) {
    return frag.querySelectorAll("img.en-todo");
  };
  mac.convertClientElementToTodo = function(el) {
    var checked = goog.dom.classes.has(el, "en-todo-checked");
    var entodo = util.todo.create(checked);
    goog.dom.replaceNode(entodo, el);
  };
  mac.convertTodoToClientElement = function(todo) {
    var img = goog.dom.createDom("img", {class:"en-todo"});
    if (util.todo.isChecked(todo)) {
      goog.dom.classes.add(img, "en-todo-checked");
    }
    goog.dom.replaceNode(img, todo);
  };
})();
goog.provide("uno.util.todo.ios");
(function() {
  var ios = uno.util.todo.ios;
  var util = uno.util;
  ios.tryToInsertTodo = function(editor) {
    return false;
  };
  ios.findTodosInClientHtml = function() {
    return [];
  };
  ios.convertTodoToClientElement = function() {
  };
  ios.convertTodoInClipboard = function(todo) {
    return util.todo.create(util.todo.isChecked(todo));
  };
  ios.convertTodoToClipboardElement = function(fragment) {
    var todo = goog.dom.createDom("input", "en-todo");
    todo.setAttribute("type", "checkbox");
    if (util.todo.isChecked(fragment)) {
      util.todo.setChecked(todo, true);
      todo.setAttribute("checked", true);
    }
    return todo;
  };
})();
goog.provide("uno.util.todo.win");
goog.require("goog.dom");
goog.require("uno.util.todo.generic");
(function() {
  var util = uno.util;
  var win = uno.util.todo.win;
  win.tryToInsertTodo = function(editor) {
    return util.todo.generic.tryToInsertTodo(editor);
  };
  win.findTodosInClientHtml = function(frag) {
    return frag.querySelectorAll("img[src^=en-resource\\:\\/\\/database\\/check]");
  };
  win.convertClientElementToTodo = function(el) {
    var src = el.getAttribute("src");
    var matches = /database\/check(\d+):(\d+)/.exec(src);
    var X = parseInt(matches[1], 10);
    var checked = X === 1 || X === 3;
    var entodo = util.todo.create(checked);
    goog.dom.replaceNode(entodo, el);
  };
  win.convertTodoToClientElement = function(todo) {
    var src = "en-resource://database/check";
    src += util.todo.isChecked(todo) ? "1" : "0";
    src += ":0";
    var img = goog.dom.createDom("img", {src:src});
    goog.dom.replaceNode(img, todo);
  };
  win.convertTodoInClipboard = function(todo) {
    return util.todo.create(util.todo.isChecked(todo));
  };
})();
goog.provide("uno.util.todo");
goog.require("goog.debug.Logger");
goog.require("goog.dom.classes");
goog.require("uno.util.todo.generic");
goog.require("uno.util.todo.mac");
goog.require("uno.util.todo.ios");
goog.require("uno.util.todo.win");
goog.require("uno.defs");
(function() {
  var util = uno.util;
  var client = uno.util.todo.generic;
  util.todo.setClient = function(clientName) {
    client = uno.util.todo[clientName] || client;
  };
  util.todo.all = function(root) {
    return root.querySelectorAll(".en-todo");
  };
  util.todo.allEnmlTodos = function(root) {
    return root.querySelectorAll("en-todo");
  };
  util.todo.isTodo = function(el) {
    return el && goog.dom.classes.has(el, "en-todo");
  };
  util.todo.create = function(checked) {
    var todo = new Image;
    todo.src = uno.defs.image.TRANSPARENT_IMAGE_DATA_URL;
    goog.dom.classes.add(todo, "en-todo");
    if (checked) {
      util.todo.toggle(todo);
    }
    return todo;
  };
  util.todo.tryToInsertTodo = function(editor) {
    return client.tryToInsertTodo(editor);
  };
  util.todo.isChecked = function(todo) {
    return todo.getAttribute("checked") === "true";
  };
  util.todo.setChecked = function(todo, checked) {
    todo.setAttribute("checked", checked);
  };
  util.todo.toggle = function(todo) {
    todo.setAttribute("checked", !util.todo.isChecked(todo));
  };
  util.todo.remove = function(todo) {
    if (!todo || !todo.parentNode) {
      return;
    }
    var textNode = goog.editor.node.getNextSibling(todo);
    if (textNode && textNode.nodeType === Node.TEXT_NODE) {
      var text = textNode.textContent;
      var updated = goog.string.trimLeft(text);
      if (updated !== text) {
        if (updated.length === 0) {
          goog.dom.removeNode(textNode);
        } else {
          textNode.textContent = updated;
        }
      }
    }
    goog.dom.removeNode(todo);
  };
  util.todo.findTodosInClientHtml = function(root) {
    return client.findTodosInClientHtml(root);
  };
  util.todo.convertClientElementToTodo = function(el) {
    client.convertClientElementToTodo(el);
  };
  util.todo.convertTodoToClientElement = function(todo) {
    client.convertTodoToClientElement(todo);
  };
  util.todo.convertTodoInClipboard = function(todo) {
    return client.convertTodoInClipboard && client.convertTodoInClipboard(todo);
  };
  util.todo.convertTodoToClipboardElement = function(todo) {
    return client.convertTodoToClipboardElement && client.convertTodoToClipboardElement(todo);
  };
  util.todo.decorate = function(entodo) {
    var checked = util.todo.isChecked(entodo);
    goog.dom.replaceNode(util.todo.create(checked), entodo);
  };
  util.todo.undecorate = function(todo) {
    var entodo = goog.dom.createDom("en-todo");
    entodo.setAttribute("checked", util.todo.isChecked(todo));
    goog.dom.replaceNode(entodo, todo);
  };
  util.todo.addTodoToParagraph = function(node) {
    var todo = util.todo.create();
    node.insertBefore(todo, node.firstChild);
    return node;
  };
})();
goog.provide("uno.util.dom");
goog.require("uno.defs");
goog.require("uno.util.zoomscale");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.editor.node");
goog.require("goog.html.SafeHtml");
goog.require("uno.util.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.dom");
  var dom = uno.util.dom;
  var util = uno.util;
  dom.inlineObjects = ["en-media", "en-todo", "en-crypt", "en-cursor", "img", "embed", "object", "input", "param", "hr", "br", "en-adornments"];
  dom.tableObjects = ["colgroup", "col", "tr", "td"];
  dom.inlineTagNames = ["en-media", "en-cursor", "span", "font", "a", "br", "img", "object", "embed"];
  dom.blockTagNames = ["en-note", "address", "article", "aside", "body", "blockquote", "caption", "center", "col", "colgroup", "dd", "details", "dir", "div", "dl", "dt", "fieldset", "figcaption", "figure", "footer", "form", "h1", "h2", "h3", "h4", "h5", "h6", "header", "hgroup", "hr", "li", "listing", "menu", "nav", "ol", "p", "plaintext", "pre", "section", "summary", "table", "en-table", "tbody", "td", "tfoot", "th", "thead", "tr", "ul", "xmp"];
  dom.isInlineObject = function(node) {
    if (!node || !dom.isElementNode(node)) {
      return false;
    }
    return dom.inlineObjects.indexOf(node.tagName.toLowerCase()) > -1;
  };
  dom.isTextNode = function(node) {
    return !!(node && node.nodeType === Node.TEXT_NODE);
  };
  dom.isElementNode = function(node) {
    return !!(node && node.nodeType === Node.ELEMENT_NODE);
  };
  dom.isBlockNode = function(node) {
    if (!node) {
      return false;
    }
    return !!(dom.blockTagNames.indexOf(dom.getTagName(node)) > -1 || node.nodeType === Node.DOCUMENT_NODE || node.nodeType === Node.DOCUMENT_FRAGMENT_NODE);
  };
  dom.isInlineNode = function(node) {
    return !!(node && !dom.isBlockNode(node));
  };
  dom.getLastParagraphItem = function(node) {
    if (!node) {
      return null;
    }
    if (!node.childNodes || !node.childNodes.length) {
      return node;
    }
    var leafNode = null;
    goog.array.forEachRight(node.childNodes, function(element) {
      if (leafNode || dom.isEmpty(element)) {
        return;
      }
      if (!element.childNodes || !element.childNodes.length || dom.isInlineObject(element)) {
        leafNode = element;
      } else {
        leafNode = dom.getLastParagraphItem(element);
      }
    });
    return leafNode;
  };
  dom.getFirstParagraphItem = function(node) {
    if (!node) {
      return null;
    }
    if (!node.childNodes || !node.childNodes.length) {
      return node;
    }
    var leafNode = null;
    goog.array.forEach(node.childNodes, function(element) {
      if (leafNode || dom.isEmpty(element)) {
        return;
      }
      if (!element.childNodes || !element.childNodes.length || dom.isInlineObject(element)) {
        leafNode = element;
      } else {
        leafNode = dom.getFirstParagraphItem(element);
      }
    });
    return leafNode;
  };
  dom.isFragment = function(node) {
    return !!(node.nodeType === Node.DOCUMENT_FRAGMENT_NODE);
  };
  dom.isNoteSection = function(node) {
    if (!node) {
      return false;
    }
    return !!(dom.isEnnote(node) || dom.isTd(node) || dom.isCodeBlock(node) || dom.isLi(node) || dom.isRevealedCrypt(node) || dom.isBlockquote(node) || dom.isFragment(node));
  };
  dom.getNodeLeaves = function(root, forcedLeaves, skipTextNodes) {
    var deepestNodes = [];
    forcedLeaves = forcedLeaves || [];
    var getNodeLeaves = function(node, forcedLeaves) {
      var isForcedLeaf = node.tagName && forcedLeaves.indexOf(node.tagName.toLowerCase()) > -1;
      if (!node.childNodes || !node.childNodes.length || isForcedLeaf) {
        if (skipTextNodes && !dom.isTextNode(node) || !skipTextNodes) {
          deepestNodes.push(node);
        }
      }
      goog.iter.forEach(node.childNodes, function(child) {
        if (!isForcedLeaf) {
          getNodeLeaves(child, forcedLeaves);
        }
      });
    };
    if (root && root.childNodes) {
      goog.iter.forEach(root.childNodes, function(node) {
        getNodeLeaves(node, forcedLeaves);
      });
    }
    return deepestNodes;
  };
  dom.getTagName = function(node) {
    return node && node.tagName && node.tagName.toLowerCase() || "";
  };
  dom.isBlockOrInlineBlockNode = function(node) {
    if (!node || !node.style) {
      return false;
    }
    if (node.style.display === "block" || node.style.display === "inline-block") {
      return true;
    }
    if (node.style.display === "" || node.style.display === "inherit" || node.style.display === "default") {
      return dom.isBlockNode(node);
    }
    return false;
  };
  dom.changeTagName = function(node, newTagName) {
    if (!node || !newTagName) {
      return false;
    }
    var attributes = {};
    goog.array.forEach(node.attributes, function(item) {
      attributes[item.name] = item.value;
    });
    var newNode = goog.dom.createDom(newTagName, attributes, node.childNodes);
    goog.dom.replaceNode(newNode, node);
    return newNode;
  };
  dom.clone = function(node) {
    var clone = goog.dom.createDom("div", null);
    if (dom.isTextNode(node)) {
      clone.innerText = node.textContent;
    } else {
      clone.innerHTML = node.outerHTML;
    }
    return clone.firstChild;
  };
  dom.nodeFromHtml = function(html, tagName, attributes, childNodes) {
    var node = goog.dom.createDom(tagName || "div", attributes, childNodes);
    node.innerHTML = html;
    return node;
  };
  dom.isEmpty = function(node) {
    if (!node) {
      return true;
    }
    if (node.nodeType === Node.TEXT_NODE) {
      return !node.data.length;
    }
    if (node.firstChild) {
      if (node.querySelectorAll("br").length > 1) {
        return false;
      }
      if (node.querySelectorAll("li, blockquote, table").length > 0) {
        return false;
      }
      if (!dom.isEnnote(node) && dom.isBlockNode(node) && node.getAttribute && node.getAttribute("style")) {
        return false;
      }
      return Array.prototype.every.call(node.childNodes, function(childNode) {
        return dom.isEmpty(childNode);
      });
    }
    if (dom.isBlockOrInlineBlockNode(node) && util.styles.hasLayoutStyle(node)) {
      return false;
    }
    var tagName = dom.getTagName(node);
    var components = ["img", "embed", "object", "input", "param", "hr", "en-media", "en-table", "en-todo", "en-crypt"];
    var isObject = components.indexOf(tagName) > -1;
    return !isObject;
  };
  dom.isEmptyContent = function(node) {
    if (!node) {
      return true;
    }
    if (node.nodeType === Node.TEXT_NODE) {
      return !node.data.length;
    }
    if (node.firstChild) {
      if (node.querySelectorAll("br, li").length > 1) {
        return false;
      }
      return Array.prototype.every.call(node.childNodes, function(childNode) {
        return dom.isEmptyContent(childNode);
      });
    }
    var tagName = node.tagName.toLowerCase();
    var components = ["img", "embed", "object", "input", "param", "hr", "en-media", "en-table", "en-todo", "en-crypt"];
    var isObject = components.indexOf(tagName) > -1;
    return !isObject;
  };
  dom.parent = function(node, selector, rootNode) {
    if (!rootNode) {
      rootNode = document.body;
    }
    if (node === rootNode) {
      return null;
    }
    if (dom.matches(node, selector)) {
      return node;
    }
    var parentNode = node && node.parentNode;
    if (parentNode) {
      return dom.parent(parentNode, selector, rootNode);
    }
    return null;
  };
  var createIsTagNames = function() {
    dom.blockTagNames.concat(dom.inlineTagNames).forEach(function(tagName) {
      var fnName = "is" + goog.string.capitalize(tagName.replace("-", ""));
      dom[fnName] = function(node) {
        return node && node.tagName && node.tagName.toLowerCase() === tagName ? node : null;
      };
    });
  };
  createIsTagNames();
  dom.isHeader = function(node) {
    return node && node.tagName && ["h1", "h2", "h3", "h4", "h5", "h6"].indexOf(node.tagName.toLowerCase()) > -1 ? node : null;
  };
  dom.isCodeBlock = function(node) {
    if (!node || !dom.isElementNode(node)) {
      return false;
    }
    return node.classList.contains("en-code") || (node.getAttribute("style") || "").indexOf("-en-codeblock:") > -1;
  };
  dom.isRevealedCrypt = function(node) {
    if (!node) {
      return false;
    }
    return !!goog.dom.classlist.contains(node, "en-crypt-revealed");
  };
  dom.getFirstAncestor = function(node, tagNames, includeNode) {
    return goog.dom.getAncestor(node, function(ancestor) {
      return ancestor && ancestor.tagName && tagNames.indexOf(ancestor.tagName.toLowerCase()) > -1;
    }, includeNode);
  };
  dom.getOrigin = function(child) {
    var origin = goog.dom.getAncestor(child, function(node) {
      return dom.isTd(node) || dom.isCodeBlock(node) || dom.isRevealedCrypt(node) || dom.isEnnote(node);
    }, true);
    return origin;
  };
  dom.ancestors = function(node) {
    var ancestors = [];
    while (node && node.parentNode) {
      ancestors.unshift(node.parentNode);
      node = node.parentNode;
    }
    return ancestors;
  };
  dom.getNextSiblings = function(node) {
    if (!node) {
      return [];
    }
    var nodes = [];
    var sib = node;
    while (sib.nextSibling) {
      nodes.push(sib.nextSibling);
      sib = sib.nextSibling;
    }
    return nodes;
  };
  dom.getPreviousSiblings = function(node) {
    if (!node) {
      return [];
    }
    var nodes = [];
    var sib = node;
    while (sib.previousSibling) {
      nodes.unshift(sib.previousSibling);
      sib = sib.previousSibling;
    }
    return nodes;
  };
  dom.contiguousInlineSiblings = function(node) {
    var nodes = [node];
    var sib = node.previousSibling;
    while (sib && !dom.isBlockNode(sib)) {
      nodes.unshift(sib);
      sib = sib.previousSibling;
    }
    sib = node.nextSibling;
    while (sib && !dom.isBlockNode(sib)) {
      nodes.push(sib);
      sib = sib.nextSibling;
    }
    return nodes;
  };
  var rxEscapeObj = /[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g;
  var rxEscape = function(value) {
    if (value instanceof RegExp) {
      return value.source;
    }
    return value.replace(rxEscapeObj, "\\$&");
  };
  var regexForAppDataNameCache = {};
  var regexForAppDataName = function(name) {
    var rx = regexForAppDataNameCache[name];
    if (!rx) {
      rx = new RegExp("(^|;)\\s*(" + rxEscape(name) + ")\\s*\\:\\s*(.*?)($|;)+", "gi");
      regexForAppDataName[name] = rx;
    } else {
      rx.lastIndex = 0;
    }
    return rx;
  };
  dom.fragFromString = function(html) {
    var frag = document.createDocumentFragment();
    var temp = document.createElement("div");
    temp.innerHTML = html;
    while (temp.firstChild) {
      if (temp.firstChild.nodeType === Node.TEXT_NODE && temp.firstChild.textContent.trim().length === 0) {
        goog.dom.removeNode(temp.firstChild);
        continue;
      }
      frag.appendChild(temp.firstChild);
    }
    return frag;
  };
  dom.stringFromFrag = function(frag) {
    return Array.prototype.reduce.call(frag.childNodes, function(html, node) {
      return html + (node.outerHTML || node.textContent);
    }, "");
  };
  dom.compareTagName = function(el, names, caseSensitive) {
    if (typeof names === "string") {
      names = [names];
    }
    if (el && el.tagName) {
      var tagName = caseSensitive ? el.tagName : el.tagName.toLowerCase();
      return names.some(function(name) {
        return caseSensitive ? tagName === name : tagName === name.toLowerCase();
      });
    }
    return false;
  };
  dom.getNodeLength = function(node) {
    if (!node) {
      return 0;
    }
    switch(node.nodeType) {
      case Node.PROCESSING_INSTRUCTION_NODE:
      case Node.DOCUMENT_TYPE_NODE:
        return 0;
      case Node.TEXT_NODE:
      case Node.COMMENT_NODE:
        return node.length;
      default:
        return node.childNodes.length;
    }
  };
  dom.nextNode = function(node) {
    if (node.hasChildNodes()) {
      return node.firstChild;
    }
    return dom.nextNodeDescendants(node);
  };
  dom.previousNode = function(node) {
    if (node.previousSibling) {
      node = node.previousSibling;
      while (node.hasChildNodes()) {
        node = node.lastChild;
      }
      return node;
    }
    if (dom.isElementNode(node.parentNode)) {
      return node.parentNode;
    }
    return null;
  };
  dom.nextNodeDescendants = function(node, root) {
    while (node && !node.nextSibling) {
      if (root === node) {
        break;
      }
      node = node.parentNode;
    }
    if (!node || root && root === node) {
      return null;
    }
    return node.nextSibling;
  };
  dom.isEditable = function(node) {
    return !!(node && dom.isInsideEditableContainer(node) && (dom.isElementNode(node) || dom.isElementNode(node.parentNode)));
  };
  dom.isComputedBlock = function(node) {
    var display = goog.style.getComputedStyle(node, "display");
    return !!(display === "block");
  };
  dom.hasEditableDescendants = function(node) {
    for (var i = 0; i < node.childNodes.length; i++) {
      if (dom.isEditable(node.childNodes[i]) || dom.hasEditableDescendants(node.childNodes[i])) {
        return true;
      }
    }
    return false;
  };
  dom.moveChildren = function(srcNode, destNode) {
    while (srcNode.firstChild) {
      destNode.appendChild(srcNode.firstChild);
    }
    return destNode;
  };
  dom.replaceContainer = function(node, replacementElement) {
    node.parentNode.insertBefore(replacementElement, node);
    dom.moveChildren(node, replacementElement);
    goog.dom.removeNode(node);
    return replacementElement;
  };
  dom.isVisible = function(node) {
    if (!node) {
      return false;
    }
    if (dom.isBlockNode(node) || dom.isImageLikeElement(node) || node.nodeType === Node.TEXT_NODE && !dom.isCollapsedWhitespaceNode(node) || node.tagName.toUpperCase() === "BR" && !dom.isExtraneousLineBreak(node)) {
      return true;
    }
    for (var i = 0; i < node.childNodes.length; i++) {
      if (dom.isVisible(node.childNodes[i])) {
        return true;
      }
    }
    return false;
  };
  dom.isImageLikeElement = function(node) {
    return !!(dom.compareTagName(node, ["img", "embed", "object", "input", "param", "hr"]) || goog.dom.classes.has(node, "en-media") || goog.dom.classes.has(node, "en-module") || goog.dom.classes.has(node, "en-richlink"));
  };
  dom.isCollapsedWhitespaceNode = function(node) {
    if (!dom.isWhitespaceNode(node)) {
      return false;
    }
    if (node.data === "") {
      return true;
    }
    var ancestor = node.parentNode;
    if (!ancestor) {
      return true;
    }
    while (!dom.isBlockNode(ancestor) && ancestor.parentNode) {
      ancestor = ancestor.parentNode;
    }
    var reference = node;
    while (reference != ancestor) {
      reference = dom.previousNode(reference);
      if (dom.isBlockNode(reference) || dom.isBr(reference)) {
        return true;
      }
      if (reference.nodeType == Node.TEXT_NODE && !dom.isWhitespaceNode(reference) || dom.isImageLikeElement(reference)) {
        break;
      }
    }
    reference = node;
    var stop = dom.nextNodeDescendants(ancestor);
    while (reference != stop) {
      reference = dom.nextNode(reference);
      if (dom.isBlockNode(reference) || dom.isBr(reference)) {
        return true;
      }
      if (reference && reference.nodeType == Node.TEXT_NODE && !dom.isWhitespaceNode(reference) || dom.isImageLikeElement(reference)) {
        break;
      }
    }
    return false;
  };
  dom.isWhitespaceNode = function(node) {
    dom.rxWhitespace.lastIndex = 0;
    return !!(node && node.nodeType === Node.TEXT_NODE && (node.data === "" || dom.rxWhitespace.test(node.data)));
  };
  dom.rxWhitespace = /^[\t\n\r ]+$/;
  dom.getEffectiveCssValue = function(node, propName) {
    if (!dom.isElementNode(node) && (!node.parentNode || !dom.isElementNode(node.parentNode))) {
      return null;
    }
    if (!dom.isElementNode(node)) {
      return dom.getEffectiveCssValue(node.parentNode, propName);
    }
    if (!dom.isRenderedDOMNode(node)) {
      log.warn("We are not on rendered DOM for fontSize retieval", node);
      return dom.styleInheritedForNode(node, propName, "");
    }
    if (node.style && node.style[propName] !== null && node.style[propName] !== "") {
      return node.style[propName];
    }
    var ret = goog.style.getComputedStyle(node, propName);
    return ret;
  };
  dom.styleInheritedForNode = function(node, styleName, defaultValue, root) {
    root = root || document.body;
    defaultValue = defaultValue || "";
    var styleValue;
    if (node == null) {
      return defaultValue;
    }
    if (!dom.isChild(node, root)) {
      do {
        if (dom.isElementNode(node) && node.hasAttribute("style")) {
          styleValue = node.style[styleName];
          if (styleValue != null) {
            break;
          }
        }
      } while ((node = node.parentNode) && root === node);
    }
    return styleValue || defaultValue;
  };
  dom.isRenderedDOMNode = function(node) {
    return !!(node && (node.isEqualNode(document.documentElement) || document.documentElement.contains(node)));
  };
  dom.isBefore = function(node1, node2) {
    return node1 != null && node2 != null && !!(node1.compareDocumentPosition(node2) & Node.DOCUMENT_POSITION_FOLLOWING);
  };
  dom.isInsideEditableContainer = function(node) {
    return true;
  };
  dom.isExtraneousLineBreak = function(br) {
    return false;
  };
  dom.firstChild = function(node) {
    if (goog.dom.isElement(node) && node.firstChild) {
      return dom.firstChild(node.firstChild);
    } else {
      return node;
    }
  };
  dom.isBeginningOfLineChild = function(node, root) {
    var beginNode = dom.firstChild(node);
    if (beginNode.parentNode !== root) {
      while (beginNode.parentNode !== root) {
        beginNode = beginNode.parentNode;
      }
      return dom.firstChild(beginNode) === dom.firstChild(node);
    } else {
      return dom.index(beginNode) === 0;
    }
  };
  dom.isPrecededByInlineContent = function(node) {
    var result = false;
    var div = goog.dom.getAncestorByTagNameAndClass(node, goog.dom.TagName.DIV);
    if (!div || !div.childNodes) {
      return result;
    }
    goog.array.some(div.childNodes, function(child) {
      if (child === node) {
        return true;
      }
      if (!dom.isBlockNode(child)) {
        if (child.nodeType === Node.TEXT_NODE && child.textContent.length === 0) {
          return false;
        }
        return true;
      }
    });
    return result;
  };
  dom.index = function(node) {
    var ret = 0;
    while (node = node.previousSibling) {
      ret++;
    }
    return ret;
  };
  dom.matches = function(node, selector) {
    if (!node || !dom.isElementNode(node)) {
      return false;
    }
    if (goog.isString(selector)) {
      if (node.matches != null) {
        return node.matches(selector);
      } else {
        var matches = document.querySelectorAll(selector);
        var i;
        for (i = 0; i < matches.length; i += 1) {
          if (matches.item(i) === node) {
            return true;
          }
        }
      }
    } else {
      if (goog.isFunction(selector)) {
        return selector(node);
      }
    }
    return false;
  };
  dom.attributes = function(node) {
    var attrs = {};
    if (node) {
      var nodeAttrs = node.attributes;
      if (nodeAttrs) {
        for (var i = nodeAttrs.length; i--;) {
          attrs[nodeAttrs[i].name.toLowerCase()] = nodeAttrs[i].value;
        }
      }
    }
    return attrs;
  };
  dom.moveNode = function(node, newParent, newIndex, activeRange) {
    if (newParent && newIndex === -1) {
      newIndex = newParent.childNodes.length;
    }
    var oldParent = node.parentNode;
    var oldIndex = dom.index(node);
    var preserve = activeRange != null;
    if (preserve) {
      var boundaryPoints = [[activeRange.getStartNode(), activeRange.getStartOffset()], [activeRange.getEndNode(), activeRange.getEndOffset()]];
      boundaryPoints.forEach(function(boundaryPoint) {
        if (boundaryPoint[0] === newParent && boundaryPoint[1] > newIndex) {
          boundaryPoint[1]++;
        }
        if (boundaryPoint[0] === oldParent && (boundaryPoint[1] === oldIndex || boundaryPoint[1] === oldIndex + 1)) {
          if (newParent) {
            boundaryPoint[0] = newParent;
            boundaryPoint[1] += newIndex - oldIndex;
          } else {
            if (boundaryPoint[1] > oldIndex && boundaryPoint[1] > 0) {
              boundaryPoint[1] -= 1;
            }
          }
        }
        if (boundaryPoint[0] === oldParent && boundaryPoint[1] > oldIndex + 1) {
          boundaryPoint[1]--;
        }
        if (!newParent && dom.isChild(boundaryPoint[0], node)) {
          boundaryPoint[0] = node.parentNode;
          boundaryPoint[1] = dom.index(node);
        }
      });
    }
    if (!newParent) {
      goog.dom.removeNode(node);
      return;
    }
    if (newParent.childNodes.length === newIndex || newIndex === -1) {
      newParent.appendChild(node);
    } else {
      newParent.insertBefore(node, newParent.childNodes[+newIndex]);
    }
    goog.dom.Range.clearSelection();
    if (preserve) {
      goog.dom.browserrange.createRangeFromNodes(boundaryPoints[0][0], boundaryPoints[0][1], boundaryPoints[1][0], boundaryPoints[1][1]).select();
    }
  };
  dom.detachNode = function(node) {
    if (node) {
      node = goog.isArray(node) ? node : [node];
      node.forEach(function(el) {
        el.parentNode.removeChild(el);
      });
      return node;
    }
  };
  dom.getNextEquivalentPoint = function(node, offset) {
    if (dom.getNodeLength(node) === 0) {
      return null;
    }
    if (offset === dom.getNodeLength(node) && node.parentNode && dom.isInlineNode(node)) {
      return [node.parentNode, 1 + dom.index(node)];
    }
    if (0 <= offset && offset < node.childNodes.length && dom.getNodeLength(node.childNodes[offset]) !== 0 && dom.isInlineNode(node.childNodes[offset])) {
      return [node.childNodes[offset], 0];
    }
    return null;
  };
  dom.getLastEquivalentPoint = function(node, offset) {
    var next;
    while (next = dom.getNextEquivalentPoint(node, offset)) {
      node = next[0];
      offset = next[1];
    }
    return [node, offset];
  };
  dom.isChild = function(node, other) {
    if (!other || !node) {
      return false;
    }
    return !!(node.compareDocumentPosition(other) & Node.DOCUMENT_POSITION_CONTAINS);
  };
  dom.isParent = function(node, other) {
    if (!other || !node) {
      return false;
    }
    return !!(node.compareDocumentPosition(other) & 16);
  };
  dom.removeStyleValue = function(node, name) {
    var styleString = dom.getStyleString(node);
    if (styleString == null) {
      return "";
    }
    styleString = styleString.replace(regexForAppDataName(name), "$1").trim();
    if (styleString.length > 0) {
      node.setAttribute("style", styleString);
    } else {
      node.removeAttribute("style");
    }
    return styleString || "";
  };
  dom.getStyleString = function(node) {
    if (!node || !node.getAttribute) {
      return "";
    }
    return node.getAttribute("style");
  };
  dom.getStyleValue = function(node, name) {
    var styleString = dom.getStyleString(node);
    if (styleString == null) {
      return null;
    }
    var match = regexForAppDataName(name).exec(styleString);
    return match === null ? null : match[3].trim();
  };
  dom.setStyleValue = function(node, name, value) {
    var styleString = dom.removeStyleValue(node, name);
    if (value == null) {
      return null;
    }
    styleString = styleString.trim();
    if (styleString.length && styleString[styleString.length - 1] !== ";") {
      styleString += ";";
    }
    styleString = styleString + name + ":" + value + ";";
    node.setAttribute("style", styleString);
    return styleString;
  };
  var TreeWalker = dom.TreeWalker = function(startNode, rootNode) {
    var node = startNode;
    function findSibling(node, startName, siblingName, shallow) {
      var sibling, parent;
      if (node) {
        if (!shallow && node[startName]) {
          return node[startName];
        }
        if (node != rootNode) {
          sibling = node[siblingName];
          if (sibling) {
            return sibling;
          }
          for (parent = node.parentNode; parent && parent != rootNode; parent = parent.parentNode) {
            sibling = parent[siblingName];
            if (sibling) {
              return sibling;
            }
          }
        }
      }
    }
    this.current = function() {
      return node;
    };
    this.next = function(shallow) {
      node = findSibling(node, "firstChild", "nextSibling", shallow);
      return node;
    };
    this.prev = function(shallow) {
      node = findSibling(node, "lastChild", "previousSibling", shallow);
      return node;
    };
  };
  dom.isBlockFormattingContext = function(node) {
    if (dom.isElementNode(node)) {
      var style = window.getComputedStyle(node);
      if (style.float !== "none") {
        return true;
      }
      if (style.position !== "static" && style.position !== "relative") {
        return true;
      }
      if (["flex", "inline-block", "inline-flex", "table-caption", "table-cell"].indexOf(style.display) != -1) {
        return true;
      }
      if (style.overlfow !== "visible") {
        return true;
      }
    }
    return false;
  };
  var voidElementNames = ["area", "base", "br", "col", "command", "embed", "hr", "img", "input", "keygen", "link", "meta", "param", "source", "track", "wbr"];
  dom.allowsChildren = function(node) {
    if (dom.isElementNode(node)) {
      if (voidElementNames.indexOf(node.tagName.toLowerCase()) != -1) {
        return true;
      }
    }
    return false;
  };
  dom.hasTextNextToIt = function(node) {
    var neighboringTextRegex = /[^\s]+/i;
    var leftNode = node.previousSibling;
    while (leftNode) {
      if (leftNode.nodeName && uno.defs.blockElements[leftNode.nodeName.toLowerCase()]) {
        break;
      }
      if (neighboringTextRegex.test(leftNode.textContent)) {
        return true;
      }
      leftNode = leftNode.previousSibling;
    }
    var rightNode = node.nextSibling;
    while (rightNode) {
      if (rightNode.nodeName && uno.defs.blockElements[rightNode.nodeName.toLowerCase()]) {
        break;
      }
      if (neighboringTextRegex.test(rightNode.textContent)) {
        return true;
      }
      rightNode = rightNode.nextSibling;
    }
    var parent = node.parentNode;
    if (parent && (!parent.nodeName || !uno.defs.blockElements[parent.nodeName.toLowerCase()])) {
      return dom.hasTextNextToIt(parent);
    }
    return false;
  };
  dom.hasTodoNextToIt = function(node) {
    var leftNode = node.previousSibling;
    while (leftNode) {
      if (util.todo.isTodo(leftNode)) {
        return true;
      }
      leftNode = leftNode.previousSibling;
    }
    var rightNode = node.nextSibling;
    while (rightNode) {
      if (util.todo.isTodo(rightNode)) {
        return true;
      }
      rightNode = rightNode.nextSibling;
    }
    return false;
  };
  dom.getViewportRect = function() {
    var rect = {top:document.body.scrollTop, left:document.body.scrollLeft, width:window.innerWidth, height:window.innerHeight, bottom:0, right:0};
    rect.bottom = rect.top + rect.height;
    rect.right = rect.left + rect.width;
    return rect;
  };
  dom.makeClientRect = function(rect, opt, client) {
    var offsetLeft;
    var offsetTop;
    if (rect == null) {
      return null;
    }
    goog.object.extend(opt, {absolute:false, zoomScale:1.0, ignoreOffset:false}, opt);
    if (client === "ios") {
      if (document.body.getClientRects()[0].top < 0 === false) {
        offsetLeft = 0;
        offsetTop = 0;
      }
    }
    if (!opt.absolute && offsetLeft == null) {
      offsetLeft = document.body.scrollLeft;
      offsetTop = document.body.scrollTop;
    } else {
      offsetLeft = 0;
      offsetTop = 0;
    }
    if (client === "android" && opt.ignoreOffset !== true) {
      var offsetElement = document.getElementById("offset");
      if (offsetElement != null) {
        offsetTop -= parseInt(offsetElement.style.height, 10);
      }
    }
    var clientRect;
    if (client === "web") {
      clientRect = {left:Math.round(rect.left * opt.zoomScale) + offsetLeft, right:Math.round(rect.right * opt.zoomScale) + offsetLeft, top:Math.round(rect.top * opt.zoomScale) + offsetTop, bottom:Math.round(rect.bottom * opt.zoomScale) + offsetTop, width:Math.round(rect.width * opt.zoomScale), height:Math.round(rect.height * opt.zoomScale)};
    } else {
      clientRect = {left:rect.left * opt.zoomScale + offsetLeft, right:rect.right * opt.zoomScale + offsetLeft, top:rect.top * opt.zoomScale + offsetTop, bottom:rect.bottom * opt.zoomScale + offsetTop, width:rect.width * opt.zoomScale, height:rect.height * opt.zoomScale};
    }
    return clientRect;
  };
  dom.getDataAttribute = function(node, key) {
    return node && node.getAttribute ? node.getAttribute(["data", key].join("-")) : null;
  };
  dom.setDataAttribute = function(node, key, value) {
    return node && (node.dataset[key] = value);
  };
  dom.removeDataAttribute = function(node, key) {
    if (node && node.dataset) {
      var value = node.dataset[key];
      delete node.dataset[key];
      return value;
    }
    return null;
  };
  dom.removeDataAttributes = function(node) {
    Object.keys(node.dataset).forEach(function(key) {
      delete node.dataset[key];
    });
  };
  dom.stripContainerElementFromMarkup = function(markup) {
    var start = markup.indexOf(">");
    var end = markup.lastIndexOf("<");
    if (start < 0 || end < 0) {
      return markup;
    }
    return markup.substring(start + 1, end);
  };
  dom.toHTML = function(obj) {
    var node;
    if (goog.isString(obj)) {
      node = document.createElement("div");
      node.textContent = obj;
    } else {
      if (obj instanceof Node) {
        node = obj.ownerDocument.createElement("div");
        node.appendChild(obj.cloneNode(true));
      } else {
        log.severe("Illegal argument type for en.toHTML");
      }
    }
    return dom.stripContainerElementFromMarkup(node.outerHTML);
  };
  dom.workOnTemporaryDOMNode = function(node, fn) {
    var domNode = goog.dom.createDom("div", {style:"position: absolute; width: 1px; height: 1px; " + "top: -9999px; left: -9999px;"});
    domNode.appendChild(node);
    document.body.appendChild(domNode);
    fn(node);
    var n = goog.dom.removeNode(node);
    goog.dom.removeNode(domNode);
    return n;
  };
  dom.isOnScreen = function(node, onScreenAmount) {
    if (!goog.dom.isElement(node)) {
      return false;
    }
    start("node.getBoundingClientRect");
    var box = node.getBoundingClientRect();
    stop("node.getBoundingClientRect");
    start("dom.isBoundingBoxOnScreen");
    var isBoundingBoxOnScreen = dom.isBoundingBoxOnScreen(box.top, box.bottom, onScreenAmount);
    stop("dom.isBoundingBoxOnScreen");
    return isBoundingBoxOnScreen;
  };
  dom.getBoundingBox = function(node, optAbsolute) {
    if (node == null) {
      return null;
    }
    if (optAbsolute == null) {
      optAbsolute = false;
    }
    if (node.nodeType == null) {
      return null;
    }
    if (!dom.isRenderedDOMNode(node)) {
      return null;
    }
    if (!goog.isFunction(node.getClientRects)) {
      return null;
    }
    var boxes = node.getClientRects();
    if (boxes.length === 0) {
      var range = node.ownerDocument.createRange();
      range.selectNode(node);
      boxes = range.getClientRects();
    }
    if (boxes.length >= 1) {
      return dom.makeClientRect(boxes[0], {absolute:optAbsolute, zoomScale:uno.util.zoomscale.getZoom()});
    }
    return null;
  };
  dom.isBoundingBoxOnScreen = function(boxTop, boxBottom, onScreenAmount) {
    var scrollTop = window.scrollY;
    var scrollBottom = scrollTop + window.innerHeight;
    onScreenAmount = onScreenAmount || 55;
    var elementTop = boxTop + scrollTop;
    var elementBottom = boxBottom + scrollTop;
    var commonTop = Math.max(scrollTop, elementTop);
    var commonBottom = Math.min(scrollBottom, elementBottom);
    var overlapPercent = Math.max(0, Math.round((commonBottom - commonTop) / (elementBottom - elementTop) * 100));
    return overlapPercent >= onScreenAmount;
  };
  dom.isVisibleInView = function(node, partial) {
    if (!dom.isElementNode(node) || !node.parentNode) {
      return false;
    }
    if (partial !== false) {
      partial = true;
    }
    var bounds = node.getBoundingClientRect();
    var parent = node.parentNode;
    var viewRect = {top:0, left:0, bottom:window.innerHeight, right:window.innerWidth, height:window.innerHeight, width:window.innerWidth};
    var isIntersect = function(rect) {
      return partial ? !(bounds.bottom <= rect.top || bounds.top >= rect.bottom || bounds.left >= rect.right || bounds.right <= rect.left) : !(rect.height === 0 || rect.width === 0 || bounds.bottom > rect.bottom && bounds.top > rect.top || bounds.top < rect.top && bounds.bottom < rect.bottom || bounds.left > rect.left && bounds.right > rect.right || bounds.left < rect.left && bounds.right < rect.right);
    };
    if (!isIntersect(viewRect)) {
      return false;
    }
    while (parent && parent !== document.documentElement) {
      var style = window.getComputedStyle(parent);
      if (style.display === "none" || style.visibility === "hidden") {
        return false;
      }
      if (style.position !== "static" && [style.overflow, style.overflowY, style.overflowX].indexOf("hidden") > -1) {
        var pbounds = parent.getBoundingClientRect();
        var rect = {top:Math.max(viewRect.top, pbounds.top), left:Math.max(viewRect.left, pbounds.left), bottom:Math.min(viewRect.bottom, pbounds.bottom), right:Math.min(viewRect.right, pbounds.right), width:pbounds.width, height:pbounds.height};
        if (!isIntersect(rect)) {
          return false;
        }
      }
      parent = parent.parentNode;
    }
    return !!parent;
  };
  dom.scrollTo = function(pixelsFromTop, animationDuration, relativeToElement) {
    relativeToElement = relativeToElement || document.body;
    animationDuration = animationDuration || 0;
    pixelsFromTop = pixelsFromTop || 0;
    if (animationDuration === 0) {
      relativeToElement.scrollTop = pixelsFromTop;
      return;
    }
    var start = relativeToElement.scrollTop;
    var change = pixelsFromTop - start;
    var currentTime = 0;
    var increment = 20;
    var easeInOutQuad = function(curTime, startValue, changeInValue, duration) {
      curTime /= duration / 2;
      if (curTime < 1) {
        return changeInValue / 2 * curTime * curTime + startValue;
      }
      curTime--;
      return -changeInValue / 2 * (curTime * (curTime - 2) - 1) + startValue;
    };
    var animateScroll = function() {
      currentTime += increment;
      relativeToElement.scrollTop = easeInOutQuad(currentTime, start, change, animationDuration);
      if (currentTime < animationDuration) {
        window.setTimeout(animateScroll, increment);
      }
    };
    animateScroll();
  };
  var voidRx = /^(area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)$/i;
  dom.isVoid = function(el) {
    return voidRx.test(el.tagName);
  };
  dom.isFollowedByContent = function(node) {
    while (node != null) {
      if (node.nextSibling) {
        return true;
      }
      node = node.parentElement;
      if (dom.isBlockNode(node)) {
        return false;
      }
    }
    return false;
  };
  dom.flattenElement = function(element) {
    var child, parent = element.parentNode;
    if (parent) {
      if (element.removeNode) {
        return element.removeNode(false);
      } else {
        while (child = element.firstChild) {
          parent.insertBefore(child, element);
        }
        return goog.dom.removeNode(element);
      }
    }
  };
})();
goog.provide("uno.util.copy.plain");
(function() {
  var util = uno.util;
  util.copy.plain.copy = function(root) {
    var resources = root.querySelectorAll("en-media");
    goog.array.forEach(resources, function(node) {
      goog.dom.removeNode(node);
    });
    var a = root.querySelectorAll("a");
    goog.array.forEach(a, function(node) {
      goog.dom.replaceNode(document.createTextNode(node.textContent), node);
    });
    var todos = util.todo.all(root);
    goog.array.forEach(todos, function(node) {
      var todo = document.createTextNode(util.todo.isChecked(node) ? "[x] " : "[ ] ");
      goog.dom.replaceNode(todo, node);
    });
    plainifyLists(root, 0);
    var entools = document.querySelector("en-tools");
    entools.appendChild(root);
    var n, walk = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
    while (n = walk.nextNode()) {
      n.data = n.data.replace(/ /g, "\u00a0");
    }
    var plainText = root.innerText;
    goog.dom.removeNode(root);
    plainText = plainText.replace(/<br>/g, "\n").replace(/-----PLACEHOLDER_TAB-----/g, "    ").replace(/\u00A0/g, " ");
    return plainText;
  };
  function plainifyLists(node) {
    var parents = [];
    if (util.dom.isUl(node) || util.dom.isOl(node)) {
      parents.push(node);
    } else {
      if (util.dom.isElementNode(node)) {
        parents = node.querySelectorAll("ul, ol");
      }
    }
    goog.array.forEach(parents, function(parent) {
      if (util.dom.isElementNode(parent)) {
        var isOL = util.dom.isOl(parent);
        var count = parseInt(parent.getAttribute("start"), 10) || 1;
        var tabsCount = getTabCounts(parent);
        goog.array.forEach(parent.childNodes, function(li) {
          if (util.dom.isLi(li) && li.firstChild) {
            var prefix = goog.dom.createTextNode(insertTabs(tabsCount) + (isOL ? count + ". " : "* "));
            goog.dom.insertSiblingBefore(prefix, li.firstChild);
            count++;
          }
        });
      }
    });
  }
  function getTabCounts(node) {
    var tabsCount = 0;
    goog.dom.getAncestor(node, function(element) {
      if (util.dom.isUl(element) || util.dom.isOl(element)) {
        tabsCount++;
      }
      return !!util.dom.isEnnote(element);
    });
    return tabsCount;
  }
  function insertTabs(count) {
    var placeholder = "";
    for (var i = 0; i < count; i++) {
      placeholder += "-----PLACEHOLDER_TAB-----";
    }
    return placeholder;
  }
})();
goog.provide("goog.color.names");
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"};
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");
goog.color.Rgb;
goog.color.Hsv;
goog.color.Hsl;
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");
};
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()]);
};
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;
};
goog.color.hexToRgbStyle = function(hexColor) {
  return goog.color.rgbStyle_(goog.color.hexToRgb(hexColor));
};
goog.color.hexTripletRe_ = /#(.)(.)(.)/;
goog.color.normalizeHex = function(hexColor) {
  if (!goog.color.isValidHexColor_(hexColor)) {
    throw Error("'" + hexColor + "' is not a valid hex color");
  }
  if (hexColor.length == 4) {
    hexColor = hexColor.replace(goog.color.hexTripletRe_, "#$1$1$2$2$3$3");
  }
  return hexColor.toLowerCase();
};
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];
};
goog.color.rgbToHex = function(r, g, b) {
  r = Number(r);
  g = Number(g);
  b = Number(b);
  if (r != (r & 255) || g != (g & 255) || b != (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;
};
goog.color.rgbArrayToHex = function(rgb) {
  return goog.color.rgbToHex(rgb[0], rgb[1], rgb[2]);
};
goog.color.rgbToHsl = function(r, g, b) {
  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;
  var l = 0.5 * (max + min);
  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);
    }
  }
  return [Math.round(h + 360) % 360, s, l];
};
goog.color.rgbArrayToHsl = function(rgb) {
  return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]);
};
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;
};
goog.color.hslToRgb = function(h, s, l) {
  var r = 0;
  var g = 0;
  var b = 0;
  var normH = h / 360;
  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)];
};
goog.color.hslArrayToRgb = function(hsl) {
  return goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]);
};
goog.color.validHexColorRe_ = /^#(?:[0-9a-f]{3}){1,2}$/i;
goog.color.isValidHexColor_ = function(str) {
  return goog.color.validHexColorRe_.test(str);
};
goog.color.normalizedHexColorRe_ = /^#[0-9a-f]{6}$/;
goog.color.isNormalizedHexColor_ = function(str) {
  return goog.color.normalizedHexColorRe_.test(str);
};
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;
goog.color.isValidRgbColor_ = function(str) {
  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 [];
};
goog.color.prependZeroIfNecessaryHelper = function(hex) {
  return hex.length == 1 ? "0" + hex : hex;
};
goog.color.prependHashIfNecessaryHelper = function(str) {
  return str.charAt(0) == "#" ? str : "#" + str;
};
goog.color.rgbStyle_ = function(rgb) {
  return "rgb(" + rgb.join(",") + ")";
};
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)];
};
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];
};
goog.color.rgbArrayToHsv = function(rgb) {
  return goog.color.rgbToHsv(rgb[0], rgb[1], rgb[2]);
};
goog.color.hsvArrayToRgb = function(hsv) {
  return goog.color.hsvToRgb(hsv[0], hsv[1], hsv[2]);
};
goog.color.hexToHsl = function(hex) {
  var rgb = goog.color.hexToRgb(hex);
  return goog.color.rgbToHsl(rgb[0], rgb[1], rgb[2]);
};
goog.color.hslToHex = function(h, s, l) {
  return goog.color.rgbArrayToHex(goog.color.hslToRgb(h, s, l));
};
goog.color.hslArrayToHex = function(hsl) {
  return goog.color.rgbArrayToHex(goog.color.hslToRgb(hsl[0], hsl[1], hsl[2]));
};
goog.color.hexToHsv = function(hex) {
  return goog.color.rgbArrayToHsv(goog.color.hexToRgb(hex));
};
goog.color.hsvToHex = function(h, s, v) {
  return goog.color.rgbArrayToHex(goog.color.hsvToRgb(h, s, v));
};
goog.color.hsvArrayToHex = function(hsv) {
  return goog.color.hsvToHex(hsv[0], hsv[1], hsv[2]);
};
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);
};
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])];
};
goog.color.darken = function(rgb, factor) {
  var black = [0, 0, 0];
  return goog.color.blend(black, rgb, factor);
};
goog.color.lighten = function(rgb, factor) {
  var white = [255, 255, 255];
  return goog.color.blend(white, rgb, factor);
};
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;
};
goog.color.yiqBrightness_ = function(rgb) {
  return Math.round((rgb[0] * 299 + rgb[1] * 587 + rgb[2] * 114) / 1000);
};
goog.color.yiqBrightnessDiff_ = function(rgb1, rgb2) {
  return Math.abs(goog.color.yiqBrightness_(rgb1) - goog.color.yiqBrightness_(rgb2));
};
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]);
};
goog.provide("uno.util.observer");
goog.require("goog.array");
goog.require("goog.events");
goog.require("uno.defs");
goog.require("uno.util.dom");
(function() {
  var util = uno.util;
  var handlers = [];
  var target = null;
  var targetBottom = null;
  var sharedObserver = null;
  util.observer.addHandler = function(handler) {
    if (!handler) {
      return;
    }
    if (handlers.indexOf(handler) === -1) {
      handlers.push(handler);
      observeIfNeeded();
    }
  };
  util.observer.removeHandler = function(handler) {
    if (!handler) {
      return;
    }
    var index = handlers.indexOf(handler);
    if (index > -1) {
      handlers.splice(index, 1);
      observeIfNeeded();
    }
  };
  function invokeHandlers() {
    var bottom = getBottom(target);
    if (targetBottom !== bottom) {
      targetBottom = bottom;
      handlers.forEach(function(handler) {
        handler();
      });
    }
  }
  function handleObservation(mutations) {
    goog.array.forEach(mutations, function(mutation) {
      goog.array.forEach(mutation.addedNodes, function(node) {
        if (util.dom.isImg(node) && !node.naturalHeight) {
          goog.events.listenOnce(node, "load", invokeHandlers);
        }
      });
    });
    invokeHandlers();
  }
  function getBottom(target) {
    if (!target || !target.lastChild) {
      return 0;
    }
    return target.lastChild.offsetTop + target.lastChild.offsetHeight;
  }
  function observeIfNeeded() {
    if (!sharedObserver) {
      if (!window || !window.MutationObserver) {
        throw new Error("MutationObserver is missing.");
      }
      sharedObserver = new MutationObserver(handleObservation);
    }
    sharedObserver.disconnect();
    goog.events.unlisten(window, "resize", invokeHandlers);
    goog.events.unlisten(window, "input", invokeHandlers);
    if (handlers.length > 0) {
      target = document.querySelector(uno.defs.containers.EDITOR_BODY_SELECTOR);
      targetBottom = getBottom(target);
      sharedObserver.observe(target, {childList:true, subtree:true});
      goog.events.listen(window, "resize", invokeHandlers);
      goog.events.listen(window, "input", invokeHandlers);
    }
  }
})();
goog.provide("uno.util.range");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("uno.defs");
goog.require("uno.util.dom");
(function() {
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.util.range");
  function getViewPortRect(margin) {
    var rect = {left:0, top:0, width:window.innerWidth, height:window.innerHeight - margin.offset.height};
    if (margin.scroll.top > 0) {
      rect.top -= margin.scroll.top;
      rect.height += margin.scroll.top;
    }
    rect.bottom = rect.top + rect.height;
    rect.right = rect.left + rect.width;
    return rect;
  }
  function scrollRectIntoView(rect, placeOnTop, margin) {
    var transY = 0;
    var viewport = getViewPortRect(margin);
    var top = document.body.scrollTop;
    if (placeOnTop === true) {
      transY = viewport.top - rect.top;
    } else {
      transY = viewport.bottom - rect.bottom;
    }
    top = Math.max(0, top - transY);
    document.body.scrollTop = top;
  }
  util.range.atBeginningOfDiv = function(range) {
    if (range && range.getStartNode() && util.dom.compareTagName(range.getStartNode(), "div") && range.isCollapsed()) {
      if (range.getStartOffset() === 0) {
        return true;
      }
      var currentChild = null;
      for (var i = 0; i < range.getStartOffset(); i++) {
        currentChild = range.getStartNode().childNodes[i];
        if (currentChild.nodeType !== Node.TEXT_NODE || currentChild.textContent.length !== 0) {
          return false;
        }
      }
      return true;
    }
    return false;
  };
  util.range.getBoundingBoxesFromRange = function(rangeObject) {
    if (!rangeObject) {
      return null;
    }
    var boxes = rangeObject.getClientRects();
    if (!boxes || !boxes.length) {
      return null;
    }
    var lastBox = null;
    var matches = [];
    for (var i = 0; i < boxes.length; i++) {
      var match = {};
      var box = boxes[i];
      if (box.width <= 1 || box.height <= 1 || lastBox && box.left >= lastBox.left && box.top >= lastBox.top && box.right <= lastBox.right && box.bottom <= lastBox.bottom) {
        continue;
      }
      lastBox = box;
      match.top = lastBox.top;
      match.bottom = lastBox.bottom;
      match.left = lastBox.left;
      match.right = lastBox.right;
      match.width = lastBox.right - lastBox.left;
      match.height = lastBox.bottom - lastBox.top;
      var prev = matches.length - 1;
      if (prev > -1 && matches[prev].left <= match.right && match.left <= matches[prev].right && matches[prev].top <= match.bottom && match.top <= matches[prev].bottom) {
        var newMatch = {};
        newMatch.top = Math.max(matches[prev].top, match.top);
        newMatch.bottom = Math.min(matches[prev].bottom, match.bottom);
        newMatch.left = matches[prev].left;
        newMatch.right = match.right;
        newMatch.width = newMatch.right - newMatch.left;
        newMatch.height = newMatch.bottom - newMatch.top;
        matches[prev] = newMatch;
      } else {
        matches.push(match);
      }
    }
    return matches;
  };
  function unionOfClientRects(rects) {
    if (rects == null || rects.length < 1) {
      return null;
    }
    var firstRect = rects[0];
    var rect = {top:firstRect.top, left:firstRect.left, right:firstRect.right, bottom:firstRect.bottom};
    for (var i = 1; i < rects.length; i++) {
      var currentRect = rects[i];
      if (currentRect.width > 0 && currentRect.height > 0) {
        rect = {top:Math.min(rect.top, currentRect.top), left:Math.min(rect.left, currentRect.left), right:Math.max(rect.right, currentRect.right), bottom:Math.max(rect.bottom, currentRect.bottom)};
      }
    }
    rect.width = rect.right - rect.left;
    rect.height = rect.bottom - rect.top;
    return rect;
  }
  util.range.scrollSelectionIntoView = function(editor) {
    if (!editor.inEditMode()) {
      return;
    }
    log.fine("Requesting to scroll selection into view");
    var range = editor.getRange();
    if (range) {
      var rect = unionOfClientRects(range.getBrowserRangeObject().getClientRects());
      if (!rect) {
        var node = range.getFocusNode();
        if (node && node.getClientRects) {
          rect = unionOfClientRects(node.getClientRects());
        }
      }
      if (rect) {
        var viewport = getViewPortRect(editor.config.margin);
        if (viewport.top >= rect.top && viewport.bottom <= rect.bottom) {
        } else {
          if (viewport.top > rect.top) {
            log.fine("  ... performing scrolling to TOP");
            scrollRectIntoView(rect, true, editor.config.margin);
          } else {
            if (viewport.bottom < rect.bottom) {
              log.fine("  ... performing scrolling to BOTTOM");
              scrollRectIntoView(rect, false, editor.config.margin);
            }
          }
        }
      } else {
        if (util.dom.isEmpty(editor.field)) {
          log.fine("  ... performing scrolling the editor field into view");
          editor.field.scrollIntoView();
        }
      }
    }
  };
  util.range.commonAncestors = function(range, opt_selector, opt_root) {
    var startNode = range.getStartNode();
    var endNode = range.getEndNode();
    var getNonTextOrSelectorParent = function(node) {
      if (opt_selector) {
        var selectorNode = util.dom.parent(node, opt_selector, opt_root);
        if (selectorNode !== null) {
          return selectorNode;
        }
      }
      while (util.dom.isTextNode(node)) {
        node = node.parentNode;
      }
      return node;
    };
    startNode = getNonTextOrSelectorParent(startNode);
    endNode = getNonTextOrSelectorParent(endNode);
    if (startNode === endNode) {
      return [startNode, endNode];
    }
    var startParents = util.dom.ancestors(startNode);
    var endParents = util.dom.ancestors(endNode);
    if (startParents[0] !== endParents[0]) {
      return [startNode, endNode];
    }
    var i = 0;
    for (; i < startParents.length && i < endParents.length; i++) {
      if (startParents[i] !== endParents[i]) {
        break;
      }
    }
    var result = [startNode, endNode];
    if (i < startParents.length) {
      result[0] = startParents[i];
    }
    if (i < endParents.length) {
      result[1] = endParents[i];
    }
    return result;
  };
  util.range.forEachWord = function(range, transformFunc) {
    goog.iter.forEach(range, function(element) {
      if (element.nodeType !== Node.TEXT_NODE) {
        return;
      }
      var nodeText = element.nodeValue;
      if (nodeText == null || goog.string.isEmpty(nodeText)) {
        return;
      }
      var re = new RegExp(uno.defs.regex.WORD_CHARACTER, "g");
      var match = null, matchRange = null;
      while ((match = re.exec(nodeText)) != null) {
        var matchStart = match.index;
        var matchEnd = match.index + match[0].length;
        if (element === range.getStartNode() && matchEnd <= range.getStartOffset() || element === range.getEndNode() && matchStart >= range.getEndOffset()) {
          continue;
        }
        matchRange = document.createRange();
        matchRange.setStart(element, matchStart);
        matchRange.setEnd(element, matchEnd);
        transformFunc(match[0], matchRange);
      }
    });
  };
  util.range.selectNode = function(node) {
    var range = goog.dom.Range.createFromNodes(node.parentElement, util.dom.index(node), node.parentElement, util.dom.index(node) + 1);
    range.select();
  };
  util.range.selectNodeContents = function(node) {
    var range = goog.dom.Range.createFromNodeContents(node);
    range.select();
  };
  util.range.fromInfo = function(start, end) {
    var range = document.createRange();
    range.setStart(start.container, start.offset);
    if (end != null) {
      range.setEnd(end.container, end.offset);
    }
    return goog.dom.Range.createFromBrowserRange(range);
  };
  util.range.selectFromInfo = function(start, end) {
    var range = util.range.fromInfo(start, end);
    range.select();
    return range;
  };
  util.range.boundary = function(node, offset) {
    return util.dom.isElementNode(node) ? node.childNodes[offset] : node;
  };
  util.range.containsTagNames = function(tagNames, range) {
    return util.range.queryTagNames(tagNames, range) != null;
  };
  util.range.queryTagNames = function(tagNames, range) {
    if (range == null) {
      return;
    }
    if (!Array.isArray(tagNames)) {
      tagNames = [tagNames];
    }
    var selector = tagNames.join(",");
    var container = range.getContainer();
    if (container.querySelector == null || container.querySelector(selector) == null) {
      return;
    }
    var start = util.range.boundary(range.getStartNode(), range.getStartOffset());
    var end = util.range.boundary(range.getEndNode(), range.getEndOffset());
    var walker = new util.dom.TreeWalker(start, container);
    var result;
    if (util.dom.compareTagName(start, tagNames)) {
      result = start;
    }
    while (result == null && walker.current() && walker.current() !== end) {
      if (util.dom.compareTagName(walker.current(), tagNames)) {
        result = walker.current();
      } else {
        if (walker.current().contains(end)) {
          walker.next(true);
        } else {
          if (walker.current().querySelector) {
            result = walker.current().querySelector(selector);
          }
          walker.next(false);
        }
      }
    }
    if (result == null && util.dom.compareTagName(end.tagName, tagNames)) {
      result = end;
    }
    return result;
  };
  util.range.queryTagNamesAll = function(tagNames, range) {
    if (range == null) {
      return [];
    }
    if (!Array.isArray(tagNames)) {
      tagNames = [tagNames];
    }
    var selector = tagNames.join(",");
    var container = range.getContainer();
    if (container.querySelector == null || container.querySelector(selector) == null) {
      return [];
    }
    var start = util.range.boundary(range.getStartNode(), range.getStartOffset());
    var end = util.range.boundary(range.getEndNode(), range.getEndOffset());
    var walker = new util.dom.TreeWalker(start, container);
    var results = [];
    var nodeList;
    if (util.dom.compareTagName(start, tagNames)) {
      results.push(start);
    }
    while (walker.current() && walker.current() !== end) {
      if (util.dom.compareTagName(walker.current(), tagNames)) {
        results.push(walker.current());
      }
      if (walker.current().contains(end)) {
        walker.next(true);
      } else {
        if (walker.current().querySelector) {
          nodeList = walker.current().querySelectorAll(selector);
          goog.array.forEach(nodeList, function(node) {
            results.push(node);
          });
        }
        walker.next(false);
      }
    }
    if (util.dom.compareTagName(end.tagName, tagNames)) {
      results.push(end);
    }
    return results;
  };
  util.range.saveCursor = function(range) {
    if (!range) {
      return null;
    }
    var oldCursors = document.querySelectorAll('[id^="goog"]');
    goog.array.forEach(oldCursors, goog.dom.removeNode);
    var savedRange = range.saveUsingCarets();
    var start = document.querySelector("#" + savedRange.startCaretId_);
    var end = document.querySelector("#" + savedRange.endCaretId_);
    if (start && end) {
      util.dom.changeTagName(start, "en-cursor");
      util.dom.changeTagName(end, "en-cursor");
    }
    return savedRange;
  };
  util.range.clientRectsRanges = function(textNode) {
    if (!textNode || !util.dom.isTextNode(textNode) || !textNode.textContent) {
      return [];
    }
    var parentNode = textNode.parentNode;
    var offsets = [];
    var offset = 0;
    var top = null;
    var rects = null;
    var node = textNode;
    var measureRange = document.createRange();
    parentNode.normalize();
    measureRange.selectNodeContents(node);
    rects = measureRange.getClientRects();
    if (rects.length === 0) {
      return [];
    } else {
      if (rects.length === 1) {
        return [goog.dom.Range.createFromNodes(node, 0, node, node.length)];
      }
    }
    var oldWidth = parentNode.style.width;
    parentNode.style.width = parentNode.getBoundingClientRect().width + "px";
    for (var i = node.textContent.length - 1; i >= 0; i--) {
      var sibling = node.splitText(i + 1);
      if (sibling.textContent) {
        measureRange.selectNodeContents(sibling);
        rects = measureRange.getClientRects();
        if (top !== rects[0].top) {
          top = rects[0].top;
          offsets.push(i + 2);
        }
      }
    }
    parentNode.normalize();
    parentNode.style.width = oldWidth;
    offsets.push(0);
    var ranges = [];
    for (var j = offsets.length - 1; j > 0; j--) {
      ranges.push(goog.dom.Range.createFromNodes(textNode, offsets[j], textNode, offsets[j - 1]));
    }
    return ranges;
  };
})();
goog.provide("uno.util.font.generic");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.style");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.font.generic");
  var util = uno.util;
  var generic = util.font.generic;
  generic.getSize = function(node) {
    var pxs = goog.style.getFontSize(node);
    return pxs;
  };
  generic.prepareSize = function(size) {
    if (goog.isString(size) && !isNaN(size) && !/[a-z]$/.test(size)) {
      size += "px";
    } else {
      if (typeof size === "number") {
        size += "px";
      }
    }
    return size;
  };
})();
goog.provide("uno.util.font.win");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.style");
goog.require("uno.util.font.generic");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.font.win");
  var util = uno.util;
  var generic = util.font.generic;
  var win = util.font.win;
  win.getSize = function(node) {
    var pxs = generic.getSize(node);
    var pts = util.font.pxsToPts(pxs);
    return pts;
  };
  win.prepareSize = function(size) {
    if (goog.isString(size) && !isNaN(size) && !/[a-z]$/i.test(size)) {
      size += "pt";
    } else {
      if (typeof size === "number") {
        size += "pt";
      }
    }
    return size;
  };
})();
goog.provide("uno.util.font");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.style");
goog.require("uno.util.font.generic");
goog.require("uno.util.font.win");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.font");
  var client = uno.util.font.generic;
  var util = uno.util;
  util.font.setClient = function(clientName) {
    client = uno.util.font[clientName] || client;
  };
  util.font.getSize = function(node) {
    return client.getSize(node);
  };
  util.font.getColor = function(node) {
    return goog.style.getComputedStyle(node, "color");
  };
  util.font.prepareSize = function(size) {
    return client.prepareSize(size);
  };
  util.font.sizeEquals = function(size1, size2) {
    size1 = util.font.prepareSize(size1);
    size2 = util.font.prepareSize(size2);
    if (size1 === size2) {
      return true;
    }
    if (size1.indexOf("px") > 0) {
      size1 = util.font.pxsToPts(size1) + "pt";
    }
    if (size2.indexOf("px") > 0) {
      size2 = util.font.pxsToPts(size2) + "pt";
    }
    return size1 === size2;
  };
  util.font.pxsToPts = function(pxs) {
    var div = goog.dom.createDom("div", {style:"position:absolute; top:-1000pt; height:100pt;"});
    goog.dom.append(document.body, div);
    var ratio = parseFloat(goog.style.getComputedStyle(div, "height"));
    goog.dom.removeNode(div);
    var pts = Math.round(parseFloat(pxs) * 100 / ratio);
    return pts;
  };
  util.font.normalizeFontSize = function(elem, size) {
    size = size || window.getComputedStyle(elem, null).getPropertyValue("font-size");
    elem.removeAttribute("size");
    elem.style.fontSize = size;
  };
  util.font.normalize = function(fontContainer, size) {
    util.font.normalizeFontSize(fontContainer, size);
    var ancestor = fontContainer;
    var outerFontContainer;
    while (!util.dom.isEnnote(ancestor) && ancestor.parentNode) {
      if (ancestor.tagName === "FONT") {
        outerFontContainer = ancestor;
      }
      ancestor = ancestor.parentNode;
    }
    var fontNodeList = outerFontContainer.querySelectorAll("font[size]");
    var fontContainers = Array.prototype.slice.call(fontNodeList);
    Array.prototype.forEach.call(fontContainers, function(elem) {
      util.font.normalizeFontSize(elem);
    });
  };
})();
goog.provide("uno.util.styles");
goog.require("goog.dom");
goog.require("goog.style");
goog.require("goog.array");
goog.require("goog.object");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.font");
(function() {
  var util = uno.util;
  var dom = uno.util.dom;
  var styles = util.styles;
  var highlightBackgroundColor = uno.defs.highlight.COLOR;
  var knownAttributes = /data-.*|face|border|name|href|rev|start|title|color|class/;
  var fontSizeMap = {1:"11px", 2:"12px", 3:"14px", 4:"18px", 5:"24px", 6:"36px", 7:"48px"};
  styles.createPendingStyles = function(editor) {
    editor.context.style.hasPendingStyles = true;
    editor.context.style.pendingStyles = {};
    editor.context.style.pendingStyles.state = goog.object.clone(editor.context.style.state);
    editor.context.style.pendingStyles.value = goog.object.clone(editor.context.style.value);
  };
  styles.clearPendingStyles = function(editor) {
    editor.context.style.hasPendingStyles = false;
    editor.context.style.pendingStyles = {state:{}, value:{}};
  };
  styles.toStyleObject = function(currentStyles, defaults) {
    var results = {};
    Object.keys(currentStyles || {}).forEach(function(key) {
      var value = currentStyles[key];
      if (value) {
        switch(key) {
          case "bold":
            results.bold = true;
            break;
          case "italic":
            results.italic = true;
            break;
          case "strikethrough":
            results.strikethrough = true;
            break;
          case "underline":
            results.underline = true;
            break;
          case "forecolor":
            results.color = defaults.fontColor === value ? "" : value;
            break;
          case "fontname":
            results["font-family"] = defaults.fontName === value || defaults.richTextFont === value ? "" : value;
            break;
          case "fontsize":
            var fontSize = util.font.prepareSize(value);
            results["font-size"] = util.font.sizeEquals(defaults.fontSize, fontSize) ? "" : fontSize;
            break;
          case "highlight":
            results["background-color"] = uno.defs.highlight.COLOR;
            break;
          default:
        }
      }
    });
    return results;
  };
  styles.addTempState = function(editor, name, state) {
    editor.context.hasTempStyles = true;
    editor.context.tempStyles.state[name] = state;
  };
  styles.addTempValue = function(editor, name, value) {
    editor.context.hasTempStyles = true;
    editor.context.tempStyles.value[name] = value;
  };
  styles.clearTempStyles = function(editor) {
    editor.context.hasTempStyles = false;
    editor.context.tempStyles = {state:{}, value:{}, enabled:{}};
  };
  styles.formattingForTempStyles = function(editor) {
    var tempStyles = editor.context.tempStyles;
    var result = {};
    Object.keys(tempStyles.state).forEach(function(key) {
      result[key] = tempStyles.state[key];
    });
    Object.keys(tempStyles.value).forEach(function(key) {
      result[key] = tempStyles.value[key];
    });
    return result;
  };
  styles.setInlineStyles = function(line, style, defaults) {
    var hadParent = true;
    if (dom.isTextNode(line) || dom.isImg(line)) {
      line = goog.dom.createDom("span", null, line);
      hadParent = false;
    }
    var fontNode = document.createElement("font");
    var node = goog.dom.findNode(line, function(n) {
      return dom.isTextNode(n) || dom.isImg(n);
    });
    if (!node) {
      return line;
    }
    var nodeWrapper = node.parentNode;
    if (style.state.bold) {
      node = goog.dom.createDom("b", null, node);
    }
    if (style.state.italic) {
      node = goog.dom.createDom("i", null, node);
    }
    if (style.state.underline) {
      node = goog.dom.createDom("u", null, node);
    }
    if (style.state.strikethrough) {
      node = goog.dom.createDom("strike", null, node);
    }
    if (style.state.subscript) {
      node = goog.dom.createDom("sub", null, node);
    }
    if (style.state.superscript) {
      node = goog.dom.createDom("sup", null, node);
    }
    if (style.state.highlight) {
      goog.style.setStyle(fontNode, "backgroundColor", highlightBackgroundColor);
    }
    if (!util.font.sizeEquals(style.value.fontsize, defaults.fontSize)) {
      goog.style.setStyle(fontNode, "fontSize", util.font.prepareSize(style.value.fontsize));
    }
    if (style.value.forecolor !== defaults.foreColor) {
      goog.style.setStyle(fontNode, "color", style.value.forecolor);
    }
    var regex = "^(normal|-webkit-standard|" + defaults.fontFamily + "|" + defaults.richTextFont + ")$";
    var fontFamilyRegex = new RegExp(regex, "i");
    if (!fontFamilyRegex.test(style.value.fontname)) {
      goog.style.setStyle(fontNode, "fontFamily", style.value.fontname);
    }
    if (fontNode.getAttribute("style")) {
      fontNode.appendChild(node);
      node = fontNode;
    }
    nodeWrapper.appendChild(node);
    return hadParent ? line : line.firstChild;
  };
  styles.mergeAttributes = function(fromNode, toNode, skipTagName, options) {
    options = options || {};
    if (options.allowedStyles) {
      options.allowedStyles = new RegExp("^(" + options.allowedStyles + ")$");
    }
    if (options.disallowedStyles) {
      options.disallowedStyles = new RegExp("^(" + options.disallowedStyles + ")$");
    }
    if (options.allowedAttrs) {
      options.allowedAttrs = new RegExp("^(" + options.allowedAttrs + ")$");
    }
    if (options.disallowedAttrs) {
      options.disallowedAttrs = new RegExp("^(" + options.disallowedAttrs + ")$");
    }
    var fromAttributes = fromNode.attributes || [];
    var toAttributes = toNode.attributes || [];
    var finalAttributes = {};
    if (dom.isTextNode(toNode)) {
      return;
    }
    styles.convertAttributesToStyle(fromNode);
    styles.convertAttributesToStyle(toNode);
    goog.array.forEach(goog.array.toArray(fromAttributes), function(attr) {
      if (attr.name !== "style" && knownAttributes.test(attr.name)) {
        finalAttributes[attr.name] = attr.value;
      }
    });
    goog.array.forEach(goog.array.toArray(toAttributes), function(attr) {
      if (attr.name !== "style") {
        if (knownAttributes.test(attr.name)) {
          finalAttributes[attr.name] = attr.value;
        }
        toNode.removeAttribute(attr.name);
      }
    });
    var fromStyle = styles.getNodeStyle(fromNode, skipTagName);
    var toStyle = styles.getNodeStyle(toNode, skipTagName);
    var finalStyle = {};
    Object.keys(fromStyle).forEach(function(key) {
      if (options.disallowedStyles && options.disallowedStyles.test(key)) {
        return;
      }
      if (options.allowedStyles && !options.allowedStyles.test(key)) {
        return;
      }
      finalStyle[key] = fromStyle[key];
    });
    Object.keys(toStyle).forEach(function(key) {
      if (options.disallowedStyles && options.disallowedStyles.test(key)) {
        return;
      }
      if (options.allowedStyles && !options.allowedStyles.test(key)) {
        return;
      }
      finalStyle[key] = toStyle[key];
    });
    var styleString = styles.getStyleString(finalStyle);
    if (styleString) {
      toNode.setAttribute("style", styleString);
    } else {
      if (dom.isElementNode(toNode)) {
        toNode.removeAttribute("style");
      }
    }
    Object.keys(finalAttributes).forEach(function(key) {
      if (options.disallowedAttrs && options.disallowedAttrs.test(key)) {
        return;
      }
      if (options.allowedAttrs && !options.allowedAttrs.test(key)) {
        return;
      }
      toNode.setAttribute(key, finalAttributes[key]);
    });
  };
  styles.getNodeStyle = function(node, skipTagName) {
    if (!node || dom.isTextNode(node)) {
      return {};
    }
    var styleAttribute = node.getAttribute("style");
    styleAttribute = styleAttribute ? styleAttribute.split(";") : [];
    styleAttribute = styleAttribute.filter(function(style) {
      return style.trim() || false;
    }).map(function(style) {
      var styleObject = style.split(":");
      var name = styleObject[0] ? styleObject[0].trim() : "";
      var value = styleObject[1] ? styleObject[1].trim() : "";
      return {name:name, value:value};
    });
    var style = {};
    if (!skipTagName) {
      var tagName = node.tagName.toLowerCase();
      if (tagName === "b" || tagName === "strong") {
        style.bold = true;
      } else {
        if (tagName === "i" || tagName === "em") {
          style.italic = true;
        } else {
          if (tagName === "u" || tagName === "ins") {
            style.underline = true;
          } else {
            if (tagName === "strike" || tagName === "s" || tagName === "del") {
              style.strikethrough = true;
            } else {
              if (tagName === "sub") {
                style.subscript = true;
              } else {
                if (tagName === "sup") {
                  style.superscript = true;
                }
              }
            }
          }
        }
      }
    }
    styleAttribute.forEach(function(attr) {
      if (attr.name === "font-weight") {
        var value = parseInt(attr.value, 10);
        if (attr.value === "bold") {
          style.bold = true;
        } else {
          if (attr.value === "normal") {
            style.bold = false;
          } else {
            if (!isNaN(value)) {
              style.bold = value >= 500;
            }
          }
        }
      } else {
        if (attr.name === "font-style") {
          if (["italic", "oblique"].indexOf(attr.value) > -1) {
            style.italic = true;
          }
        } else {
          if (attr.name === "text-decoration") {
            if (attr.value.indexOf("line-through") > -1) {
              style.strikethrough = true;
            }
            if (attr.value.indexOf("underline") > -1) {
              style.underline = true;
            }
          } else {
            if (attr.name === "vertical-align" && ["top", "bottom", "middle"].indexOf(attr.value) === -1) {
              if (["sub"].indexOf(attr.value) > -1) {
                style.subscript = true;
              }
              if (["super"].indexOf(attr.value) > -1) {
                style.superscript = true;
              }
            } else {
              var supportedStyle = ".*";
              var regex = new RegExp("^(" + supportedStyle + ")$");
              if (regex.test(attr.name)) {
                style[attr.name] = attr.value;
              }
            }
          }
        }
      }
    });
    return style;
  };
  styles.convertAttributesToStyle = function(node) {
    if (dom.isTextNode(node)) {
      return;
    }
    if (node.attributes.face) {
      var face = node.attributes.face.value;
      var fontFamily = goog.style.getStyle(node, "font-family");
      node.removeAttribute("face");
      if (!fontFamily) {
        goog.style.setStyle(node, "font-family", face);
      }
    }
    if (node.attributes.color) {
      var color = node.attributes.color.value;
      var fontColor = goog.style.getStyle(node, "color");
      node.removeAttribute("color");
      if (!fontColor) {
        goog.style.setStyle(node, "color", color);
      }
    }
    if (node.attributes.size) {
      var size = node.attributes.size.value;
      var fontSize = goog.style.getStyle(node, "font-size");
      node.removeAttribute("size");
      if (!fontSize) {
        goog.style.setStyle(node, "font-size", fontSizeMap[size]);
      }
    }
  };
  styles.getStyleString = function(nodeStyles) {
    var finalStyle = "";
    var textDecoration = "";
    Object.keys(nodeStyles).forEach(function(key) {
      var style = nodeStyles[key];
      if (style === "inherit" || style === "initial") {
        return;
      }
      if (key === "bold") {
        if (style) {
          finalStyle += "font-weight: bold; ";
        }
      } else {
        if (key === "background-color") {
          if (style !== "transparent") {
            finalStyle += "background-color: " + style + "; ";
          }
        } else {
          if (key === "italic") {
            finalStyle += "font-style: italic; ";
          } else {
            if (key === "underline") {
              textDecoration += "underline ";
            } else {
              if (key === "strikethrough") {
                textDecoration += "line-through ";
              } else {
                if (key === "superscript") {
                  finalStyle += "vertical-align: super; font-size: smaller; ";
                } else {
                  if (key === "subscript") {
                    finalStyle += "vertical-align: sub; font-size: smaller; ";
                  } else {
                    if (style) {
                      finalStyle += key + ": " + style + "; ";
                    }
                  }
                }
              }
            }
          }
        }
      }
    });
    if (textDecoration) {
      finalStyle += "text-decoration: " + textDecoration.trim() + "; ";
    }
    return finalStyle.trim();
  };
  styles.getNoteWidth = function(element) {
    if (!dom.isEnnote(element)) {
      element = document.querySelector(uno.defs.containers.EDITOR_BODY_SELECTOR);
    }
    if (!element) {
      return null;
    }
    var computedStyle = window.getComputedStyle(element);
    var padding = parseInt(computedStyle.paddingLeft, 10) * 2;
    return element.getBoundingClientRect().width - (isNaN(padding) ? 0 : padding);
  };
  styles.getDevicePixelRatio = function() {
    if ("devicePixelRatio" in window) {
      return window.devicePixelRatio;
    } else {
      if (window.matchMedia) {
        var testDensity = function(density) {
          var mediaQuery = ["-webkit-min", "min--moz", "min"].map(function(prefix) {
            return "(" + prefix + "device-pixel-ratio: " + density + ")";
          }).concat("(min-resolution: " + density + "dppx)").join(",");
          return !!window.matchMedia(mediaQuery).matches;
        };
        if (testDensity("2")) {
          return 2;
        } else {
          if (testDensity("1.5")) {
            return 1.5;
          } else {
            if (testDensity("1")) {
              return 1;
            } else {
              if (testDensity("0.75")) {
                return 0.75;
              }
            }
          }
        }
      }
    }
    return 1;
  };
  styles.hasInlineStyle = function(node) {
    var styleText = node.getAttribute("style");
    if (styleText == null || styleText === "") {
      return false;
    }
    var style = node.style;
    var inlineStyles = styles.inlineStyles;
    var result = Object.keys(style).some(function(key) {
      return isNaN(key) && style.hasOwnProperty(key) && style[key] !== "" && inlineStyles.indexOf(key) !== -1;
    });
    return result;
  };
  styles.hasLayoutStyle = function(node) {
    var styleText = node.getAttribute("style");
    if (styleText == null || styleText === "") {
      return false;
    }
    var style = node.style;
    var inlineStyles = styles.inlineStyles;
    var result = Object.keys(style).some(function(key) {
      return isNaN(key) && style.hasOwnProperty(key) && style[key] !== "" && (inlineStyles.indexOf(key) === -1 || key === "backgroundColor" || key === "fontSize");
    });
    return result;
  };
  styles.inlineStyles = ["alignmentBaseline", "backgroundColor", "baselineShift", "bottom", "breakAfter", "breakBefore", "breakInside", "color", "dominantBaseline", "fill", "fillOpacity", "fillRule", "fontFamily", "fontFeatureSettings", "fontKerning", "fontSize", "fontStretch", "fontStyle", "fontVariant", "fontVariantCaps", "fontVariantLigatures", "fontVariantNumeric", "fontWeight", "lineHeight", "textDecoration", "textDecorationColor", "textDecorationLine", "textDecorationSkip", "textDecorationStyle"];
})();
goog.provide("uno.util.table");
goog.require("goog.array");
goog.require("goog.color");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.editor.node");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("goog.object");
goog.require("goog.style");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.observer");
goog.require("uno.util.range");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.table");
  var util = uno.util;
  var defs = uno.defs.table;
  var measureTable = null;
  var activeTable = null;
  var activeCell = null;
  var queryCache = null;
  util.table.State = {SELECTED:1 << 0, WHOLE_SELECTED:1 << 1, DRAGGABLE:1 << 2, MERGED:1 << 3, MERGE_CANDIDATE:1 << 4};
  util.table.Axis = {HORIZONTAL:"x", VERTICAL:"y"};
  util.table.for = function(node) {
    return goog.dom.getAncestor(node, util.dom.isTable, true);
  };
  util.table.getParagraphs = function(table) {
    return util.table.cellsForNode(table);
  };
  util.table.cellsForRange = function(range) {
    var td = goog.dom.getAncestor(range.getContainer(), util.dom.isTd, true);
    if (td) {
      return [td];
    }
    var tds = [];
    goog.iter.forEach(goog.iter.filter(range, function(node, _, iter) {
      return iter.isStartTag() && uno.util.dom.isTd(node);
    }), function(node) {
      tds.push(node);
    });
    return tds;
  };
  util.table.cellsForNode = function(root) {
    if (!root) {
      return [];
    }
    var table = null;
    if (util.dom.isTable(root)) {
      table = root;
    } else {
      if (util.dom.isEntable(root)) {
        table = util.table.query_(root, "table");
      } else {
        table = root.querySelector("table");
      }
    }
    if (!table) {
      return [];
    }
    return [].concat.apply([], goog.array.map(table.rows, function(row) {
      return [].slice.call(row.children);
    }));
  };
  util.table.upCell = function(node) {
    var td = goog.dom.getAncestor(node, util.dom.isTd, true);
    if (!td) {
      return null;
    }
    var matrix = util.table.matrix(goog.dom.getAncestor(td, util.dom.isTable));
    var info = util.table.infoForCell(td, matrix);
    return info.startRowIndex === 0 ? null : matrix[info.startRowIndex - 1][info.startColIndex].info.node;
  };
  util.table.downCell = function(node) {
    var td = goog.dom.getAncestor(node, util.dom.isTd, true);
    if (!td) {
      return null;
    }
    var matrix = util.table.matrix(goog.dom.getAncestor(td, util.dom.isTable));
    var info = util.table.infoForCell(td, matrix);
    return info.endRowIndex < matrix.length - 1 ? matrix[info.endRowIndex + 1][info.startColIndex].info.node : null;
  };
  util.table.prevCell = function(node, navigateByDOM) {
    return prevNextCell(node, navigateByDOM, -1);
  };
  util.table.nextCell = function(node, navigateByDOM) {
    return prevNextCell(node, navigateByDOM, 1);
  };
  util.table.darkenBorderColor = function(backgroundColor) {
    var obj = goog.color.parse(backgroundColor);
    var rgb = obj.type === "rgb" ? backgroundColor : goog.color.hexToRgb(obj.hex);
    return goog.color.rgbToHex.apply(goog.color, goog.color.darken(rgb, 0.2));
  };
  util.table.create = function(options) {
    options = options || {};
    options.rows = options.rows || 2;
    options.columns = options.columns || 2;
    options.align = options.align || "left";
    var bgColor = goog.color.isValidColor(options.cellColor || "") ? goog.color.parse(options.cellColor).hex : null;
    var borderColor = options.borderColor !== defs.BORDER_COLOR && goog.color.isValidColor(options.borderColor || "") ? options.borderColor : null;
    if (bgColor && !borderColor) {
      borderColor = util.table.darkenBorderColor(bgColor);
    }
    var colgroup = document.createElement("colgroup");
    var tbody = document.createElement("tbody");
    var width = "width: " + defs.CELL_WIDTH + "px;";
    var style = [borderColor && "border-color: " + borderColor, bgColor && "background-color: " + bgColor].filter(Boolean).join("; ");
    var table = goog.dom.createDom("table", null, [colgroup, tbody]);
    table.compat = true;
    for (var rowIndex = 0; rowIndex < options.rows; rowIndex++) {
      var tr = document.createElement("tr");
      tbody.appendChild(tr);
      for (var colIndex = 0; colIndex < options.columns; colIndex++) {
        if (rowIndex === 0) {
          colgroup.appendChild(goog.dom.createDom("col", {style:width}));
        }
        tr.appendChild(util.table.createEmptyTd({style:style}));
      }
    }
    util.table.setAlignment(table, options.align);
    return util.table.attachAdornments(table);
  };
  util.table.delete = function(target) {
    var isEntable = util.dom.isEntable(target);
    if (!isEntable && !util.dom.isTable(target) || !target.parentNode) {
      return false;
    }
    if (isEntable && util.table.getActive() === target) {
      util.table.setActive(null);
    }
    var tableIndex = util.dom.index(target);
    var tableParent = target.parentElement;
    goog.dom.removeNode(target);
    goog.dom.Range.createCaret(tableParent, tableIndex).select();
    return true;
  };
  util.table.getAlignment = function(table) {
    var marginLeft = table.style.marginLeft;
    var marginRight = table.style.marginRight;
    if (marginLeft === "auto" && marginRight === "auto") {
      return "center";
    } else {
      if (marginLeft === "auto") {
        return "right";
      }
    }
    return "left";
  };
  util.table.setAlignment = function(table, align) {
    table.style.marginLeft = align === "left" ? "" : "auto";
    table.style.marginRight = align === "center" ? "auto" : "";
  };
  util.table.createEmptyTd = function(attrs) {
    var td = goog.dom.createDom("td");
    attrs = attrs || {};
    if (attrs.style) {
      td.setAttribute("style", attrs.style);
    }
    if (attrs.class) {
      td.setAttribute("class", attrs.class);
    }
    if (attrs.colSpan > 1) {
      util.table.setColSpan(td, attrs.colSpan);
    }
    if (attrs.rowSpan > 1) {
      util.table.setRowSpan(td, attrs.rowSpan);
    }
    td.innerHTML = defs.CELL_HTML;
    return td;
  };
  util.table.insertTd = function(node, rowIndex, colIndex, table, optMatrix) {
    var matrix = optMatrix || util.table.matrix(table);
    var refNode = null;
    var info;
    while (info = (matrix[rowIndex][colIndex] || {}).info) {
      if (info.startRowIndex !== rowIndex || info.startColIndex !== colIndex) {
        colIndex = info.endColIndex + 1;
      } else {
        refNode = info.node;
        break;
      }
    }
    table.rows[rowIndex].insertBefore(node, refNode);
  };
  util.table.insertColumns = function(target, index, count) {
    var colgroup = util.table.query_(target, "colgroup");
    if (index < 0 || index > colgroup.children.length) {
      return false;
    }
    var isEntable = util.dom.isEntable(target);
    var table = isEntable ? util.table.query_(target, "table") : target;
    var matrix = util.table.matrix(table);
    var colIndex = Math.max(index - 1, 0);
    var refCol = colgroup.children[index] || null;
    var col = colgroup.children[colIndex];
    count = count || 1;
    for (var i = count; i > 0; i--) {
      colgroup.insertBefore(col.cloneNode(), refCol);
    }
    matrix.forEach(function(row, rowIndex) {
      var info = row[colIndex].info;
      var cell = info.node;
      if (info.startRowIndex !== rowIndex) {
        return;
      }
      if (index !== colIndex && info.startColIndex < index && info.endColIndex >= index) {
        util.table.setColSpan(cell, cell.colSpan + count);
        return;
      }
      for (var j = count; j > 0; j--) {
        var newTd = util.table.createEmptyTd({style:cell.getAttribute("style"), rowSpan:cell.rowSpan});
        util.table.insertTd(newTd, rowIndex, index, table, matrix);
      }
    });
    if (isEntable) {
      util.table.normalizeCellBorders(table);
      util.table.layout(target);
    }
    return true;
  };
  util.table.insertRows = function(target, index, count) {
    var isEntable = util.dom.isEntable(target);
    var table = isEntable ? util.table.query_(target, "table") : target;
    if (index < 0 || index > table.rows.length) {
      return false;
    }
    var matrix = util.table.matrix(table);
    var rowIndex = Math.max(index - 1, 0);
    var tbody = table.rows[0].parentElement;
    var refRow = table.rows[index] || null;
    count = count || 1;
    for (var c = count; c > 0; c--) {
      var newRow = goog.dom.createDom("tr");
      tbody.insertBefore(newRow, refRow);
      matrix[rowIndex].forEach(function(obj, colIndex) {
        var info = obj.info;
        var cell = info.node;
        if (info.startColIndex !== colIndex) {
          return;
        }
        if (index !== rowIndex && info.startRowIndex < index && info.endRowIndex >= index) {
          util.table.setRowSpan(cell, cell.rowSpan + count);
          return;
        }
        var newTd = util.table.createEmptyTd({style:cell.getAttribute("style"), colSpan:cell.colSpan});
        newTd.style.height = "";
        newRow.appendChild(newTd);
      });
    }
    if (isEntable) {
      util.table.normalizeCellBorders(table);
      util.table.updateAdornments(target, util.table.Axis.HORIZONTAL);
      util.table.layoutMenuButton();
    }
    return true;
  };
  util.table.deleteColumns = function(target, indexes) {
    var isEntable = util.dom.isEntable(target);
    var table = isEntable ? util.table.query_(target, "table") : target;
    if (!table || !indexes || indexes.length === 0) {
      return false;
    }
    var matrix = util.table.matrix(table);
    indexes = processDeleteIndexes(indexes, 0, matrix[0].length - 1);
    if (!indexes) {
      return false;
    }
    if (indexes.length === matrix[0].length) {
      return util.table.delete(target);
    }
    var cols = util.table.query_(target, "colgroup").children;
    indexes.forEach(function(colIndex) {
      matrix.forEach(function(row, rowIndex) {
        var info = row[colIndex].info;
        var td = info.node;
        if (info.startRowIndex === rowIndex) {
          if (info.startColIndex === colIndex) {
            if (td.colSpan > 1) {
              util.table.setColSpan(td, td.colSpan - 1);
              util.table.insertTd(td, rowIndex, colIndex + 1, table, matrix);
            } else {
              td.remove();
            }
          } else {
            util.table.setColSpan(td, td.colSpan - 1);
          }
        }
        row.splice(colIndex, 1);
      });
      cols[colIndex].remove();
    });
    if (isEntable) {
      util.table.normalizeCellBorders(table);
      util.table.layout(target);
    }
    return true;
  };
  util.table.deleteRows = function(target, indexes) {
    var isEntable = util.dom.isEntable(target);
    var table = isEntable ? util.table.query_(target, "table") : target;
    if (!table || !indexes || indexes.length === 0) {
      return false;
    }
    var matrix = util.table.matrix(table);
    indexes = processDeleteIndexes(indexes, 0, matrix.length - 1);
    if (!indexes) {
      return false;
    }
    if (indexes.length === matrix.length) {
      return util.table.delete(target);
    }
    indexes.forEach(function(rowIndex) {
      matrix[rowIndex].forEach(function(obj, colIndex) {
        var info = obj.info;
        var td = info.node;
        if (info.startColIndex === colIndex) {
          if (info.startRowIndex === rowIndex) {
            if (td.rowSpan > 1) {
              util.table.setRowSpan(td, td.rowSpan - 1);
              util.table.insertTd(td, rowIndex + 1, colIndex, table, matrix);
            } else {
              td.remove();
            }
          } else {
            util.table.setRowSpan(td, td.rowSpan - 1);
          }
        }
      });
      table.rows[rowIndex].remove();
      matrix.splice(rowIndex, 1);
    });
    if (isEntable) {
      util.table.normalizeCellBorders(table);
      util.table.updateAdornments(target, util.table.Axis.HORIZONTAL);
      util.table.layoutMenuButton();
    }
    return true;
  };
  util.table.mergeable = function(nodes, optMatrix) {
    if (nodes.length <= 1) {
      return false;
    }
    var matrix = optMatrix || util.table.matrix(goog.dom.getAncestor(nodes[0], util.dom.isTable));
    var infos = util.table.infosForMerge(nodes, matrix);
    return !!infos;
  };
  util.table.unmergeable = function(nodes) {
    for (var i = 0, l = nodes.length; i < l; i++) {
      if (nodes[i].rowSpan > 1 || nodes[i].colSpan > 1) {
        return true;
      }
    }
    return false;
  };
  util.table.mergeCells = function(nodes, optMatrix) {
    if (nodes.length <= 1) {
      return null;
    }
    var table = goog.dom.getAncestor(nodes[0], util.dom.isTable);
    var matrix = optMatrix || util.table.matrix(table);
    var infos = util.table.infosForMerge(nodes, matrix);
    if (!infos) {
      return null;
    }
    var firstInfo = infos[0];
    var targetCell = firstInfo.node;
    var empty = util.dom.isEmpty(targetCell);
    var colSpan = 1;
    var rowSpan = 1;
    infos.forEach(function(info) {
      var cell = info.node;
      if (!cell.parentNode || cell === targetCell) {
        return;
      }
      colSpan = Math.max(info.endColIndex - firstInfo.startColIndex + 1, colSpan);
      rowSpan = Math.max(info.endRowIndex - firstInfo.startRowIndex + 1, rowSpan);
      goog.dom.removeNode(cell);
      if (util.dom.isEmpty(cell)) {
        return;
      }
      if (empty) {
        empty = false;
        targetCell.innerHTML = cell.innerHTML;
      } else {
        var lastTargetChild = targetCell.lastChild;
        var lastMovedChild = null;
        goog.array.forEachRight(cell.childNodes, function(child) {
          lastTargetChild.parentNode.insertBefore(child, lastTargetChild.nextSibling);
          lastMovedChild = child;
        });
        if (util.dom.isInlineNode(lastTargetChild) && util.dom.isInlineNode(lastMovedChild)) {
          lastTargetChild.parentNode.insertBefore(document.createTextNode(" "), lastTargetChild.nextSibling);
        }
      }
    });
    util.table.setColSpan(targetCell, colSpan);
    util.table.setRowSpan(targetCell, rowSpan);
    var enTable = goog.dom.getAncestor(table, util.dom.isEntable);
    if (enTable) {
      util.table.normalizeCellBorders(table);
      util.table.layout(enTable);
    }
    return targetCell;
  };
  util.table.splitCell = function(node, optMatrix) {
    if (node.rowSpan <= 1 && node.colSpan <= 1) {
      return [node];
    }
    var table = goog.dom.getAncestor(node, util.dom.isTable);
    var matrix = optMatrix || util.table.matrix(table);
    var info = util.table.infoForCell(node, matrix);
    var nodes = [node];
    node.style.height = "";
    var style = node.getAttribute("style");
    for (var i = 0; i < node.rowSpan; i++) {
      for (var j = 0; j < node.colSpan; j++) {
        if (i > 0 || j > 0) {
          var newTd = util.table.createEmptyTd({style:style});
          nodes.push(newTd);
          util.table.insertTd(newTd, info.startRowIndex + i, info.startColIndex + j, table, matrix);
        }
      }
    }
    util.table.setColSpan(node, 1);
    util.table.setRowSpan(node, 1);
    var enTable = goog.dom.getAncestor(table, util.dom.isEntable);
    if (enTable) {
      util.table.normalizeCellBorders(table);
    }
    return nodes;
  };
  util.table.splitCells = function(tds) {
    if (tds.length === 0) {
      return [];
    }
    var nodes = [];
    goog.array.forEach(tds, function(td) {
      nodes = nodes.concat(util.table.splitCell(td));
    });
    return nodes;
  };
  util.table.setColSpan = function(td, value) {
    if (td.colSpan !== value) {
      if (value > 1) {
        td.colSpan = value;
      } else {
        td.removeAttribute("colspan");
      }
    }
  };
  util.table.setRowSpan = function(td, value) {
    if (td.rowSpan !== value) {
      if (value > 1) {
        td.rowSpan = value;
        td.style.height = (value * 2 - 2) * defs.CELL_PADDING + value * defs.CELL_LINE_HEIGHT + "px";
      } else {
        td.removeAttribute("rowspan");
        td.style.height = "";
      }
    }
  };
  util.table.cellForStructureChange = function(range) {
    if (!range) {
      return null;
    }
    var cell = util.table.getActiveCell();
    if (cell) {
      return cell;
    }
    var table = null;
    var nested = false;
    var node = range.getStartNode();
    while (node && node.parentNode) {
      if (util.dom.isTable(node)) {
        if (table) {
          nested = true;
          break;
        }
        table = node;
      } else {
        if (util.dom.isTd(node)) {
          cell = node;
        }
      }
      node = node.parentNode;
    }
    if (nested || !cell || goog.dom.getAncestor(range.getEndNode(), util.dom.isTable) !== table) {
      return null;
    }
    return cell;
  };
  util.table.matrix = function(table, opt) {
    opt = opt || {selection:false};
    if (util.dom.isEntable(table)) {
      table = util.table.query_(table, "table");
    }
    if (!util.dom.isTable(table)) {
      return null;
    }
    var matrix = [];
    var rowCount = table.rows.length;
    var getWithDefault = function(arr, index, def) {
      var obj = arr[index];
      if (!obj) {
        obj = def;
        arr[index] = obj;
      }
      return obj;
    };
    goog.array.forEach(table.rows, function(tr, trIndex) {
      var row = getWithDefault(matrix, trIndex, []);
      var colIndex = 0;
      goog.array.forEach(tr.children, function(td, tdIndex) {
        var colSpan = td.colSpan;
        var rowSpan = Math.min(rowCount - trIndex, td.rowSpan);
        while (row[colIndex]) {
          colIndex += 1;
        }
        var info = {startRowIndex:trIndex, endRowIndex:trIndex + rowSpan - 1, startColIndex:colIndex, endColIndex:colIndex + colSpan - 1, nodeRowIndex:trIndex, nodeColIndex:tdIndex, node:td, state:0};
        if (opt.selection && td.classList.contains("selected")) {
          info.state |= util.table.State.SELECTED;
        }
        if (rowSpan > 1 || colSpan > 1) {
          info.state |= util.table.State.MERGED;
        }
        var obj = getWithDefault(row, tdIndex, {});
        obj.origin = info;
        for (var c = colSpan; c > 0; c--) {
          obj = getWithDefault(row, colIndex, {});
          obj.info = info;
          for (var r = 1; r < rowSpan; r++) {
            var nextRow = getWithDefault(matrix, trIndex + r, []);
            obj = getWithDefault(nextRow, colIndex, {});
            obj.info = info;
          }
          colIndex += 1;
        }
      });
    });
    return matrix;
  };
  util.table.rowIndex = function(td, next, optMatrix) {
    var info = util.table.infoForCell(td, optMatrix);
    return next ? info.endRowIndex + 1 : info.startRowIndex;
  };
  util.table.colIndex = function(td, next, optMatrix) {
    var info = util.table.infoForCell(td, optMatrix);
    return next ? info.endColIndex + 1 : info.startColIndex;
  };
  util.table.infoForCell = function(td, optMatrix) {
    if (!util.dom.isTd(td)) {
      return null;
    }
    var matrix = optMatrix || util.table.matrix(goog.dom.getAncestor(td, util.dom.isTable));
    var info = matrix[util.dom.index(td.parentNode)][util.dom.index(td)].origin;
    if (!info || info.node !== td) {
      throw new Error("Failed to get info object for a td", td, matrix);
    }
    return info;
  };
  util.table.infosForMerge = function(tds, matrix) {
    if (tds.length <= 1) {
      return null;
    }
    var startRowIndex = Infinity;
    var startColIndex = Infinity;
    var endRowIndex = 0;
    var endColIndex = 0;
    var infos = [];
    var info;
    tds.forEach(function(cell) {
      info = util.table.infoForCell(cell, matrix);
      startRowIndex = Math.min(info.startRowIndex, startRowIndex);
      startColIndex = Math.min(info.startColIndex, startColIndex);
      endRowIndex = Math.max(info.endRowIndex, endRowIndex);
      endColIndex = Math.max(info.endColIndex, endColIndex);
      info.state |= util.table.State.MERGE_CANDIDATE;
    });
    for (var rowIndex = startRowIndex; rowIndex <= endRowIndex; rowIndex++) {
      for (var colIndex = startColIndex; colIndex <= endColIndex; colIndex++) {
        info = matrix[rowIndex][colIndex].info;
        if (!(info.state & util.table.State.MERGE_CANDIDATE)) {
          return null;
        }
        if (info.startRowIndex === rowIndex && info.startColIndex === colIndex) {
          infos.push(info);
        }
      }
    }
    return infos;
  };
  util.table.expandIntoRectIndexes = function(matrix, startRowIndex, endRowIndex, startColIndex, endColIndex) {
    loop: while (true) {
      for (var rowIndex = startRowIndex; rowIndex <= endRowIndex; rowIndex++) {
        for (var colIndex = startColIndex; colIndex <= endColIndex; colIndex++) {
          var info = matrix[rowIndex][colIndex].info;
          if (info.startRowIndex < startRowIndex || info.startColIndex < startColIndex || info.endRowIndex > endRowIndex || info.endColIndex > endColIndex) {
            startRowIndex = Math.min(info.startRowIndex, startRowIndex);
            startColIndex = Math.min(info.startColIndex, startColIndex);
            endRowIndex = Math.max(info.endRowIndex, endRowIndex);
            endColIndex = Math.max(info.endColIndex, endColIndex);
            continue loop;
          }
        }
      }
      break;
    }
    return {startRowIndex:startRowIndex, endRowIndex:endRowIndex, startColIndex:startColIndex, endColIndex:endColIndex};
  };
  util.table.isProcessedRange = function(range, rangeState) {
    return range && rangeState && range.isCollapsed() === rangeState.isCollapsed && range.getStartNode() === rangeState.startNode && range.getEndNode() === rangeState.endNode;
  };
  util.table.processRange = function(range, noteEnTables, source) {
    var startNode = range.getStartNode();
    var endNode = range.getEndNode();
    var isCollapsed = range.isCollapsed();
    var isMulticlick = source === "multiclick";
    var isArrowSelection = source === "arrowkey";
    var startAncestor = goog.dom.getAncestor(startNode, util.dom.isEntable, true);
    var endAncestor = goog.dom.getAncestor(endNode, util.dom.isEntable, true);
    var enTable = startAncestor && startAncestor === endAncestor ? startAncestor : null;
    if (isArrowSelection) {
      enTable = goog.dom.getAncestor(range.getAnchorNode(), util.dom.isEntable, true);
    }
    var cell = enTable ? goog.dom.getAncestor(range.getAnchorNode(), util.dom.isTd, true) : null;
    if (!cell) {
      enTable = null;
    }
    if (!enTable && (startAncestor || endAncestor)) {
      var newStartNode = null;
      var newStartOffset = 0;
      var newEndNode = null;
      var newEndOffset = 0;
      if (startAncestor && startAncestor !== startNode) {
        newStartNode = startAncestor;
        newStartOffset = 0;
      } else {
        newStartNode = startNode;
        newStartOffset = range.getStartOffset();
      }
      if (endAncestor && endAncestor !== endNode) {
        newEndNode = endAncestor;
        newEndOffset = endAncestor.childNodes.length;
      } else {
        newEndNode = endNode;
        newEndOffset = range.getEndOffset();
      }
      if (newStartNode) {
        if (range.isReversed()) {
          goog.dom.Range.createFromNodes(newEndNode, newEndOffset, newStartNode, newStartOffset).select();
        } else {
          goog.dom.Range.createFromNodes(newStartNode, newStartOffset, newEndNode, newEndOffset).select();
        }
        range = goog.dom.Range.createFromWindow();
        startNode = range.getStartNode();
        endNode = range.getEndNode();
      }
    }
    var isSelection = false;
    var focusCell = undefined;
    if (enTable && cell && !range.isCollapsed()) {
      var tmpFocusCell = goog.dom.getAncestor(range.getFocusNode(), util.dom.isTd, true);
      if (cell !== tmpFocusCell) {
        var nextCell = util.table.nextCell(cell);
        if (isMulticlick && nextCell === tmpFocusCell && range.getFocusOffset() === 0) {
          var node = range.getFocusNode();
          while (node && node !== tmpFocusCell) {
            node = node.previousSibling ? null : node.parentNode;
          }
          if (node) {
            tmpFocusCell = cell;
          }
        }
        focusCell = tmpFocusCell;
        isSelection = true;
      }
    }
    goog.array.forEach(noteEnTables, function(node) {
      var contained = range.containsNode(node, true);
      if (enTable || !contained) {
        node.classList.remove("selected");
      } else {
        if (contained) {
          node.classList.add("selected");
        }
      }
    });
    return {startNode:startNode, endNode:endNode, isCollapsed:isCollapsed, isSelection:isSelection, enTable:enTable, cell:cell, focusCell:focusCell};
  };
  util.table.createKeyState = function(enTable, cell, event) {
    return {scrollLeft:util.table.query_(enTable, ".container").scrollLeft, keyCode:event.keyCode, shiftKey:event.shiftKey, cell:cell, enTable:enTable};
  };
  util.table.navigateByKeyState = function(keyState) {
    if (keyState.shiftKey) {
      return false;
    }
    var KeyCodes = goog.events.KeyCodes;
    var atEnd = false;
    var isCell = true;
    var targetNode;
    var getTableSibling = function(enTable, fnName) {
      var node = enTable[fnName];
      while (node && node.childNodes.length === 0) {
        node = node[fnName];
      }
      return enTable === node ? null : node;
    };
    if (keyState.keyCode === KeyCodes.UP) {
      targetNode = util.table.upCell(keyState.cell);
      atEnd = true;
      if (!targetNode) {
        isCell = false;
        targetNode = getTableSibling(keyState.enTable, "previousSibling");
      }
    } else {
      if (keyState.keyCode === KeyCodes.DOWN) {
        targetNode = util.table.downCell(keyState.cell);
        if (!targetNode) {
          isCell = false;
          targetNode = getTableSibling(keyState.enTable, "nextSibling");
        }
      } else {
        if (keyState.keyCode === KeyCodes.LEFT) {
          targetNode = util.table.prevCell(keyState.cell);
          atEnd = true;
        } else {
          if (keyState.keyCode === KeyCodes.RIGHT) {
            targetNode = util.table.nextCell(keyState.cell);
          }
        }
      }
    }
    if (!targetNode) {
      return false;
    }
    goog.dom.Range.createCaret(targetNode, atEnd ? targetNode.childNodes.length : 0).select();
    if (isCell) {
      util.table.setActive(keyState.enTable, targetNode);
      util.table.query_(keyState.enTable, ".container").scrollLeft = keyState.scrollLeft;
      util.table.scrollCellIntoView(targetNode);
    } else {
      util.table.setActive();
    }
    return true;
  };
  util.table.navigatedFocusSelectionCell = function(keyState) {
    if (!keyState.shiftKey) {
      return null;
    }
    var KeyCodes = goog.events.KeyCodes;
    var matrix = util.table.matrix(keyState.enTable);
    var info = util.table.infoForCell(keyState.cell, matrix);
    if (keyState.scrollLeft !== undefined) {
      util.table.query_(keyState.enTable, ".container").scrollLeft = keyState.scrollLeft;
    }
    if (keyState.keyCode === KeyCodes.UP && info.startRowIndex > 0) {
      return matrix[info.startRowIndex - 1][info.startColIndex].info.node;
    } else {
      if (keyState.keyCode === KeyCodes.DOWN && info.endRowIndex < matrix.length - 1) {
        return matrix[info.endRowIndex + 1][info.startColIndex].info.node;
      } else {
        if (keyState.keyCode === KeyCodes.LEFT && info.startColIndex > 0) {
          return matrix[info.startRowIndex][info.startColIndex - 1].info.node;
        } else {
          if (keyState.keyCode === KeyCodes.RIGHT && info.endColIndex < matrix[0].length - 1) {
            return matrix[info.startRowIndex][info.endColIndex + 1].info.node;
          }
        }
      }
    }
    return null;
  };
  util.table.navigateInto = function(range, direction) {
  };
  util.table.getActive = function() {
    return activeTable;
  };
  util.table.getActiveCell = function() {
    return activeCell;
  };
  util.table.setActive = function(enTable, cell) {
    if (!enTable && !activeTable || enTable && !util.dom.isEntable(enTable)) {
      return;
    }
    if (enTable !== activeTable) {
      if (activeTable) {
        activeTable.classList.remove("active");
        activeTable = null;
        util.observer.removeHandler(updateActiveTableAdornmentRows);
      }
      if (enTable) {
        activeTable = enTable;
        activeTable.classList.add("active");
        util.table.layout(enTable, true);
        util.observer.addHandler(updateActiveTableAdornmentRows);
      }
    }
    if (cell !== activeCell) {
      if (cell && (!activeTable || !goog.dom.getAncestor(cell, function(node) {
        return node === activeTable;
      }))) {
        throw new Error("Active cell is not part of active table:", activeTable);
      }
      activeCell = cell;
      util.table.layoutMenuButton();
    }
  };
  util.table.setLine = function(enTable, index, axis) {
    enTable.classList.remove("xline-visible");
    enTable.classList.remove("yline-visible");
    if (axis) {
      enTable.classList.add(axis + "line-visible");
      var selector = "." + axis + "line";
      var line = util.table.query_(enTable, selector);
      if (axis === util.table.Axis.HORIZONTAL) {
        var top = 0;
        if (index > 0) {
          var row = util.table.query_(enTable, "table").rows[index - 1];
          top = row.offsetTop + row.offsetHeight;
        }
        line.style.top = (top === 0 ? top - 5 : top - 7) + "px";
      } else {
        var left = 0;
        if (index > 0) {
          var cols = util.table.query_(enTable, "colgroup").children;
          left = goog.array.reduce(cols, function(sum, col, i) {
            return i < index ? sum + parseInt(col.style.width, 10) : sum;
          }, 0);
        }
        line.style.left = (left === 0 ? left - 5 : left - 7) + "px";
      }
    }
  };
  util.table.handleToObject = function(node) {
    var index = util.dom.index(node);
    var axis = node.parentNode.parentNode.parentNode.classList.contains("columns") ? util.table.Axis.VERTICAL : util.table.Axis.HORIZONTAL;
    return {axis:axis, index:index};
  };
  util.table.insertionToObject = function(node) {
    var parent = node.parentNode;
    var index = parent.classList.contains("insertions") ? util.dom.index(node) + 1 : 0;
    var axis = parent.classList.contains("columns") || parent.parentNode.parentNode.classList.contains("columns") ? util.table.Axis.VERTICAL : util.table.Axis.HORIZONTAL;
    return {axis:axis, index:index};
  };
  util.table.scrollCellIntoView = function(targetCell) {
    if (!util.dom.isTd(targetCell)) {
      return;
    }
    var enTable = goog.dom.getAncestor(targetCell, util.dom.isEntable);
    var container = util.table.query_(enTable, ".container");
    var offset = 16;
    var offsetLeft = targetCell.offsetLeft;
    var offsetWidth = targetCell.offsetWidth;
    if (container.scrollLeft > offsetLeft) {
      container.scrollLeft -= container.scrollLeft - offsetLeft + offset;
      util.table.translateX(enTable);
    } else {
      if (container.scrollLeft + container.clientWidth < offsetLeft + offsetWidth) {
        container.scrollLeft += offsetLeft + offsetWidth - container.scrollLeft - container.clientWidth + offset;
        util.table.translateX(enTable);
      }
    }
  };
  util.table.translateX = function(enTable) {
    if (!util.dom.isEntable(enTable) || enTable.dataset.lazy) {
      return;
    }
    var container = util.table.query_(enTable, ".container");
    var transAttr = container.style.transform === undefined ? "webkitTransform" : "transform";
    var left = container.scrollLeft;
    var scrollWidth = container.scrollWidth;
    var offsetWidth = container.offsetWidth;
    util.table.query_(enTable, ".columns .handles").style[transAttr] = "translateX(" + -left + "px)";
    util.table.query_(enTable, ".columns .insertions").style[transAttr] = "translateX(" + -left + "px)";
    util.table.query_(enTable, ".content").style[transAttr] = "translateX(" + -left + "px)";
    util.table.query_(enTable, ".lscroll").style.opacity = Math.max(Math.min(1, left / 10), 0);
    util.table.query_(enTable, ".rscroll").style.opacity = Math.max(Math.min(1, (scrollWidth - offsetWidth - left) / 10), 0);
    var thumb = util.table.query_(enTable, ".scrollbar-thumb");
    var scale = offsetWidth / scrollWidth;
    if (scale >= 1) {
      thumb.parentNode.style.display = "";
    } else {
      thumb.parentNode.style.display = "block";
      thumb.style.width = offsetWidth * scale + "px";
      thumb.style[transAttr] = "translateX(" + left * scale + "px)";
    }
  };
  util.table.layout = function(enTable, generateMissingAdornemnts) {
    var width = util.table.updateWidth(enTable);
    if (generateMissingAdornemnts || enTable.dataset.lazy && enTable.clientWidth < width) {
      util.table.generateAdornments(enTable);
      util.table.updateWidth(enTable);
    }
    util.table.updateAdornments(enTable);
    util.table.translateX(enTable);
    util.table.layoutMenuButton();
  };
  util.table.layoutMenuButton = function() {
    var button = document.querySelector(".en-cell-btn");
    if (!activeCell || !activeTable) {
      if (button) {
        button.remove();
      }
      return;
    }
    if (!button) {
      button = goog.dom.createDom("div", {class:"en-cell-btn"});
    }
    button.style.top = activeCell.offsetTop + 5 + "px";
    button.style.left = activeCell.offsetLeft + activeCell.offsetWidth - 23 + "px";
    activeTable.querySelector(".content").appendChild(button);
  };
  util.table.equalizeColumns = function(enTable, indexes) {
    if (indexes.length < 2) {
      return;
    }
    var cols = util.table.query_(enTable, "colgroup").children;
    var widths = util.table.getColumnsMinWidth(enTable);
    var totalWidth = 0;
    var columns = [];
    widths.forEach(function(width, index) {
      if (indexes.indexOf(index) > -1) {
        totalWidth += parseInt(cols[index].style.width, 10);
        columns.push({index:index, minWidth:width});
      }
    });
    var sumWidth = 0;
    var avg = totalWidth / indexes.length;
    columns.sort(function(a, b) {
      return b.minWidth - a.minWidth;
    }).forEach(function(obj, n) {
      var width = obj.minWidth;
      if (width > avg) {
        sumWidth += width;
        avg = (totalWidth - sumWidth) / (indexes.length - n - 1);
      } else {
        width = avg;
      }
      cols[obj.index].style.width = Math.round(width) + "px";
    });
    util.table.layout(enTable);
  };
  util.table.fitNote = function(enTable) {
    var tableWidth = enTable ? parseInt(enTable.style.width, 10) : null;
    if (isNaN(tableWidth) || !tableWidth) {
      return false;
    }
    var cols = util.table.query_(enTable, "colgroup").children;
    var noteWidth = util.styles.getNoteWidth();
    var scale = noteWidth / tableWidth;
    var reminder = 0;
    var objs = util.table.getColumnsMinWidth(enTable).map(function(width, index) {
      return {index:index, minWidth:width, width:parseInt(cols[index].style.width, 10)};
    });
    objs.sort(function(a, b) {
      return b.minWidth - a.minWidth;
    }).forEach(function(obj, n) {
      var width = obj.width * scale - reminder;
      if (width < obj.minWidth) {
        reminder += (obj.minWidth - width) / (cells.length - n - 1);
        width = obj.minWidth;
      }
      cols[obj.index].style.width = Math.floor(width) + "px";
    });
    util.table.layout(enTable);
  };
  util.table.fitColumnContent = function(enTable, colIndex) {
    var width = util.table.getColumnContentWidth(enTable, colIndex);
    if (width === null) {
      return false;
    }
    util.table.setColumnWidth(enTable, colIndex, width);
    return true;
  };
  util.table.fitColumnIfNeeded = function(enTable, index) {
  };
  util.table.getColumnsMinWidth = function(enTable, colIndex) {
    var table = util.table.query_(enTable, "table");
    var matrix = util.table.matrix(table);
    var left = null;
    var selector = ["ul", "ol", "object"].join(",");
    var widths = [];
    for (var c = 0, l = matrix[0].length; c < l; c++) {
      widths[c] = colIndex === undefined || colIndex === c ? defs.CELL_MIN_WIDTH : null;
    }
    goog.array.forEach(table.querySelectorAll(selector), function(node) {
      var cell = goog.dom.getAncestor(node, util.dom.isTd);
      var info = util.table.infoForCell(cell, matrix);
      if (colIndex !== undefined && info.startColIndex !== colIndex) {
        return;
      }
      if (!left) {
        left = cell.getBoundingClientRect().left;
      }
      var width = widths[info.startColIndex];
      if (node.tagName === "OBJECT") {
        width = Math.max(node.getBoundingClientRect().left - left + 12, width);
      } else {
        width = Math.max(node.getBoundingClientRect().left - left + 76, width);
      }
      widths[info.startColIndex] = Math.ceil(width);
    });
    return widths;
  };
  util.table.getColumnContentWidth = function(enTable, colIndex) {
    if (!measureTable) {
      measureTable = goog.dom.createDom("table", {class:"en-measure-table"});
      measureTable.innerHTML = "<tbody><tr><td></td></tr></tbody>";
    }
    var table = util.table.query_(enTable, "table");
    var matrix = util.table.matrix(table);
    var width = defs.CELL_MIN_WIDTH;
    var empty = true;
    var measureCell = measureTable.rows[0].firstChild;
    enTable.parentNode.appendChild(measureTable);
    matrix.forEach(function(row, rowIndex) {
      var info = row[colIndex].info;
      var cell = info.node;
      if (info.startColIndex < colIndex || info.startRowIndex < rowIndex) {
        return;
      }
      if (!util.dom.isEmpty(cell)) {
        measureCell.innerHTML = cell.innerHTML;
        measureCell.setAttribute("style", cell.getAttribute("style"));
        width = Math.max(measureCell.offsetWidth, width);
        empty = false;
      }
    });
    measureTable.remove();
    return empty ? null : Math.min(width, util.styles.getNoteWidth());
  };
  util.table.setColumnWidth = function(enTable, colIndex, width) {
    var colgroup = util.table.query_(enTable, "colgroup");
    colgroup.children[colIndex].style.width = Math.max(width, defs.CELL_MIN_WIDTH) + "px";
    util.table.layout(enTable);
    util.table.setLine(enTable);
  };
  util.table.updateWidth = function(enTable, width) {
    if (!util.dom.isEntable(enTable)) {
      return;
    }
    var table = util.table.query_(enTable, "table");
    if (!table) {
      return;
    }
    if (!width) {
      var colgroup = util.table.query_(enTable, "colgroup");
      if (!colgroup) {
        return;
      }
      width = 0;
      goog.array.forEach(colgroup.children, function(col) {
        width += parseInt(col.style.width, 10);
      });
    }
    var widthStr = width + "px";
    enTable.style.width = widthStr;
    table.style.width = widthStr;
    if (!enTable.dataset.lazy) {
      util.table.query_(enTable, ".columns .handles").style.width = widthStr;
      util.table.query_(enTable, ".columns .insertions").style.width = widthStr;
      util.table.query_(enTable, ".content").style.width = widthStr;
    }
    return width;
  };
  util.table.updateAdornments = function(enTable, axis) {
    if (!util.dom.isEntable(enTable) || enTable.dataset.lazy) {
      return;
    }
    var table = util.table.query_(enTable, "table");
    if (axis !== util.table.Axis.VERTICAL) {
      var rowHandles = util.table.query_(enTable, ".rows .handles");
      var rowInsertions = util.table.query_(enTable, ".rows .insertions");
      var rowCount = table.rows.length;
      goog.array.forEach(table.rows, function(tr, index) {
        var height = tr.getBoundingClientRect().height;
        var handle = rowHandles.children[index];
        if (!handle) {
          handle = goog.dom.createDom("div", {class:"handle"});
          rowHandles.appendChild(handle);
        }
        handle.style.height = height + "px";
        var insertion = rowInsertions.children[index];
        if (!insertion) {
          insertion = goog.dom.createDom("div", {class:"insertion"}, goog.dom.createDom("div", {class:"insertion-shape"}));
          rowInsertions.appendChild(insertion);
        }
        insertion.style.marginTop = height - 18 + "px";
      });
      if (rowHandles.children.length - rowCount > 0) {
        goog.array.forEachRight([].slice.call(rowHandles.children, rowCount), goog.dom.removeNode);
        goog.array.forEachRight([].slice.call(rowInsertions.children, rowCount), goog.dom.removeNode);
      }
    }
    if (axis !== util.table.Axis.HORIZONTAL) {
      var colgroup = util.table.query_(enTable, "colgroup");
      var colHandles = util.table.query_(enTable, ".columns .handles");
      var colInsertions = util.table.query_(enTable, ".columns .insertions");
      var colCount = colgroup.children.length;
      goog.array.forEach(colgroup.children, function(col, index) {
        var width = parseInt(col.style.width, 10);
        var handle = colHandles.children[index];
        if (!handle) {
          handle = goog.dom.createDom("div", {class:"handle"});
          colHandles.appendChild(handle);
        }
        handle.style.width = width + "px";
        var insertion = colInsertions.children[index];
        if (!insertion) {
          insertion = goog.dom.createDom("div", {class:"insertion"}, goog.dom.createDom("div", {class:"insertion-shape"}));
          colInsertions.appendChild(insertion);
        }
        insertion.style.marginLeft = width - 18 + "px";
      });
      if (colHandles.children.length - colCount > 0) {
        goog.array.forEachRight([].slice.call(colHandles.children, colCount), goog.dom.removeNode);
        goog.array.forEachRight([].slice.call(colInsertions.children, colCount), goog.dom.removeNode);
      }
    }
  };
  util.table.attachAdornments = function(table) {
    if (!util.table.isCompatible(table) || goog.dom.getAncestor(table, util.dom.isEntable)) {
      return table;
    }
    var placeholder = null;
    var inDOMTree = !!table.parentNode;
    if (inDOMTree) {
      placeholder = goog.dom.createDom("div");
      goog.dom.replaceNode(placeholder, table);
    }
    var enTable = goog.dom.createDom("en-table", {"data-lazy":1}, [goog.dom.createDom("div", {class:"container"}, table), goog.dom.createDom("en-adornments", {contentEditable:"false"})]);
    enTable.style.marginLeft = table.style.marginLeft;
    enTable.style.marginRight = table.style.marginRight;
    table.style.marginLeft = "";
    table.style.marginRight = "";
    util.table.updateWidth(enTable);
    if (inDOMTree) {
      goog.dom.replaceNode(enTable, placeholder);
    }
    return enTable;
  };
  util.table.generateAdornments = function(enTable) {
    if (!enTable.dataset.lazy) {
      return;
    }
    delete enTable.dataset.lazy;
    var adornments = util.table.query_(enTable, "en-adornments");
    adornments.appendChild(goog.dom.createDom("div", {class:"columns"}, [goog.dom.createDom("div", {class:"handles-container"}, goog.dom.createDom("div", {class:"handles"})), goog.dom.createDom("div", {class:"insertions-container"}, goog.dom.createDom("div", {class:"insertions"})), goog.dom.createDom("div", {class:"insertion"}, goog.dom.createDom("div", {class:"insertion-shape"}))]));
    adornments.appendChild(goog.dom.createDom("div", {class:"rows"}, [goog.dom.createDom("div", {class:"handles-container"}, goog.dom.createDom("div", {class:"handles"})), goog.dom.createDom("div", {class:"insertions-container"}, goog.dom.createDom("div", {class:"insertions"})), goog.dom.createDom("div", {class:"insertion"}, goog.dom.createDom("div", {class:"insertion-shape"}))]));
    adornments.appendChild(goog.dom.createDom("div", {class:"content-container"}, [goog.dom.createDom("div", {class:"content"}, [goog.dom.createDom("div", {class:"xline"}), goog.dom.createDom("div", {class:"yline"})]), goog.dom.createDom("div", {class:"lscroll"}), goog.dom.createDom("div", {class:"rscroll"})]));
    adornments.appendChild(goog.dom.createDom("div", {class:"scrollbar"}, goog.dom.createDom("div", {class:"scrollbar-thumb"})));
    adornments.appendChild(goog.dom.createDom("div", {class:"en-table-btn"}));
  };
  util.table.clearAdornments = function(enTable, legacyCompatible) {
    if (!util.dom.isEntable(enTable)) {
      return enTable;
    }
    var table = util.table.query_(enTable, "table");
    if (!util.dom.isTable(table)) {
      return enTable;
    }
    table.style.marginLeft = enTable.style.marginLeft;
    table.style.marginRight = enTable.style.marginRight;
    var colgroup, tableWidth, widths;
    if (legacyCompatible) {
      colgroup = util.table.query_(enTable, "colgroup");
      widths = goog.array.map(colgroup.children, function(col) {
        return parseInt(col.style.width, 10);
      });
      table.style.borderCollapse = "collapse";
      table.style.width = "";
      table.style.minWidth = "100%";
    }
    goog.dom.removeNode(table.querySelector("cursor-proxy"));
    goog.dom.replaceNode(table, enTable);
    var getWidthStr = function(from, length) {
      var width = 0;
      for (var i = from; i < from + length; i++) {
        width += widths[i];
      }
      return width + "px";
    };
    var matrix = util.table.matrix(table);
    matrix.forEach(function(row, rowIndex) {
      row.forEach(function(obj, colIndex) {
        var info = obj.info;
        var td = info.node;
        if (info.startRowIndex > rowIndex || info.startColIndex > colIndex) {
          return;
        }
        var borderWidth = td.style.borderWidth || "1px";
        var borderStyle = td.style.borderStyle || "solid";
        var borderColor = td.style.borderColor || defs.BORDER_COLOR;
        if (legacyCompatible) {
          td.style.width = getWidthStr(info.startColIndex, info.endColIndex - info.startColIndex + 1);
          if (!td.style.padding) {
            td.style.padding = defs.CELL_PADDING + "px";
          }
        }
        td.style.border = [borderWidth, borderStyle, borderColor].join(" ");
      });
    });
    return table;
  };
  util.table.migrateToEnTable = function(table) {
    if (goog.dom.getAncestor(table, util.dom.isEntable) || !util.table.isCompatible(table, true)) {
      return false;
    }
    util.table.normalizeColgroup(table, true, true);
    util.table.normalizeStyles(table);
    util.table.flatten(table);
    util.table.normalizeCellBorders(table);
    var enTable = util.table.attachAdornments(table);
    util.table.normalizeDOMPlacement(enTable);
    util.table.layout(enTable);
    return true;
  };
  util.table.flatten = function(table) {
    var childTables;
    var colgroup = util.table.query_(table, "colgroup");
    while ((childTables = goog.array.filter(table.querySelectorAll("table"), function(node) {
      return goog.dom.getAncestor(node, util.dom.isTable) === table;
    })).length > 0) {
      var expansions = [];
      childTables.forEach(function(childTable) {
        var info = processTableForExpansion(childTable, expansions);
        if (info.addRowCount) {
          util.table.insertRows(table, info.insertRowIndex, info.addRowCount);
        }
        if (info.addColCount) {
          var col = colgroup.children[info.endColIndex];
          var width = Math.ceil(parseInt(col.style.width, 10) / (info.addColCount + 1));
          col.style.width = Math.max(width, defs.CELL_MIN_WIDTH) + "px";
          util.table.insertColumns(table, info.insertColIndex, info.addColCount);
        }
        var rootMatrix = util.table.matrix(table);
        var rootInfo = null;
        var rowOffset = info.beforeHTML ? 1 : 0;
        if (info.afterHTML) {
          rootInfo = rootMatrix[info.endRowIndex + info.rowCount - 1][info.startColIndex].info;
          rootInfo.node.innerHTML = info.afterHTML;
        }
        info.matrix.forEach(function(row, rowIndex) {
          row.forEach(function(obj, colIndex) {
            rootInfo = rootMatrix[rowIndex + info.startRowIndex + rowOffset][colIndex + info.startColIndex].info;
            rootInfo.node.innerHTML = obj.info.node.innerHTML;
          });
        });
        var exp = {startRowIndex:info.startRowIndex, startColIndex:info.startColIndex, endRowIndex:info.startRowIndex + info.rowCount - 1, endColIndex:info.startColIndex + info.colCount - 1, rowCount:info.rowCount, colCount:info.colCount};
        expansions.push(exp);
        if (info.afterHTML) {
          rootInfo = rootMatrix[exp.endRowIndex][exp.startColIndex].info;
          rootInfo.node.innerHTML = info.afterHTML;
          mergeColumnTdsAfterFlattening(rootMatrix, exp.endRowIndex, exp.endRowIndex, exp.startColIndex, exp.endColIndex);
        }
        if (info.beforeHTML) {
          mergeColumnTdsAfterFlattening(rootMatrix, exp.startRowIndex, exp.startRowIndex, exp.startColIndex, exp.endColIndex);
        }
      });
    }
  };
  util.table.isMSTable = function(table) {
    var tableMSO = (table.getAttribute("style") || "").indexOf("mso-") > -1;
    if (tableMSO) {
      return true;
    }
    var col = table.querySelector("col");
    return col ? (col.getAttribute("style") || "").indexOf("mso-") > -1 : false;
  };
  util.table.isCompatible = function(table, loose) {
    if (table.compat !== undefined) {
      return table.compat;
    }
    table.compat = true;
    if (!util.dom.isTable(table)) {
      table.compat = false;
    } else {
      if (table.tBodies.length === 0 || table.rows.length === 0) {
        table.compat = false;
      } else {
        if (table.querySelectorAll("tfoot").length > 1 || table.querySelectorAll("thead").length > 1) {
          table.compat = false;
        } else {
          if (goog.dom.getAncestor(table, util.dom.isTable)) {
            table.compat = false;
          } else {
            if (!loose && util.table.isMSTable(table)) {
              table.compat = true;
            } else {
              if (!loose && table.querySelector("table")) {
                table.compat = false;
              } else {
                if (!loose && (table.cellPadding || table.cellSpacing || table.border)) {
                  table.compat = false;
                } else {
                  if (!loose && !table.style.width && !table.style.minWidth) {
                    table.compat = false;
                  } else {
                    if (!loose && table.style.borderColor === "transparent") {
                      table.compat = false;
                    } else {
                      if (!loose && !goog.array.some(table.querySelectorAll("td"), function(td) {
                        return td.style.borderStyle === "solid" && td.style.borderWidth !== "0px" && td.style.borderWidth !== "";
                      })) {
                        table.compat = false;
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    return table.compat;
  };
  util.table.normalize = function(root, skipStyleManipulation) {
    var tables = util.dom.isTable(root) ? [root] : root.querySelectorAll("table");
    goog.array.forEach(tables, function(table) {
      var isCompatible = util.table.isCompatible(table);
      util.table.normalizeStructure(table);
      if (!skipStyleManipulation && isCompatible) {
        util.table.normalizeColgroup(table, true);
        util.table.normalizeStyles(table);
        util.table.normalizeCellBorders(table);
      } else {
        util.table.normalizeColgroup(table);
      }
    });
  };
  util.table.normalizeStructure = function(table) {
    if (table.tBodies.length === 0) {
      table.appendChild(document.createElement("tbody"));
    }
    var tBody = table.tBodies[0];
    goog.array.forEachRight(tBody.childNodes || [], function(child) {
      if (!util.dom.isTr(child)) {
        goog.dom.removeNode(child);
      }
    });
    if (tBody.childNodes.length === 0) {
      tBody.innerHTML = "<tr><td>" + defs.CELL_HTML + "</td></tr>";
      return;
    }
    if (table.tHead) {
      goog.array.forEachRight(table.tHead.childNodes || [], function(child) {
        if (util.dom.isTr(child)) {
          goog.dom.insertSiblingBefore(child, tBody.firstChild);
        }
      });
    }
    if (table.tFoot) {
      goog.array.forEachRight(table.tFoot.childNodes || [], function(child) {
        if (util.dom.isTr(child)) {
          goog.dom.insertSiblingAfter(child, tBody.lastChild);
        }
      });
    }
    goog.array.forEachRight(table.childNodes || [], function(child) {
      if (!util.dom.isTbody(child) && !util.dom.isColgroup(child)) {
        goog.dom.removeNode(child);
      }
    });
    goog.array.forEach(table.rows, function(tr) {
      goog.array.forEachRight(tr.childNodes || [], function(child) {
        if (util.dom.isTd(child) || util.dom.isTh(child)) {
          if (util.dom.isTh(child)) {
            child = util.dom.changeTagName(child, "td");
          }
          if (util.dom.isEmpty(child)) {
            child.innerHTML = defs.CELL_HTML;
          }
        } else {
          goog.dom.removeNode(child);
        }
      });
    });
    var matrix = util.table.matrix(table);
    var colCount = Math.max.apply(null, matrix.map(function(row) {
      return row.length;
    }));
    matrix.forEach(function(row, rowIndex) {
      for (var colIndex = 0; colIndex < colCount; colIndex++) {
        if (row[colIndex] === undefined) {
          util.table.insertTd(util.table.createEmptyTd(), rowIndex, colIndex, table, matrix);
        }
      }
    });
  };
  util.table.normalizeColgroup = function(table, normalizeToPixel, layoutCalculation) {
    var colgroup = util.table.query_(table, "colgroup");
    var matrix = util.table.matrix(table);
    var colEquations = [];
    var colWidthUnit = colgroup ? null : parseWidth(matrix[0][0].info.node.style.width).unit;
    var colCount = matrix[0].length;
    var debug = false;
    if (layoutCalculation) {
      colWidthUnit = "px";
    }
    if (layoutCalculation && !normalizeToPixel) {
      throw new Error("Invalid combination of normalizeToPixel=false and layoutCalculation=true.");
    }
    for (var rowIndex = 0; rowIndex < matrix.length; rowIndex++) {
      for (var colIndex = 0, row = matrix[rowIndex]; colIndex < row.length; colIndex++) {
        var info = row[colIndex].info;
        if (info.startRowIndex > rowIndex || info.startColIndex > colIndex) {
          continue;
        }
        var td = info.node;
        if (colWidthUnit || layoutCalculation) {
          var obj = parseWidth(td.style.width);
          var value = layoutCalculation ? td.offsetWidth : obj.value;
          if (!layoutCalculation && value && obj.unit !== colWidthUnit) {
            colWidthUnit = null;
            colEquations = [];
          } else {
            if (value) {
              colEquations.push([value].concat(goog.array.repeat(0, td.colSpan).map(function(_, i) {
                return i + info.startColIndex;
              })));
            }
          }
        }
        if (!layoutCalculation) {
          td.style.width = "";
          td.style.minWidth = "";
          td.style.maxWidth = "";
        }
      }
    }
    if (layoutCalculation) {
      for (var rowIndex = 0; rowIndex < matrix.length; rowIndex++) {
        for (var colIndex = 0, row = matrix[0]; colIndex < row.length; colIndex++) {
          var info = row[colIndex].info;
          if (info.startRowIndex > rowIndex || info.startColIndex > colIndex) {
            continue;
          }
          var td = info.node;
          td.style.width = "";
          td.style.minWidth = "";
          td.style.maxWidth = "";
        }
      }
    }
    var styleWidths = [];
    var tableWidthObj = parseWidth(table.style.width);
    if (!tableWidthObj.unit && table.hasAttribute("width")) {
      tableWidthObj = parseWidth(table.getAttribute("width"));
    }
    if (colgroup && !layoutCalculation) {
      styleWidths = calculateStyleWidthsFromColgroup(colCount, tableWidthObj, colgroup, normalizeToPixel);
      debug && console.log("[normalizeColgroup] calculateStyleWidthsFromColgroup");
    } else {
      if (colEquations.length > 0) {
        styleWidths = calculateStyleWidthsFromEquations(colCount, tableWidthObj, colWidthUnit, colEquations, normalizeToPixel);
        debug && console.log("[normalizeColgroup] calculateStyleWidthsFromEquations");
      } else {
        if (normalizeToPixel || tableWidthObj.unit === "px") {
          styleWidths = calculateStyleWidthsFromRatio(colCount, tableWidthObj);
          debug && console.log("[normalizeColgroup] calcualteStyleWidthsFromRatio");
        } else {
          debug && console.log("[normalizeColgroup] ignoring width calculation");
        }
      }
    }
    var newColgroup = document.createElement("colgroup");
    for (var i = 0; i < colCount; i++) {
      var col = document.createElement("col");
      col.style.width = styleWidths[i] || "";
      newColgroup.appendChild(col);
    }
    goog.dom.removeNode(colgroup);
    goog.dom.insertSiblingBefore(newColgroup, table.tBodies[0]);
  };
  util.table.normalizeStyles = function(table) {
    var matrix = util.table.matrix(table);
    var marginLeft = table.style.marginLeft === "auto" ? "auto" : "";
    var marginRight = table.style.marginRight === "auto" ? "auto" : "";
    table.removeAttribute("border");
    table.removeAttribute("align");
    table.removeAttribute("valign");
    table.removeAttribute("bordercolor");
    table.removeAttribute("cellspacing");
    table.removeAttribute("cellpadding");
    table.style.borderCollapse = "";
    table.style.border = "";
    table.style.width = "";
    table.style.minWidth = "";
    table.style.maxWidth = "";
    table.style.padding = "";
    table.style.margin = "";
    table.style.marginLeft = marginLeft;
    table.style.marginRight = marginRight;
    goog.array.forEach(table.rows, function(tr) {
      if (tr.hasAttribute("style")) {
        tr.style.border = "";
        tr.style.margin = "";
        tr.style.paddig = "";
        tr.style.height = "";
        tr.style.minHeight = "";
        tr.style.maxHeight = "";
      }
    });
    matrix.forEach(function(row, rowIndex) {
      row.forEach(function(obj, colIndex) {
        var info = obj.info;
        var td = info.node;
        if (info.startRowIndex > rowIndex || info.startColIndex > colIndex) {
          return;
        }
        var backgroundColor = td.style.backgroundColor;
        td.style.background = "";
        td.style.backgroundColor = goog.color.isValidColor(backgroundColor) ? backgroundColor : "";
        var borderColor = td.style.borderColor;
        td.style.border = "";
        td.style.borderColor = goog.color.isValidColor(borderColor) ? borderColor : "";
        td.style.padding = "";
        td.style.margin = "";
        td.style.width = "";
        td.style.minWidth = "";
        td.style.maxWidth = "";
        td.style.minHeight = "";
        td.style.maxHeight = "";
        if (td.colSpan === 1) {
          td.removeAttribute("colSpan");
        }
        util.table.setRowSpan(td, td.rowSpan);
        td.removeAttribute("width");
        td.removeAttribute("align");
        td.removeAttribute("valign");
      });
    });
  };
  util.table.normalizeCellBorders = function(table, optMatrix) {
    var matrix = optMatrix || util.table.matrix(table);
    goog.array.forEach(table.rows, function(row, rowIndex) {
      var td = row.firstChild;
      if (td) {
        td.style.borderLeftStyle = matrix[rowIndex][0].info.node === td ? "" : "none";
      }
    });
  };
  util.table.normalizeDOMPlacement = function(enTable) {
    var prev = enTable.previousElementSibling;
    if (util.dom.isDiv(prev) && util.dom.isBr(prev.firstChild) && prev.children.length === 1) {
      prev.remove();
    }
    var next = enTable.nextElementSibling;
    if (util.dom.isBr(next)) {
      next.remove();
    }
    var invalidSibling = function(node) {
      return !node || node.classList && node.classList.contains("en-code") || util.dom.isEntable(node) || util.dom.isHr(node);
    };
    if (invalidSibling(enTable.previousElementSibling)) {
      goog.dom.insertSiblingBefore(goog.dom.createDom("div", null, document.createElement("br")), enTable);
    }
    if (invalidSibling(enTable.nextElementSibling)) {
      goog.dom.insertSiblingAfter(goog.dom.createDom("div", null, document.createElement("br")), enTable);
    }
  };
  util.table.query_ = function(owner, selector) {
    if (!queryCache || queryCache.owner !== owner) {
      queryCache = {owner:owner};
    }
    var node = queryCache[selector];
    if (!node || !node.parentNode) {
      node = owner.querySelector(selector);
      queryCache[selector] = node;
    }
    return node;
  };
  function updateActiveTableAdornmentRows() {
    if (activeTable) {
      util.table.updateAdornments(activeTable, util.table.Axis.HORIZONTAL);
    }
  }
  function calculateStyleWidthsFromColgroup(colCount, tableWidthObj, colgroup, normalizeToPixel) {
    if (colCount !== colgroup.children.length) {
      return goog.array.repeat(normalizeToPixel ? defs.CELL_WIDTH : null, colCount);
    }
    var colFlexIndexes = [];
    var colWidthSum = 0;
    var unit = normalizeToPixel ? "px" : tableWidthObj.unit;
    var tableWidth;
    var widths = [];
    if (tableWidthObj.unit === "%") {
      tableWidth = tableWidthObj.value * (util.styles.getNoteWidth() - 1);
    } else {
      if (tableWidthObj.unit === "px") {
        tableWidth = tableWidthObj.value;
      } else {
        tableWidth = util.styles.getNoteWidth();
      }
    }
    goog.array.forEach(colgroup.children, function(col, i) {
      var colWidthStr = col.getAttribute("width") || col.style.width;
      var colWidthObj = parseWidth(colWidthStr);
      var width;
      if (colWidthStr === "*") {
        colFlexIndexes.push(i);
        unit = "px";
        width = 0;
      } else {
        if (colWidthObj.unit === "%" && normalizeToPixel) {
          width = tableWidth * colWidthObj.value;
        } else {
          if (colWidthObj.unit === "%") {
            unit = "%";
            width = colWidthObj.value;
          } else {
            if (colWidthObj.unit === "px" || normalizeToPixel) {
              unit = "px";
              width = colWidthObj.value || defs.CELL_WIDTH;
            }
          }
        }
      }
      colWidthSum += width;
      for (var i = parseInt(col.getAttribute("span"), 10) || 1; i > 0; i--) {
        widths.push(width);
      }
    });
    if (!unit) {
      return goog.array.repeat(defs.CELL_WIDTH, colCount);
    }
    var flexCount = colFlexIndexes.length;
    var flexTotal = unit === "%" ? 1 : tableWidth;
    var flexWidth = Math.max(0, flexTotal - colWidthSum);
    colFlexIndexes.forEach(function(i) {
      widths[i] = Math.round(flexWidth / flexCount);
    });
    var styleWidths = [];
    for (var i = 0; i < colCount; i++) {
      var width;
      if (unit === "px" && normalizeToPixel) {
        width = Math.max(widths[i] || defs.CELL_WIDTH, defs.CELL_MIN_WIDTH);
      } else {
        if (unit === "px") {
          width = widths[i] || defs.CELL_WIDTH;
        } else {
          width = widths[i] * 100;
        }
      }
      styleWidths.push(Math.round(width) + unit);
    }
    return styleWidths;
  }
  function calculateStyleWidthsFromEquations(colCount, tableWidthObj, colWidthUnit, colEquations, normalizeToPixel) {
    var change = true;
    var divide = false;
    var tableWidth;
    var widthIndexCount = 0;
    var widths = [];
    if (tableWidthObj.unit === "%") {
      tableWidth = tableWidthObj.value * (util.styles.getNoteWidth() - 1);
    } else {
      if (tableWidthObj.unit === "px") {
        tableWidth = tableWidthObj.value;
      } else {
        tableWidth = util.styles.getNoteWidth();
      }
    }
    colEquations.sort(function(a, b) {
      return b.length - a.length;
    });
    while (change && widthIndexCount < colCount) {
      change = false;
      goog.array.forEachRight(colEquations, function(eq, i) {
        if (eq.length > 2) {
          for (var j = eq.length - 1; j > 0; j--) {
            var wval = widths[eq[j]];
            if (wval) {
              change = true;
              eq[0] -= wval;
              eq.splice(j, 1);
            }
          }
        }
        if (divide || eq.length === 2) {
          for (var l = eq.length - 1, j = l; j > 0; j--) {
            if (!widths[eq[j]]) {
              change = true;
              widthIndexCount += 1;
              widths[eq[j]] = eq[0] / l;
            }
          }
          colEquations.splice(i, 1);
        }
      });
      if (!change && !divide) {
        divide = true;
        change = true;
      }
    }
    for (var i = 0; i < colCount; i++) {
      var width = widths[i];
      if (colWidthUnit === "px" && normalizeToPixel) {
        widths[i] = Math.max(width || defs.CELL_WIDTH, defs.CELL_MIN_WIDTH);
      } else {
        if (colWidthUnit === "px") {
          widths[i] = width || defs.CELL_WIDTH;
        } else {
          if (colWidthUnit === "%" && width) {
            widths[i] = tableWidth * width;
          } else {
            if (colWidthUnit === "%" || !width) {
              widths[i] = defs.CELL_WIDTH;
            }
          }
        }
      }
    }
    return widths.map(function(width) {
      return Math.round(width) + "px";
    });
  }
  function calculateStyleWidthsFromRatio(colCount, tableWidthObj) {
    var noteWidth = util.styles.getNoteWidth() - 1;
    var styleWidths = [];
    var width = null;
    if (tableWidthObj.unit === "%") {
      width = noteWidth * tableWidthObj.value / colCount;
    } else {
      if (tableWidthObj.unit === "px") {
        width = tableWidthObj.value / colCount;
      } else {
        width = defs.CELL_WIDTH;
      }
    }
    for (var i = 0; i < colCount; i++) {
      styleWidths.push(Math.round(Math.max(width, defs.CELL_MIN_WIDTH)) + "px");
    }
    return styleWidths;
  }
  function processDeleteIndexes(indexes, lowerBound, upperBound) {
    var inBounds = goog.array.every(indexes, function(index) {
      return index >= lowerBound && index <= upperBound;
    });
    if (!inBounds) {
      return null;
    }
    return indexes.slice().sort(function(a, b) {
      return b - a;
    });
  }
  function parseWidth(val) {
    if (val && val.indexOf("%") > -1) {
      return {unit:"%", value:parseInt(val, 10) / 100};
    } else {
      if (val && (val.indexOf("px") > -1 || val.indexOf("pt") > -1 || !isNaN(parseInt(val, 10)))) {
        return {unit:"px", value:parseInt(val, 10)};
      }
    }
    return {unit:null, value:null};
  }
  function prevNextCell(node, navigateByDOM, direction) {
    var td = goog.dom.getAncestor(node, util.dom.isTd, true);
    if (!td) {
      return null;
    }
    var matrix = util.table.matrix(goog.dom.getAncestor(td, util.dom.isTable));
    var info = util.table.infoForCell(td, matrix);
    var maxColIndex = matrix[0].length - 1;
    var maxRowIndex = matrix.length - 1;
    var rowIndex = info.startRowIndex;
    var colIndex = info.startColIndex;
    while (true) {
      if (direction < 0 && colIndex === 0) {
        rowIndex += direction;
        colIndex = maxColIndex;
      } else {
        if (direction > 0 && colIndex >= maxColIndex) {
          rowIndex += direction;
          colIndex = 0;
        } else {
          colIndex += direction;
        }
      }
      if (rowIndex < 0 || rowIndex > maxRowIndex) {
        break;
      }
      var itInfo = matrix[rowIndex][colIndex].info;
      if (!navigateByDOM && itInfo !== info || navigateByDOM && itInfo !== info && itInfo.startRowIndex === rowIndex) {
        return itInfo.node;
      }
    }
    return null;
  }
  function mergeColumnTdsAfterFlattening(matrix, startRowIndex, endRowIndex, startColIndex, endColIndex) {
    for (var rowIndex = startRowIndex; rowIndex <= endRowIndex; rowIndex++) {
      var tds = [];
      for (var colIndex = startColIndex; colIndex <= endColIndex; colIndex++) {
        var info = matrix[rowIndex][colIndex].info;
        if (info.startRowIndex === rowIndex && info.startColIndex === colIndex) {
          tds.push(info.node);
        }
      }
      util.table.mergeCells(tds);
    }
  }
  function mergeRowTdsAfterFlattening(matrix, startRowIndex, endRowIndex, startColIndex, endColIndex) {
    for (var colIndex = startColIndex; colIndex <= endColIndex; colIndex++) {
      var tds = [];
      for (var rowIndex = startRowIndex; rowIndex <= endRowIndex; rowIndex++) {
        var info = matrix[rowIndex][colIndex].info;
        if (info.startRowIndex === rowIndex && info.startColIndex === colIndex) {
          tds.push(info.node);
        }
      }
      util.table.mergeCells(tds);
    }
  }
  function mergeTdsAfterFlattening(matrix, expansions) {
  }
  function processTableForExpansion(table, expansions) {
    var td = goog.dom.getAncestor(table, util.dom.isTd);
    var cellInfo = util.table.infoForCell(td);
    var matrix = util.table.matrix(table);
    var afterHTML = null;
    var beforeHTML = null;
    var rowOffset = 0;
    var nextNode = util.dom.nextNodeDescendants(table, td);
    if (nextNode) {
      var afterNodeSplit = goog.editor.node.splitDomTreeAt(nextNode, nextNode, td);
      if (!util.dom.isEmptyContent(afterNodeSplit)) {
        afterHTML = afterNodeSplit.innerHTML;
        rowOffset += 1;
      }
    }
    goog.editor.node.splitDomTreeAt(table, table, td);
    if (!util.dom.isEmptyContent(td)) {
      beforeHTML = td.innerHTML;
      rowOffset += 1;
    }
    var info = {matrix:matrix, beforeHTML:beforeHTML, afterHTML:afterHTML, startRowIndex:cellInfo.startRowIndex, endRowIndex:cellInfo.endRowIndex, startColIndex:cellInfo.startColIndex, endColIndex:cellInfo.endColIndex, rowCount:matrix.length + rowOffset, colCount:matrix[0].length, insertRowIndex:cellInfo.endRowIndex + 1, insertColIndex:cellInfo.endColIndex + 1, addRowCount:matrix.length - 1 + rowOffset, addColCount:matrix[0].length - 1};
    var rowExp = expansions.reduce(function(prev, cur) {
      return !prev && cur.startRowIndex === info.startRowIndex || prev && prev.rowCount < cur.rowCount && cur.startRowIndex === info.startRowIndex ? cur : prev;
    }, null);
    if (rowExp) {
      info.addRowCount = Math.max(0, info.addRowCount + 1 - (rowExp.rowCount - (rowExp.startRowIndex - info.startRowIndex)));
      if (info.addRowCount) {
        info.insertRowIndex = Math.max(rowExp.endRowIndex + 1, info.insertRowIndex);
      }
    }
    var colExp = expansions.reduce(function(prev, cur) {
      return !prev && cur.startColIndex === info.startColIndex || prev && prev.colCount < cur.colCount && cur.startColIndex === info.startColIndex ? cur : prev;
    }, null);
    if (colExp) {
      info.addColCount = Math.max(0, info.addColCount + 1 - (colExp.colCount - (colExp.startColIndex - info.startColIndex)));
      if (info.addColCount) {
        info.insertColIndex = Math.max(colExp.endColIndex + 1, info.insertColIndex);
      }
    }
    return info;
  }
  function mergeExpansions(expansions, info) {
    var addition = {startRowIndex:info.startRowIndex, startColIndex:info.startColIndex, endRowIndex:info.startRowIndex + info.rowCount - 1, endColIndex:info.startColIndex + info.colCount - 1, rowCount:info.rowCount, colCount:info.colCount};
    var index = goog.array.findIndex(expansions, function(obj) {
      return obj.startRowIndex === addition.startRowIndex && obj.startColIndex === addition.startColIndex && (obj.rowCount < addition.rowCount || obj.colCount < addition.colCount);
    });
    if (index > -1) {
      var exp = expansions[index];
      exp.endRowIndex = Math.max(exp.endRowIndex, addition.endRowIndex);
      exp.endColIndex = Math.max(exp.endColIndex, addition.endColIndex);
      exp.rowCount = Math.max(exp.rowCount, addition.rowCount);
      exp.colCount = Math.max(exp.colCount, addition.colCount);
    } else {
      expansions.push(addition);
    }
  }
})();
goog.provide("uno.util.table.selection");
goog.require("goog.debug.Logger");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("uno.util.dom");
goog.require("uno.util.range");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.table.selection");
  var util = uno.util;
  var State = util.table.State;
  var Axis = util.table.Axis;
  var model = null;
  util.table.selection.isActive = function(enTable) {
    return !!(model && !model.activationTimer && (enTable === undefined || model.enTable === enTable));
  };
  util.table.selection.isPending = function(enTable) {
    return !!(model && model.activationTimer && (enTable === undefined || model.enTable === enTable));
  };
  util.table.selection.create = function(enTable, multirange, anchorCell, focusCell, axis) {
    var matrix = util.table.matrix(enTable, {selection:true});
    var info = !anchorCell ? findSelectedInfo(matrix) : null;
    util.table.selection.clear();
    if (!anchorCell) {
      if (!info) {
        enTable.classList.remove("multirange");
        return false;
      }
      anchorCell = info.node;
    }
    enTable.classList.add("multirange");
    var timer = setTimeout(function() {
      util.range.selectNodeContents(model.cursorProxy);
      model.activationTimer = setTimeout(function() {
        if (model) {
          model.activationTimer = null;
        }
      }, 10);
    }, 10);
    model = {enTable:enTable, cursorProxy:createCursorProxy(enTable), multirange:multirange, activationTimer:timer, anchorCell:anchorCell, colVector:createVector(util.table.query_(enTable, ".columns .handles").children), rowVector:createVector(util.table.query_(enTable, ".rows .handles").children), matrix:util.table.matrix(enTable)};
    if (info) {
      return applyDiff(model, matrix, true);
    }
    return util.table.selection.selectTo(focusCell || anchorCell, axis);
  };
  util.table.selection.selectTo = function(focusCell, axis) {
    if (!model) {
      throw new Error("Calling util.table.selection.selectTo on inactive model.");
    }
    var matrix = util.table.matrix(model.enTable);
    if (!axis && model.anchorCell === focusCell) {
      util.table.infoForCell(focusCell, matrix).state |= State.SELECTED;
      util.table.setActive(model.enTable, focusCell);
      return applyDiff(model, matrix);
    }
    var aInfo = util.table.infoForCell(model.anchorCell, matrix);
    var fInfo = model.anchorCell === focusCell ? aInfo : util.table.infoForCell(focusCell, matrix);
    var startRowIndex = axis === Axis.VERTICAL ? 0 : Math.min(aInfo.startRowIndex, fInfo.startRowIndex);
    var endRowIndex = axis === Axis.VERTICAL ? matrix.length - 1 : Math.max(aInfo.endRowIndex, fInfo.endRowIndex);
    var startColIndex = axis === Axis.HORIZONTAL ? 0 : Math.min(aInfo.startColIndex, fInfo.startColIndex);
    var endColIndex = axis === Axis.HORIZONTAL ? matrix[0].length - 1 : Math.max(aInfo.endColIndex, fInfo.endColIndex);
    setSelectedInRect(matrix, startRowIndex, endRowIndex, startColIndex, endColIndex, true);
    if (axis === Axis.VERTICAL) {
      focusCell = model.matrix[0][fInfo.startColIndex].info.node;
    } else {
      if (axis === Axis.HORIZONTAL) {
        focusCell = model.matrix[fInfo.startRowIndex][0].info.node;
      }
    }
    util.table.setActive(model.enTable, focusCell);
    return applyDiff(model, matrix);
  };
  util.table.selection.toggleAt = function(focusCell, axis) {
    if (!model) {
      throw new Error("Calling util.table.selection.toggleAt on inactive model.");
    }
    var matrix = cloneMatrix(model.enTable, model.matrix);
    var info = util.table.infoForCell(focusCell, matrix);
    if (!axis) {
      info.state ^= State.SELECTED;
      util.table.setActive(model.enTable, focusCell);
      return applyDiff(model, matrix);
    }
    var vert = axis === Axis.VERTICAL;
    var state = vert ? model.colVector[info.startColIndex].state : model.rowVector[info.startRowIndex].state;
    var selected = !(state & State.WHOLE_SELECTED);
    var startRowIndex = vert ? 0 : info.startRowIndex;
    var endRowIndex = vert ? matrix.length - 1 : info.endRowIndex;
    var startColIndex = !vert ? 0 : info.startColIndex;
    var endColIndex = !vert ? matrix[0].length - 1 : info.endColIndex;
    setSelectedInRect(matrix, startRowIndex, endRowIndex, startColIndex, endColIndex, selected);
    focusCell = vert ? model.matrix[0][info.startColIndex].info.node : model.matrix[info.startRowIndex][0].info.node;
    util.table.setActive(model.enTable, focusCell);
    return applyDiff(model, matrix);
  };
  util.table.selection.clear = function() {
    if (!util.table.selection.isActive()) {
      return;
    }
    clearTimeout(model.activationTimer);
    applyDiff(model, util.table.matrix(model.enTable));
    model.multirange.clear();
    model.cursorProxy.remove();
    model.enTable.classList.remove("multirange");
    model = null;
  };
  util.table.selection.getColumnIndexes = function(state) {
    if (!model) {
      return [];
    }
    return model.colVector.map(function(obj, index) {
      return obj.state & (state || State.SELECTED) ? index : null;
    }).filter(goog.isDefAndNotNull);
  };
  util.table.selection.getRowIndexes = function(state) {
    if (!model) {
      return [];
    }
    return model.rowVector.map(function(obj, index) {
      return obj.state & (state || State.SELECTED) ? index : null;
    }).filter(goog.isDefAndNotNull);
  };
  util.table.selection.getCells = function() {
    if (!model) {
      return [];
    }
    var nodes = [];
    model.matrix.forEach(function(row, rowIndex) {
      row.forEach(function(obj, colIndex) {
        var info = obj.info;
        if (info.state & State.SELECTED && info.startRowIndex === rowIndex && info.startColIndex === colIndex) {
          nodes.push(info.node);
        }
      });
    });
    return nodes;
  };
  util.table.selection.getPasteCell = function() {
    if (!model) {
      return null;
    }
    var rowIndexes = util.table.selection.getRowIndexes();
    var colIndexes = util.table.selection.getColumnIndexes();
    if (rowIndexes.length === 0 || colIndexes.length === 0) {
      return null;
    }
    return model.matrix[rowIndexes[0]][colIndexes[0]].info.node;
  };
  function applyDiff(mod, matrix, force) {
    var hasSelection = false;
    var clen = mod.colVector.length;
    var rlen = mod.rowVector.length;
    var colSelectedCounts = goog.array.repeat(0, clen);
    var rowSelectedCounts = goog.array.repeat(0, rlen);
    var colOverlapIndexes = goog.array.repeat(undefined, clen);
    var rowOverlapIndexes = goog.array.repeat(undefined, rlen);
    mod.matrix.forEach(function(row, rowIndex) {
      row.forEach(function(obj, colIndex) {
        var info = obj.info;
        var state = matrix[rowIndex][colIndex].info.state;
        var selected = state & State.SELECTED;
        var root = info.startRowIndex === rowIndex && info.startColIndex === colIndex;
        if (root && (force || (info.state & State.SELECTED) !== selected)) {
          var cell = info.node;
          var range = goog.dom.Range.createFromNodes(cell, 0, cell, cell.childNodes.length);
          mod.multirange.toggleTextRange(range, selected);
          cell.classList.toggle("selected", selected);
          info.state = state;
        }
        if (selected) {
          hasSelection = true;
          colSelectedCounts[colIndex] += 1;
          rowSelectedCounts[rowIndex] += 1;
          storeOverlapIndexes(colOverlapIndexes, colIndex, info.startColIndex, info.endColIndex);
          storeOverlapIndexes(rowOverlapIndexes, rowIndex, info.startRowIndex, info.endRowIndex);
        }
      });
    });
    applyVectorDiff(mod.colVector, colSelectedCounts, colOverlapIndexes, rlen);
    applyVectorDiff(mod.rowVector, rowSelectedCounts, rowOverlapIndexes, clen);
    return hasSelection;
  }
  function applyVectorDiff(vector, selectedCounts, overlapIndexes, length) {
    overlapIndexes = overlapIndexes.map(function(obj) {
      return Object.keys(obj || {}).map(function(key) {
        return parseInt(key, 10);
      });
    });
    var compare = function(i) {
      return selectedCounts[i] === length;
    };
    vector.forEach(function(obj, index) {
      var state = 0;
      var count = selectedCounts[index];
      if (count === length) {
        state |= State.WHOLE_SELECTED;
        if (goog.array.every(overlapIndexes[index], compare)) {
          state |= State.DRAGGABLE;
        }
      }
      if (count > 0) {
        state |= State.SELECTED;
      }
      obj.state = state;
      obj.node.classList.toggle("wselected", state & State.WHOLE_SELECTED);
      obj.node.classList.toggle("selected", state & State.SELECTED);
      obj.node.classList.toggle("draggable", state & State.DRAGGABLE);
    });
  }
  function storeOverlapIndexes(arr, index, startIndex, endIndex) {
    if (startIndex === index && endIndex === index) {
      return;
    }
    var obj = arr[index];
    if (!obj) {
      obj = {};
      arr[index] = obj;
    }
    for (var i = startIndex; i <= endIndex; i++) {
      if (i !== index) {
        obj[i] = true;
      }
    }
  }
  function findSelectedInfo(matrix) {
    var info = null;
    for (var i = 0, il = matrix.length; i < il; i++) {
      for (var j = 0, jl = matrix[i].length; j < jl; j++) {
        var obj = matrix[i][j];
        if (obj.info.state & State.SELECTED) {
          info = obj.info;
          break;
        }
      }
      if (info) {
        break;
      }
    }
    return info;
  }
  function setSelectedInRect(matrix, startRowIndex, endRowIndex, startColIndex, endColIndex, selected) {
    var indexes = util.table.expandIntoRectIndexes(matrix, startRowIndex, endRowIndex, startColIndex, endColIndex);
    for (var rowIndex = indexes.startRowIndex; rowIndex <= indexes.endRowIndex; rowIndex++) {
      for (var colIndex = indexes.startColIndex; colIndex <= indexes.endColIndex; colIndex++) {
        if (selected) {
          matrix[rowIndex][colIndex].info.state |= State.SELECTED;
        } else {
          matrix[rowIndex][colIndex].info.state &= ~State.SELECTED;
        }
      }
    }
  }
  function cloneMatrix(enTable, matrix) {
    var newMatrix = util.table.matrix(enTable);
    matrix.forEach(function(row, rowIndex) {
      row.forEach(function(obj, colIndex) {
        newMatrix[rowIndex][colIndex].info.state = obj.info.state;
      });
    });
    return newMatrix;
  }
  function createVector(nodesOrVector) {
    return goog.array.map(nodesOrVector, function(obj) {
      return {node:util.dom.isElementNode(obj) ? obj : obj.node, state:0};
    });
  }
  function createCursorProxy(enTable) {
    var node = enTable.querySelector(".cursor-proxy");
    if (!node) {
      node = goog.dom.createDom("cursor-proxy");
      node.innerHTML = "&nbsp;";
      enTable.querySelector("table").appendChild(node);
    }
    return node;
  }
})();
goog.provide("uno.util.copy.table");
goog.require("uno.defs");
goog.require("uno.util.table");
goog.require("uno.util.table.selection");
(function() {
  var util = uno.util;
  var defs = uno.defs;
  util.copy.table.getPastableHtml = function() {
    var selectedCells = util.table.selection.getCells();
    if (selectedCells.length === 0) {
      return "";
    } else {
      if (selectedCells.length === 1) {
        return selectedCells[0].innerHTML;
      }
    }
    var table = util.table.getActive().querySelector("table").cloneNode(true);
    var cols = table.querySelector("colgroup").children;
    var matrix = util.table.matrix(table, {selection:true});
    var colIndexes = util.table.selection.getColumnIndexes();
    var rowIndexes = util.table.selection.getRowIndexes();
    var indexes = util.table.expandIntoRectIndexes(matrix, rowIndexes[0], goog.array.peek(rowIndexes), colIndexes[0], goog.array.peek(colIndexes));
    var proxy = table.querySelector("cursor-proxy");
    if (proxy) {
      proxy.remove();
    }
    goog.array.forEachRight(matrix, function(row, rowIndex) {
      if (!(indexes.startRowIndex <= rowIndex && rowIndex <= indexes.endRowIndex)) {
        table.rows[rowIndex].remove();
      } else {
        goog.array.forEachRight(row, function(obj, colIndex) {
          var info = obj.info;
          if (!info.node.style.borderWidth) {
            info.node.style.borderWidth = "1px";
          }
          if (!info.node.style.borderStyle) {
            info.node.style.borderStyle = "solid";
          }
          if (!info.node.style.borderColor) {
            info.node.style.borderColor = "#ccc";
          }
          if (info.startRowIndex > rowIndex && info.startColIndex > colIndex) {
            return;
          }
          if (!(indexes.startColIndex <= colIndex && colIndex <= indexes.endColIndex)) {
            info.node.remove();
          } else {
            if (info.state & util.table.State.SELECTED) {
              info.node.classList.remove("selected");
            } else {
              info.node.innerHTML = defs.table.CELL_HTML;
            }
          }
        });
      }
    });
    goog.array.forEachRight(matrix[0], function(row, colIndex) {
      if (!(indexes.startColIndex <= colIndex && colIndex <= indexes.endColIndex)) {
        cols[colIndex].remove();
      }
    });
    return table.outerHTML;
  };
})();
goog.provide("uno.util.copy.rich");
(function() {
  var util = uno.util;
  var dom = util.dom;
  util.copy.rich.copy = function(root) {
    if (root.childNodes.length === 1 && dom.isDiv(root.firstChild)) {
      return root.firstChild.innerHTML;
    }
    return root.innerHTML;
  };
})();
goog.provide("uno.util.canvas");
goog.require("goog.debug.Logger");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.canvas");
  var util = uno.util;
  var scratch;
  util.canvas.create = function(width, height) {
    var canvas = document.createElement("canvas");
    util.canvas.resize(canvas, width, height);
    return canvas;
  };
  util.canvas.resize = function(canvas, width, height) {
    var ratio = util.styles.getDevicePixelRatio();
    var ctx = canvas.getContext("2d");
    canvas.width = width * ratio;
    canvas.height = height * ratio;
    canvas.style.width = width + "px";
    canvas.style.height = height + "px";
    ctx.scale(ratio, ratio);
    return canvas;
  };
  util.canvas.width = function(canvas) {
    return parseFloat(canvas.style.width) || canvas.width;
  };
  util.canvas.height = function(canvas) {
    return parseFloat(canvas.style.height) || canvas.height;
  };
  util.canvas.getScratchCanvas = function(width, height) {
    if (!scratch) {
      scratch = util.canvas.create(width, height);
    } else {
      util.canvas.resize(scratch, width, height);
    }
    var ctx = scratch.getContext("2d");
    ctx.save();
    ctx.fillStyle = "#fff";
    ctx.fillRect(0, 0, width, height);
    ctx.restore();
    return scratch;
  };
  util.canvas.fillText = function(ctx, text, x, y, width) {
    if (text) {
      var len = text.length - 4;
      var metrics = ctx.measureText(text);
      while (metrics.width > width && len > 0) {
        text = text.substring(0, len) + "...";
        len--;
        metrics = ctx.measureText(text);
      }
      ctx.fillText(text, x, y);
    }
  };
  util.canvas.rad = function(deg) {
    return deg * Math.PI / 180;
  };
})();
goog.provide("uno.components.ImageResizer");
goog.require("goog.dom");
goog.require("goog.events");
goog.require("goog.style");
goog.require("uno.util.dom");
goog.require("uno.util.styles");
goog.require("uno.util.table");
goog.require("uno.util.zoomscale");
(function() {
  var BORDER_WIDTH = 2;
  var MIN_WIDTH = 50 + BORDER_WIDTH * 2;
  var util = uno.util;
  var ImageResizer = uno.components.ImageResizer = function(editor) {
    this.resizing = false;
    this.editor_ = editor;
    this.target_ = null;
    this.meta_ = null;
    this.frame_ = goog.dom.createDom("div", {class:"en-imageresizer-frame"});
    this.element = goog.dom.createDom("div", {class:"en-imageresizer-trigger"});
    goog.events.listen(this.element, "mousedown", handleResizeStart.bind(this));
    goog.events.listen(window, "mousemove", handleResizeChange.bind(this));
    goog.events.listen(window, "mouseup", handleResizeEnd.bind(this));
    goog.events.listen(window, "contextmenu", handleContextMenu.bind(this));
  };
  Object.defineProperty(ImageResizer.prototype, "attached", {get:function() {
    return !!this.target_;
  }});
  ImageResizer.prototype.attach = function(img) {
    if (this.resizing || !img) {
      return;
    }
    this.detach();
    this.element.style.display = "block";
    this.target_ = img;
    this.layout();
  };
  ImageResizer.prototype.detach = function() {
    if (this.resizing) {
      return;
    }
    this.element.style.display = "none";
    this.frame_.remove();
    this.target_ = null;
  };
  ImageResizer.prototype.layout = function() {
    if (!this.target_) {
      return false;
    }
    var zoom = uno.util.zoomscale.getZoom();
    var rect = this.target_.getBoundingClientRect();
    if (!rect.width || !rect.height) {
      return false;
    }
    this.element.style.zoom = zoom;
    this.element.style.top = rect.top + rect.height + document.body.scrollTop / zoom + "px";
    this.element.style.left = rect.left + rect.width + document.body.scrollLeft / zoom + "px";
    return true;
  };
  function handleResizeEnd(evt) {
    if (!this.meta_) {
      return;
    }
    evt.preventDefault();
    evt.stopPropagation();
    if (this.meta_.width) {
      this.target_.setAttribute("width", this.meta_.width);
      this.target_.dataset.width = this.meta_.width;
    }
    this.frame_.remove();
    this.meta_ = null;
    this.resizing = false;
    document.documentElement.classList.remove("nwse-resizing");
    this.layout();
    var enTable = goog.dom.getAncestor(this.target_, util.dom.isEntable);
    if (enTable) {
      util.table.layout(enTable);
    }
    this.editor_.execCommand("focus", true);
    this.editor_.dispatchChange();
  }
  function handleResizeChange(evt) {
    if (!this.meta_) {
      return;
    }
    evt.preventDefault();
    evt.stopPropagation();
    var d = this.meta_;
    var x = evt.clientX - d.rect.left;
    var y = evt.clientY - d.rect.top;
    var scaleX = x / d.fromPoint.x;
    var scaleY = y / d.fromPoint.y;
    var belowDiagonal = d.ratio > Math.abs(x / y);
    var scaledWidth = belowDiagonal ? d.rect.height * scaleY * d.ratio : scaleX * d.rect.width;
    var width = Math.round(Math.max(Math.min(scaledWidth, d.maxWidth), d.minWidth));
    var height = width / d.ratio;
    if (this.meta_.width !== width) {
      this.meta_.width = width;
      this.frame_.style.width = width + "px";
      this.frame_.style.height = height + "px";
    }
  }
  function handleResizeStart(evt) {
    if (!this.target_) {
      return;
    }
    evt.preventDefault();
    evt.stopPropagation();
    this.resizing = true;
    var zoom = uno.util.zoomscale.getZoom();
    var noteWidth = uno.util.styles.getNoteWidth(this.editor_.field);
    var rect = this.target_.getBoundingClientRect();
    this.frame_.style.zoom = zoom;
    this.frame_.style.top = rect.top + document.body.scrollTop / zoom + "px";
    this.frame_.style.left = rect.left + document.body.scrollLeft / zoom + "px";
    this.frame_.style.width = rect.width + "px";
    this.frame_.style.height = rect.height + "px";
    var tdWidth = Infinity;
    var td = goog.dom.getAncestor(this.target_, util.dom.isTd);
    if (td) {
      tdWidth = td.getBoundingClientRect().width - 20;
    }
    this.meta_ = {fromPoint:{x:evt.clientX - rect.left, y:evt.clientY - rect.top}, rect:rect, ratio:this.target_.naturalWidth / this.target_.naturalHeight, width:null, maxWidth:Math.min(this.target_.naturalWidth, noteWidth, tdWidth), minWidth:MIN_WIDTH};
    this.element.parentNode.appendChild(this.frame_);
    if (!this.target_.getAttribute("width")) {
      this.meta_.rect.width += BORDER_WIDTH;
      this.meta_.rect.height += BORDER_WIDTH;
    }
    document.documentElement.classList.add("nwse-resizing");
  }
  function handleContextMenu(evt) {
    if (this.resizing) {
      evt.preventDefault();
    }
  }
})();
goog.provide("uno.util.img");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.classlist");
goog.require("uno.components.ImageResizer");
goog.require("uno.util.dom");
goog.require("uno.util.observer");
goog.require("uno.util.styles");
goog.require("uno.util.tools");
goog.require("uno.util.zoomscale");
(function() {
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.util.img");
  var selectedImage = null;
  var toolbarImage = null;
  var toolbarHandler = null;
  var resizer = null;
  var toolbar = null;
  var scrollableCandidate = null;
  var scrollableTimeout = null;
  var toolsHiddenByScroll = false;
  util.img.all = function(root) {
    return root.querySelectorAll("img.en-media-image");
  };
  util.img.convertMediaToSlug = function(enmedia, props, editor) {
    var img = new Image;
    goog.dom.classlist.addAll(img, ["en-media", "en-media-image"]);
    img.dataset.hash = props.hash;
    img.dataset.type = props.type;
    img.dataset.url = props.url;
    if (props.elementId) {
      img.id = props.elementId;
    }
    if (props.width != null) {
      img.setAttribute("width", props.width);
    }
    if (props.height != null && editor.hasForeignSource()) {
      img.setAttribute("height", props.height);
    }
    if (img.getAttribute("width")) {
      img.dataset.width = img.getAttribute("width");
    }
    if (typeof props.overlayOpacity !== "undefined") {
      img.style.opacity = 1 - parseInt(props.overlayOpacity, 10);
    }
    if (props.overlayImageURL) {
      img.src = props.overlayImageURL;
      img.style.backgroundImage = "url(" + props.url + ")";
      img.style.backgroundSize = "cover";
    } else {
      img.src = props.url;
    }
    goog.dom.replaceNode(img, enmedia);
    return img;
  };
  util.img.preloadTools = function(editor) {
    util.img.preloadToolbar(editor.config);
    util.img.preloadResizer(editor);
  };
  util.img.preloadToolbar = function(config) {
    if (toolbar) {
      toolbar.remove();
      toolbar = null;
    }
    if (!config.images.annotate) {
      return;
    }
    toolbar = goog.dom.createDom("div", {class:"en-imagebar"});
    util.tools.append(toolbar);
    var factoryButton = function(type) {
      var node = goog.dom.createDom("div", {class:"en-imagebar-button en-imagebar-" + type, "data-command":type});
      goog.events.listen(node, "click", function() {
        if (toolbarImage && toolbarHandler) {
          toolbarHandler(toolbarImage, this.dataset.command);
        }
      });
      toolbar.appendChild(node);
    };
    if (config.images.annotate) {
      factoryButton("annotate");
    }
  };
  util.img.preloadResizer = function(editor) {
    if (resizer) {
      resizer.element.remove();
      resizer = null;
    }
    if (!editor.config.images.resize) {
      return;
    }
    resizer = new uno.components.ImageResizer(editor);
    util.tools.append(resizer.element);
  };
  util.img.createImage = function(src) {
    var img = new Image;
    if (src != null) {
      img.src = src;
    }
    return img;
  };
  util.img.convertClientElementToSlug = function(img) {
    return img;
  };
  util.img.isToolbarButton = function(node) {
    return goog.dom.classlist.contains(node, "en-imagebar-button");
  };
  util.img.isResource = function(node) {
    return node && goog.dom.classlist.contains(node, "en-media-image");
  };
  util.img.isSelected = function(nodeOrRange) {
    if (!selectedImage) {
      return false;
    }
    if (util.dom.isElementNode(nodeOrRange)) {
      return nodeOrRange === selectedImage;
    } else {
      if (nodeOrRange && nodeOrRange.isCollapsed && !nodeOrRange.isCollapsed()) {
        var anchorNode = nodeOrRange.getAnchorNode();
        var focusNode = nodeOrRange.getFocusNode();
        if (anchorNode === focusNode && anchorNode.children) {
          for (var i = 0, l = anchorNode.children.length; i < l; i++) {
            if (anchorNode.children[i] === selectedImage) {
              return true;
            }
          }
        }
      }
    }
    return false;
  };
  util.img.setToolbar = function(img, handler) {
    if (!toolbar || selectedImage || img === toolbarImage || !img && !toolbarImage) {
      return;
    }
    toolbarImage = img;
    toolbarHandler = handler;
    if (img) {
      scrollableCandidate = getScrollableCandidate(img);
      toolbar.style.display = "block";
      util.img.layoutToolbar();
      util.observer.addHandler(util.img.layoutToolbar);
    } else {
      scrollableCandidate = null;
      toolbar.style.display = "none";
      util.observer.removeHandler(util.img.layoutToolbar);
    }
  };
  util.img.setSelected = function(img) {
    if (resizer && resizer.resizing || img === selectedImage || !img && !selectedImage) {
      return;
    }
    if (selectedImage) {
      selectedImage.classList.remove("en-media-selected");
      selectedImage = null;
    }
    if (img) {
      util.img.setToolbar(null);
      scrollableCandidate = getScrollableCandidate(img);
      selectedImage = img;
      selectedImage.classList.add("en-media-selected");
      goog.dom.Range.createFromNodeContents(img).select();
    } else {
      scrollableCandidate = null;
    }
    if (resizer && img) {
      resizer.attach(img);
      util.observer.addHandler(util.img.layoutResizer);
    } else {
      if (resizer) {
        resizer.detach();
        util.observer.removeHandler(util.img.layoutResizer);
      }
    }
  };
  util.img.hideToolsOnScrollIfNeeded = function(scrollingTarget) {
    if (!scrollableCandidate || scrollingTarget !== scrollableCandidate) {
      return;
    } else {
      if (!toolsHiddenByScroll) {
        document.documentElement.classList.add("scrolling-x");
        toolsHiddenByScroll = true;
      }
    }
    clearTimeout(scrollableTimeout);
    scrollableTimeout = setTimeout(function() {
      util.img.layoutResizer();
      util.img.layoutToolbar();
      document.documentElement.classList.remove("scrolling-x");
      toolsHiddenByScroll = false;
    }, 200);
  };
  util.img.layoutResizer = function() {
    if (!resizer || !selectedImage || resizer.resizing || !resizer.attached) {
      return;
    }
    if (!resizer.layout()) {
      util.img.setSelected(null);
    }
  };
  util.img.layoutToolbar = function() {
    if (!toolbar || !toolbarImage) {
      return;
    }
    var rect = toolbarImage.getBoundingClientRect();
    if (!rect.width || !rect.height) {
      util.img.setToolbar(null);
    } else {
      var zoom = util.zoomscale.getZoom();
      toolbar.style.zoom = zoom;
      toolbar.style.top = rect.top + document.body.scrollTop / zoom + "px";
      toolbar.style.left = rect.left + "px";
    }
  };
  util.img.getSelectedImage = function() {
    return selectedImage;
  };
  util.img.removeOverlay = function(img) {
    if (util.img.isResource(img) && !!img.style.backgroundImage) {
      img.src = img.dataset.url;
      img.style.backgroundImage = null;
      img.style.backgroundSize = null;
    }
  };
  util.img.loadAsync = function(src) {
    return new Promise(function(resolve, reject) {
      var img = document.createElement("img");
      img.src = src;
      goog.events.listenOnce(img, "load", function() {
        resolve(img);
      });
      goog.events.listenOnce(img, "error", reject);
    });
  };
  util.img.loadFromClientAsync = function(src, client) {
    var fixtures = client && client.fixtures ? client.fixtures.map : null;
    if (fixtures && fixtures[src]) {
      return new Promise(function(resolve, reject) {
        var img = new Image;
        img.crossOrigin = "Anonymous";
        img.src = fixtures[src];
        goog.events.listenOnce(img, "load", function() {
          resolve(img);
        });
        goog.events.listenOnce(img, "error", reject);
      });
    } else {
      return util.img.loadAsync(src);
    }
  };
  util.img.ratioResizeIfNeeded = function(node) {
    return new Promise(function(resolve) {
      var ratio = util.styles.getDevicePixelRatio();
      if (!util.dom.isImg(node) || !node.parentNode || node.hasAttribute("width") || ratio === 1) {
        resolve(false);
        return;
      }
      var resize = function() {
        var width = Math.round(node.naturalWidth / ratio);
        node.setAttribute("width", width);
        node.dataset.width = width;
        resolve(true);
      };
      if (node.naturalWidth) {
        resize();
      } else {
        goog.events.listenOnce(node, "load", resize);
      }
    });
  };
  function getScrollableCandidate(node) {
    while (node !== document.body) {
      if (getComputedStyle(node).overflowX !== "visible") {
        return node;
      }
      node = node.parentNode;
    }
    return null;
  }
})();
goog.provide("uno.util.resource.generic");
goog.require("uno.util.canvas");
goog.require("uno.util.img");
(function() {
  var generic = uno.util.resource.generic;
  var util = uno.util;
  var resourceFillStyle = "#8E8E93";
  var resourceFontStyle = '12px "Helvetica Neue", Helvetica, Arial, sans';
  generic.findResourcesInClientHtml = function() {
    return [];
  };
  generic.findResourcesInClipboardHtml = function() {
    return [];
  };
  generic.convertMediaToSlug = function(enmedia, props, editor) {
    var slug;
    if (util.resource.isImage(props.type)) {
      slug = util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      slug = convertMediaToImage(enmedia, props, editor);
    }
    return slug;
  };
  function convertMediaToImage(enmedia, props, editor) {
    var img = util.resource.findByRef(props.reference, editor.field);
    if (img == null) {
      img = new Image;
      img.width = 160;
      img.height = 120;
      img.style.width = "160px";
      img.style.height = "120px";
      img.dataset.hash = props.hash;
      img.dataset.type = props.type;
    }
    var canvas = util.canvas.getScratchCanvas(img.width, img.height);
    var ctx = canvas.getContext("2d");
    var padding = 10;
    if (props.state === "unloaded") {
      renderUnloadedResource(ctx, img, props, padding);
    } else {
      if (props.state === "loading") {
        renderLoadingResource(ctx, img, props, padding);
      } else {
        if (props.state === "loaded" || props.state == null) {
          renderFilename(ctx, img, props, padding);
          if (props.thumbnailURL != null) {
            var thumbnail = new Image;
            thumbnail.src = props.thumbnailURL;
            editor.eventRegister.listenOnce(thumbnail, "load", function() {
              var newCanvas = util.canvas.getScratchCanvas(img.width, img.height);
              var newCtx = newCanvas.getContext("2d");
              var image = util.resource.findByRef(props.reference, editor.field);
              renderLoadedResource(newCtx, img, props, padding, thumbnail);
              image.src = newCanvas.toDataURL();
            });
          }
        }
      }
    }
    img.src = canvas.toDataURL();
    return img;
  }
  function renderLoadedResource(ctx, img, props, padding, thumbnail) {
    var dHeight = Math.min(thumbnail.height, 48);
    var dWidth = dHeight / thumbnail.height * thumbnail.width;
    ctx.drawImage(thumbnail, (img.width - dWidth) / 2, padding, dWidth, dHeight);
    renderFilename(ctx, img, props, padding);
  }
  function renderFilename(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.filename != null) {
      var filename = props.filename;
      var len = filename.length - 4;
      var metrics = ctx.measureText(filename);
      while (metrics.width > img.width - padding * 2 && len > 0) {
        filename = props.filename.substring(0, len) + "...";
        len--;
        metrics = ctx.measureText(filename);
      }
      ctx.fillText(filename, img.width / 2, img.height * 0.75);
    }
    ctx.restore();
  }
  function renderUnloadedResource(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.title != null) {
      ctx.save();
      ctx.fillStyle = "#167EFB";
      ctx.font = '700 14px "Helvetica Neue", Helvetica, Arial, sans';
      ctx.textAlign = "center";
      ctx.fillText(props.title, img.width / 2, img.height * 0.25);
      ctx.restore();
    }
    if (props.filesize != null) {
      ctx.fillText(props.filesize, img.width / 2, img.height * 0.75 + 15);
    }
    ctx.restore();
    renderFilename(ctx, img, props, padding);
  }
  function renderLoadingResource(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.downloaded != null) {
      ctx.fillText(props.downloaded, img.width / 2, img.height * 0.75 + 15);
    }
    var progress = Math.max(Math.min(1, props.progress), 0);
    var cx = img.width / 2;
    var cy = img.height * 0.25;
    var radius = 25;
    ctx.lineWidth = 3;
    ctx.strokeStyle = "#dedede";
    ctx.beginPath();
    ctx.arc(cx, cy, radius, 0, 2 * Math.PI, false);
    ctx.stroke();
    ctx.fillStyle = "#dedede";
    ctx.beginPath();
    ctx.arc(cx, cy, radius, util.canvas.rad(360 * progress - 90), util.canvas.rad(270), false);
    ctx.lineTo(cx, cy);
    ctx.closePath();
    ctx.fill();
    ctx.restore();
    renderFilename(ctx, img, props, padding);
  }
  generic.formatForExport = function(html) {
    return html;
  };
  generic.dictFromElement = function() {
    return {};
  };
  generic.dictFromClipboardElement = function() {
    return {};
  };
  generic.convertClientElementToSlug = function(el) {
    return el;
  };
  generic.convertSlugToClientElement = function(el) {
    return el;
  };
  generic.convertSlugToClipboardElement = function(slug) {
    return slug;
  };
  generic.toggleObjectsInRange = function(range, dict) {
    return false;
  };
})();
goog.provide("uno.util.resource.android");
goog.require("uno.util.canvas");
goog.require("uno.util.resource.generic");
(function() {
  var util = uno.util;
  var android = util.resource.android;
  var generic = util.resource.generic;
  android.findResourcesInClientHtml = function(root) {
    return [];
  };
  android.findResourcesInClipboardHtml = function(root) {
    return [];
  };
  android.convertMediaToSlug = function(enmedia, props, editor) {
    var slug;
    if (util.resource.isImage(props.type)) {
      slug = util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      slug = convertMediaToImage(enmedia, props, editor);
    }
    return slug;
  };
  function convertMediaToImage(enmedia, props, editor) {
    var img = util.resource.findByRef(props.reference, editor.field);
    if (img == null) {
      img = new Image;
      img.width = 320;
      img.height = 40;
      img.style.width = "320px";
      img.style.height = "40px";
      img.dataset.hash = props.hash;
      img.dataset.type = props.type;
    }
    var canvas = util.canvas.getScratchCanvas(img.width, img.height);
    var ctx = canvas.getContext("2d");
    ctx.save();
    ctx.fillStyle = "#8E8E93";
    ctx.font = '12px "Helvetica Neue", Helvetica, Arial, sans';
    ctx.textAlign = "center";
    ctx.fillText(props.filename || "resource", img.width / 2, img.height / 2);
    ctx.restore();
    img.src = canvas.toDataURL();
    return img;
  }
  android.dictFromElement = function(el) {
    return {};
  };
  android.dictFromClipboardElement = function(el, context) {
    return {};
  };
  android.formatForExport = function(html) {
    return html;
  };
  android.convertClientElementToSlug = function(el) {
    return el;
  };
  android.convertSlugToClientElement = function(el) {
    return el;
  };
  android.convertSlugToClipboardElement = function(slug) {
    return slug;
  };
  android.toggleObjectsInRange = function(range, clonedObjects) {
    return false;
  };
})();
goog.provide("uno.util.resource.ios");
goog.require("uno.util.dom");
goog.require("uno.util.resource.generic");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.resource.ios");
  var util = uno.util;
  var ios = util.resource.ios;
  var generic = util.resource.generic;
  var resourceFillStyle = "#8E8E93";
  var resourceFontStyle = '12px "Helvetica Neue", Helvetica, Arial, sans';
  ios.findResourcesInClientHtml = function(root) {
    return [];
  };
  ios.findResourcesInClipboardHtml = function(root) {
    return root.querySelectorAll("img:not(.en-todo):not(.en-crypt):not(.en-richlink)");
  };
  ios.convertMediaToSlug = function(enmedia, props, editor) {
    var slug;
    if (util.resource.isImage(props.type)) {
      slug = util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      slug = convertMediaToImage(enmedia, props, editor);
    }
    return slug;
  };
  function convertMediaToImage(enmedia, props, editor) {
    var img = util.resource.findByRef(props.reference, editor.field);
    if (img == null) {
      img = new Image;
      img.width = 160;
      img.height = 120;
      img.style.width = "160px";
      img.style.height = "120px";
      img.dataset.hash = props.hash;
      img.dataset.type = props.type;
    }
    var canvas = util.canvas.getScratchCanvas(img.width, img.height);
    var ctx = canvas.getContext("2d");
    var padding = 10;
    if (props.state === "unloaded") {
      renderUnloadedResource(ctx, img, props, padding);
    } else {
      if (props.state === "loading") {
        renderLoadingResource(ctx, img, props, padding);
      } else {
        if (props.state === "loaded" || props.state == null) {
          renderFilename(ctx, img, props, padding);
          if (props.thumbnailURL != null) {
            var thumbnail = new Image;
            thumbnail.src = props.thumbnailURL;
            editor.eventRegister.listenOnce(thumbnail, "load", function() {
              var canvas = util.canvas.getScratchCanvas(img.width, img.height);
              var ctx = canvas.getContext("2d");
              var image = util.resource.findByRef(props.reference, editor.field);
              renderLoadedResource(ctx, img, props, padding, thumbnail);
              image.src = canvas.toDataURL();
            });
          }
        }
      }
    }
    img.src = canvas.toDataURL();
    return img;
  }
  function renderUnloadedResource(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.title != null) {
      ctx.save();
      ctx.fillStyle = "#167EFB";
      ctx.font = '700 14px "Helvetica Neue", Helvetica, Arial, sans';
      ctx.textAlign = "center";
      ctx.fillText(props.title, img.width / 2, img.height * .25);
      ctx.restore();
    }
    if (props.filesize != null) {
      ctx.fillText(props.filesize, img.width / 2, img.height * .75 + 15);
    }
    ctx.restore();
    renderFilename(ctx, img, props, padding);
  }
  function renderLoadingResource(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.downloaded != null) {
      ctx.fillText(props.downloaded, img.width / 2, img.height * .75 + 15);
    }
    var progress = Math.max(Math.min(1, props.progress), 0);
    var cx = img.width / 2;
    var cy = img.height * .25;
    var radius = 25;
    ctx.lineWidth = 3;
    ctx.strokeStyle = "#dedede";
    ctx.beginPath();
    ctx.arc(cx, cy, radius, 0, 2 * Math.PI, false);
    ctx.stroke();
    ctx.fillStyle = "#dedede";
    ctx.beginPath();
    ctx.arc(cx, cy, radius, util.canvas.rad(360 * progress - 90), util.canvas.rad(270), false);
    ctx.lineTo(cx, cy);
    ctx.closePath();
    ctx.fill();
    ctx.restore();
    renderFilename(ctx, img, props, padding);
  }
  function renderLoadedResource(ctx, img, props, padding, thumbnail) {
    var dHeight = Math.min(thumbnail.height, 48);
    var dWidth = dHeight / thumbnail.height * thumbnail.width;
    ctx.drawImage(thumbnail, (img.width - dWidth) / 2, padding, dWidth, dHeight);
    renderFilename(ctx, img, props, padding);
  }
  function renderFilename(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.filename != null) {
      var filename = props.filename;
      var len = filename.length - 4;
      var metrics = ctx.measureText(filename);
      while (metrics.width > img.width - padding * 2 && len > 0) {
        filename = props.filename.substring(0, len) + "...";
        len--;
        metrics = ctx.measureText(filename);
      }
      ctx.fillText(filename, img.width / 2, img.height * .75);
    }
    ctx.restore();
  }
  ios.decorateMedia = function(enmedia, props) {
    enmedia.dataset.url = props.url;
    goog.dom.append(enmedia, goog.dom.createDom("en-ux", {}, [goog.dom.createDom("span", {class:"en-resource-progress"}, goog.dom.createDom("span", {class:"en-resource-progress-fill"}, goog.dom.createDom("span", {class:"en-resource-progress-mask"}))), goog.dom.createDom("span", {class:"en-resource-icon"}, goog.dom.createDom("img", {src:props.thumbnailURL})), goog.dom.createDom("span", {class:"en-resource-title"}, props.title), goog.dom.createDom("span", {class:"en-resource-name"}, props.filename), 
    goog.dom.createDom("span", {class:"en-resource-value"}, props.state == "loading" ? props.downloaded : props.filesize)]));
    if (props.state) {
      goog.dom.classes.add(enmedia, props.state);
    }
    if (props.state === "loading") {
      var value = Math.max(Math.min(1, props.progress), 0);
      var halfValue = value > 0.5 ? value - 0.5 : value;
      var progressFill = enmedia.querySelector(".en-resource-progress-fill");
      goog.style.setStyle(progressFill, "-webkit-transform", "rotate(" + 360 * value + "deg)");
      var progressMask = progressFill.children[0];
      goog.style.setStyle(progressMask, "-webkit-transform", "rotate(" + -180 * halfValue * 2 + "deg)");
      goog.style.setStyle(progressMask, "background", value * 2 <= 1 ? "#fff" : "#dedede");
    }
    if (props.overlayOpacity > 0) {
      goog.dom.classes.add(enmedia, "overlayed");
      var overlay = goog.dom.createDom("span", {class:"en-resource-overlay"});
      overlay.style.backgroundColor = "rgba(0, 0, 0, " + props.overlayOpacity + ")";
      enmedia.appendChild(overlay);
    }
    return enmedia;
  };
  ios.dictFromElement = function(el) {
    return {};
  };
  ios.dictFromClipboardElement = function(el, context) {
    var dict;
    if (util.dom.compareTagName(el, "img")) {
      dict = context.resources[el.getAttribute("src")];
    } else {
      log.severe("ios resource from clipboard is not an img");
      if (el) {
        log.info("ios.dictFromClipboardElement received " + el.tagName);
      }
    }
    return dict;
  };
  ios.formatForExport = function(html) {
    return html;
  };
  ios.convertClientElementToSlug = function(el) {
    return el;
  };
  ios.convertSlugToClientElement = function(el) {
    return el;
  };
  ios.convertSlugToClipboardElement = function(el) {
    return el;
  };
  ios.toggleObjectsInRange = function(range, clonedObjects) {
    return false;
  };
})();
goog.provide("uno.util.resource.mac");
(function() {
  var util = uno.util;
  var mac = uno.util.resource.mac;
  var rxEmbedImplicitVoidTags = /<embed([^>]*[^/]\s*)>/g;
  mac.findResourcesInClientHtml = function(root) {
    return goog.array.filter(root.querySelectorAll('img:not(.en-todo):not(.en-crypt):not(.en-richlink),embed[id^="en-media"]'), function(el) {
      return el;
    });
  };
  mac.findResourcesInClipboardHtml = function(root) {
    return mac.findResourcesInClientHtml(root);
  };
  mac.convertMediaToSlug = function(enmedia, props, editor) {
    var slug;
    if (util.resource.isImage(props.type)) {
      slug = util.img.convertMediaToSlug(enmedia, props, editor);
      if (!props.elementId) {
        props.elementId = mac.getElementId(props);
      }
    } else {
      if (util.resource.isPdf(props.type)) {
        slug = convertPdfMediaToSlug(enmedia, props);
      } else {
        slug = convertFileMediaToSlug(enmedia, props);
      }
    }
    if (props.elementId) {
      slug.id = props.elementId;
    }
    return slug;
  };
  mac.getElementId = function(props) {
    if (props) {
      return "en-media:" + props.type + ":" + props.hash + ":none:none";
    }
  };
  mac.dictFromElement = function(el) {
    var hash = el.dataset.hash;
    var mime = el.dataset.type;
    var url = el.dataset.url;
    var elementId = mac.getElementId({type:mime, hash:hash});
    var width = el.getAttribute("width");
    var dict;
    if (mime && hash && url && url.indexOf("evernotecid") > -1) {
      dict = {url:url, mime:mime || util.dom.compareTagName(el, "img") && "image/unknown", hash:hash, elementId:elementId};
    } else {
      var data = (el.getAttribute("id") || ":::").split(":");
      dict = {url:el.src, mime:data[1] || util.dom.compareTagName(el, "img") && "image/unknown", hash:data[2], elementId:el.getAttribute("id")};
    }
    if (width != null && width != "") {
      dict.width = width;
    }
    return dict;
  };
  mac.dictFromClipboardElement = function(el, context) {
    return mac.dictFromElement(el);
  };
  mac.formatForExport = function(html) {
    if (html == null) {
      return html;
    }
    return html.replace(rxEmbedImplicitVoidTags, "<embed $1 />");
  };
  function convertPdfMediaToSlug(enmedia, props) {
    var attr = {src:props.url, type:"evernote/x-pdf", id:"en-media:application/pdf:" + props.hash};
    ["style", "width", "height"].forEach(function(name) {
      if (props[name]) {
        attr[name] = props[name];
      }
    });
    return goog.dom.createDom("embed", attr);
  }
  function convertFileMediaToSlug(enmedia, props) {
    var attr = {src:props.url, type:"evernote/x-attachment", id:"en-media:evernote/x-attachment:" + props.hash};
    ["style", "width", "height", "id"].forEach(function(name) {
      if (props[name]) {
        attr[name] = props[name];
      }
    });
    return goog.dom.createDom("embed", attr);
  }
  mac.convertClientElementToSlug = function(el, props, editor) {
    if (util.resource.isImage(props.type)) {
      return util.img.convertClientElementToSlug(el, props, editor);
    }
    return el;
  };
  mac.convertSlugToClientElement = function(el) {
    return el;
  };
  mac.convertSlugToClipboardElement = function(slug) {
    return slug;
  };
  mac.toggleObjectsInRange = function(range, clonedObjects) {
    return false;
  };
})();
goog.provide("uno.util.resource.win");
goog.require("goog.array");
goog.require("uno.util.dom");
goog.require("uno.util.img");
(function() {
  var util = uno.util;
  var win = util.resource.win;
  win.findResourcesInClientHtml = function(root) {
    return goog.array.filter(root.querySelectorAll('img:not(.en-todo):not(.en-crypt):not(.en-richlink):not([src^="en-resource://database/pprotect:"]), object'), function(el) {
      return util.dom.compareTagName(el, "object") || !/\/check/i.test(el.src);
    });
  };
  win.findResourcesInClipboardHtml = function(root) {
    return win.findResourcesInClientHtml(root);
  };
  win.convertMediaToSlug = function(enmedia, props, editor) {
    if (util.resource.isImage(props.type)) {
      return util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      return createFileSlug(enmedia, props);
    }
  };
  function createFileSlug(enmedia, props) {
    var slug = goog.dom.createDom("object", {data:props.url, type:props.type}, goog.dom.createDom("param", {name:"filename", value:props.filename}));
    if (props.width != null) {
      slug.setAttribute("width", props.width);
    }
    if (props.height != null) {
      slug.setAttribute("height", props.height);
    }
    if (props.style != null) {
      slug.setAttribute("style", props.style);
    }
    return slug;
  }
  win.dictFromElement = function(el) {
    var mime = el.getAttribute("type");
    var url = el.getAttribute("data");
    var style = el.getAttribute("style");
    var width = el.getAttribute("width");
    var height = el.getAttribute("height");
    var paramFilename = el.querySelector("param[name=filename]") || (el.dataset.filename ? {value:el.dataset.filename} : null);
    var paramUrl = el.querySelector("param[name=data]");
    if (paramFilename) {
      paramFilename = paramFilename.value;
    }
    if (!url && paramUrl) {
      url = paramUrl.value;
    }
    var dict;
    if (url && url.indexOf("en-resource") > -1) {
      dict = {url:url, mime:mime || util.dom.compareTagName(el, "img") && "image/unknown"};
    } else {
      dict = {url:el.src, mime:el.getAttribute("type") || util.dom.compareTagName(el, "img") && "image/unknown"};
    }
    if (style) {
      dict.style = style;
    }
    if (width) {
      dict.width = width;
    }
    if (height && dict.mime.indexOf("image/") < 0) {
      dict.height = height;
    }
    if (paramFilename) {
      dict.filename = paramFilename;
    }
    return dict;
  };
  win.dictFromClipboardElement = function(el) {
    return win.dictFromElement(el);
  };
  win.formatForExport = function(html) {
    return html;
  };
  win.convertClientElementToSlug = function(el) {
    return el;
  };
  win.convertSlugToClientElement = function(el) {
    return el;
  };
  win.convertSlugToClipboardElement = function(slug) {
    return slug;
  };
  win.toggleObjectsInRange = function(range, clonedObjects) {
    clonedObjects = clonedObjects || [];
    var containerNode;
    if (range.isCollapsed()) {
      containerNode = range.getStartNode();
    } else {
      containerNode = range.getContainerElement();
    }
    if (util.dom.isTextNode(containerNode)) {
      return false;
    }
    var objects = containerNode.querySelectorAll("object");
    if (!!clonedObjects.length) {
      goog.array.forEach(objects, function(brokenObject) {
        var brokenObjectNodeAttrs = util.dom.attributes(brokenObject);
        goog.array.forEach(clonedObjects, function(clonedObject) {
          var clonedObjectAttrs = util.dom.attributes(clonedObject);
          if (brokenObjectNodeAttrs["data-reference"] === clonedObjectAttrs["data-reference"] && brokenObjectNodeAttrs["data-filename"] === clonedObjectAttrs["data-filename"] && brokenObjectNodeAttrs["data-url"] === clonedObjectAttrs["data-url"]) {
            brokenObject.parentNode.replaceChild(clonedObject, brokenObject);
          }
        });
      });
    } else {
      goog.array.forEach(objects, function(brokenObject) {
        clonedObjects.push(brokenObject.cloneNode(true));
      });
      return clonedObjects;
    }
    return false;
  };
})();
goog.provide("uno.util.resource");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.events");
goog.require("uno.util.dom");
goog.require("uno.util.resource.android");
goog.require("uno.util.resource.generic");
goog.require("uno.util.resource.ios");
goog.require("uno.util.resource.mac");
goog.require("uno.util.resource.win");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.resource");
  var util = uno.util;
  util.resource.counter = 0;
  var client = uno.util.resource.generic;
  util.resource.setClient = function(clientName) {
    client = uno.util.resource[clientName] || client;
  };
  util.resource.all = function(root) {
    return root.querySelectorAll(".en-media");
  };
  util.resource.findResourcesInClientHtml = function(root) {
    return client.findResourcesInClientHtml(root);
  };
  util.resource.findResourcesInClipboardHtml = function(root) {
    return client.findResourcesInClipboardHtml(root);
  };
  util.resource.findByRef = function(ref, node) {
    var selector = '.en-media[data-reference="' + ref + '"]';
    var el = node.querySelector(selector);
    return el;
  };
  util.resource.findByURL = function(url, node) {
    var selector = '.en-media[data-url="' + url + '"]';
    return node.querySelectorAll(selector);
  };
  util.resource.findByHash = function(hash, node) {
    var selector = '.en-media[data-hash="' + hash + '"]';
    return node.querySelectorAll(selector);
  };
  util.resource.createUid = function() {
    return "resource-" + util.resource.counter++;
  };
  util.resource.isResource = function(node) {
    return node && util.dom.matches(node, ".en-media");
  };
  util.resource.isImage = function(elOrMime) {
    var mime = (util.resource.parseMime(elOrMime) || "").toLowerCase();
    var isImage = mime.indexOf("image/") === 0;
    var isPsd = mime === "image/vnd.adobe.photoshop";
    var isXcf = mime === "image/x-xcf";
    var isInk = mime === "application/vnd.evernote.ink";
    return isInk || isImage && !isPsd && !isXcf;
  };
  util.resource.isPdf = function(elOrMime) {
    var mimes = ["application/pdf", "evernote/x-pdf", "application/x-evernote-pdf"];
    var mime = util.resource.parseMime(elOrMime);
    return mime && mimes.indexOf(mime.toLowerCase()) != -1;
  };
  util.resource.isFileUI = function(el) {
    return goog.dom.classes.has(el, "en-media-file");
  };
  util.resource.createMediaFromDict = function(dict) {
    var enmedia = goog.dom.createElement("en-media");
    enmedia.setAttribute("type", dict.mime);
    enmedia.setAttribute("hash", dict.hash);
    if (dict.style) {
      enmedia.setAttribute("style", dict.style);
    }
    if (dict.width) {
      enmedia.setAttribute("width", dict.width);
    }
    if (dict.height) {
      enmedia.setAttribute("height", dict.height);
    }
    return enmedia;
  };
  util.resource.addMetaData = function(el, props) {
    if (props.reference != null) {
      el.dataset.reference = props.reference;
    }
    if (props.hash != null) {
      el.dataset.hash = props.hash;
    }
    if (props.type != null) {
      el.dataset.type = props.type;
    }
    if (props.filename != null) {
      el.dataset.filename = props.filename;
    }
    if (props.filesize != null) {
      el.dataset.filesize = props.filesize;
    }
    if (props.thumbnailURL != null) {
      el.dataset.thumbnailUrl = props.thumbnailURL;
    }
    if (props.title != null) {
      el.dataset.title = props.title;
    }
    if (props.url != null) {
      el.dataset.url = props.url;
    }
  };
  util.resource.convertClipboardElementToSlug = function(el, context, editor) {
    var enmedia;
    var slug;
    var dict = client.dictFromClipboardElement(el, context);
    if (!dict) {
      log.warning("Could not find resource dictionary for resource");
      goog.dom.removeNode(el);
    } else {
      enmedia = util.resource.createMediaFromDict(dict);
      slug = util.resource.convertMediaToSlug(enmedia, dict, editor);
      goog.dom.replaceNode(slug, el);
    }
    return slug;
  };
  util.resource.convertClientElementToSlug = function(el, editor) {
    var dict = client.dictFromElement(el);
    var props = util.resource.propsFromDict(dict);
    props.reference = props.reference || el.dataset.reference || util.resource.createUid();
    var slug = client.convertClientElementToSlug(el, props, editor);
    if (util.resource.isImage(dict.mime) && el.getAttribute("height") && el.getAttribute("width") && !editor.hasForeignSource()) {
      el.removeAttribute("height");
    }
    util.resource.addMetaData(slug, props);
    goog.dom.replaceNode(slug, el);
    addCssClasses(slug, props.type);
  };
  util.resource.convertSlugToClientElement = function(slug) {
    var el = client.convertSlugToClientElement(slug);
    el.removeAttribute("class");
    util.dom.removeDataAttributes(el);
    goog.dom.replaceNode(el, slug);
    return el;
  };
  util.resource.convertMediaToSlug = function(enmedia, dict, editor) {
    var props = {};
    var enmlProps = util.resource.propsFromEnml(enmedia);
    Object.keys(enmlProps).forEach(function(key) {
      if (enmlProps[key] == null) {
        delete enmlProps[key];
      }
    });
    goog.object.extend(props, util.resource.propsFromDict(dict), enmlProps);
    props.reference = props.reference || enmedia.dataset.reference || util.resource.createUid();
    var slug = client.convertMediaToSlug(enmedia, props, editor);
    util.resource.addMetaData(slug, props);
    if (props.style != null) {
      var style = slug.getAttribute("style") || "";
      slug.setAttribute("style", style + props.style);
    }
    if (props.hidden === true) {
      goog.style.setStyle(slug, "display", "none");
    }
    if (!util.dom.isFollowedByContent(slug)) {
      goog.dom.insertSiblingAfter(document.createElement("br"), slug);
    }
    goog.dom.replaceNode(slug, enmedia);
    addCssClasses(slug, props.type);
    return slug;
  };
  util.resource.convertSlugToMedia = function(slug) {
    var enmedia = goog.dom.createDom("en-media");
    if (!slug.dataset.hash || !slug.dataset.type) {
      return;
    }
    enmedia.setAttribute("hash", slug.dataset.hash);
    enmedia.setAttribute("type", slug.dataset.type);
    if (slug.getAttribute("style") != null) {
      enmedia.setAttribute("style", slug.getAttribute("style"));
    }
    ["width", "height", "align", "alt", "longdesc", "title", "lang", "dir", "border", "hspace", "vspace", "usemap"].forEach(function(name) {
      if (slug.dataset[name] != null) {
        enmedia.setAttribute(name, slug.dataset[name]);
      }
    });
    goog.dom.replaceNode(enmedia, slug);
    return enmedia;
  };
  util.resource.dictFromElement = function(el) {
    if (!el) {
      return {};
    }
    return {filename:el.dataset.filename, filesize:el.dataset.filesize, hash:el.getAttribute("hash") || el.dataset.hash, reference:el.dataset.reference, thumbnailURL:el.dataset.thumbnailUrl, title:el.dataset.title, mime:el.getAttribute("type") || el.dataset.type, url:el.dataset.url};
  };
  util.resource.propsFromEnml = function(enmedia) {
    if (!enmedia) {
      return {};
    }
    return {hash:enmedia.getAttribute("hash"), type:enmedia.getAttribute("type"), width:enmedia.getAttribute("width"), height:enmedia.getAttribute("height"), style:enmedia.getAttribute("style"), align:enmedia.getAttribute("align"), alt:enmedia.getAttribute("alt"), longdesc:enmedia.getAttribute("longdesc"), title:enmedia.getAttribute("title"), lang:enmedia.getAttribute("lang"), dir:enmedia.getAttribute("dir"), border:enmedia.getAttribute("border"), hspace:enmedia.getAttribute("hspace"), vspace:enmedia.getAttribute("vspace"), 
    usemap:enmedia.getAttribute("usemap")};
  };
  util.resource.propsFromDict = function(dict) {
    if (!dict) {
      return {};
    }
    return {contextURL:dict.contextURL, defaultActionURL:dict.defaultActionURL, downloaded:dict.downloaded, filename:dict.filename, filesize:dict.filesize, hash:dict.hash, height:dict.height, hidden:dict.hidden === true, elementId:dict.elementId, overlayImageURL:dict.overlayImageURL, overlayColor:dict.overlayColor, overlayOpacity:dict.overlayOpacity, progress:dict.progress, reference:dict.reference, state:dict.state, thumbnailURL:dict.thumbnailURL, title:dict.title, type:dict.mime.toLowerCase(), 
    url:dict.url, width:dict.width};
  };
  util.resource.applyProps = function(target, props) {
    target.setAttribute("hash", props.hash);
    target.setAttribute("type", props.type);
    ["reference", "width", "height", "align", "alt", "longdesc", "title", "lang", "dir", "border", "hspace", "vspace", "usemap"].forEach(function(name) {
      if (props[name]) {
        target.dataset[name] = props[name];
      }
    });
  };
  util.resource.referenceFor = function(el) {
    return el.dataset.reference;
  };
  util.resource.urlFor = function(el) {
    return el.dataset.url;
  };
  util.resource.mimeTypeFor = function(el) {
    return el.getAttribute("type") || el.getAttribute("data-type");
  };
  util.resource.parseMime = function(elOrMime) {
    var mime;
    if (elOrMime.getAttribute) {
      mime = util.resource.mimeTypeFor(elOrMime);
    } else {
      if (typeof elOrMime === "string") {
        mime = elOrMime;
      }
    }
    return mime;
  };
  util.resource.hashFor = function(el) {
    return el.getAttribute("hash") || el.dataset.hash;
  };
  util.resource.isDefaultContextButton = function(el) {
    return goog.dom.classes.has(el, "en-resource-context-default");
  };
  util.resource.isOverflowContextButton = function(el) {
    return goog.dom.classes.has(el, "en-resource-context-overflow");
  };
  util.resource.formatClientHtmlForExport = function(html) {
    return client.formatForExport(html);
  };
  util.resource.toDict = function(el, range) {
    return {hash:el.getAttribute("hash") || el.dataset.hash, mime:el.getAttribute("type") || el.dataset.type, url:el.dataset.url, rect:goog.style.getBounds(el), reference:el.dataset.reference, selected:!!(range && !range.isCollapsed() && range.containsNode(el)), filename:el.dataset.filename, filesize:el.dataset.filesize};
  };
  util.resource.toggleObjectsInRange = function(range, clonedObjects) {
    return client.toggleObjectsInRange(range, clonedObjects);
  };
  function addCssClasses(el, type) {
    goog.dom.classlist.add(el, "en-media");
    if (util.resource.isImage(type)) {
      goog.dom.classlist.add(el, "en-media-image");
    } else {
      goog.dom.classlist.add(el, "en-media-file");
      if (util.resource.isPdf(type)) {
        goog.dom.classlist.add(el, "en-media-pdf");
      }
    }
  }
})();
goog.provide("uno.util.copy.resources");
goog.require("uno.util.resource");
(function() {
  var util = uno.util;
  util.copy.resources.copy = function(root) {
    return goog.array.map(util.resource.all(root), function(el) {
      return util.resource.toDict(el);
    });
  };
})();
goog.provide("uno.util.copy");
goog.require("goog.dom");
goog.require("uno.util.dom");
goog.require("uno.util.copy.plain");
goog.require("uno.util.copy.table");
goog.require("uno.util.copy.rich");
goog.require("uno.util.copy.resources");
(function() {
  var util = uno.util;
  var dom = util.dom;
  var copy = util.copy;
  util.copy.copy = function(editor, options, range) {
    range = range || editor.getRange();
    var pastableHtml = "";
    if (!editor.multirange.isEmpty()) {
      pastableHtml = util.copy.table.getPastableHtml();
    } else {
      if (range && !range.isCollapsed()) {
        pastableHtml = util.copy.getPastableHtml(range);
      } else {
        return {plain:"", html:"", resources:[]};
      }
    }
    var root = dom.nodeFromHtml("<div>" + pastableHtml + "</div>");
    var resourcesNode = dom.nodeFromHtml(pastableHtml);
    addContext(root.firstChild, range, editor);
    pastableHtml = editor.getClipboardContent(root);
    var richNode = dom.nodeFromHtml(pastableHtml);
    var plainNode = dom.nodeFromHtml(pastableHtml);
    if (options.addMarker || typeof options.addMarker === "undefined") {
      var clipboardMarker = richNode.firstElementChild;
      if (clipboardMarker) {
        util.dom.setStyleValue(clipboardMarker, "-en-clipboard", "true");
      }
    }
    return {resources:options.resources ? copy.resources.copy(resourcesNode) : [], html:options.html ? util.copy.rich.copy(richNode) : "", plain:options.plain ? util.copy.plain.copy(plainNode) : ""};
  };
  util.copy.getPastableHtml = function(range) {
    var html = range.getPastableHtml();
    if (html.indexOf("<en-table") !== 0) {
      return html;
    }
    var parts = html.split("</table>");
    if (parts[0].indexOf("colgroup") > -1) {
      return html;
    }
    var colgroup = goog.dom.getAncestor(range.getStartNode(), util.dom.isTable, true).querySelector("colgroup");
    var index = html.indexOf("<tbody>");
    if (index === -1 || !colgroup) {
      return html;
    }
    return html.substr(0, index) + colgroup.outerHTML + html.substr(index);
  };
  function addContext(root, range, editor) {
    if (!editor.multirange.isEmpty()) {
      return;
    }
    var href = getHrefForRange(range);
    var anchor;
    if (href) {
      anchor = goog.dom.createDom("a", {href:href}, root.childNodes);
      root.appendChild(anchor);
    }
    var styledNode = getStyleForRange(range);
    util.styles.mergeAttributes(styledNode, anchor || root);
  }
  function getHrefForRange(range) {
    var matcher = function(node) {
      return node && dom.isA(node) && node.getAttribute("href");
    };
    var startAnchor = goog.dom.getAncestor(range.getStartNode(), matcher, true);
    var endAnchor = goog.dom.getAncestor(range.getEndNode(), matcher, true);
    return startAnchor && endAnchor && startAnchor === endAnchor && startAnchor.getAttribute("href");
  }
  function getStyleForRange(range) {
    var node = range.getContainer();
    var styledNode = goog.dom.createDom("div");
    if (node) {
      while (node && !dom.isEnnote(node) && !dom.isTd(node) && !dom.isLi(node) && !dom.isCodeBlock(node) && !dom.isRevealedCrypt(node) && !dom.isBlockquote(node)) {
        util.styles.mergeAttributes(node, styledNode);
        node = node.parentNode;
      }
    }
    return styledNode;
  }
})();
goog.provide("uno.util.crypto");
goog.require("goog.crypt");
goog.require("goog.crypt.Md5");
goog.require("goog.dom");
goog.require("goog.dom.classlist");
goog.require("goog.string");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.copy");
(function() {
  var util = uno.util;
  var CRYPT_CLASS = uno.defs.crypto.CRYPT_CLASS;
  var CRYPT_HIDDEN_CLASS = uno.defs.crypto.CRYPT_HIDDEN_CLASS;
  var CRYPT_VISIBLE_CLASS = uno.defs.crypto.CRYPT_VISIBLE_CLASS;
  util.crypto.all = function(root) {
    return root.querySelectorAll("." + CRYPT_CLASS);
  };
  util.crypto.for = function(node) {
    return goog.dom.getAncestor(node, util.crypto.isCrypt, true);
  };
  util.crypto.isCrypt = function(node) {
    return node && goog.dom.classlist.contains(node, CRYPT_CLASS);
  };
  util.crypto.isOpen = function(node) {
    return util.crypto.isCrypt(node) && goog.dom.classlist.contains(node, CRYPT_VISIBLE_CLASS);
  };
  util.crypto.createCryptoPlaceholder = function(cryptInfo) {
    var cryptNode = goog.dom.createDom("img", {id:cryptInfo.id, class:CRYPT_CLASS + " " + CRYPT_HIDDEN_CLASS, src:cryptInfo.src || uno.defs.image.TRANSPARENT_IMAGE_DATA_URL, "data-src":cryptInfo.src || "", "data-length":cryptInfo.length || "", "data-cipher":cryptInfo.cipher || "", "data-hint":cryptInfo.hint || "", "data-ciphertext":cryptInfo.cipherText || "", "data-hash":cryptInfo.plainText && util.crypto.hash(cryptInfo.plainText) || ""});
    return cryptNode;
  };
  util.crypto.getCryptInfoFromNode = function(node) {
    if (!node) {
      return null;
    }
    var cryptInfo = {id:node.getAttribute("id"), src:node.getAttribute("data-src"), length:node.getAttribute("data-length"), cipher:node.getAttribute("data-cipher"), hint:node.getAttribute("data-hint") || "", cipherText:node.getAttribute("data-ciphertext"), plainText:node.innerHTML, hash:node.getAttribute("data-hash"), boundingbox:goog.style.getBounds(node)};
    return cryptInfo;
  };
  util.crypto.getNodeFromCryptInfo = function(cryptInfo, options) {
    var selector = "#" + cryptInfo.id.replace(/([^a-z0-9_-])/gi, "\\$1");
    if (options && options.encryptedOnly) {
      selector += ":not(." + CRYPT_VISIBLE_CLASS + ")";
    }
    if (options && options.decryptedOnly) {
      selector += "." + CRYPT_VISIBLE_CLASS;
    }
    return document.querySelector(selector);
  };
  util.crypto.handleClick = function(node, readOnly, dispatchEvent) {
    var cryptNode = node && goog.dom.getAncestor(node, util.crypto.isCrypt, true);
    if (cryptNode && (cryptNode === node || readOnly)) {
      var cryptInfo = util.crypto.getCryptInfoFromNode(cryptNode);
      var hasClass = goog.dom.classlist.contains;
      if (hasClass(cryptNode, CRYPT_HIDDEN_CLASS)) {
        dispatchEvent({type:"decrypt", cryptInfo:cryptInfo});
      } else {
        if (readOnly && hasClass(cryptNode, CRYPT_VISIBLE_CLASS)) {
          dispatchEvent({type:"encrypt", cryptInfo:cryptInfo});
        }
      }
      return true;
    }
    return false;
  };
  util.crypto.isDirty = function(cryptNode) {
    var contentHash = cryptNode.getAttribute("data-hash");
    return util.crypto.isOpen(cryptNode) && contentHash !== util.crypto.hash(cryptNode.innerHTML || "");
  };
  util.crypto.getDirtyCrypto = function(root) {
    var cryptElements = util.crypto.all(root);
    var dirtyCrypto = [];
    goog.iter.forEach(cryptElements, function(cryptNode) {
      if (util.crypto.isDirty(cryptNode)) {
        cryptNode.setAttribute("data-ciphertext", "");
        cryptNode.setAttribute("data-hash", "");
        dirtyCrypto.push(util.crypto.getCryptInfoFromNode(cryptNode));
      }
    });
    return dirtyCrypto;
  };
  util.crypto.updateCryptNodes = function(cryptInfos) {
    cryptInfos.forEach(function(cryptInfo) {
      var cryptNode = util.crypto.getNodeFromCryptInfo(cryptInfo);
      cryptNode.setAttribute("data-ciphertext", cryptInfo.cipherText);
      if (cryptNode.innerHTML) {
        cryptNode.setAttribute("data-hash", util.crypto.hash(cryptNode.innerHTML));
      }
    });
  };
  util.crypto.hash = function(content) {
    var md5 = new goog.crypt.Md5;
    md5.update(content);
    return goog.crypt.byteArrayToHex(md5.digest());
  };
})();
goog.provide("uno.commands.BasicTextFormatter");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("goog.dom");
goog.require("goog.editor.range");
goog.require("uno.BasePlugin");
goog.require("uno.EditorMultiRange");
goog.require("uno.util.crypto");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.BasicTextFormatter");
  var WEBKIT_DEFAULT_FONT = "-webkit-standard";
  var util = uno.util;
  var BasicTextFormatter = uno.commands.BasicTextFormatter = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(BasicTextFormatter, uno.BasePlugin);
  BasicTextFormatter.GOOG_COMMAND = {bold:goog.editor.Command.BOLD, fontname:goog.editor.Command.FONT_FACE, indent:goog.editor.Command.INDENT, insertorderedlist:goog.editor.Command.ORDERED_LIST, insertunorderedlist:goog.editor.Command.UNORDERED_LIST, italic:goog.editor.Command.ITALIC, justifycenter:goog.editor.Command.JUSTIFY_CENTER, justifyfull:goog.editor.Command.JUSTIFY_FULL, justifyleft:goog.editor.Command.JUSTIFY_LEFT, justifyright:goog.editor.Command.JUSTIFY_RIGHT, outdent:goog.editor.Command.OUTDENT, 
  subscript:goog.editor.Command.SUBSCRIPT, superscript:goog.editor.Command.SUPERSCRIPT};
  BasicTextFormatter.COMMANDS = Object.keys(BasicTextFormatter.GOOG_COMMAND);
  BasicTextFormatter.prototype.isSupportedCommand = function(command) {
    return BasicTextFormatter.COMMANDS.indexOf(command) > -1;
  };
  BasicTextFormatter.prototype.activeOnUneditableFields = goog.functions.TRUE;
  goog.editor.plugins.BasicTextFormatter.prototype.isSilentCommand = goog.functions.TRUE;
  BasicTextFormatter.prototype.registerFieldObject = function(fieldObject) {
    uno.BasePlugin.prototype.registerFieldObject.call(this, fieldObject);
    var plugin = fieldObject.plugins_.BTF;
    plugin.activeOnUneditableFields = goog.functions.TRUE;
  };
  BasicTextFormatter.prototype.fixFloatingUnwrappedBR = function() {
    var tags = ["ol", "ul"];
    var range = this.editor.getRange();
    if (range && range.isCollapsed() && range.getStartNode().children) {
      var children = range.getStartNode().children;
      var offset = range.getStartOffset();
      if (offset <= 0 || children.length < 2 || offset >= children.length) {
        return;
      }
      if (tags.indexOf(util.dom.getTagName(children[offset - 1])) > -1 && util.dom.getTagName(children[offset]) === "br") {
        var newdiv = goog.dom.createDom("div");
        newdiv.appendChild(goog.dom.createDom("br"));
        goog.dom.replaceNode(newdiv, children[offset]);
        goog.dom.Range.createFromNodes(newdiv, 0, newdiv, 0).select();
      }
    }
  };
  BasicTextFormatter.prototype.execCommand = function(command, value) {
    var commands = BasicTextFormatter.GOOG_COMMAND;
    var styleOverride = {state:{}, value:{}, enabled:{}};
    var googleCommand = commands[command];
    var swappedObjects;
    var currentState = this.editor.context.style.state[command];
    var isOrderedListCommand = !!(command === "insertorderedlist");
    var isUnorderedListCommand = !!(command === "insertunorderedlist");
    var isIndentCommand = !!(command === "indent");
    var isOutdentCommand = !!(command === "outdent");
    this.editor.dispatchBeforeChange();
    var range = this.editor.getRange();
    if (range && !range.isCollapsed()) {
      this.editor.dispatchBeforeChange();
    }
    if ((isOrderedListCommand || isUnorderedListCommand || isIndentCommand || isOutdentCommand) && range) {
      swappedObjects = util.resource.toggleObjectsInRange(range, false);
    }
    this.editor.execCommand(googleCommand, value);
    this.fixFloatingUnwrappedBR();
    removeTextSizeAdjust(this.editor);
    var newRange = this.editor.getRange();
    if (range && range.isCollapsed() && !newRange) {
      newRange = range;
      newRange.select();
    }
    if ((isOrderedListCommand || isUnorderedListCommand || isIndentCommand || isOutdentCommand) && swappedObjects && newRange) {
      util.resource.toggleObjectsInRange(newRange, swappedObjects);
    }
    if (newRange) {
      if (newRange.isCollapsed()) {
        if (["indent", "insertorderedlist", "insertunorderedlist", "justifycenter", "justifyfull", "justifyleft", "justifyright", "outdent"].indexOf(command) > -1) {
          this.editor.dispatchChange();
        }
      } else {
        this.editor.dispatchChange();
      }
    }
    if (command.indexOf("justify") === 0 && currentState) {
      styleOverride.state[command] = true;
    } else {
      styleOverride.state[command] = !currentState;
    }
    this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:styleOverride});
    return true;
  };
  BasicTextFormatter.prototype.queryCommandValue = function(command) {
    var result;
    switch(command) {
      case "fontname":
        {
          result = this.editor.queryCommandValue(goog.editor.Command.FONT_FACE);
          if (result === WEBKIT_DEFAULT_FONT) {
            result = this.editor.config.defaults.richTextFont;
          }
          if (result) {
            result = result.replace(/,.*/, "").replace(/['"]/g, "");
          }
          break;
        }
      case "insertorderedlist":
      case "insertunorderedlist":
        {
          if (this.editor.queryCommandValue(goog.editor.Command.UNORDERED_LIST) !== false) {
            result = "ul";
          } else {
            if (this.editor.queryCommandValue(goog.editor.Command.ORDERED_LIST) !== false) {
              result = "ol";
            } else {
              result = "none";
            }
          }
          break;
        }
      case "justifyleft":
      case "justifycenter":
      case "justifyright":
      case "justifyfull":
        {
          if (this.editor.queryCommandValue(goog.editor.Command.JUSTIFY_LEFT) !== false) {
            result = "left";
          } else {
            if (this.editor.queryCommandValue(goog.editor.Command.JUSTIFY_CENTER) !== false) {
              result = "center";
            } else {
              if (this.editor.queryCommandValue(goog.editor.Command.JUSTIFY_RIGHT) !== false) {
                result = "right";
              } else {
                if (this.editor.queryCommandValue(goog.editor.Command.JUSTIFY_FULL) !== false) {
                  result = "justify";
                }
              }
            }
          }
          break;
        }
      default:
        result = this.editor.queryCommandValue(BasicTextFormatter.GOOG_COMMAND[command]);
    }
    return result;
  };
  BasicTextFormatter.prototype.queryCommandEnabled = function(command) {
    if (command === "indent" || command === "outdent" || command === "insertorderedlist" || command === "insertunorderedlist") {
      var range = this.editor.getRange();
      if (!range) {
        return false;
      }
      var node = range.getStartNode();
      if (command === "indent" || command === "outdent") {
        return !(util.codeblock.for(node) || util.crypto.for(node));
      }
      if (command === "insertorderedlist" || command === "insertunorderedlist") {
        return !(util.crypto.for(node) || util.codeblock.for(node));
      }
    }
    return true;
  };
  function removeTextSizeAdjust(editor) {
    var elements = editor.field.querySelectorAll('*[style*="-webkit-text-size-adjust:"]');
    goog.iter.forEach(elements, function(element) {
      element.style.removeProperty("-webkit-text-size-adjust");
    });
  }
})();
goog.provide("uno.commands.Bounds");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Bounds");
  var Bounds = uno.commands.Bounds = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Bounds, uno.BasePlugin);
  Bounds.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Bounds.prototype.isSupportedCommand = function(command) {
    return command === "bounds";
  };
  Bounds.prototype.execCommand = function() {
    return false;
  };
  Bounds.prototype.queryCommandValue = function() {
    var result = goog.style.getBounds(this.editor.field);
    result.right = result.left + result.width;
    result.bottom = result.top + result.height;
    result.x = result.left;
    result.y = document.body.scrollHeight - result.bottom;
    return result;
  };
})();
goog.provide("uno.commands.Capitalize");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Capitalize");
  var util = uno.util;
  var Capitalize = uno.commands.Capitalize = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(Capitalize, uno.BasePlugin);
  Capitalize.prototype.isSupportedCommand = function(command) {
    return command === "capitalize";
  };
  Capitalize.prototype.execCommandInternal = function() {
    var range = this.editor.getRange();
    var savedRange = range.saveUsingDom();
    util.range.forEachWord(range, function(word, wordRange) {
      var container = wordRange.startContainer;
      var text = container.nodeValue;
      container.nodeValue = text.slice(0, wordRange.startOffset) + word[0].toLocaleUpperCase() + word.slice(1).toLocaleLowerCase() + text.slice(wordRange.endOffset);
    });
    savedRange.restore().select();
  };
})();
goog.provide("uno.commands.Changes");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Changes");
  var Changes = uno.commands.Changes = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Changes, uno.BasePlugin);
  Changes.prototype.isSupportedCommand = function(command) {
    return command === "changes";
  };
  Changes.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Changes.prototype.execCommand = function() {
    return false;
  };
  Changes.prototype.queryCommandValue = function() {
    return this.editor.dirty || this.editor.isModified();
  };
})();
goog.provide("goog.dom.NodeIterator");
goog.require("goog.dom.TagIterator");
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);
goog.dom.NodeIterator.prototype.next = function() {
  do {
    goog.dom.NodeIterator.superClass_.next.call(this);
  } while (this.isEndTag());
  return this.node;
};
goog.provide("uno.util.paragraph");
goog.require("goog.debug.Logger");
goog.require("goog.editor.node");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.paragraph");
  var util = uno.util;
  util.paragraph.all = function(root) {
    return root.querySelectorAll(["h1", "h2", "h3", "h4", "h5", "h6", 'div:not(.en-code):not([style*="-en-codeblock"])', "p"].join(","));
  };
  util.paragraph.create = function() {
    var div = document.createElement("div");
    div.appendChild(document.createElement("br"));
    return div;
  };
  util.paragraph.for = function(node) {
    if (!node) {
      return null;
    }
    if (node.tagName && node.tagName.toLowerCase() === "en-note") {
      node = node.firstChild;
    }
    var paraNode = goog.dom.getAncestor(node, function(ancestor) {
      return util.dom.isBlockNode(ancestor);
    }, true);
    if (paraNode) {
      if (paraNode.tagName.toLowerCase() === "en-note") {
        var savedRange;
        var range = goog.dom.Range.createFromWindow();
        if (range && (range.isCollapsed() || range.containsNode(node))) {
          savedRange = range.saveUsingCarets();
        }
        while (node.parentNode !== paraNode) {
          node = node.parentNode;
        }
        var sibs = util.dom.contiguousInlineSiblings(node);
        var blockWrapper = goog.dom.createDom("div");
        goog.dom.replaceNode(blockWrapper, node);
        sibs.forEach(function(sib) {
          blockWrapper.appendChild(sib);
        });
        if (savedRange) {
          savedRange.restore().select();
        }
        return blockWrapper;
      }
    }
    return paraNode;
  };
  util.paragraph.insertAfter = function(paraNode) {
    var newParaNode = util.paragraph.create();
    goog.dom.insertSiblingAfter(newParaNode, paraNode);
    return newParaNode;
  };
  util.paragraph.startsWithTodo = function(paragraph) {
    var node = util.dom.getFirstParagraphItem(paragraph);
    return !!util.todo.isTodo(node);
  };
  util.paragraph.getLeadingTodo = function(paragraph) {
    var firstItem = util.dom.getFirstParagraphItem(paragraph);
    return util.todo.isTodo(firstItem) ? firstItem : null;
  };
  util.paragraph.prevParagraph = function(paraNode) {
    return goog.dom.getPreviousElementSibling(paraNode);
  };
  util.paragraph.nextParagraph = function(paraNode) {
    return goog.dom.getNextElementSibling(paraNode);
  };
  util.paragraph.placeCursorAtStart = function(paraNode) {
    var range = goog.dom.Range.createCaret(paraNode, 0);
    range.select();
    return range;
  };
  util.paragraph.remove = function(paraNode) {
    goog.dom.removeNode(paraNode);
  };
  util.paragraph.hasVisibleContent = function(paraNode, opt) {
    var contentTags = "en-media,embed,img,object";
    var result;
    if (!paraNode) {
      log.warning("hasVisibleContent paraNode is null");
      return false;
    }
    opt = opt || {};
    result = goog.array.some(paraNode.querySelectorAll(contentTags), function(el) {
      return el !== opt.excluding;
    });
    if (!result) {
      result = !goog.string.isEmptyOrWhitespace(paraNode.innerText);
    }
    return result;
  };
  util.paragraph.hasBr = function(paraNode) {
    return paraNode.querySelector("br") != null;
  };
  util.paragraph.appendBr = function(paraNode) {
    paraNode.appendChild(goog.dom.createElement("br"));
  };
})();
goog.provide("uno.util.list");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.util.dom");
(function() {
  var util = uno.util;
  var dom = util.dom;
  util.list.for = function(node) {
    if (node == null) {
      return null;
    }
    if (util.dom.isOl(node) || util.dom.isUl(node)) {
      return node;
    }
    if (!util.dom.isElementNode(node)) {
      node = goog.dom.getParentElement(node);
    }
    var itemNode = util.list.itemFor(node);
    var listNode = itemNode && itemNode.parentNode;
    return listNode;
  };
  util.list.itemFor = function(node) {
    if (!node) {
      return null;
    }
    if (!util.dom.isElementNode(node)) {
      node = goog.dom.getParentElement(node);
    }
    var itemNode = util.dom.compareTagName(node, "li") ? node : goog.dom.getAncestorByTagNameAndClass(node, "li");
    return itemNode;
  };
  util.list.getParagraphs = function(node) {
    var paragraphs = [];
    if (dom.isUl(node) || dom.isOl(node)) {
      var lis = node.querySelectorAll("li");
      goog.array.forEach(lis, function(li) {
        paragraphs = paragraphs.concat(goog.array.toArray(li.childNodes));
      });
    }
    return paragraphs;
  };
  util.list.normalize = function(root) {
    util.list.flattenInvisibleLists(root);
    util.list.flattenInvalidLists(root);
    util.list.moveBlocksOfLis(root);
    util.list.mergeSiblingUls(root);
    util.list.ensureValidLiWrapInUl(root);
  };
  util.list.flattenInvisibleLists = function(root) {
    var invisibleLists = goog.array.filter(root.querySelectorAll("ol, ul"), function(li) {
      return li.style.listStyle === "none";
    });
    goog.array.forEachRight(invisibleLists, function(invisibleList) {
      var isWithinList = goog.dom.getAncestor("ol, ul");
      if (!isWithinList) {
        goog.array.forEachRight(invisibleList.childNodes, function(child) {
          if (dom.isLi(child)) {
            dom.changeTagName(child, "div");
          }
        });
        goog.dom.flattenElement(invisibleList);
      }
    });
  };
  util.list.flattenInvalidLists = function(node) {
    goog.array.forEachRight(node.querySelectorAll("ol,ul"), function(list) {
      if (list.childNodes.length > 0 && !list.querySelector("li")) {
        goog.dom.flattenElement(list);
      }
    });
  };
  util.list.moveBlocksOfLis = function(root) {
    var blocks = root.querySelectorAll('ul, ol, table, [style*="-en-codeblock"], .en-code');
    goog.array.forEachRight(blocks, function(block) {
      if (dom.isLi(block.parentNode)) {
        var parentNode = block.parentNode;
        var lastNodeMoved = block.parentNode;
        var currentNode = block;
        while (currentNode) {
          var nextSibling = currentNode.nextSibling;
          if (dom.isDiv(currentNode)) {
            currentNode = dom.changeTagName(currentNode, "li");
          }
          goog.dom.insertSiblingAfter(currentNode, lastNodeMoved);
          lastNodeMoved = currentNode;
          currentNode = nextSibling;
        }
        if (!parentNode.firstChild) {
          goog.dom.removeNode(parentNode);
        }
      }
    });
  };
  util.list.mergeSiblingUls = function(node) {
    goog.array.forEachRight(node.querySelectorAll("ul"), function(list) {
      while (util.dom.isUl(list.previousSibling)) {
        var prevList = list.previousSibling;
        while (list.firstChild) {
          prevList.appendChild(list.firstChild);
        }
        list.remove();
        list = prevList;
      }
    });
  };
  util.list.ensureValidLiWrapInUl = function(node) {
    goog.array.forEachRight(node.querySelectorAll("li"), function(li) {
      if (!util.dom.isUl(li.parentNode) && !util.dom.isOl(li.parentNode)) {
        var ul = goog.dom.createDom("ul", null);
        var childNodes = li.parentNode ? goog.array.toArray(li.parentNode.childNodes) : [li];
        goog.dom.replaceNode(ul, li);
        goog.array.forEach(childNodes, function(child) {
          ul.appendChild(child);
        });
      }
    });
  };
  util.list.convertParagraphsToBrs = function(root) {
    var lis = dom.isLi(root) ? [root] : root.querySelectorAll("li");
    goog.array.forEachRight(lis, function(list) {
      goog.array.forEachRight(list.childNodes, function(child) {
        if (util.dom.isBlockNode(child)) {
          if (child.lastChild && !util.dom.isBr(child.lastChild)) {
            var br = goog.dom.createDom("br");
            child.appendChild(br);
          }
          goog.dom.flattenElement(child);
        }
      });
      var previousSibling = list.lastChild && list.lastChild.previousSibling;
      while (dom.isEncursor(previousSibling)) {
        previousSibling = previousSibling.previousSibling;
      }
      if (list.childNodes.length > 1 && util.dom.isBr(list.lastChild) && !util.dom.isBr(previousSibling)) {
        goog.dom.removeNode(list.lastChild);
      }
    });
  };
})();
goog.provide("uno.commands.CodeBlock");
goog.require("goog.debug.Logger");
goog.require("goog.dom.NodeIterator");
goog.require("uno.BasePlugin");
goog.require("uno.util.paragraph");
goog.require("uno.util.table");
goog.require("uno.util.list");
goog.require("uno.util.crypto");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.CodeBlock");
  var util = uno.util;
  var CodeBlock = uno.commands.CodeBlock = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CodeBlock, uno.BasePlugin);
  CodeBlock.prototype.isSupportedCommand = function(command) {
    return command === "codeblock";
  };
  CodeBlock.prototype.execCommandInternal = function() {
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    if (this.queryCommandValue("codeblock")) {
      this.findAndRemoveCodeBlock(range);
      return true;
    }
    var copiedText = range.isCollapsed() ? null : this.editor.queryCommandValue("cut");
    var insertParagraphIfRequired = function(editor, updateRange) {
      var result = false;
      var currentRange = editor.getRange();
      if (!util.dom.isEmpty(util.paragraph.for(currentRange.getStartNode())) || editor.field.childNodes && currentRange.getStartNode() === editor.field.childNodes[0]) {
        editor.execCommand("insertparagraph");
        result = true;
      }
      if (updateRange) {
        currentRange.select();
      }
      return result;
    };
    insertParagraphIfRequired(this.editor, true);
    insertParagraphIfRequired(this.editor, false);
    var innerBr = goog.dom.createDom("br");
    var innerDiv = goog.dom.createDom("div", {}, innerBr);
    var codeBlockElement = goog.dom.createDom("div", {class:"en-code"}, innerDiv);
    goog.dom.replaceNode(codeBlockElement, this.editor.getRange().getStartNode());
    var newRange = goog.editor.range.placeCursorNextTo(innerBr);
    if (copiedText && copiedText.plain && copiedText.plain.length > 0) {
      goog.editor.range.placeCursorNextTo(innerBr);
      this.editor.execCommand("inserttext", copiedText.plain);
      newRange = goog.editor.range.placeCursorNextTo(codeBlockElement);
    }
    newRange.select();
    return true;
  };
  CodeBlock.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var containerNode = range.getContainerElement();
    return this.isParentNodeCodeBlock(containerNode) || this.isChildNodeCodeBlock([containerNode], range);
  };
  CodeBlock.prototype.isChildNodeCodeBlock = function(nodes, range) {
    return Array.prototype.some.call(nodes, function(node) {
      if (util.dom.isElementNode(node)) {
        if (range.containsNode(node, true) && util.dom.isCodeBlock(node)) {
          return true;
        }
        return this.isChildNodeCodeBlock(node.childNodes, range);
      }
      return false;
    }.bind(this));
  };
  CodeBlock.prototype.isParentNodeCodeBlock = function(node) {
    return goog.dom.getAncestor(node, function(ancestor) {
      return util.dom.isCodeBlock(ancestor);
    }, true);
  };
  CodeBlock.prototype.findAndRemoveCodeBlock = function(range) {
    var containerNode = range.getContainerElement();
    if (util.dom.isCodeBlock(containerNode)) {
      this.unwrapCodeBlock(containerNode);
      return true;
    }
    var block = goog.dom.getAncestor(containerNode, function(ancestor) {
      return util.dom.isCodeBlock(ancestor);
    }, true);
    if (block) {
      this.unwrapCodeBlock(block);
      return true;
    }
    var ci = new goog.dom.NodeIterator(containerNode, true, false);
    var currentChild;
    var foundBlocks = [];
    try {
      while (currentChild = ci.next()) {
        if (range.containsNode(currentChild, true) && util.dom.isCodeBlock(currentChild)) {
          foundBlocks.push(currentChild);
        }
      }
    } catch (err$10) {
      log.fine(err$10.stack || err$10);
    }
    foundBlocks.forEach(function(foundBlock) {
      this.unwrapCodeBlock(foundBlock);
    });
    return true;
  };
  CodeBlock.prototype.unwrapCodeBlock = function(node) {
    var lastChild;
    while (node.firstChild) {
      lastChild = node.firstChild;
      node.parentElement.insertBefore(lastChild, node);
    }
    if (lastChild) {
      var cursorTarget = lastChild.childNodes ? lastChild.childNodes[0] : lastChild;
      goog.editor.range.placeCursorNextTo(cursorTarget);
    }
    node.remove();
    return true;
  };
  CodeBlock.prototype.queryCommandEnabled = function(command) {
    var range = this.editor.getRange();
    if (range) {
      var containerNode = range.getContainer();
      if (util.table.for(containerNode) || util.list.for(containerNode) || util.crypto.for(containerNode)) {
        return false;
      }
    }
    return true;
  };
})();
goog.provide("uno.commands.Content");
goog.require("goog.array");
goog.require("goog.functions");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.crypto");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Content");
  var util = uno.util;
  var Content = uno.commands.Content = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Content, uno.BasePlugin);
  Content.prototype.isSupportedCommand = function(command) {
    return command === "content";
  };
  Content.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Content.prototype.execCommand = function(command, value) {
    var editor = this.editor;
    value = {type:value.type || uno.defs.format.ENML, content:goog.isString(value.content) ? value.content : value, resources:value.resources || {}};
    if (value.type === "html") {
      value.type = uno.defs.format.CLIENT_HTML;
    }
    var content = value.content;
    editor.context.format = value.type;
    if (editor.context.format === uno.defs.format.CLIENT_HTML) {
      if (content && content.indexOf('<div id="en-note">') !== -1) {
        content = content.replace('<div id="en-note">', "").replace(/<\/div>\s*$/, "");
      } else {
        if (content && content.indexOf('<div id="en-note"/>') !== -1) {
          content = editor.config.defaults.html;
        }
      }
    }
    goog.object.extend(editor.context.resources, value.resources);
    start("set content");
    editor.setHtml(false, content, true);
    stop("set content");
    editor.plugins_.UndoRedo.refreshCurrentState(editor);
    this.waitForImages();
    editor.updateEmpty();
    return true;
  };
  Content.prototype.queryCommandValue = function(command, opt) {
    var editor = this.editor;
    var value;
    var initialFormat = editor.context.format;
    opt = opt || {};
    opt.resetChangesState = opt.resetChangesState !== false;
    if (opt.type === "html") {
      editor.context.format = uno.defs.format.CLIENT_HTML;
    } else {
      if (opt.type) {
        editor.context.format = opt.type;
      } else {
        editor.context.format = uno.defs.format.ENML;
      }
    }
    if (opt.cryptInfo) {
      util.crypto.updateCryptNodes(opt.cryptInfo);
    } else {
      var cryptInfo = util.crypto.getDirtyCrypto(editor.field);
      if (cryptInfo.length) {
        return {success:false, cryptInfo:cryptInfo};
      }
    }
    value = editor.getCleanContents();
    if (editor.context.format === uno.defs.format.CLIENT_HTML) {
      value = '<div id="en-note">' + value + "</div>";
    }
    if (opt.resetChangesState) {
      editor.dirty = false;
    }
    editor.context.format = initialFormat;
    return {success:value != null, value:value};
  };
  Content.prototype.waitForImages = function() {
    var me = this;
    var completeImageCount = 0;
    var images = this.editor.field.querySelectorAll("img");
    if (images.length === 0) {
      return setTimeout(function() {
        if (me.editor) {
          me.dispatchContentLoaded();
        }
      }, 0);
    }
    var onImageComplete = function() {
      if (++completeImageCount === images.length) {
        return setTimeout(function() {
          if (me.editor) {
            me.dispatchContentLoaded();
          }
        }, 0);
      }
    };
    goog.array.forEach(images, function waitForImageComplete(img) {
      if (img.getAttribute("src") && !img.naturalWidth && !img.naturalHeight) {
        goog.events.listen(img, "load", onImageComplete);
        goog.events.listen(img, "error", onImageComplete);
      } else {
        onImageComplete();
      }
    });
  };
  Content.prototype.dispatchContentLoaded = function() {
    this.dispatchEvent("contentloaded");
  };
})();
goog.provide("uno.commands.ControlTodos");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.ControlTodos");
  var util = uno.util;
  var ControlTodos = uno.commands.ControlTodos = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(ControlTodos, uno.BasePlugin);
  ControlTodos.prototype.isSupportedCommand = function(command) {
    return command === "controltodos";
  };
  ControlTodos.prototype.execCommandInternal = function(command, state) {
    var range = this.editor.getRange();
    var todos = util.todo.all(this.editor.field);
    if (!range.isCollapsed()) {
      todos = goog.array.filter(todos, function(node) {
        return range.containsNode(node, true);
      });
    }
    goog.array.forEach(todos, function(entodo) {
      if (state === "on") {
        util.todo.setChecked(entodo, true);
      } else {
        if (state === "off") {
          util.todo.setChecked(entodo, false);
        } else {
          util.todo.toggle(entodo);
        }
      }
    });
  };
})();
goog.provide("uno.commands.Copy");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.copy");
goog.require("uno.util.objects");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Copy");
  var defs = uno.defs;
  var util = uno.util;
  var Copy = uno.commands.Copy = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Copy, uno.BasePlugin);
  Copy.prototype.isSupportedCommand = function(command) {
    return command === "copy";
  };
  Copy.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Copy.prototype.execCommand = function() {
    return false;
  };
  Copy.prototype.queryCommandValue = function(command, opt) {
    var options = getOptions(opt);
    this.editor.context.format = defs.format.CLIPBOARD;
    return util.copy.copy(this.editor, options);
  };
  function getOptions(options) {
    return util.objects.mergeOptions(options, {html:true, resources:true, plain:true});
  }
})();
goog.provide("uno.commands.Count");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("goog.string");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Count");
  var Count = uno.commands.Count = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Count, uno.BasePlugin);
  Count.prototype.isSupportedCommand = function(command) {
    return command === "count";
  };
  Count.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Count.prototype.queryCommandValue = function() {
    var text = goog.string.canonicalizeNewlines(this.editor.field.innerText).trim();
    var lines = text.split("\n");
    var words = goog.string.collapseWhitespace(text).split(" ");
    var paragraphs = text.split(/\n{2,}/);
    return {words:words.length, charsWithoutSpaces:words.join("").length, charsWithSpaces:lines.join("").length, paragraphs:paragraphs.length, lines:lines.length};
  };
})();
goog.provide("goog.dom.InputType");
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"};
goog.provide("goog.dom.selection");
goog.require("goog.dom.InputType");
goog.require("goog.string");
goog.require("goog.userAgent");
goog.dom.selection.setStart = function(textfield, pos) {
  if (goog.dom.selection.useSelectionProperties_(textfield)) {
    textfield.selectionStart = pos;
  } else {
    if (goog.dom.selection.isLegacyIe_()) {
      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();
      }
    }
  }
};
goog.dom.selection.getStart = function(textfield) {
  return goog.dom.selection.getEndPoints_(textfield, true)[0];
};
goog.dom.selection.getEndPointsTextareaIe_ = function(range, selRange, getOnlyStart) {
  var selectionRange = selRange.duplicate();
  var beforeSelectionText = range.text;
  var untrimmedBeforeSelectionText = beforeSelectionText;
  var selectionText = selectionRange.text;
  var untrimmedSelectionText = selectionText;
  var isRangeEndTrimmed = false;
  while (!isRangeEndTrimmed) {
    if (range.compareEndPoints("StartToEnd", range) == 0) {
      isRangeEndTrimmed = true;
    } else {
      range.moveEnd("character", -1);
      if (range.text == beforeSelectionText) {
        untrimmedBeforeSelectionText += "\r\n";
      } else {
        isRangeEndTrimmed = true;
      }
    }
  }
  if (getOnlyStart) {
    return [untrimmedBeforeSelectionText.length, -1];
  }
  var isSelectionRangeEndTrimmed = false;
  while (!isSelectionRangeEndTrimmed) {
    if (selectionRange.compareEndPoints("StartToEnd", selectionRange) == 0) {
      isSelectionRangeEndTrimmed = true;
    } else {
      selectionRange.moveEnd("character", -1);
      if (selectionRange.text == selectionText) {
        untrimmedSelectionText += "\r\n";
      } else {
        isSelectionRangeEndTrimmed = true;
      }
    }
  }
  return [untrimmedBeforeSelectionText.length, untrimmedBeforeSelectionText.length + untrimmedSelectionText.length];
};
goog.dom.selection.getEndPoints = function(textfield) {
  return goog.dom.selection.getEndPoints_(textfield, false);
};
goog.dom.selection.getEndPoints_ = function(textfield, getOnlyStart) {
  textfield = textfield;
  var startPos = 0;
  var endPos = 0;
  if (goog.dom.selection.useSelectionProperties_(textfield)) {
    startPos = textfield.selectionStart;
    endPos = getOnlyStart ? -1 : textfield.selectionEnd;
  } else {
    if (goog.dom.selection.isLegacyIe_()) {
      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;
        }
      }
    }
  }
  return [startPos, endPos];
};
goog.dom.selection.setEnd = function(textfield, pos) {
  if (goog.dom.selection.useSelectionProperties_(textfield)) {
    textfield.selectionEnd = pos;
  } else {
    if (goog.dom.selection.isLegacyIe_()) {
      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);
        var startCursorPos = goog.dom.selection.canonicalizePositionIe_(textfield, goog.dom.selection.getStart(textfield));
        selectionRange.collapse(true);
        selectionRange.moveEnd("character", pos - startCursorPos);
        selectionRange.select();
      }
    }
  }
};
goog.dom.selection.getEnd = function(textfield) {
  return goog.dom.selection.getEndPoints_(textfield, false)[1];
};
goog.dom.selection.setCursorPosition = function(textfield, pos) {
  if (goog.dom.selection.useSelectionProperties_(textfield)) {
    textfield.selectionStart = pos;
    textfield.selectionEnd = pos;
  } else {
    if (goog.dom.selection.isLegacyIe_()) {
      pos = goog.dom.selection.canonicalizePositionIe_(textfield, pos);
      var sel = textfield.createTextRange();
      sel.collapse(true);
      sel.move("character", pos);
      sel.select();
    }
  }
};
goog.dom.selection.setText = function(textfield, text) {
  textfield = textfield;
  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.dom.selection.isLegacyIe_()) {
      var tmp = goog.dom.selection.getRangeIe_(textfield);
      var range = tmp[0];
      var selectionRange = tmp[1];
      if (!range.inRange(selectionRange)) {
        return;
      }
      var range2 = selectionRange.duplicate();
      selectionRange.text = text;
      selectionRange.setEndPoint("StartToStart", range2);
      selectionRange.select();
    } else {
      throw Error("Cannot set the selection end");
    }
  }
};
goog.dom.selection.getText = function(textfield) {
  textfield = textfield;
  if (goog.dom.selection.useSelectionProperties_(textfield)) {
    var s = textfield.value;
    return s.substring(textfield.selectionStart, textfield.selectionEnd);
  }
  if (goog.dom.selection.isLegacyIe_()) {
    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");
};
goog.dom.selection.getSelectionRangeText_ = function(selRange) {
  var selectionRange = selRange.duplicate();
  var selectionText = selectionRange.text;
  var untrimmedSelectionText = selectionText;
  var isSelectionRangeEndTrimmed = false;
  while (!isSelectionRangeEndTrimmed) {
    if (selectionRange.compareEndPoints("StartToEnd", selectionRange) == 0) {
      isSelectionRangeEndTrimmed = true;
    } else {
      selectionRange.moveEnd("character", -1);
      if (selectionRange.text == selectionText) {
        untrimmedSelectionText += "\r\n";
      } else {
        isSelectionRangeEndTrimmed = true;
      }
    }
  }
  return untrimmedSelectionText;
};
goog.dom.selection.getRangeIe_ = function(el) {
  var doc = el.ownerDocument || el.document;
  var selectionRange = doc.selection.createRange();
  var range;
  if (el.type == goog.dom.InputType.TEXTAREA) {
    range = doc.body.createTextRange();
    range.moveToElementText(el);
  } else {
    range = el.createTextRange();
  }
  return [range, selectionRange];
};
goog.dom.selection.canonicalizePositionIe_ = function(textfield, pos) {
  textfield = textfield;
  if (textfield.type == goog.dom.InputType.TEXTAREA) {
    var value = textfield.value.substring(0, pos);
    pos = goog.string.canonicalizeNewlines(value).length;
  }
  return pos;
};
goog.dom.selection.useSelectionProperties_ = function(el) {
  try {
    return typeof el.selectionStart == "number";
  } catch (e) {
    return false;
  }
};
goog.dom.selection.isLegacyIe_ = function() {
  return goog.userAgent.IE && !goog.userAgent.isVersionOrHigher("9");
};
goog.provide("uno.util.richlink");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.classlist");
goog.require("goog.dom.selection");
goog.require("goog.string");
goog.require("uno.defs");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.richlink");
  var defs = uno.defs;
  var util = uno.util;
  util.richlink.counter = 0;
  util.richlink.DISPLAY_TYPE = {NONE:"en_rl_none", MINIMAL:"en_rl_minimal", TEXT:"en_rl_text", SMALL:"en_rl_small"};
  util.richlink.isRichLink = function(node) {
    return node && util.dom.matches(node, ".en-richlink");
  };
  util.richlink.componentElementFor = function(el) {
    return goog.dom.getAncestorByTagNameAndClass(el, null, "en-richlink");
  };
  util.richlink.all = function(root) {
    return root.querySelectorAll(".en-richlink");
  };
  util.richlink.allPlain = function(root) {
    return root.querySelectorAll("a:not(.en-richlink)");
  };
  util.richlink.allPending = function(root) {
    return root.querySelectorAll("a.en-richlink-pending");
  };
  util.richlink.allUndecorated = function(root) {
    return Array.prototype.filter.call(util.richlink.allPlain(root), function(link) {
      return link.rev === util.richlink.DISPLAY_TYPE.NONE || link.rev === util.richlink.DISPLAY_TYPE.MINIMAL || link.rev === util.richlink.DISPLAY_TYPE.TEXT || link.rev === util.richlink.DISPLAY_TYPE.SMALL;
    });
  };
  util.richlink.canDecorate = function(el, editor) {
    return !!util.richlink.getProvider(el, editor);
  };
  util.richlink.getProvider = function(el, editor) {
    var provider;
    editor.richlinkProviders.some(function(p) {
      if (p.canDecorate(el.href)) {
        provider = p;
        return true;
      }
    });
    return provider;
  };
  util.richlink.decorate = function(el, editor) {
    if (!el.href || util.richlink.hasNonDecoratableChildren(el)) {
      return;
    }
    var provider = util.richlink.getProvider(el, editor);
    if (provider) {
      el.dataset.provider = provider.name;
      el.dataset.title = el.innerText;
      el.dataset.href = el.href;
      util.richlink.setDisplayType(el, util.richlink.getDisplayType(el));
      provider.decorate(el, editor);
      return true;
    }
  };
  util.richlink.undecorate = function(el, editor) {
    editor.richlinkProviders.some(function(provider) {
      if (provider.name === el.dataset.provider) {
        var anchor = provider.undecorate(el);
        anchor.href = el.dataset.href;
        anchor.removeAttribute("class");
        anchor.innerText = anchor.dataset.title;
        Object.keys(anchor.dataset).forEach(function(key) {
          delete anchor.dataset[key];
        });
        return true;
      }
    });
  };
  util.richlink.setPending = function(el, pending) {
    if (el) {
      if (pending) {
        goog.dom.classlist.add(el, "en-richlink-pending");
      } else {
        goog.dom.classlist.remove(el, "en-richlink-pending");
      }
    }
  };
  util.richlink.setDisplayType = function(el, displayType) {
    el.setAttribute("rev", displayType || util.richlink.DISPLAY_TYPE.SMALL);
  };
  util.richlink.getDisplayType = function(el) {
    var parent;
    var displayType;
    if (!el) {
      displayType = util.richlink.DISPLAY_TYPE.SMALL;
    } else {
      if (el.hasAttribute("rev")) {
        displayType = el.getAttribute("rev");
      } else {
        if ((parent = util.dom.parent(el, "ul, ol, il, dl, td", null)) !== null) {
          displayType = util.richlink.DISPLAY_TYPE.MINIMAL;
        } else {
          if (util.dom.hasTextNextToIt(el)) {
            displayType = util.richlink.DISPLAY_TYPE.MINIMAL;
          } else {
            if (util.dom.hasTodoNextToIt(el)) {
              displayType = util.richlink.DISPLAY_TYPE.MINIMAL;
            } else {
              displayType = util.richlink.DISPLAY_TYPE.SMALL;
            }
          }
        }
      }
    }
    return displayType;
  };
  util.richlink.hasNonDecoratableChildren = function(node) {
    if (!node || !node.childNodes || node.childNodes.length == 0) {
      return false;
    }
    for (var index = 0; index < node.children.length; index++) {
      if (node.children[index].nodeName && (node.children[index].nodeName.toLowerCase() == "img" || uno.defs.blockElements[node.children[index].nodeName.toLowerCase()] && node.children[index].nodeName.toLowerCase() != "p")) {
        return true;
      }
      if (util.richlink.hasNonDecoratableChildren(node.children[index])) {
        return true;
      }
    }
    return false;
  };
  util.richlink.handleClick = function(el, target, editor) {
    var result = false;
    editor.richlinkProviders.some(function(provider) {
      if (provider.name === el.dataset.provider) {
        result = provider.handleClick(el, target, editor);
      }
    });
    return result;
  };
  util.richlink.handleMouseMove = function(el, target, editor) {
    var result = false;
    editor.richlinkProviders.some(function(provider) {
      if (provider.name === el.dataset.provider) {
        result = provider.handleMouseMove(el, target, editor);
      }
    });
    return result;
  };
  util.richlink.handleMouseOut = function(el, target, editor) {
    var result = false;
    editor.richlinkProviders.some(function(provider) {
      if (provider.name === el.dataset.provider) {
        result = provider.handleMouseOut(el, target, editor);
      }
    });
    return result;
  };
})();
goog.provide("uno.commands.CreateLink");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.editor.plugins.BasicTextFormatter");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.richlink");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.CreateLink");
  var util = uno.util;
  var CreateLink = uno.commands.CreateLink = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CreateLink, uno.BasePlugin);
  CreateLink.prototype.isSupportedCommand = function(command) {
    return command === "createlink";
  };
  CreateLink.prototype.activeOnUneditableFields = goog.functions.TRUE;
  CreateLink.prototype.execCommandInternal = function(command, value) {
    var container;
    var editor = this.editor;
    var url = goog.isObject(value) ? value.url : value;
    var title = goog.isObject(value) ? value.title || value.url : value;
    var range = editor.getRange();
    var dom = goog.dom;
    var node;
    if (range == null) {
      return;
    }
    if (url == null) {
      return;
    }
    if (range.isCollapsed()) {
      node = dom.createTextNode(title);
      range.replaceContentsWithNode(node);
      range = goog.dom.Range.createFromNodes(node, 0, node, title.length);
      range.select();
    }
    editor.execCommand(goog.editor.plugins.BasicTextFormatter.COMMAND.CREATE_LINK, range, url);
    range = editor.getRange();
    container = range.getContainerElement();
    if (util.dom.compareTagName(container, "a")) {
      container.setAttribute("href", url);
      util.richlink.decorate(container, editor);
    }
    goog.array.forEachRight(container.querySelectorAll("a"), function(a) {
      if (editor.getRange() && editor.getRange().containsNode(a)) {
        a.setAttribute("href", url);
        util.richlink.decorate(a, editor);
      }
    });
    editor.updateEmpty();
  };
  CreateLink.prototype.queryCommandValue = function() {
    var anchor;
    var range = this.editor.getRange();
    if (range && (range.isCollapsed() || range.getContainer() === range.getStartNode())) {
      anchor = goog.dom.getAncestorByTagNameAndClass(range.getStartNode(), "a");
      if (anchor && anchor.hasAttribute("href")) {
        return anchor.getAttribute("href");
      }
    }
    return null;
  };
  CreateLink.prototype.queryCommandEnabled = function(command) {
    return !!this.editor.getRange();
  };
})();
goog.provide("uno.commands.Crypt");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.classlist");
goog.require("goog.editor.range");
goog.require("goog.functions");
goog.require("goog.object");
goog.require("goog.string");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.crypto");
goog.require("uno.util.dom");
goog.require("uno.util.list");
goog.require("uno.util.copy");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Crypt");
  var util = uno.util;
  var Crypt = uno.commands.Crypt = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Crypt, uno.BasePlugin);
  var CRYPT_CLASS = uno.defs.crypto.CRYPT_CLASS;
  var CRYPT_HIDDEN_CLASS = uno.defs.crypto.CRYPT_HIDDEN_CLASS;
  var CRYPT_VISIBLE_CLASS = uno.defs.crypto.CRYPT_VISIBLE_CLASS;
  Crypt.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Crypt.prototype.isSupportedCommand = function(command) {
    return command === "crypt";
  };
  Crypt.prototype.queryCommandEnabled = function(command, value) {
    if (value) {
      return true;
    }
    var range = this.editor.getRange();
    var selection = getSelectedContents(this.editor);
    return !!(range && !range.isCollapsed() && !getCryptNodeFromRange(range) && selection && isValidHtml(selection.html));
  };
  Crypt.prototype.queryCommandValue = function(command, value) {
    var range = this.editor.getRange();
    if (range) {
      var cryptNode = getCryptNodeFromRange(range);
      var hasClass = goog.dom.classlist.contains;
      if (cryptNode) {
        if (value === "open") {
          return hasClass(cryptNode, CRYPT_VISIBLE_CLASS);
        } else {
          if (value === "closed") {
            return hasClass(cryptNode, CRYPT_HIDDEN_CLASS) || !hasClass(cryptNode, CRYPT_VISIBLE_CLASS);
          } else {
            if (value === "selected") {
              var cryptInfo = util.crypto.getCryptInfoFromNode(cryptNode);
              cryptInfo.open = !!hasClass(cryptNode, CRYPT_VISIBLE_CLASS);
              return cryptInfo;
            }
          }
        }
        return true;
      }
    }
    return false;
  };
  Crypt.prototype.execCommand = function(command, options) {
    var editor = this.editor;
    var range = editor.getRange();
    var result;
    if (!options) {
      result = requestEncryption(null, editor);
    } else {
      if (options.encrypt) {
        result = encrypt(options.encrypt, range, editor);
      } else {
        if (options.decrypt) {
          result = decrypt(options.decrypt, range, editor);
        } else {
          if (options.revert) {
            result = revert(options.revert, range, editor);
          } else {
            if (options.open) {
              result = open(options.open, range, editor);
            } else {
              if (options.close) {
                result = close(options.close, range, editor);
              } else {
                result = false;
              }
            }
          }
        }
      }
    }
    return result;
  };
  function isValidHtml(html) {
    var frag = util.dom.fragFromString(html);
    return frag.querySelectorAll("img,object,embed,table,tr,td,th,tbody,thead,ul,ol,hr").length === 0;
  }
  function getSelectedContents(editor) {
    return util.copy.copy(editor, {html:true, addMarker:false});
  }
  function requestEncryption(options, editor) {
    var selection = getSelectedContents(editor);
    if (!selection.html) {
      return false;
    }
    var cryptInfo = {id:"crypt-" + editor.context.crypt.incrementUniqueId(), length:"", cipher:"", hint:"", cipherText:"", plainText:selection.html, src:options && options.src || ""};
    editor.dispatchEvent({type:"encrypt", cryptInfo:cryptInfo});
    return cryptInfo;
  }
  function hide(options, range, editor) {
    if (!range || range.isCollapsed()) {
      return false;
    }
    var selection = getSelectedContents(editor);
    if (!selection.html) {
      return false;
    }
    var encryptedNode = util.crypto.createCryptoPlaceholder({id:options.cryptInfo.id, src:options.cryptInfo.src, plainText:options.cryptInfo.plainText});
    editor.execCommand("delete");
    editor.getRange().insertNode(encryptedNode, true);
    return encryptedNode;
  }
  function encrypt(options, range, editor) {
    if (!options) {
      return false;
    }
    if (!options.cryptInfo) {
      return options.src ? requestEncryption(options, editor) : false;
    }
    if (!options.cipherText) {
      return false;
    }
    var cryptNode = hide(options, range, editor);
    if (cryptNode) {
      cryptNode.setAttribute("data-ciphertext", options.cipherText);
      cryptNode.setAttribute("data-cipher", options.cipher);
      cryptNode.setAttribute("data-length", options.length);
      cryptNode.setAttribute("data-hint", options.hint);
      editor.dispatchChange();
      return true;
    }
    return false;
  }
  function decrypt(options, range, editor) {
    var cryptInfo = options && options.cryptInfo;
    var encryptedOnly = cryptInfo.revert ? {} : {encryptedOnly:true};
    var cryptNode = util.crypto.getNodeFromCryptInfo(cryptInfo, encryptedOnly);
    if (!cryptNode || !options.plainText) {
      return false;
    }
    var result = openCrypt(cryptNode, options.plainText, cryptInfo.revert, editor);
    return result;
  }
  function revert(options, range, editor) {
    var cryptInfo = {};
    var cryptNode = getCryptNode(options, range);
    if (cryptNode) {
      if (util.crypto.isOpen(cryptNode)) {
        openCrypt(cryptNode, cryptNode.innerHTML, true, editor);
      } else {
        goog.object.extend(cryptInfo, options, util.crypto.getCryptInfoFromNode(cryptNode), {revert:true});
        editor.dispatchEvent({type:"decrypt", cryptInfo:cryptInfo});
      }
      return true;
    }
    return false;
  }
  function open(options, range, editor) {
    var cryptInfo = {};
    var cryptNode = getCryptNode(options, range);
    if (cryptNode) {
      goog.object.extend(cryptInfo, options, util.crypto.getCryptInfoFromNode(cryptNode));
      editor.dispatchEvent({type:"decrypt", cryptInfo:cryptInfo});
      return true;
    }
    return false;
  }
  function getCryptNode(options, range) {
    var cryptNode;
    if (options.id) {
      cryptNode = util.crypto.getNodeFromCryptInfo(options);
    } else {
      if (range) {
        var container = range.getContainerElement();
        cryptNode = util.crypto.isCrypt(container) ? container : container.querySelector("." + CRYPT_CLASS);
        if (cryptNode) {
          options.id = cryptNode.id;
        }
      }
    }
    return cryptNode;
  }
  function close(options, range, editor) {
    var cryptInfo = {};
    var cryptNode;
    if (options.id) {
      cryptNode = util.crypto.getNodeFromCryptInfo(options, {decryptedOnly:true});
    }
    if (!cryptNode) {
      return false;
    }
    goog.object.extend(cryptInfo, options, util.crypto.getCryptInfoFromNode(cryptNode));
    if (util.crypto.isDirty(cryptNode)) {
      goog.object.extend(cryptInfo, {plainText:cryptNode.innerHTML});
      editor.dispatchEvent({type:"encrypt", cryptInfo:cryptInfo});
      return true;
    }
    var placeholder = util.crypto.createCryptoPlaceholder(cryptInfo);
    return !!replaceNodeAndKeepSelection(cryptNode, placeholder);
  }
  function openCrypt(cryptNode, plainText, openPermanently, editor) {
    var placeholder = null;
    var cryptInfo = util.crypto.getCryptInfoFromNode(cryptNode);
    if (!plainText) {
      return false;
    }
    if (openPermanently) {
      placeholder = document.createElement("span");
      placeholder.innerHTML = plainText;
      editor.dispatchChange();
    } else {
      var attrs = {class:CRYPT_CLASS + " " + CRYPT_VISIBLE_CLASS, id:cryptInfo.id, "data-src":cryptInfo.src || "", "data-length":cryptInfo.length, "data-cipher":cryptInfo.cipher, "data-hint":cryptInfo.hint, "data-ciphertext":cryptInfo.cipherText};
      placeholder = goog.dom.createDom("blockquote", attrs);
      placeholder.innerHTML = plainText;
      placeholder.dataset.hash = util.crypto.hash(placeholder.innerHTML);
      placeholder.setAttribute("contentEditable", !editor.config.crypt.readOnly);
    }
    return !!replaceNodeAndKeepSelection(cryptNode, placeholder, openPermanently);
  }
  function getCryptNodeFromRange(range) {
    var container = document.createElement("div");
    container.innerHTML = range.getValidHtml();
    return container.querySelector("." + CRYPT_CLASS);
  }
  function replaceNodeAndKeepSelection(oldNode, newNode, flatten) {
    goog.dom.replaceNode(newNode, oldNode);
    var range = goog.editor.range.placeCursorNextTo(newNode);
    range.select();
    if (flatten) {
      goog.dom.flattenElement(newNode);
    }
    return range;
  }
})();
goog.provide("uno.commands.Cut");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Cut");
  var Cut = uno.commands.Cut = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Cut, uno.BasePlugin);
  Cut.prototype.isSupportedCommand = function(command) {
    return command === "cut";
  };
  Cut.prototype.execCommandInternal = function(command, opt) {
    return !!this.queryCommandValue(command, opt);
  };
  Cut.prototype.queryCommandValue = function() {
    var result = this.editor.queryCommandValue("copy");
    this.editor.execCommand("delete", "selection", undefined, true);
    return result;
  };
})();
goog.provide("uno.commands.Delete");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.iter");
goog.require("uno.BasePlugin");
goog.require("uno.EditorMultiRange");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.table");
(function() {
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.commands.Delete");
  var ZERO_WIDTH_SPACE = uno.defs.unicode.ZERO_WIDTH_SPACE;
  var Delete = uno.commands.Delete = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(Delete, uno.BasePlugin);
  Delete.WORD = "word";
  Delete.SELECTION = "selection";
  Delete.prototype.isSupportedCommand = function(command) {
    return command === "delete";
  };
  Delete.prototype.queryCommandValue = function(command) {
    return document.queryCommandValue(command);
  };
  Delete.prototype.execCommand = function(command, value, options) {
    if (options && options.smart === false) {
      clearBaseAndExtent();
    }
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var forward = options ? options.forward : false;
    var native = options ? options.native : false;
    var focusNode = range.getFocusNode();
    var focusOffset = range.getFocusOffset();
    if (value === Delete.SELECTION && range.isCollapsed()) {
      return false;
    }
    if (value === Delete.WORD) {
      var wordRange = getWordRange(range, focusOffset, forward);
      selectRange(wordRange);
      range = this.editor.getRange();
      value = 1;
    }
    this.editor.dispatchBeforeChange();
    var result;
    var count = parseInt(value, 10);
    count = isNaN(count) ? 1 : count;
    for (var i = 0; i < count; i++) {
      var currentNode = focusNode.childNodes && focusNode.childNodes[focusOffset - 1];
      if (isCursorAfterCodeBlock(focusNode, focusOffset) && range.isCollapsed()) {
        result = moveCursorToEndOfCodeBlock(focusNode, this.editor);
      } else {
        if (isCursorAtBeginningOfCodeBlock(focusNode, focusOffset) && range.isCollapsed()) {
          result = moveFirstLineOutOfCodeBlock(focusNode, this.editor);
        }
      }
      if (this.editor.multirange.isInvoking()) {
        result = emptyCell(focusNode);
      } else {
        if (shouldEmptyCell(range, forward)) {
          result = emptyCell(focusNode, true);
        } else {
          if (!forward && isTableSelectedBeforeCursor(range) || forward && isTableSelectedAfterCursor(range)) {
            result = true;
          } else {
            if (assistedTableDelete(range, forward)) {
              result = true;
            } else {
              if (isLastIndentation(focusNode, focusOffset) && range.isCollapsed() && !forward) {
                result = deleteIndentation(focusNode);
              } else {
                if (isAfterResource(focusNode, focusOffset, forward)) {
                  result = removeResource(focusNode, range.isCollapsed());
                } else {
                  if (isEditorDefaultEmpty(this.editor)) {
                    result = true;
                  } else {
                    if (range.isCollapsed() && isEmptyParagraph(focusNode) && !isAtBeginningOfNote(focusNode, focusOffset, this.editor)) {
                      result = removeParagraph(focusNode);
                    }
                  }
                }
              }
            }
          }
        }
      }
      if (typeof result !== "undefined") {
        if (result === true) {
          this.editor.dispatchChange();
        }
        return result;
      } else {
        if (native) {
          return false;
        }
      }
      deleteSelection(forward);
    }
    this.editor.dispatchChange();
    return true;
  };
  function isEditorDefaultEmpty(editor) {
    return editor.field.innerHTML === editor.config.defaults.html;
  }
  function isAtBeginningOfNote(node, offset, editor) {
    if (offset === 0 && editor.field && util.dom.isBeginningOfLineChild(node, editor.field)) {
      return true;
    }
    return false;
  }
  function removeParagraph(paragraph) {
    var blockquote = goog.dom.getAncestor(paragraph, util.dom.isBlockquote, true, 2);
    var previousParagraph;
    var lastWord;
    if (blockquote) {
      previousParagraph = blockquote.previousSibling;
      var newNode = goog.dom.createDom("div", {}, goog.dom.createDom("br"));
      if (util.dom.isEmpty(blockquote)) {
        goog.dom.replaceNode(newNode, blockquote);
        lastWord = util.dom.getLastParagraphItem(blockquote.previousSibling);
      } else {
        lastWord = util.dom.getLastParagraphItem(paragraph.previousSibling);
        util.paragraph.remove(paragraph);
      }
      if (lastWord) {
        goog.editor.range.placeCursorNextTo(lastWord);
      }
    } else {
      lastWord = util.dom.getLastParagraphItem(paragraph.previousParagraph);
      util.paragraph.remove(paragraph);
      if (lastWord) {
        goog.editor.range.placeCursorNextTo(lastWord);
      }
    }
    return true;
  }
  function clearBaseAndExtent() {
    var sel = window.getSelection();
    if (!sel || sel.setBaseAndExtent === undefined || sel.baseNode === undefined) {
      return;
    }
    var clear = sel.type === "Range" && (sel.anchorNode !== sel.baseNode || sel.anchorOffset !== sel.baseOffset || sel.extentNode !== sel.focusNode || sel.extentOffset !== sel.focusOffset);
    if (clear) {
      sel.setBaseAndExtent(sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset);
    }
  }
  function deleteSelection(forward) {
    var commandName = forward ? "forwarddelete" : "delete";
    return document.execCommand(commandName);
  }
  function selectRange(range) {
    var currentSelection = window.getSelection();
    currentSelection.removeAllRanges();
    currentSelection.addRange(range.getBrowserRangeObject());
  }
  function getWordRange(currentRange, offset, forward) {
    var wordRange = currentRange;
    var wordNode = currentRange.getContainer();
    if (offset && wordNode && wordNode.nodeType === Node.TEXT_NODE) {
      var found = false;
      var index = 0;
      wordNode.nodeValue.split(" ").forEach(function(word, i, arr) {
        var oldIndex = index;
        index += word.length;
        if (i < arr.length - 1) {
          index++;
        }
        if (!found) {
          if (forward && (offset === oldIndex || offset === oldIndex - 1)) {
            found = true;
          } else {
            if (!forward && (offset === index || offset === index - 1)) {
              found = true;
            } else {
              if (offset > oldIndex && offset < index) {
                found = true;
              }
            }
          }
          if (found) {
            wordRange = goog.dom.Range.createFromNodes(wordNode, oldIndex, wordNode, index);
          }
        }
      });
    }
    return wordRange;
  }
  function isTableSelectedBeforeCursor(range) {
    if (!range.isCollapsed() || range.getFocusOffset() > 0 || isCursorAtBeginningOfLI(range)) {
      return false;
    }
    var beforeNode = getParagraphBeforeNode(range.getFocusNode());
    if (!beforeNode) {
      return false;
    }
    var enTable = util.dom.isEntable(beforeNode) ? beforeNode : beforeNode.querySelector("en-table");
    if (enTable) {
      goog.dom.Range.createFromNodes(enTable, 0, enTable, enTable.childNodes.length).select();
      enTable.classList.add("selected");
      return true;
    }
    return false;
  }
  function isTableSelectedAfterCursor(range) {
    if (!range.isCollapsed()) {
      return false;
    }
    var node = util.dom.getLastParagraphItem(range.getFocusNode());
    if (!node || util.dom.isTextNode(node) && node.length > range.getFocusOffset()) {
      return false;
    }
    var nextNode = util.dom.nextNode(node);
    if (!nextNode) {
      return false;
    }
    var enTable = util.dom.isEntable(nextNode) ? nextNode : nextNode.querySelector("en-table");
    if (enTable) {
      goog.dom.Range.createFromNodes(enTable, 0, enTable, enTable.childNodes.length).select();
      enTable.classList.add("selected");
      return true;
    }
    return false;
  }
  function assistedTableDelete(range, forward) {
    if (range.isCollapsed()) {
      return false;
    }
    var startAncestor = goog.dom.getAncestor(range.getStartNode(), util.dom.isEntable, true);
    var endAncestor = goog.dom.getAncestor(range.getEndNode(), util.dom.isEntable, true);
    var tableParent = null;
    var tableIndex = 0;
    var deleted = false;
    if (endAncestor && endAncestor !== startAncestor && endAncestor.classList.contains("selected")) {
      tableIndex = util.dom.index(endAncestor);
      tableParent = endAncestor.parentElement;
      endAncestor.remove();
      deleted = true;
    }
    if (startAncestor && startAncestor.classList.contains("selected")) {
      tableIndex = util.dom.index(startAncestor);
      tableParent = startAncestor.parentElement;
      startAncestor.remove();
      deleted = true;
    }
    if (deleted && !range.isCollapsed()) {
      deleteSelection(forward);
    }
    return deleted;
  }
  function shouldEmptyCell(range, forward) {
    var startNode = range.getStartNode();
    var endNode = range.getEndNode();
    var cell = goog.dom.getAncestor(startNode, util.dom.isTd, true);
    var endAncestor = goog.dom.getAncestor(endNode, util.dom.isTd, true);
    if (!cell || cell !== endAncestor) {
      return false;
    }
    if (util.dom.isEmptyContent(cell)) {
      return true;
    }
    var startOffset = range.getStartOffset();
    var endOffset = range.getEndOffset();
    var leaves = goog.array.filter(util.dom.getNodeLeaves(cell), function(node) {
      return !util.dom.isBr(node);
    });
    if (range.isCollapsed() && leaves.length === 1) {
      if (util.dom.isTextNode(leaves[0]) && leaves[0] === startNode && startNode.length === 1 && (startOffset === 1 && !forward || startOffset === 0 && forward)) {
        return true;
      }
      if (leaves[0].parentNode === startNode && (startOffset === 1 && !forward || startOffset === 0 && forward)) {
        return true;
      }
    }
    if (!range.isCollapsed() && goog.array.every(leaves, range.containsNode, range)) {
      return true;
    }
    return false;
  }
  function isEmptyParagraph(node) {
    return node === util.paragraph.for(node) && util.dom.isEmpty(node);
  }
  function isLastIndentation(node, offset) {
    if (offset) {
      return false;
    }
    if (util.dom.isElementNode(node) && (util.dom.isLi(node) || util.dom.isBlockquote(node))) {
      return true;
    } else {
      if (util.dom.isTextNode(node) && (util.dom.isLi(node.parentNode) || util.dom.isBlockquote(node.parentNode))) {
        return true;
      }
    }
    return false;
  }
  function getParagraphBeforeNode(node) {
    var previousParagraph = null;
    var currentParagraph = util.paragraph.for(node);
    if (!currentParagraph) {
      return false;
    }
    while (!previousParagraph) {
      previousParagraph = util.paragraph.prevParagraph(currentParagraph);
      if (previousParagraph && !util.dom.isEnnote(previousParagraph)) {
        break;
      } else {
        if (util.dom.isEnnote(previousParagraph)) {
          break;
        } else {
          currentParagraph = currentParagraph.parentNode;
        }
      }
    }
    return previousParagraph;
  }
  function isCursorAtBeginningOfLI(range) {
    if (!range.isCollapsed() || range.getFocusOffset() > 0) {
      return false;
    }
    var node = range.getFocusNode();
    while (node && !util.dom.isEnnote(node)) {
      if (!node.previousSibling && util.dom.isLi(node)) {
        return true;
      }
      node = node.parentNode;
    }
    return false;
  }
  function isCursorAtBeginningOfCodeBlock(node, offset) {
    var block = goog.dom.getAncestor(node, function(ancestor) {
      return util.dom.isCodeBlock(ancestor);
    }, true);
    if (offset === 0 && block && block.childNodes && block.childNodes[0] === util.paragraph.for(node)) {
      return true;
    }
    return false;
  }
  function moveFirstLineOutOfCodeBlock(node) {
    var block = goog.dom.getAncestor(node, function(ancestor) {
      return util.dom.isCodeBlock(ancestor);
    }, true);
    var textLine = block.childNodes[0].textContent;
    if (textLine.length === 0) {
      textLine = goog.dom.createDom("br");
    }
    block.childNodes[0].remove();
    var newLine = goog.dom.createDom("div", {}, textLine);
    block.parentElement.insertBefore(newLine, block);
    goog.editor.range.selectNodeStart(newLine);
    if (!block.childNodes || block.childNodes.length === 0) {
      block.remove();
    }
    return true;
  }
  function getCodeBlockBeforeNode(node) {
    var previousParagraph = getParagraphBeforeNode(node);
    if (previousParagraph && util.dom.isCodeBlock(previousParagraph)) {
      var block = previousParagraph;
      while (block.childNodes && block.childNodes.length > 0) {
        block = block.childNodes[block.childNodes.length - 1];
      }
      return block;
    }
    return false;
  }
  function moveCursorToEndOfCodeBlock(node, editor) {
    var newText = node.textContent;
    var block = getCodeBlockBeforeNode(node);
    if (block) {
      goog.editor.range.placeCursorNextTo(block);
      var range = editor.getRange();
      range.insertNode(goog.dom.createTextNode(newText));
      node.remove();
      return true;
    }
    return false;
  }
  function isCursorAfterCodeBlock(node, offset) {
    if (offset > 0) {
      return false;
    }
    return getCodeBlockBeforeNode(node);
  }
  function isAfterResource(node, offset, forward) {
    if (node.nodeType === Node.TEXT_NODE) {
      if (forward && (node.length === offset || node.textContent === ZERO_WIDTH_SPACE)) {
        node = node.nextSibling;
      } else {
        if (offset === 0 || node.textContent === ZERO_WIDTH_SPACE) {
          node = node.previousSibling;
        }
      }
    }
    if (util.dom.isEnmedia(node)) {
      return true;
    }
    return false;
  }
  function emptyCell(focusNode, placeCursor) {
    var cell = goog.dom.getAncestor(focusNode, util.dom.isTd, true);
    if (cell) {
      cell.innerHTML = "<div><br></div>";
      if (placeCursor) {
        goog.editor.range.placeCursorNextTo(cell.firstChild);
      }
      return true;
    }
    return false;
  }
  function removeResource(node, isCursorCollapsed, forward) {
    var enMedia = node;
    if (node.nodeType === Node.TEXT_NODE) {
      var sibling = forward ? node.nextSibling : node.previousSibling;
      if (sibling && sibling.tagName && sibling.tagName.toLowerCase() === "en-media") {
        enMedia = sibling;
      }
    }
    var previousSibling = enMedia.previousSibling;
    var nextSibling = enMedia.nextSibling;
    var startNode = enMedia.parentNode;
    var startOffset = util.dom.index(enMedia);
    if (previousSibling && previousSibling.textContent === ZERO_WIDTH_SPACE) {
      startNode = previousSibling;
      startOffset = 0;
    }
    var endNode = enMedia.parentNode;
    var endOffset = util.dom.index(enMedia) + 1;
    if (nextSibling && nextSibling.textContent === ZERO_WIDTH_SPACE) {
      endNode = nextSibling;
      endOffset = 1;
    }
    var range = goog.dom.Range.createFromNodes(startNode, startOffset, endNode, endOffset);
    if (isCursorCollapsed) {
      range.select();
    } else {
      deleteSelection(forward);
    }
    return true;
  }
  function deleteIndentation(element, forward) {
    var node = element.nodeType === Node.TEXT_NODE ? element.parentNode : element;
    var parent = node.parentNode;
    if (util.dom.isBlockquote(parent) || util.dom.isUl(parent) || util.dom.isOl(parent)) {
      var tagName = node.tagName.toLowerCase();
      var lis = parent.querySelectorAll(tagName);
      if (lis.length && lis[0] === node) {
        var grandParent = parent.parentNode;
        var line;
        var isParentAList = tagName === "li" && util.dom.isUl(grandParent) || util.dom.isOl(grandParent);
        var isParentABlockquote = tagName === "blockquote" && util.dom.isBlockquote(grandParent);
        if (grandParent && isParentAList || isParentABlockquote) {
          line = node;
        } else {
          line = document.createElement("div");
          line.innerHTML = node.innerHTML || "<br>";
        }
        if (lis.length === 0) {
          goog.dom.replaceNode(line, parent);
        } else {
          goog.dom.removeNode(node);
          grandParent.insertBefore(line, parent);
        }
        var range = goog.dom.Range.createFromNodes(line, 0, line, 0);
        range.select();
        return true;
      }
    }
    return deleteSelection(forward);
  }
})();
goog.provide("uno.commands.DeleteTable");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.editor.plugins.TableEditor");
goog.require("uno.BasePlugin");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.DeleteTable");
  var util = uno.util;
  var DeleteTable = uno.commands.DeleteTable = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(DeleteTable, uno.BasePlugin);
  DeleteTable.prototype.isSupportedCommand = function(command) {
    return command === "deletetable";
  };
  DeleteTable.prototype.execCommandInternal = function() {
    var table = goog.dom.getAncestor(this.editor.getRange().getStartNode(), util.dom.isTable);
    return util.table.delete(goog.dom.getAncestor(table, util.dom.isEntable) || table);
  };
  DeleteTable.prototype.queryCommandEnabled = function() {
    return !!util.table.cellForStructureChange(this.editor.getRange());
  };
})();
goog.provide("uno.commands.DeleteTableCol");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.DeleteTableCol");
  var util = uno.util;
  var DeleteTableCol = uno.commands.DeleteTableCol = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(DeleteTableCol, uno.BasePlugin);
  DeleteTableCol.prototype.isSupportedCommand = function(command) {
    return command === "deletetablecol";
  };
  DeleteTableCol.prototype.execCommandInternal = function() {
    var indexes = [];
    var enTable = util.table.getActive();
    var table = null;
    if (util.table.selection.isActive(enTable)) {
      indexes = util.table.selection.getColumnIndexes();
      util.table.selection.clear();
    } else {
      if (enTable) {
        var info = util.table.infoForCell(util.table.getActiveCell());
        if (info) {
          for (var c = info.startColIndex; c <= info.endColIndex; c++) {
            indexes.push(c);
          }
        }
      } else {
        var cell = util.table.cellForStructureChange(this.editor.getRange());
        var info = util.table.infoForCell(cell);
        if (info) {
          table = goog.dom.getAncestor(cell, util.dom.isTable);
          indexes.push(info.startColIndex);
        }
      }
    }
    return util.table.deleteColumns(enTable || table, indexes);
  };
  DeleteTableCol.prototype.queryCommandEnabled = function() {
    return !!util.table.cellForStructureChange(this.editor.getRange());
  };
})();
goog.provide("uno.commands.DeleteTableRow");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.DeleteTableRow");
  var util = uno.util;
  var DeleteTableRow = uno.commands.DeleteTableRow = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(DeleteTableRow, uno.BasePlugin);
  DeleteTableRow.prototype.isSupportedCommand = function(command) {
    return command === "deletetablerow";
  };
  DeleteTableRow.prototype.execCommandInternal = function() {
    var indexes = [];
    var enTable = util.table.getActive();
    var table = null;
    if (util.table.selection.isActive(enTable)) {
      indexes = util.table.selection.getRowIndexes();
      util.table.selection.clear();
    } else {
      if (enTable) {
        var info = util.table.infoForCell(util.table.getActiveCell());
        if (info) {
          for (var r = info.startRowIndex; r <= info.endRowIndex; r++) {
            indexes.push(r);
          }
        }
      } else {
        var cell = util.table.cellForStructureChange(this.editor.getRange());
        var info = util.table.infoForCell(cell);
        if (info) {
          table = goog.dom.getAncestor(cell, util.dom.isTable);
          indexes.push(info.startRowIndex);
        }
      }
    }
    return util.table.deleteRows(enTable || table, indexes);
  };
  DeleteTableRow.prototype.queryCommandEnabled = function() {
    return !!util.table.cellForStructureChange(this.editor.getRange());
  };
})();
goog.provide("uno.commands.searchapi");
(function() {
  var searchapi = uno.commands.searchapi;
  var DIACRITIC_CHARS = {a:"a\u24d0\uff41\u1e9a\u00e0\u00e1\u00e2\u1ea7\u1ea5\u1eab\u1ea9\u00e3\u0101\u0103\u1eb1\u1eaf\u1eb5\u1eb3\u0227\u01e1\u00e4\u01df\u1ea3\u00e5\u01fb\u01ce\u0201\u0203\u1ea1\u1ead\u1eb7\u1e01\u0105\u2c65\u0250", b:"b\u24d1\uff42\u1e03\u1e05\u1e07\u0180\u0183\u0253", c:"c\u24d2\uff43\u0107\u0109\u010b\u010d\u00e7\u1e09\u0188\u023c\ua73f\u2184", d:"d\u24d3\uff44\u1e0b\u010f\u1e0d\u1e11\u1e13\u1e0f\u0111\u018c\u0256\u0257\ua77a", e:"e\u24d4\uff45\u00e8\u00e9\u00ea\u1ec1\u1ebf\u1ec5\u1ec3\u1ebd\u0113\u1e15\u1e17\u0115\u0117\u00eb\u1ebb\u011b\u0205\u0207\u1eb9\u1ec7\u0229\u1e1d\u0119\u1e19\u1e1b\u0247\u025b\u01dd", 
  f:"f\u24d5\uff46\u1e1f\u0192\ua77c", g:"g\u24d6\uff47\u01f5\u011d\u1e21\u011f\u0121\u01e7\u0123\u01e5\u0260\ua7a1\u1d79\ua77f", h:"h\u24d7\uff48\u0125\u1e23\u1e27\u021f\u1e25\u1e29\u1e2b\u1e96\u0127\u2c68\u2c76\u0265", i:"i\u24d8\uff49\u00ec\u00ed\u00ee\u0129\u012b\u012d\u00ef\u1e2f\u1ec9\u01d0\u0209\u020b\u1ecb\u012f\u1e2d\u0268\u0131", j:"j\u24d9\uff4a\u0135\u01f0\u0249", k:"k\u24da\uff4b\u1e31\u01e9\u1e33\u0137\u1e35\u0199\u2c6a\ua741\ua743\ua745\ua7a3", l:"l\u24db\uff4c\u0140\u013a\u013e\u1e37\u1e39\u013c\u1e3d\u1e3b\u017f\u0142\u019a\u026b\u2c61\ua749\ua781\ua747", 
  m:"m\u24dc\uff4d\u1e3f\u1e41\u1e43\u0271\u026f", n:"n\u24dd\uff4e\u01f9\u0144\u00f1\u1e45\u0148\u1e47\u0146\u1e4b\u1e49\u019e\u0272\u0149\ua791\ua7a5", o:"o\u24de\uff4f\u00f2\u00f3\u00f4\u1ed3\u1ed1\u1ed7\u1ed5\u00f5\u1e4d\u022d\u1e4f\u014d\u1e51\u1e53\u014f\u022f\u0231\u00f6\u022b\u1ecf\u0151\u01d2\u020d\u020f\u01a1\u1edd\u1edb\u1ee1\u1edf\u1ee3\u1ecd\u1ed9\u01eb\u01ed\u00f8\u01ff\u0254\ua74b\ua74d\u0275", p:"p\u24df\uff50\u1e55\u1e57\u01a5\u1d7d\ua751\ua753\ua755", q:"q\u24e0\uff51\u024b\ua757\ua759", 
  r:"r\u24e1\uff52\u0155\u1e59\u0159\u0211\u0213\u1e5b\u1e5d\u0157\u1e5f\u024d\u027d\ua75b\ua7a7\ua783", s:"s\u24e2\uff53\u00df\u015b\u1e65\u015d\u1e61\u0161\u1e67\u1e63\u1e69\u0219\u015f\u023f\ua7a9\ua785\u1e9b", t:"t\u24e3\uff54\u1e6b\u1e97\u0165\u1e6d\u021b\u0163\u1e71\u1e6f\u0167\u01ad\u0288\u2c66\ua787", u:"u\u24e4\uff55\u00f9\u00fa\u00fb\u0169\u1e79\u016b\u1e7b\u016d\u00fc\u01dc\u01d8\u01d6\u01da\u1ee7\u016f\u0171\u01d4\u0215\u0217\u01b0\u1eeb\u1ee9\u1eef\u1eed\u1ef1\u1ee5\u1e73\u0173\u1e77\u1e75\u0289", 
  v:"v\u24e5\uff56\u1e7d\u1e7f\u028b\ua75f\u028c", w:"w\u24e6\uff57\u1e81\u1e83\u0175\u1e87\u1e85\u1e98\u1e89\u2c73", x:"x\u24e7\uff58\u1e8b\u1e8d", y:"y\u24e8\uff59\u1ef3\u00fd\u0177\u1ef9\u0233\u1e8f\u00ff\u1ef7\u1e99\u1ef5\u01b4\u024f\u1eff", z:"z\u24e9\uff5a\u017a\u1e91\u017c\u017e\u1e93\u1e95\u01b6\u0225\u0240\u2c6c\ua763"};
  var DIACRITICMAP = {};
  for (var s in DIACRITIC_CHARS) {
    if (DIACRITIC_CHARS.hasOwnProperty(s)) {
      var characters = DIACRITIC_CHARS[s];
      DIACRITICMAP[s] = "[" + s + characters + "]";
      for (var i = 0; i < characters.length; i++) {
        var letter = characters[i];
        if (!DIACRITICMAP[letter]) {
          DIACRITICMAP[letter] = DIACRITICMAP[s];
        }
      }
    }
  }
  var UNICODE_CJK_RANGES = "\u1100-\u11ff\u2e80-\u312f\u3130-\u31bf\u31f0-\u9fff\ua960-\ua97f\uac00-\ud7ff\uf900-\ufaff\ufe30-\ufe4f\uff61-\uffdc";
  var UNICODE_LETTER_CATEGORY_RANGES = "A-Za-z\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0-\u08b4\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16f1-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2183\u2184\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005\u3006\u3031-\u3035\u303b\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6e5\ua717-\ua71f\ua722-\ua788\ua78b-\ua7ad\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc";
  var UNICODE_MARK_CATEGORY_RANGES = "\u0300-\u036f\u0483-\u0489\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u065f\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u0711\u0730-\u074a\u07a6-\u07b0\u07eb-\u07f3\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a70\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0c00-\u0c03\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0d01-\u0d03\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0f18\u0f19\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f\u109a-\u109d\u135d-\u135f\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u180b-\u180d\u18a9\u1920-\u192b\u1930-\u193b\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f\u1ab0-\u1abe\u1b00-\u1b04\u1b34-\u1b44\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1be6-\u1bf3\u1c24-\u1c37\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf8\u1cf9\u1dc0-\u1df5\u1dfc-\u1dff\u20d0-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua66f-\ua672\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c4\ua8e0-\ua8f1\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9e5\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f";
  var UNICODE_DECIMAL_DIGIT_CATEGORY_RANGES = "0-9\u0660-\u0669\u06f0-\u06f9\u07c0-\u07c9\u0966-\u096f\u09e6-\u09ef\u0a66-\u0a6f\u0ae6-\u0aef\u0b66-\u0b6f\u0be6-\u0bef\u0c66-\u0c6f\u0ce6-\u0cef\u0d66-\u0d6f\u0de6-\u0def\u0e50-\u0e59\u0ed0-\u0ed9\u0f20-\u0f29\u1040-\u1049\u1090-\u1099\u17e0-\u17e9\u1810-\u1819\u1946-\u194f\u19d0-\u19d9\u1a80-\u1a89\u1a90-\u1a99\u1b50-\u1b59\u1bb0-\u1bb9\u1c40-\u1c49\u1c50-\u1c59\ua620-\ua629\ua8d0-\ua8d9\ua900-\ua909\ua9d0-\ua9d9\ua9f0-\ua9f9\uaa50-\uaa59\uabf0-\uabf9\uff10-\uff19";
  var UNICODE_ALPHANUM_RANGES = UNICODE_LETTER_CATEGORY_RANGES + UNICODE_MARK_CATEGORY_RANGES + UNICODE_DECIMAL_DIGIT_CATEGORY_RANGES;
  var UNDERSCORE_RANGES = "_\uff3f";
  var EN_CJK_ALPHANUM_CHARSET = "(?=[" + UNICODE_LETTER_CATEGORY_RANGES + UNICODE_MARK_CATEGORY_RANGES + UNICODE_DECIMAL_DIGIT_CATEGORY_RANGES + "])[" + UNICODE_CJK_RANGES + "]";
  var EN_CJK_ALPHANUM_REGEX = RegExp(EN_CJK_ALPHANUM_CHARSET);
  var EN_WORD_BOUNDARY_CHARSET = "(?:[^" + UNICODE_LETTER_CATEGORY_RANGES + UNICODE_MARK_CATEGORY_RANGES + UNICODE_DECIMAL_DIGIT_CATEGORY_RANGES + "]|[" + UNICODE_CJK_RANGES + "])";
  var STARTSWITH_EN_WORD_BOUNDARY_REGEX = RegExp("^" + EN_WORD_BOUNDARY_CHARSET);
  var ENDSWITH_EN_WORD_BOUNDARY_REGEX = RegExp(EN_WORD_BOUNDARY_CHARSET + "$");
  var EN_WORD_DELIMITER_CHARSET = "[^" + UNICODE_ALPHANUM_RANGES + UNDERSCORE_RANGES + "]";
  var EN_WORD_DELIMITER_REGEX = RegExp(EN_WORD_DELIMITER_CHARSET);
  var ONE_OR_MORE_EN_WORD_DELIMITER_PATTERN = EN_WORD_DELIMITER_CHARSET + "+";
  var ZERO_OR_MORE_EN_WORD_DELIMITER_PATTERN = EN_WORD_DELIMITER_CHARSET + "*";
  var EN_STOPWORDS = ["a", "an", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"];
  var EN_STOPWORDS_REGEX = RegExp("^(" + EN_STOPWORDS.join("|") + ")$", "i");
  searchapi.getNoteSearchRegex = function(rawSearchTerm) {
    var searchTerm = rawSearchTerm.trim();
    var prefixMatch = /\*$/.test(searchTerm);
    searchTerm = prefixMatch ? searchTerm.substring(0, searchTerm.length - 1) : searchTerm;
    if (searchTerm.length <= 0) {
      return null;
    }
    if (EN_STOPWORDS_REGEX.test(searchTerm)) {
      return null;
    }
    var pattern = searchTerm;
    var newValue = [];
    var prevCharDelimeter = false;
    var prevCharCJK = false;
    for (var s = 0; s < pattern.length; s++) {
      var character = pattern[s];
      if (isCharCJKAlphanum(character)) {
        if (prevCharCJK) {
          newValue.push(ZERO_OR_MORE_EN_WORD_DELIMITER_PATTERN);
        }
        newValue.push(character);
        prevCharDelimeter = false;
        prevCharCJK = true;
      } else {
        if (isCharWordDelimiter(character)) {
          if (!prevCharDelimeter) {
            newValue.push(ONE_OR_MORE_EN_WORD_DELIMITER_PATTERN);
          }
          prevCharDelimeter = true;
          prevCharCJK = false;
        } else {
          if (prevCharCJK) {
            newValue.push(ZERO_OR_MORE_EN_WORD_DELIMITER_PATTERN);
          }
          var item = DIACRITICMAP[character.toLowerCase()];
          if (item) {
            newValue.push(item);
          } else {
            newValue.push(character);
          }
          prevCharDelimeter = false;
          prevCharCJK = false;
        }
      }
    }
    pattern = newValue.join("");
    pattern = pattern.replace(/\s/g, "\\s");
    pattern = "(" + pattern + ")";
    var groupIdxForHighlight = 1;
    if (!startsWithWordBoundary(searchTerm)) {
      pattern = "(^|" + EN_WORD_BOUNDARY_CHARSET + ")" + pattern;
      groupIdxForHighlight++;
    }
    if (!prefixMatch && !endsWithWordBoundary(searchTerm)) {
      pattern = pattern + "(?:" + EN_WORD_BOUNDARY_CHARSET + "|$)";
    }
    return {regex:new RegExp(pattern, "gi"), getTextRange:function(m) {
      var startIdx = m.index;
      var endIdx = startIdx;
      for (var idx = 1; idx <= groupIdxForHighlight; idx++) {
        startIdx = endIdx;
        endIdx = startIdx + m[idx].length;
      }
      return {start:startIdx, end:endIdx};
    }};
  };
  searchapi.getFindInNoteRegex = function(searchTerm) {
    var pattern = [searchTerm].map(function(word) {
      if (word instanceof RegExp) {
        return word.source;
      }
      return word.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, "\\$&");
    });
    return {regex:new RegExp(pattern, "gi"), getTextRange:function(m, regex) {
      return {start:m.index, end:regex.lastIndex};
    }};
  };
  var isCharCJKAlphanum = function(character) {
    return EN_CJK_ALPHANUM_REGEX.test(character);
  };
  var isCharWordDelimiter = function(character) {
    return EN_WORD_DELIMITER_REGEX.test(character);
  };
  var startsWithWordBoundary = function(sentence) {
    return STARTSWITH_EN_WORD_BOUNDARY_REGEX.test(sentence);
  };
  var endsWithWordBoundary = function(sentence) {
    return ENDSWITH_EN_WORD_BOUNDARY_REGEX.test(sentence);
  };
})();
goog.provide("uno.commands.Find");
goog.require("uno.commands.searchapi");
goog.require("goog.functions");
goog.require("goog.object");
goog.require("goog.debug.Logger");
goog.require("goog.iter");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.range");
goog.require("uno.util.zoomscale");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Find");
  var util = uno.util;
  var Find = uno.commands.Find = function() {
    uno.BasePlugin.call(this, log.getName());
    this.current = {hasMore:false, matches:[], index:-1, term:null, regex:null};
  };
  goog.inherits(Find, uno.BasePlugin);
  Find.NEXT = "next";
  Find.PREV = "prev";
  Find.FIRST = "first";
  Find.LAST = "last";
  Find.ALL = "all";
  Find.CLEAR = "clear";
  Find.prototype.isSupportedCommand = function(command) {
    return command === "find";
  };
  Find.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Find.prototype.queryCommandValue = function(command, rawOptions) {
    this.options = mergeOptions(this.editor.config.find, rawOptions || this.options);
    var options = this.options;
    var current = this.current;
    var result = {limit:options.limit, hasMore:current.hasMore, count:current.matches.length, items:current.matches, index:current.index};
    if (options.value) {
      if (typeof options.value === "string" && options.value.length && options.limit) {
        var getNoteSearchRegex = uno.commands.searchapi.getNoteSearchRegex;
        var getFindInNoteRegex = uno.commands.searchapi.getFindInNoteRegex;
        var searchApi = options.noteSearchMatching ? getNoteSearchRegex(options.value) : getFindInNoteRegex(options.value);
        var searchElements = document.querySelectorAll(options.selector);
        var matches = [];
        var regexResult;
        Array.prototype.forEach.call(searchElements, function(searchElement) {
          var searchRange = goog.dom.Range.createFromNodeContents(searchElement);
          var textNodesArray = textNodesFor(searchRange);
          var rawText = textNodesArray.map(function(textNode) {
            return textNode.text;
          }).join(" ");
          while ((regexResult = searchApi.regex.exec(rawText)) && regexResult && matches.length < options.limit) {
            var textRange = searchApi.getTextRange(regexResult, searchApi.regex);
            searchApi.regex.lastIndex = textRange.end;
            var boundingBoxes = getBoundingBoxes(textNodesArray, textRange);
            if (boundingBoxes) {
              var scrollTop = document.body.scrollTop;
              if (util.dom.isBoundingBoxOnScreen(boundingBoxes[0].top - scrollTop, boundingBoxes[0].bottom - scrollTop)) {
                current.index = matches.length;
              }
              matches.push(boundingBoxes);
            }
          }
        });
        current.hasMore = !!regexResult;
        current.matches = matches;
        current.term = options.value;
        current.regex = searchApi.regex;
        current.index = current.index > -1 ? current.index : 0;
      }
      result = {limit:options.limit, hasMore:current.hasMore, count:current.matches.length, items:current.matches, index:current.index};
    }
    if (options.excludeMatches) {
      delete result.items;
    }
    return JSON.stringify(result);
  };
  function mergeOptions(configOptions, options) {
    var parsedOptions = {};
    var defaultOptions = {limit:100, excludeMatches:false, selector:"en-note", noteSearchMatching:false};
    goog.object.extend(parsedOptions, defaultOptions || {});
    goog.object.extend(parsedOptions, configOptions || {});
    goog.object.extend(parsedOptions, options || {});
    parsedOptions.limit = isNaN(parsedOptions.limit) || parsedOptions.limit < 0 ? 100 : parseInt(parsedOptions.limit, 10);
    parsedOptions.selector = parsedOptions.selector && typeof parsedOptions.selector === "string" ? parsedOptions.selector : "en-note";
    return parsedOptions;
  }
  function textNodesFor(range) {
    var textNodesArray = [];
    var startIndex = 0;
    var isPrevCharBlock = false;
    goog.iter.forEach(range, function(node, notUsed, element) {
      if ((util.dom.isBlockNode(node) || util.dom.isBr(node)) && textNodesArray.length > 0) {
        if (!isPrevCharBlock && element.tagType === 1) {
          startIndex++;
          isPrevCharBlock = true;
        }
      } else {
        if (node.nodeType === Node.TEXT_NODE) {
          var wordOffsetInTextNode = 0;
          node.nodeValue.split(" ").forEach(function(text, i) {
            if (i > 0) {
              startIndex++;
              wordOffsetInTextNode++;
            } else {
              if (!isPrevCharBlock && textNodesArray.length) {
                startIndex++;
              }
            }
            var endIndex = startIndex + text.length;
            textNodesArray.push({wordOffsetInTextNode:wordOffsetInTextNode, node:node, text:text, startIndex:startIndex, endIndex:endIndex});
            startIndex = endIndex;
            wordOffsetInTextNode += text.length;
          });
          isPrevCharBlock = false;
        }
      }
    });
    return textNodesArray;
  }
  function getBoundingBoxes(textNodesArray, textRange) {
    var startNode = null;
    var endNode = null;
    var boundingBoxes = null;
    var searchedText = [];
    textNodesArray.some(function(textNode) {
      if (!startNode && textRange.start >= textNode.startIndex && textRange.start < textNode.endIndex) {
        startNode = textNode;
        searchedText.push(textNode.text);
      }
      if (startNode) {
        if (!endNode && textRange.end <= textNode.endIndex) {
          endNode = textNode;
        }
        if (startNode !== textNode) {
          searchedText.push(textNode.text);
        }
      }
      if (startNode && endNode) {
        var startOffset = startNode.wordOffsetInTextNode + textRange.start - startNode.startIndex;
        var endOffset = endNode.wordOffsetInTextNode + textRange.end - endNode.startIndex;
        var elementRange = goog.dom.Range.createFromNodes(startNode.node, startOffset, endNode.node, endOffset);
        boundingBoxes = util.range.getBoundingBoxesFromRange(elementRange.getBrowserRangeObject());
        if (boundingBoxes && boundingBoxes.length) {
          var match = {string:searchedText.join(" "), length:endNode.endIndex - startNode.startIndex, from:startNode.startIndex, to:endNode.endIndex};
          var adjustedScroll = document.body.scrollTop;
          boundingBoxes = boundingBoxes.map(function(boundingBox) {
            if (boundingBox) {
              boundingBox = util.zoomscale.normalizeRect(boundingBox);
              boundingBox.top = adjustedScroll + boundingBox.top;
              boundingBox.string = match.string;
              boundingBox.length = match.length;
              boundingBox.from = match.from;
              boundingBox.to = match.to;
            }
            return boundingBox;
          });
        }
        return true;
      }
      return false;
    });
    return boundingBoxes;
  }
})();
goog.provide("uno.commands.Focus");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Focus");
  var util = uno.util;
  var Focus = uno.commands.Focus = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Focus, uno.BasePlugin);
  Focus.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Focus.prototype.isSupportedCommand = function(command) {
    return command === "focus";
  };
  Focus.prototype.execCommand = function(command, value) {
    if (this.editor.readOnly) {
      return false;
    }
    var opt = {force:false, pos:"top", scroll:false};
    goog.object.extend(opt, value || {});
    this.editor.enterEditMode(true);
    this.editor.focus();
    if (opt.force) {
      if (opt.pos === "top") {
        this.editor.placeCursorAtStart();
      } else {
        if (opt.pos === "bottom") {
          this.editor.placeCursorAtEnd();
        }
      }
    }
    if (opt.scroll) {
      util.range.scrollSelectionIntoView(this.editor);
    }
    return true;
  };
  Focus.prototype.queryCommandValue = function() {
    return this.editor.isFocused();
  };
})();
goog.provide("uno.commands.FontSize");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("goog.style");
goog.require("uno.BasePlugin");
goog.require("uno.util.font");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.FontSize");
  var util = uno.util;
  var ZERO_WIDTH_SPACE = uno.defs.unicode.ZERO_WIDTH_SPACE;
  var FontSize = uno.commands.FontSize = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(FontSize, uno.BasePlugin);
  FontSize.prototype.isSupportedCommand = function(command) {
    return command === "fontsize";
  };
  FontSize.prototype.activeOnUneditableFields = goog.functions.TRUE;
  FontSize.prototype.execCommand = function(command, size) {
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var sizeValue = util.font.prepareSize(size);
    if (range.isCollapsed()) {
      this.setFontSizeCollapsed(sizeValue, range);
    } else {
      this.editor.dispatchBeforeChange();
      this.setFontSizeExpanded(sizeValue, range);
      this.editor.dispatchChange();
      this.dispatchEvent(uno.Editor.EventType.STYLE_CHANGED);
    }
    return true;
  };
  FontSize.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    if (!range) {
      return "";
    }
    var startNode = range.getStartNode();
    var startEl = startNode.nodeType === goog.dom.NodeType.TEXT ? goog.dom.getParentElement(startNode) : startNode;
    var size = util.font.getSize(startEl);
    return size.toString();
  };
  FontSize.prototype.setFontSizeCollapsed = function(size, range) {
    var node = range.getStartNode();
    var container = range.getContainerElement();
    var fontEl;
    var lineEmpty = util.dom.isEmpty(range.getStartNode());
    if (container.tagName === "FONT" && node.textContent.split(ZERO_WIDTH_SPACE).join("").length === 0) {
      fontEl = container;
    } else {
      this.editor.execCommand(goog.editor.Command.FONT_SIZE, 1);
      document.execCommand("inserttext", false, ZERO_WIDTH_SPACE);
      range = this.editor.getRange();
      if (lineEmpty) {
        var br = goog.dom.createDom("br");
        range.insertNode(br);
        range = this.editor.getRange();
      }
      fontEl = range.getContainerElement();
    }
    util.font.normalize(fontEl, size);
  };
  FontSize.prototype.setFontSizeExpanded = function(size, range) {
    var fontEls;
    this.editor.execCommand(goog.editor.Command.FONT_SIZE, 1);
    range = this.editor.getRange();
    fontEls = document.querySelectorAll("font[size]");
    goog.array.forEach(fontEls, function(fontEl) {
      if (range.containsNode(fontEl, true)) {
        util.font.normalizeFontSize(fontEl, size);
      }
    });
  };
})();
goog.provide("uno.commands.ForeColor");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.EditorMultiRange");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.ForeColor");
  var util = uno.util;
  var ForeColor = uno.commands.ForeColor = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(ForeColor, uno.BasePlugin);
  ForeColor.prototype.activeOnUneditableFields = goog.functions.TRUE;
  ForeColor.prototype.isSupportedCommand = function(command) {
    return command === "forecolor";
  };
  ForeColor.prototype.execCommand = function(command, color) {
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var isCollapsed = range.isCollapsed();
    if (!isCollapsed) {
      this.editor.dispatchBeforeChange();
    }
    this.editor.execCommand(goog.editor.Command.FONT_COLOR, color);
    var container = range.getContainerElement();
    var fontAnchors = container.querySelectorAll("font a");
    for (var i = 0; i < fontAnchors.length; i++) {
      goog.style.setStyle(fontAnchors[i], "color", color);
    }
    if (!isCollapsed) {
      this.editor.dispatchChange();
    }
    this.dispatchEvent(uno.Editor.EventType.STYLE_CHANGED);
    return true;
  };
  ForeColor.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    if (!range) {
      return "";
    }
    var startNode = range.getStartNode();
    var startEl = startNode.nodeType === goog.dom.NodeType.TEXT ? goog.dom.getParentElement(startNode) : startNode;
    var color = util.font.getColor(startEl) || "rgb(0, 0, 0)";
    return color.toString();
  };
})();
goog.provide("uno.commands.ForwardDelete");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.ForwardDelete");
  var ForwardDelete = uno.commands.ForwardDelete = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ForwardDelete, uno.BasePlugin);
  ForwardDelete.prototype.isSupportedCommand = function(command) {
    return command === "forwarddelete";
  };
  ForwardDelete.prototype.queryCommandValue = function(command) {
    return document.queryCommandValue(command);
  };
  ForwardDelete.prototype.execCommand = function(command, value) {
    this.editor.execCommand("delete", value, {forward:true}, true);
  };
})();
goog.provide("uno.commands.Highlight");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
(function() {
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.commands.Highlight");
  var highlightBackgroundColor = uno.defs.highlight.COLOR;
  var highlightPlaceholder = "rgb(255, 255, 255)";
  var Highlight = uno.commands.Highlight = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(Highlight, uno.BasePlugin);
  Highlight.prototype.isSupportedCommand = function(command) {
    return command === "highlight";
  };
  Highlight.prototype.execCommand = function() {
    var multirange = this.editor.multirange;
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var highlighted = this.editor.context.style.state.highlight;
    this.editor.dispatchBeforeChange();
    document.execCommand("backColor", null, highlighted ? highlightPlaceholder : highlightBackgroundColor);
    cleanupHighlight([range.getContainerElement()], range);
    if (!multirange.isInvoking() || multirange.isLastInvokedRange()) {
      this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:{state:{highlight:!highlighted}, value:{}, enabled:{}}});
    }
    this.editor.dispatchChange();
    return true;
  };
  Highlight.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    var state = document.queryCommandValue("backColor");
    if (!range) {
      return false;
    }
    var startNode = range.getStartNode();
    var endNode = range.getEndNode();
    if (range && range.isCollapsed()) {
      if (startNode.nodeType === Node.TEXT_NODE) {
        return highlightBackgroundColor === state;
      }
    }
    if (highlightBackgroundColor === state) {
      return true;
    }
    var container = range.getContainerElement();
    var nodes = [];
    if (container === startNode && container === endNode) {
      nodes.push(container);
    } else {
      Array.prototype.forEach.call(container.childNodes || [], function(node) {
        if (range.containsNode(node, true) || node.contains(startNode) || node.contains(endNode)) {
          nodes.push(node);
        }
      });
    }
    return isHighlighted(range, nodes);
  };
  Highlight.prototype.queryCommandEnabled = goog.functions.TRUE;
  function cleanupHighlight(nodes, range) {
    Array.prototype.forEach.call(nodes || [], function(node) {
      if (range.containsNode(node, true)) {
        if (util.dom.isElementNode(node)) {
          if (node.style.backgroundColor === highlightPlaceholder) {
            node.style.backgroundColor = "";
          }
          if (node.childNodes) {
            cleanupHighlight(node.childNodes, range);
          }
        }
      }
    });
  }
  function isHighlighted(range, nodes) {
    if (!nodes) {
      return false;
    }
    var filteredNodes = Array.prototype.filter.call(nodes, function(node) {
      return range.containsNode(node, true);
    });
    if (filteredNodes.length === 0) {
      return false;
    }
    return Array.prototype.every.call(filteredNodes, function(node) {
      if (util.dom.isElementNode(node)) {
        var style = window.getComputedStyle(node);
        if (style.backgroundColor === highlightBackgroundColor) {
          return true;
        }
        if (["rgba(0, 0, 0, 0)", "rgb(255, 255, 255)"].indexOf(style.backgroundColor) > -1) {
          return isHighlighted(range, node.childNodes);
        }
      }
      return false;
    });
  }
})();
goog.provide("uno.commands.InsertHorizontalRule");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("uno.util.dom");
goog.require("uno.util.table");
goog.require("uno.util.crypto");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.InsertHorizontalRule");
  var util = uno.util;
  var InsertHorizontalRule = uno.commands.InsertHorizontalRule = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertHorizontalRule, uno.BasePlugin);
  InsertHorizontalRule.prototype.isSupportedCommand = function(command) {
    return command === "inserthorizontalrule";
  };
  InsertHorizontalRule.prototype.activeOnUneditableFields = goog.functions.TRUE;
  InsertHorizontalRule.prototype.execCommandInternal = function() {
    this.editor.execCommand(goog.editor.Command.HORIZONTAL_RULE);
    return true;
  };
  InsertHorizontalRule.prototype.queryCommandValue = function() {
    return this.editor.queryCommandValue(goog.editor.Command.HORIZONTAL_RULE);
  };
  InsertHorizontalRule.prototype.queryCommandEnabled = function() {
    var range = this.editor.getRange();
    if (range) {
      if (util.crypto.for(range.getStartNode()) || util.table.for(range.getStartNode())) {
        return false;
      }
    }
    return true;
  };
})();
goog.provide("uno.commands.InsertHtml");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.InsertHtml");
  var InsertHtml = uno.commands.InsertHtml = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertHtml, uno.BasePlugin);
  InsertHtml.prototype.isSupportedCommand = function(command) {
    return command === "inserthtml";
  };
  InsertHtml.prototype.execCommandInternal = function(command, html) {
    return this.editor.execCommand("paste", {type:"html", value:html});
  };
})();
goog.provide("uno.commands.InsertText");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.InsertText");
  var InsertText = uno.commands.InsertText = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertText, uno.BasePlugin);
  InsertText.prototype.isSupportedCommand = function(command) {
    return command === "inserttext";
  };
  InsertText.prototype.execCommandInternal = function(command, plainText) {
    return this.editor.execCommand("paste", {type:"plain", value:plainText});
  };
})();
goog.provide("uno.commands.InsertParagraph");
goog.require("goog.debug.Logger");
goog.require("goog.object");
goog.require("uno.BasePlugin");
goog.require("uno.util.todo");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.InsertParagraph");
  var util = uno.util;
  var InsertParagraph = uno.commands.InsertParagraph = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertParagraph, uno.BasePlugin);
  InsertParagraph.prototype.isSupportedCommand = function(command) {
    return command === "insertparagraph";
  };
  InsertParagraph.prototype.execCommandInternal = function(command, options) {
    options = options || {};
    var editor = this.editor;
    var range = editor.getRange();
    if (!range) {
      return false;
    }
    if (!range.isCollapsed()) {
      editor.execCommand("delete");
    }
    range = this.editor.getRange();
    var p = util.paragraph.for(range.getStartNode());
    range = this.editor.getRange();
    var node = range.getStartNode();
    var offset = range.getStartOffset();
    var isTextNode = util.dom.isTextNode(node);
    if (isTextNode && offset > 0 && offset < node.length) {
      node.splitText(offset);
    }
    util.styles.createPendingStyles(editor);
    var savedRange = range.saveUsingCarets();
    if (!goog.dom.contains(p, savedRange.getCaret(true))) {
      savedRange.removeCarets();
      return false;
    }
    var newp = goog.editor.node.splitDomTreeAt(savedRange.getCaret(true), savedRange.getCaret(true), p);
    if (!p.childNodes.length || !util.dom.isBr(goog.dom.getLastElementChild(p))) {
      p.appendChild(document.createElement("br"));
    }
    goog.dom.insertSiblingAfter(newp, p);
    newp.normalize();
    if (!newp.childNodes.length || !util.dom.isBr(goog.dom.getLastElementChild(newp))) {
      newp.appendChild(document.createElement("br"));
    }
    savedRange.restore().select();
    var hasPrevTodoItem = util.todo.all(p).length > 0;
    if (hasPrevTodoItem) {
      goog.array.forEach(newp.children, function(child) {
        if (util.dom.isEmpty(child)) {
          child.remove();
        }
      });
    }
    if (!util.dom.isEmpty(newp) && !hasPrevTodoItem) {
      util.styles.clearPendingStyles(this.editor);
    }
    if (options.cursorPosition === "new" && newp.children.length > 0) {
      goog.dom.Range.createCaret(newp, 0).select();
    } else {
      if (options.cursorPosition === "original" && node) {
        goog.dom.Range.createCaret(node, isTextNode ? node.length : node.children.length).select();
      }
    }
    return true;
  };
})();
goog.provide("uno.commands.InsertTable");
goog.require("goog.debug.Logger");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.editor.range");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.table");
goog.require("uno.util.list");
goog.require("uno.util.paragraph");
goog.require("uno.util.crypto");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.InsertTable");
  var util = uno.util;
  var InsertTable = uno.commands.InsertTable = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertTable, uno.BasePlugin);
  InsertTable.prototype.isSupportedCommand = function(command) {
    return command === "inserttable";
  };
  InsertTable.prototype.activeOnUneditableFields = goog.functions.TRUE;
  InsertTable.prototype.execCommandInternal = function(command, options) {
    var enTable = util.table.create(options);
    var range = this.editor.getRange();
    if (!range.isCollapsed()) {
      this.editor.execCommand("delete");
      range = this.editor.getRange();
    }
    if (!util.dom.isEmpty(util.paragraph.for(range.getStartNode()))) {
      this.editor.execCommand("insertparagraph", {cursorPosition:"original"});
      range = this.editor.getRange();
      if (!util.dom.isEmpty(util.paragraph.for(range.getStartNode()))) {
        this.editor.execCommand("insertparagraph", {cursorPosition:"new"});
      }
    }
    range = this.editor.getRange();
    range.insertNode(enTable);
    util.table.normalizeDOMPlacement(enTable);
    var targetBr = enTable.querySelector("td br");
    goog.editor.range.placeCursorNextTo(targetBr, true);
    return true;
  };
  InsertTable.prototype.queryCommandEnabled = function() {
    var range = this.editor.getRange();
    if (range == null) {
      return false;
    }
    var startNode = range.getStartNode();
    if (util.list.itemFor(startNode)) {
      return false;
    }
    if (util.crypto.for(startNode)) {
      return false;
    }
    if (util.codeblock.for(startNode)) {
      return false;
    }
    var startTable = util.table.for(range.getStartNode());
    var endTable = util.table.for(range.getEndNode());
    if (startTable == null && endTable == null) {
      return true;
    }
    return false;
  };
})();
goog.provide("uno.commands.InsertTableCol");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.table");
goog.require("uno.util.table.selection");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.InsertTableCol");
  var util = uno.util;
  var InsertTableCol = uno.commands.InsertTableCol = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertTableCol, uno.BasePlugin);
  InsertTableCol.prototype.isSupportedCommand = function(command) {
    return command === "inserttablecol";
  };
  InsertTableCol.prototype.execCommandInternal = function(command, value) {
    var enTable = util.table.getActive();
    var cell = util.table.getActiveCell();
    var retVal = false;
    var index = -1;
    if (enTable && cell) {
      index = util.table.colIndex(cell, value === "after");
      retVal = util.table.insertColumns(enTable, index);
      if (retVal && util.table.selection.isActive(enTable)) {
        util.table.selection.create(enTable, this.editor.multirange);
      }
    } else {
      cell = util.table.cellForStructureChange(this.editor.getRange());
      if (cell) {
        var table = goog.dom.getAncestor(this.editor.getRange().getStartNode(), util.dom.isTable);
        index = util.table.colIndex(cell, value === "after");
        retVal = util.table.insertColumns(table, index);
      }
    }
    return retVal;
  };
  InsertTableCol.prototype.queryCommandEnabled = function() {
    return !!util.table.cellForStructureChange(this.editor.getRange());
  };
})();
goog.provide("uno.commands.InsertTableRow");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.table");
goog.require("uno.util.table.selection");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.InsertTableRow");
  var util = uno.util;
  var InsertTableRow = uno.commands.InsertTableRow = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertTableRow, uno.BasePlugin);
  InsertTableRow.prototype.isSupportedCommand = function(command) {
    return command === "inserttablerow";
  };
  InsertTableRow.prototype.execCommandInternal = function(command, value) {
    var enTable = util.table.getActive();
    var cell = util.table.getActiveCell();
    var retVal = false;
    var index = -1;
    if (enTable && cell) {
      index = util.table.rowIndex(cell, value === "after");
      retVal = util.table.insertRows(enTable, index);
      if (retVal && util.table.selection.isActive(enTable)) {
        util.table.selection.create(enTable, this.editor.multirange);
      }
    } else {
      cell = util.table.cellForStructureChange(this.editor.getRange());
      if (cell) {
        var table = goog.dom.getAncestor(this.editor.getRange().getStartNode(), util.dom.isTable);
        index = util.table.rowIndex(cell, value === "after");
        retVal = util.table.insertRows(table, index);
      }
    }
    return retVal;
  };
  InsertTableRow.prototype.queryCommandEnabled = function() {
    return !!util.table.cellForStructureChange(this.editor.getRange());
  };
})();
goog.provide("uno.components.Preview");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.events");
goog.require("goog.events.KeyCodes");
goog.require("uno.util.dom");
goog.require("uno.util.zoomscale");
(function() {
  var Preview = uno.components.Preview = function(opt) {
    this.items = [];
    this.index_ = -1;
    this.state_ = 0;
    this.resizeTimer_ = null;
    this.lblFilename_ = goog.dom.createDom("span", {class:"lbl-filename"});
    this.btnClose_ = goog.dom.createDom("button", {class:"btn-close"});
    this.btnPrev_ = goog.dom.createDom("button", {class:"btn-prev"});
    this.btnNext_ = goog.dom.createDom("button", {class:"btn-next"});
    this.container_ = goog.dom.createDom("div", {class:"container"});
    var toolbar = goog.dom.createDom("div", {class:"toolbar"}, this.lblFilename_);
    var children = [toolbar, this.btnPrev_, this.btnNext_, this.btnClose_, this.container_];
    this.element = goog.dom.createDom("div", {class:"en-preview"}, children);
    opt = opt || {};
    this.onClose = typeof opt.onClose === "function" ? opt.onClose : null;
    this.onChange = typeof opt.onChange === "function" ? opt.onChange : null;
    this.animated = opt.animated === false ? false : true;
    this.translucent = opt.translucent === false ? false : true;
    goog.events.listen(this.element, "click", handleClick.bind(this));
    goog.events.listen(document.body, "keydown", handleKey.bind(this));
    goog.events.listen(window, "resize", handleResize.bind(this));
  };
  Preview.Transition = {PRESENT:1, DISMISS:2};
  Preview.State = {ACTIVE:1 << 0, ZOOMABLE:1 << 1, FULLSIZE:1 << 2, RESIZED:1 << 3};
  Object.defineProperty(Preview.prototype, "state", {get:function() {
    return this.state_;
  }});
  Preview.prototype.present = function(items, initialItem) {
    this.items = items;
    this.state_ = 0;
    if (initialItem && items.indexOf(initialItem) > -1) {
      this.index_ = items.indexOf(initialItem);
    } else {
      if (items.length > 0) {
        this.index_ = 0;
      } else {
        this.index_ = -1;
      }
    }
    this.element.classList.toggle("nonav", items.length <= 1);
    var self = this;
    this.renderItem_(this.items[this.index_], true).then(function(img) {
      return self.transitionTo_(Preview.Transition.PRESENT, img, initialItem);
    }).then(function() {
      self.state_ |= Preview.State.ACTIVE;
      self.updateZoomIndicator_();
    });
  };
  Preview.prototype.dismiss = function() {
    this.state_ &= ~Preview.State.ACTIVE;
    var img = this.container_.children[0];
    var src = img.getAttribute("src");
    var reference = img.dataset.reference;
    var origin = goog.array.find(this.items, function(node) {
      return node.getAttribute("src") === src && node.dataset.reference === reference;
    });
    if (origin && !(this.state_ & Preview.State.RESIZED)) {
      this.transitionTo_(Preview.Transition.DISMISS, img, origin).then(this.onClose);
    } else {
      this.onClose();
    }
  };
  Preview.prototype.cleanup = function() {
    this.container_.innerHTML = "";
    this.element.remove();
    this.element.classList.remove("animated");
    this.element.classList.remove("presented");
    this.element.classList.remove("nonav");
    this.element.classList.remove("fullsize");
    this.element.classList.remove("zoomable");
    this.element.classList.remove("opaque");
  };
  Preview.prototype.go = function(index) {
    if (!this.items.length || index === this.index_) {
      return;
    }
    this.index_ = Math.max(Math.min(this.items.length - 1, index), 0);
    var item = this.items[this.index_];
    var self = this;
    this.renderItem_(item).then(function() {
      self.updateZoomIndicator_();
      self.onChange(item);
    });
  };
  Preview.prototype.next = function() {
    this.go(this.index_ + 1 >= this.items.length ? 0 : this.index_ + 1);
  };
  Preview.prototype.previous = function() {
    this.go(this.index_ === 0 ? this.items.length - 1 : this.index_ - 1);
  };
  Preview.prototype.zoomIn = function() {
    this.state_ |= Preview.State.FULLSIZE;
    this.element.classList.add("fullsize");
  };
  Preview.prototype.zoomOut = function() {
    this.state_ &= ~Preview.State.FULLSIZE;
    this.element.classList.remove("fullsize");
  };
  Preview.prototype.transitionTo_ = function(direction, item, origin) {
    var ib = item.getBoundingClientRect();
    var ob = origin.getBoundingClientRect();
    var presenting = direction === Preview.Transition.PRESENT;
    var zoom = uno.util.zoomscale.getZoom();
    var translate = uno.util.dom.isVisibleInView(origin);
    var self = this;
    var x = ob.left * zoom - ib.left;
    var y = ob.top * zoom - ib.top;
    var sx = ob.width * zoom / ib.width;
    var sy = ob.height * zoom / ib.height;
    var itemOpacity = 1;
    var itemTransform = "translate3d(0, 0, 0) scale(1, 1)";
    var originOpacity = 0;
    var originTransform = itemTransform;
    if (translate) {
      originOpacity = 1;
      originTransform = ["translate3d(" + x + "px, " + y + "px, 0)", "scale(" + sx + ", " + sy + ")"].join(" ");
    }
    item.style.transform = presenting ? originTransform : itemTransform;
    item.style.opacity = presenting ? originOpacity : itemOpacity;
    item.style.visibility = "";
    return new Promise(function(resolve) {
      var safetyTimer = null;
      var timerDuration = 350;
      var resolveHandler = function() {
        clearTimeout(safetyTimer);
        if (!presenting) {
          self.element.classList.remove("animated");
        }
        resolve();
      };
      setTimeout(function() {
        if (self.animated) {
          safetyTimer = setTimeout(function() {
            goog.events.unlisten(item, "transitionend", resolveHandler);
            resolveHandler();
          }, timerDuration);
          goog.events.listenOnce(item, "transitionend", resolveHandler);
        } else {
          resolve();
        }
        if (presenting) {
          if (self.animated) {
            self.element.classList.add("animated");
          }
          if (!self.translucent) {
            self.element.classList.add("opaque");
          }
          self.element.classList.add("presented");
          item.style.transform = itemTransform;
          item.style.opacity = itemOpacity;
        } else {
          self.element.classList.remove("presented");
          item.style.transform = originTransform;
          item.style.opacity = originOpacity;
        }
      }, 10);
    });
  };
  Preview.prototype.updateZoomIndicator_ = function() {
    var img = this.container_.children[0];
    if (!img || img.naturalWidth <= window.innerWidth && img.naturalHeight <= window.innerHeight) {
      this.state_ &= ~Preview.State.ZOOMABLE;
      this.element.classList.remove("zoomable");
    } else {
      this.state_ |= Preview.State.ZOOMABLE;
      this.element.classList.add("zoomable");
    }
  };
  Preview.prototype.renderItem_ = function(node, hiddenOnRender) {
    var self = this;
    var img = goog.dom.createDom("img", {src:node.getAttribute("src"), "data-reference":node.dataset.reference});
    var title = createFilename(node);
    if (hiddenOnRender === true) {
      img.style.visibility = "hidden";
    }
    return new Promise(function(resolve) {
      var fn = function() {
        resolve(img);
      };
      goog.events.listenOnce(img, "load", fn);
      goog.events.listenOnce(img, "error", fn);
      self.lblFilename_.textContent = title;
      self.container_.innerHTML = "";
      self.container_.appendChild(img);
      self.element.classList.remove("zoomable");
    });
  };
  function createFilename(node) {
    var title = node.dataset.title || node.dataset.filename || null;
    if (title) {
      return title;
    }
    var ext;
    switch(node.dataset.type) {
      case "image/jpeg":
      case "image/jpg":
        ext = ".jpg";
        break;
      case "image/png":
        ext = ".png";
        break;
      case "image/tiff":
        ext = ".tiff";
        break;
      case "image/bmp":
        ext = ".bmp";
        break;
      case "image/gif":
        ext = ".gif";
        break;
      default:
        ext = "";
    }
    return "Untitled" + ext;
  }
  function handleResize() {
    if (!(this.state_ & Preview.State.ACTIVE)) {
      return;
    }
    clearTimeout(this.resizeTimer_);
    this.resizeTimer_ = setTimeout(this.updateZoomIndicator_.bind(this), 250);
    if (this.state_ & Preview.State.RESIZED) {
      return;
    }
    this.state_ |= Preview.State.RESIZED;
    this.element.classList.add("opaque");
  }
  function handleClick(evt) {
    if (!(this.state_ & Preview.State.ACTIVE)) {
      return;
    }
    evt.preventDefault();
    var target = evt.target;
    var isFullsize = this.state_ & Preview.State.FULLSIZE;
    var isZoomable = this.state_ & Preview.State.ZOOMABLE;
    if (isFullsize && this.btnClose_ === target || !isFullsize && [this.btnClose_, this.container_, this.element].indexOf(target) > -1) {
      this.dismiss();
    } else {
      if (!isFullsize && this.btnNext_ === target) {
        this.next();
      } else {
        if (!isFullsize && this.btnPrev_ === target) {
          this.previous();
        } else {
          if (isFullsize && this.btnClose_ !== target) {
            this.zoomOut();
          } else {
            if (isZoomable && this.container_.children[0] === target) {
              this.zoomIn();
            }
          }
        }
      }
    }
  }
  function handleKey(evt) {
    if (!(this.state_ & Preview.State.ACTIVE)) {
      return;
    }
    var KeyCodes = goog.events.KeyCodes;
    var code = evt.keyCode;
    var isFullsize = this.state_ & Preview.State.FULLSIZE;
    if (code === KeyCodes.ESC) {
      this.dismiss();
      evt.preventDefault();
    } else {
      if (!isFullsize && [KeyCodes.RIGHT, KeyCodes.DOWN].indexOf(code) > -1) {
        this.next();
        evt.preventDefault();
      } else {
        if (!isFullsize && [KeyCodes.LEFT, KeyCodes.UP].indexOf(code) > -1) {
          this.previous();
          evt.preventDefault();
        }
      }
    }
  }
})();
goog.provide("uno.util.preview.generic");
(function() {
  var generic = uno.util.preview.generic;
  generic.getOptions = function() {
    return {};
  };
})();
goog.provide("uno.util.preview.win");
(function() {
  var win = uno.util.preview.win;
  win.getOptions = function() {
    return {animated:false, translucent:false};
  };
})();
goog.provide("uno.util.preview");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("uno.components.Preview");
goog.require("uno.defs");
goog.require("uno.util.img");
goog.require("uno.util.preview.generic");
goog.require("uno.util.preview.win");
goog.require("uno.util.table");
goog.require("uno.util.tools");
goog.require("uno.util.zoomscale");
(function() {
  var util = uno.util;
  var client = uno.util.preview.generic;
  var preview = null;
  var pendingTimer = null;
  var clickNode = null;
  var scrollTop = 0;
  util.preview.setClient = function(clientName) {
    client = util.preview[clientName] || client;
  };
  util.preview.requestOpen = function(node) {
    if (!node) {
      return;
    }
    clickNode = node || null;
    scrollTop = document.body.scrollTop;
    EN.notification("requestPreview", {action:"open"});
    document.body.classList.add("preview-cef-opening");
    clearTimeout(pendingTimer);
    pendingTimer = setTimeout(function() {
      clickNode = null;
    }, 500);
  };
  util.preview.requestClose = function() {
    EN.notification("requestPreview", {action:"close"});
  };
  util.preview.present = function(editor, bounds, commandNode) {
    var items = util.preview.getItems(editor.field);
    var node = clickNode || commandNode;
    if (!editor || !bounds || !node || !items.length || util.preview.isVisible()) {
      return false;
    }
    if (!preview) {
      var opt = {onClose:util.preview.requestClose, onChange:handleOnChange};
      goog.object.extend(opt, client.getOptions());
      preview = new uno.components.Preview(opt);
    }
    preserve(editor, bounds, scrollTop);
    if (!preview.element.parentNode) {
      util.tools.append(preview.element);
    }
    setTimeout(function() {
      preview.present(items, node);
    }, 0);
    return true;
  };
  util.preview.dismiss = function(editor) {
    if (!util.preview.isVisible()) {
      return false;
    }
    preview.cleanup();
    restore(editor, scrollTop);
    return true;
  };
  util.preview.isPending = function() {
    return !!clickNode;
  };
  util.preview.isVisible = function() {
    return preview ? !!preview.element.parentNode : false;
  };
  util.preview.getItems = function(root) {
    var items = [].slice.call(root.querySelectorAll("img.en-media-image"));
    var diversity = true;
    if (items.length > 1) {
      var src = items[0].getAttribute("src");
      diversity = !goog.array.every(items, function(node) {
        return node.getAttribute("src") === src;
      });
    }
    return diversity ? items : [items[0]];
  };
  function preserve(editor, bounds, y) {
    document.body.classList.add("preview");
    document.body.classList.add("preview-cef");
    var zoom = util.zoomscale.getZoom();
    editor.execCommand("active", false);
    editor.field.style.position = "fixed";
    editor.field.style.overflow = "hidden";
    editor.field.style.top = bounds.top / zoom + "px";
    editor.field.style.left = bounds.left / zoom + "px";
    editor.field.style.width = bounds.width / zoom + "px";
    editor.field.style.height = bounds.height / zoom + "px";
    util.img.layoutResizer();
    editor.field.scrollTop = y / zoom;
  }
  function restore(editor, y) {
    document.body.classList.remove("preview");
    document.body.classList.remove("preview-cef");
    document.body.classList.remove("preview-cef-opening");
    editor.field.style.position = "";
    editor.field.style.overflow = "";
    editor.field.style.top = "";
    editor.field.style.left = "";
    editor.field.style.width = "";
    editor.field.style.height = "";
    document.body.scrollTop = y;
    util.img.layoutResizer();
    setTimeout(function() {
      editor.execCommand("active", true);
      editor.execCommand("focus", true);
    }, 100);
  }
  function handleOnChange(img) {
    util.img.setSelected(img);
    var note = document.querySelector(uno.defs.containers.EDITOR_BODY_SELECTOR);
    var ib = img.getBoundingClientRect();
    var nb = note.getBoundingClientRect();
    var offset = 10;
    ib = {top:ib.top - offset, bottom:ib.bottom + offset, height:ib.height + offset * 2};
    var direction = null;
    var isTaller = ib.height > nb.height;
    if (ib.top < nb.top && ib.bottom < nb.bottom) {
      direction = "top";
    } else {
      if (ib.top > nb.top && ib.bottom > nb.bottom) {
        direction = "bottom";
      }
    }
    if (direction === "top" && !isTaller || direction === "bottom" && isTaller) {
      scrollTop = note.scrollTop - (nb.top - ib.top);
      note.scrollTop = scrollTop;
    } else {
      if (direction === "bottom" && !isTaller || direction === "top" && isTaller) {
        scrollTop = note.scrollTop - (nb.bottom - ib.bottom);
        note.scrollTop = scrollTop;
      }
    }
    util.table.scrollCellIntoView(goog.dom.getAncestor(img, util.dom.isTd));
  }
})();
goog.provide("uno.commands.Preview");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.preview");
goog.require("uno.util.resource");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Preview");
  var util = uno.util;
  var Preview = uno.commands.Preview = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Preview, uno.BasePlugin);
  Preview.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Preview.prototype.isSupportedCommand = function(command) {
    return command === "preview";
  };
  Preview.prototype.execCommand = function(command, value) {
    var options = value || {};
    var action = options.action;
    if (action === "open") {
      var node = findImageByHash(options.hash, this.editor.field);
      return util.preview.present(this.editor, options.bounds, node);
    } else {
      if (action === "close") {
        return util.preview.dismiss(this.editor);
      }
    }
    return true;
  };
  Preview.prototype.queryCommandEnabled = function(command, value) {
    var options = value || {};
    var action = options.action;
    var bounds = options.bounds;
    var visible = util.preview.isVisible();
    if (action === "open" && bounds && !visible) {
      var node = findImageByHash(options.hash, this.editor.field);
      return node || util.preview.isPending();
    } else {
      if (action === "close") {
        return visible;
      }
    }
    return false;
  };
  Preview.prototype.queryCommandValue = function() {
    return util.preview.isVisible();
  };
  function findImageByHash(hash, root) {
    if (!hash) {
      return null;
    }
    var nodes = util.resource.findByHash(hash, root);
    if (nodes.length > 0 && util.resource.isImage(nodes[0])) {
      return nodes[0];
    }
    return null;
  }
})();
goog.provide("uno.commands.MergeCells");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.table");
goog.require("uno.util.table.selection");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.MergeCells");
  var util = uno.util;
  var MergeCells = uno.commands.MergeCells = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(MergeCells, uno.BasePlugin);
  MergeCells.prototype.isSupportedCommand = function(command) {
    return command === "mergecells";
  };
  MergeCells.prototype.execCommandInternal = function(command, value) {
    var cell = util.table.getActiveCell();
    var cells = !util.table.selection.isActive() && cell ? [cell] : util.table.selection.getCells();
    var selected = util.table.selection.isActive();
    var enTable = util.table.getActive();
    var mergedCell, splitCells;
    if ((value === true || value === undefined) && util.table.mergeable(cells)) {
      util.table.selection.clear();
      mergedCell = util.table.mergeCells(cells);
      util.table.selection.create(enTable, this.editor.multirange, mergedCell);
    } else {
      if (!value && util.table.unmergeable(cells)) {
        util.table.selection.clear();
        splitCells = util.table.splitCells(cells);
        if (selected) {
          util.table.selection.create(enTable, this.editor.multirange, splitCells[0], splitCells[splitCells.length - 1]);
        }
      }
    }
    if (mergedCell || splitCells) {
      this.dispatchEvent(uno.Editor.EventType.STYLE_CHANGED);
      return true;
    }
    return false;
  };
  MergeCells.prototype.queryCommandEnabled = function() {
    var selected = util.table.selection.isActive() || util.table.selection.isPending();
    var cell = util.table.getActiveCell();
    var cells = !selected && cell ? [cell] : util.table.selection.getCells();
    return util.table.unmergeable(cells) || util.table.mergeable(cells);
  };
  MergeCells.prototype.queryCommandValue = function() {
    var selected = util.table.selection.isActive() || util.table.selection.isPending();
    var cell = util.table.getActiveCell();
    var cells = !selected && cell ? [cell] : util.table.selection.getCells();
    return util.table.unmergeable(cells) && !util.table.mergeable(cells);
  };
})();
goog.provide("uno.commands.MigrateTable");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.MigrateTable");
  var util = uno.util;
  var MigrateTable = uno.commands.MigrateTable = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(MigrateTable, uno.BasePlugin);
  MigrateTable.prototype.isSupportedCommand = function(command) {
    return command === "migratetable";
  };
  MigrateTable.prototype.execCommandInternal = function(command, value) {
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var table = null;
    var node = range.getStartNode();
    while (node && node.parentNode) {
      if (util.dom.isTable(node)) {
        table = node;
      }
      node = node.parentNode;
    }
    if (!table) {
      return false;
    }
    if (!range.isCollapsed()) {
      var startTd = goog.dom.getAncestor(range.getStartNode(), util.dom.isTd);
      var endTd = goog.dom.getAncestor(range.getEndNode(), util.dom.isTd);
      if (startTd !== endTd) {
        range.collapse(true);
      }
    }
    var savedRange = range.saveUsingCarets();
    if (!util.table.migrateToEnTable(table)) {
      return false;
    }
    savedRange.restore();
    return true;
  };
  MigrateTable.prototype.queryCommandEnabled = function() {
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var table = null;
    var td = null;
    var enTable = goog.dom.getAncestor(range.getStartNode(), function(node) {
      if (util.dom.isTable(node)) {
        table = node;
      }
      if (util.dom.isTd(node)) {
        td = node;
      }
      return util.dom.isEntable(node);
    }, true);
    return !enTable && table && td;
  };
})();
goog.provide("uno.commands.TableAlign");
goog.require("goog.debug.Logger");
goog.require("goog.style");
goog.require("uno.BasePlugin");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.TableAlign");
  var util = uno.util;
  var TableAlign = uno.commands.TableAlign = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TableAlign, uno.BasePlugin);
  TableAlign.prototype.isSupportedCommand = function(command) {
    return command === "tablealign";
  };
  TableAlign.prototype.execCommand = function(command, direction) {
    if (["left", "center", "right"].indexOf(direction) < 0) {
      log.warning("Saw unexpected alignment value", direction);
      direction = "left";
    }
    var table = util.table.getActive();
    if (!table) {
      return false;
    }
    this.editor.dispatchBeforeChange();
    util.table.setAlignment(table, direction);
    this.editor.dispatchChange();
    return true;
  };
  TableAlign.prototype.queryCommandValue = function() {
    var table = util.table.getActive();
    if (!table) {
      return "";
    }
    return util.table.getAlignment(table);
  };
  TableAlign.prototype.queryCommandEnabled = function() {
    return !!util.table.getActive();
  };
})();
goog.provide("uno.commands.TableBorderColor");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.style");
goog.require("uno.BasePlugin");
goog.require("uno.EditorMultiRange");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.TableBorderColor");
  var util = uno.util;
  var TableBorderColor = uno.commands.TableBorderColor = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(TableBorderColor, uno.BasePlugin);
  TableBorderColor.prototype.isSupportedCommand = function(command) {
    return command === "tablebordercolor";
  };
  TableBorderColor.prototype.execCommand = function(command, color) {
    color = color || "";
    var enTable = util.table.getActive();
    if (!enTable) {
      return false;
    }
    this.editor.dispatchBeforeChange();
    enTable.style.borderColor = color;
    goog.array.forEach(enTable.querySelectorAll("td"), function(cell) {
      cell.style.borderColor = color;
    });
    this.editor.dispatchChange();
    return true;
  };
  TableBorderColor.prototype.queryCommandValue = function() {
    var enTable = util.table.getActive();
    if (enTable) {
      var td = enTable.querySelector("td");
      return td ? goog.style.getComputedStyle(td, "borderColor") : "";
    }
    return "";
  };
  TableBorderColor.prototype.queryCommandEnabled = function() {
    return !!util.table.getActive();
  };
})();
goog.provide("uno.commands.TableBorderWidth");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.style");
goog.require("uno.BasePlugin");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.TableBorderWidth");
  var util = uno.util;
  var TableBorderWidth = uno.commands.TableBorderWidth = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TableBorderWidth, uno.BasePlugin);
  TableBorderWidth.prototype.isSupportedCommand = function(command) {
    return command === "tableborderwidth";
  };
  TableBorderWidth.prototype.execCommand = function(command, value) {
    var borderWidth = parseInt(value, 10);
    if (isNaN(borderWidth) || borderWidth < 0) {
      log.warning("Invalid value given to tableborderwidth: " + value);
      return false;
    }
    var enTable = util.table.getActive();
    if (!enTable) {
      return false;
    }
    this.editor.dispatchBeforeChange();
    var val = borderWidth + "px";
    enTable.style.borderWidth = val;
    goog.array.forEach(enTable.querySelectorAll("td"), function(cell) {
      cell.style.borderWidth = val;
    });
    this.editor.dispatchChange();
    return true;
  };
  TableBorderWidth.prototype.queryCommandValue = function() {
    var enTable = util.table.getActive();
    if (enTable) {
      var td = enTable.querySelector("td");
      var val = parseInt(td ? goog.style.getComputedStyle(td, "borderWidth") : "", 10);
      if (!isNaN(val)) {
        return "" + val;
      }
    }
    return "0";
  };
  TableBorderWidth.prototype.queryCommandEnabled = function() {
    return !!util.table.getActive();
  };
})();
goog.provide("uno.commands.TableCellColor");
goog.require("goog.color");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.EditorMultiRange");
goog.require("uno.defs");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.TableCellColor");
  var util = uno.util;
  var TableCellColor = uno.commands.TableCellColor = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(TableCellColor, uno.BasePlugin);
  TableCellColor.prototype.isSupportedCommand = function(command) {
    return command === "tablecellcolor";
  };
  TableCellColor.prototype.execCommandInternal = function(command, value) {
    var hexValue = goog.color.parse(value).hex;
    var isTransparent = hexValue === "#ffffff";
    var range = this.editor.getRange();
    var cells = util.table.cellsForRange(range);
    var colorPalette = ["#ffffff", "#eaeaea", "#d4d4d4", "#ddd1f3", "#f0d1f6", "#fbcfd6", "#fedec1", "#ffe697", "#cdedd8", "#cdeef0", "#cde6f9", "#ccd7ea", "#3f3f3f", "#737373", "#979797", "#8b65e0", "#c064d1", "#fc5356", "#fd7b39", "#ffc200", "#57b779", "#57bfc4", "#54a9e6", "#426bb3"];
    cells.forEach(function(cell) {
      var textColor = colorPalette.indexOf(hexValue) >= 12 ? "white" : "black";
      goog.dom.Range.createFromNodeContents(cell).select();
      this.editor.execCommand("forecolor", textColor);
      range.select();
      cell.style.background = "";
      if (isTransparent) {
        cell.style.backgroundColor = "";
        cell.style.borderColor = uno.defs.table.BORDER_COLOR;
      } else {
        cell.style.borderColor = util.table.darkenBorderColor(hexValue);
        cell.style.backgroundColor = hexValue;
      }
    }, this);
    return true;
  };
  TableCellColor.prototype.queryCommandValue = function() {
    var cells = util.table.cellsForRange(this.editor.getRange());
    if (!cells.length) {
      return "";
    }
    var style = cells[0].style;
    var color;
    if (style.backgroundColor) {
      try {
        color = goog.color.hexToRgbStyle(goog.color.parse(style.backgroundColor).hex);
      } catch (ex) {
        color = null;
        log.fine(ex.stack || ex);
      }
      return color != null ? color : "";
    }
    return "";
  };
  TableCellColor.prototype.queryCommandEnabled = function() {
    return !this.editor.multirange.isEmpty() || util.table.cellsForRange(this.editor.getRange()).length > 0;
  };
})();
goog.provide("uno.commands.TableEqualCol");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.TableEqualCol");
  var util = uno.util;
  var TableEqualCol = uno.commands.TableEqualCol = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TableEqualCol, uno.BasePlugin);
  TableEqualCol.prototype.isSupportedCommand = function(command) {
    return command === "tableequalcol";
  };
  TableEqualCol.prototype.execCommandInternal = function(command) {
    var indexes = util.table.selection.getColumnIndexes();
    if (indexes.length < 2) {
      return false;
    }
    util.table.equalizeColumns(util.table.getActive(), indexes);
    return true;
  };
  TableEqualCol.prototype.queryCommandEnabled = function() {
    return !this.editor.multirange.isEmpty() || util.table.selection.getColumnIndexes() > 1;
  };
})();
goog.provide("uno.commands.TableFitNote");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.TableFitNote");
  var util = uno.util;
  var TableFitNote = uno.commands.TableFitNote = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TableFitNote, uno.BasePlugin);
  TableFitNote.prototype.isSupportedCommand = function(command) {
    return command === "tablefitnote";
  };
  TableFitNote.prototype.execCommandInternal = function(command) {
    return util.table.fitNote(util.table.getActive());
  };
  TableFitNote.prototype.queryCommandEnabled = function() {
    return !!util.table.getActive();
  };
})();
goog.provide("uno.commands.TableVerticalAlign");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.EditorMultiRange");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.TableVerticalAlign");
  var util = uno.util;
  var TableVerticalAlign = uno.commands.TableVerticalAlign = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(TableVerticalAlign, uno.BasePlugin);
  TableVerticalAlign.prototype.isSupportedCommand = function(command) {
    return command === "tableverticalalign";
  };
  TableVerticalAlign.prototype.execCommandInternal = function(command, align) {
    if (["", "middle", "top", "bottom"].indexOf(align) < 0) {
      log.warning("Saw unexpected vertical-align value", align);
      align = "";
    }
    if (align === "top") {
      align = "";
    }
    util.table.cellsForRange(this.editor.getRange()).forEach(function(cell) {
      cell.style.verticalAlign = align;
    });
    return true;
  };
  TableVerticalAlign.prototype.queryCommandEnabled = function() {
    return !this.editor.multirange.isEmpty() || util.table.cellsForRange(this.editor.getRange()).length > 0;
  };
})();
goog.provide("uno.commands.InsertTodo");
goog.require("goog.debug.Logger");
goog.require("goog.editor.node");
goog.require("goog.editor.range");
goog.require("uno.BasePlugin");
goog.require("goog.string");
goog.require("uno.util.dom");
goog.require("uno.util.todo");
goog.require("uno.util.crypto");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.InsertTodo");
  var util = uno.util;
  var InsertTodo = uno.commands.InsertTodo = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(InsertTodo, uno.BasePlugin);
  InsertTodo.prototype.isSupportedCommand = function(command) {
    return command === "inserttodo";
  };
  InsertTodo.prototype.execCommandInternal = function(command, value) {
    var editor = this.editor;
    var toggle = value === "toggle";
    var range = editor.getRange();
    var startNode = range.getStartNode();
    var node;
    if (toggle) {
      node = startNode;
      while (node = goog.dom.getPreviousElementSibling(node)) {
        if (util.todo.isTodo(node)) {
          util.todo.toggle(node);
          return true;
        }
      }
    } else {
      if (range.isCollapsed()) {
        var todo = util.todo.create();
        if (editor.context.style.hasPendingStyles) {
          node = util.styles.setInlineStyles(todo, editor.context.style.pendingStyles, editor.config.defaults);
        } else {
          node = todo;
        }
        range.insertNode(node);
        if (node.parentNode) {
          node.parentNode.normalize();
        }
        goog.editor.range.placeCursorNextTo(todo);
        util.styles.clearPendingStyles(editor);
      } else {
        var container = range.getContainer();
        if (container === range.getAnchorNode()) {
          container = null;
        }
        var existing = goog.array.toArray(util.todo.all(editor.field)).filter(function(node) {
          return range.containsNode(node, true);
        });
        if (existing.length > 0) {
          existing.forEach(util.todo.remove);
        } else {
          var nodes = goog.array.toArray(editor.field.querySelectorAll("div,li"));
          nodes = nodes.filter(function(node) {
            return range.containsNode(node, true) && (!container || container.contains(node)) && goog.array.every(node.childNodes, util.dom.isInlineNode) && (!goog.string.isEmpty(node.textContent) || !!node.querySelector("img"));
          });
          if (nodes.length > 0) {
            nodes.forEach(function(node) {
              var entodo = util.todo.create();
              if (node.childNodes.length === 0) {
                node.appendChild(entodo);
              } else {
                var leftMostLeaf = goog.editor.node.getLeftMostLeaf(node);
                goog.dom.insertSiblingBefore(entodo, leftMostLeaf);
              }
            });
            goog.dom.Range.createFromNodes(nodes[0], 0, range.getEndNode(), range.getEndOffset()).select();
          }
        }
      }
    }
  };
  InsertTodo.prototype.queryCommandEnabled = function() {
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    if (util.crypto.for(range.getContainerElement())) {
      return false;
    }
    return true;
  };
})();
goog.provide("uno.commands.Lowercase");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Lowercase");
  var util = uno.util;
  var Lowercase = uno.commands.Lowercase = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(Lowercase, uno.BasePlugin);
  Lowercase.prototype.isSupportedCommand = function(command) {
    return command === "lowercase";
  };
  Lowercase.prototype.execCommandInternal = function() {
    var range = this.editor.getRange();
    var savedRange = range.saveUsingDom();
    util.range.forEachWord(range, function(word, wordRange) {
      var container = wordRange.startContainer;
      var text = container.nodeValue;
      container.nodeValue = text.slice(0, wordRange.startOffset) + word.toLocaleLowerCase() + text.slice(wordRange.endOffset);
    });
    savedRange.restore().select();
    return true;
  };
})();
goog.provide("uno.commands.Margin");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Margin");
  var Margin = uno.commands.Margin = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Margin, uno.BasePlugin);
  Margin.prototype.isSupportedCommand = function(command) {
    return command === "margin";
  };
  Margin.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Margin.prototype.execCommand = function(command, value) {
    if (value == null) {
      return false;
    }
    if (this.editor == null || this.editor.field == null) {
      return false;
    }
    var field = this.editor.field;
    var note = value.note;
    if (note) {
      field.style.paddingTop = toCssValue(note.top, "px");
      field.style.paddingBottom = toCssValue(note.bottom, "px");
      field.style.paddingLeft = toCssValue(note.left, "px");
      field.style.paddingRight = toCssValue(note.right, "px");
    }
    if (value.scroll) {
      this.editor.config.margin.scroll = {top:value.scroll.top || 0, left:value.scroll.left || 0, bottom:value.scroll.bottom || 0, right:value.scroll.right || 0};
    }
    if (value.offset) {
      this.editor.config.margin.offset = {height:value.offset.height || 0, width:value.offset.width || 0};
    }
    return true;
  };
  function toCssValue(value, unit) {
    var result;
    switch(typeof value) {
      case "number":
        result = value + unit;
        break;
      case "string":
        if (value.indexOf(unit) > -1) {
          result = value;
        } else {
          result = value + unit;
        }
        break;
      case "undefined":
        result = null;
        break;
      default:
        result = value;
    }
    return result;
  }
})();
goog.provide("uno.util.normalize");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.list");
goog.require("uno.util.table");
goog.require("uno.util.paragraph");
goog.require("uno.util.richlink");
goog.require("uno.util.styles");
goog.require("goog.array");
goog.require("goog.dom");
(function() {
  var util = uno.util;
  var dom = util.dom;
  util.normalize.normalizeNode = function(node, options) {
    options = options || {};
    if (dom.isTextNode(node)) {
      node = node.parentNode;
    }
    var savedCursor = null;
    var endCursor = null;
    if (options.cleanUX && options.editor) {
      options.editor.cleanUX();
    }
    if (options.range) {
      savedCursor = util.range.saveCursor(options.range);
    }
    node.innerHTML = util.normalize.normalizeHtml(node.innerHTML);
    util.normalize.normalizeDom(node, options);
    if (savedCursor) {
      endCursor = node.querySelector("#" + savedCursor.endCaretId_);
      if (options.range.isCollapsed() && endCursor && !dom.isBr(endCursor.nextSibling) && endCursor.parentNode.childNodes === 2) {
        goog.dom.insertSiblingAfter(document.createElement("br"), endCursor);
      }
      savedCursor.restore();
    }
    if (options.cleanUX && options.editor) {
      options.editor.restoreUX();
    }
    return node;
  };
  util.normalize.normalizeHtml = function(html) {
    var nonVoidTag = /<(?!area|base|br|col|command|embed|hr|img|input|keygen|link|meta|param|source|track|wbr)([\w-]+)([^>]*)\/>/g;
    var invalidCharacters = /[\u0000\u0001-\u0008\u000E-\u001F\u007F-\u009F\uFDD0-\uFDEF\u000B\uFFFE\uFFFF]|[\x01-\x10][\uFFFE-\uFFFF]/g;
    var zwsRegex = new RegExp(uno.defs.unicode.ZERO_WIDTH_SPACE, "g");
    html = html.replace(zwsRegex, "").replace(invalidCharacters, "").replace(/(<pre(?:>|\s[^>]*>))([\u0000-\uffff]*?)<\/pre>/g, function(m, g1, g2) {
      return "<div" + g1.substr(4) + g2.replace(/\r?\n/g, "<br>").replace(/\t/g, "&nbsp;&nbsp;&nbsp;&nbsp;") + "</div>";
    }).replace(/[\n\t\r]/g, "").replace(/\n\n\/\*\*\/\n\x3c!--[\s\w{:}#;-]+>\n\/\*\*\/\n/g, "").replace(nonVoidTag, "<$1$2></$1>");
    html = util.normalize.removeExcessiveEmptyLinesInHtml(html);
    return html;
  };
  util.normalize.normalizeDom = function(root, options) {
    options = options || {};
    root.normalize();
    if (dom.isTextNode(root)) {
      return;
    }
    util.normalize.removeUnsupportedNodes(root);
    util.normalize.removeUnsupportedTags(root);
    util.normalize.normalizeRenderingBox(root);
    util.normalize.replaceBrsByParagraphs(root.querySelectorAll("br"));
    util.normalize.removeEmptyNodes(root);
    util.list.normalize(root);
    util.table.normalize(root, options.ignoreTableStyles);
    util.normalize.ensureValidParagraph(root.childNodes);
    util.normalize.flattenRedundantNodes(root);
    if (!options.ignoreInlineNodes) {
      util.normalize.inlineNodes(root, options);
    }
    util.list.convertParagraphsToBrs(root);
    if (options.removeFormat) {
      util.normalize.removeRichLinkFormat(root);
    }
  };
  util.normalize.removeUnsupportedTags = function(frag) {
    goog.array.forEachRight(frag.querySelectorAll("en-note, script, meta, style, input, option, select, button"), goog.dom.removeNode);
    goog.array.forEachRight(frag.querySelectorAll('a[x-apple-data-detectors="true"]'), goog.dom.flattenElement);
  };
  util.normalize.normalizeRenderingBox = function(frag) {
    var nodes = frag.querySelectorAll('[style*="display"]');
    goog.array.forEachRight(nodes, function(node) {
      if (dom.isBlockNode(node) && node.style && ["inline", "inline-block"].indexOf(node.style.display) > -1) {
        node = dom.changeTagName(node, "span");
      }
      if (dom.isInlineNode(node) && node.style && ["block"].indexOf(node.style.display) > -1) {
        node = dom.changeTagName(node, "div");
      }
      dom.removeStyleValue(node, "display");
    });
  };
  util.normalize.replaceBrsByParagraphs = function(brs) {
    var getCloneTagName = function(node) {
      return isInvalidParent(node) || dom.isNoteSection(node) || dom.isP(node) || dom.isPre(node) ? "div" : node.tagName;
    };
    goog.array.forEach(brs, function(br) {
      var clone;
      var sibling;
      var parent;
      var nodes = [];
      var node = br;
      var hasSiblings = false;
      if (dom.isBlockNode(br.parentNode) && br.parentNode.childNodes.length === 1) {
        return;
      }
      while (dom.isInlineNode(node)) {
        var siblings = [];
        sibling = node.previousSibling;
        parent = node.parentNode;
        while (sibling && dom.isInlineNode(sibling)) {
          siblings.push(sibling);
          sibling = sibling.previousSibling;
        }
        if (siblings.length) {
          hasSiblings = true;
        }
        node = node.parentNode;
        var newClone = dom.isInlineNode(node) ? node.cloneNode() : goog.dom.createDom(getCloneTagName(node));
        if (clone) {
          newClone.appendChild(clone);
        }
        clone = newClone;
        goog.array.forEach(siblings, function(child) {
          goog.dom.insertChildAt(clone, child, 0);
        });
      }
      if (hasSiblings) {
        goog.dom.removeNode(br);
        if (dom.isEmpty(clone)) {
          return;
        }
      } else {
        clone = goog.dom.createDom(getCloneTagName(node));
        clone.appendChild(br);
      }
      if (sibling) {
        goog.dom.insertSiblingAfter(clone, sibling);
      } else {
        if (parent) {
          goog.dom.insertChildAt(parent, clone, 0);
        }
      }
      if (dom.isInlineNode(clone.nextSibling) && !dom.isBr(clone.nextSibling) && dom.isEmptyContent(clone.nextSibling) && !clone.nextSibling.querySelector("br")) {
        goog.dom.removeNode(clone.nextSibling);
      }
    });
  };
  util.normalize.removeEmptyNodes = function(root) {
    var deepestNodes = dom.getNodeLeaves(root, dom.inlineObjects, true);
    goog.array.forEachRight(deepestNodes, function(node) {
      var parent = node.parentNode;
      while (node && util.normalize.isEmptyNode(node)) {
        goog.dom.removeNode(node);
        node = parent;
        parent = node && node.parentNode;
      }
    });
  };
  util.normalize.isEmptyNode = function(node) {
    return [].concat(dom.inlineObjects, dom.tableObjects).indexOf(dom.getTagName(node)) === -1 && dom.isEmpty(node);
  };
  util.normalize.ensureValidParagraph = function(siblings) {
    var paragraphNodes = [];
    goog.array.forEachRight(siblings, function(node) {
      var parentNode = node.parentNode;
      var previousSibling = node.previousSibling;
      var nextSibling = node.nextSibling;
      var paragraph = node;
      if (dom.isInlineNode(node) && (dom.isBlockNode(previousSibling) || dom.isBlockNode(nextSibling) || dom.isNoteSection(parentNode))) {
        var tagName = dom.isBlockNode(parentNode) && !dom.isNoteSection(parentNode) ? parentNode.tagName : "div";
        if (dom.isBlockNode(nextSibling) || !nextSibling) {
          paragraphNodes.push(node);
          while (dom.isInlineNode(node.previousSibling)) {
            paragraphNodes.unshift(node.previousSibling);
            node = node.previousSibling;
          }
          paragraph = goog.dom.createDom(tagName, null, paragraphNodes);
          if (nextSibling) {
            goog.dom.insertSiblingBefore(paragraph, nextSibling);
          } else {
            parentNode.appendChild(paragraph);
          }
        } else {
          if (dom.isBlockNode(previousSibling)) {
            paragraphNodes.push(node);
            while (dom.isInlineNode(node.nextSibling)) {
              paragraphNodes.push(node.nextSibling);
              node = node.nextSibling;
            }
            paragraph = goog.dom.createDom(tagName, null, paragraphNodes);
            goog.dom.insertSiblingAfter(paragraph, previousSibling);
          }
        }
        paragraphNodes = [];
      }
      if (paragraph && paragraph.childNodes.length) {
        util.normalize.ensureValidParagraph(paragraph.childNodes);
      }
    });
  };
  var isInvalidParent = function(parentNode) {
    return !parentNode || !parentNode.parentNode || dom.isEnnote(parentNode) || dom.isFragment(parentNode);
  };
  util.normalize.flattenRedundantNodes = function(root) {
    var deepestNodes = dom.getNodeLeaves(root, dom.inlineObjects);
    var dumbParentNode = goog.dom.createDom("div");
    deepestNodes.forEach(function(node) {
      while (!isInvalidParent(node.parentNode)) {
        var parentNode = node.parentNode;
        if (dom.isUl(parentNode) || dom.isOl(parentNode) || dom.isLi(parentNode) || dom.isTd(parentNode) || dom.isTd(node) || dom.isTr(node) || dom.isColgroup(parentNode) || dom.isCodeBlock(parentNode) || dom.isRevealedCrypt(parentNode) || dom.isBlockquote(parentNode) || dom.isTextNode(node)) {
          if (dom.isTd(parentNode) || dom.isTr(node) || dom.isColgroup(parentNode)) {
            node = goog.dom.getAncestor(node, dom.isEntable) || goog.dom.getAncestor(node, dom.isTable) || parentNode;
          } else {
            node = parentNode;
          }
        } else {
          if (dom.isBlockNode(node)) {
            if (dom.isBlockNode(parentNode)) {
              if (parentNode.getAttribute("style")) {
                node = parentNode;
              } else {
                goog.array.forEachRight(parentNode.childNodes, function(child) {
                  util.styles.mergeAttributes(parentNode, child, true);
                  goog.dom.insertSiblingAfter(child, parentNode);
                });
                if (!parentNode.childNodes.length) {
                  goog.dom.removeNode(parentNode);
                } else {
                  goog.dom.flattenElement(parentNode);
                }
              }
            } else {
              goog.array.forEachRight(parentNode.childNodes, function(child) {
                var paragraphs = [child];
                if (dom.isTable(child)) {
                  paragraphs = util.table.getParagraphs(child);
                } else {
                  if (dom.isUl(child) || dom.isOl(child)) {
                    paragraphs = util.list.getParagraphs(child);
                  }
                }
                goog.array.forEach(paragraphs, function(paragraph) {
                  if (dom.isTextNode(paragraph)) {
                    paragraph = goog.dom.createDom("div", null, paragraph);
                  }
                  var newNode = parentNode.cloneNode();
                  dom.moveChildren(paragraph, newNode);
                  paragraph.appendChild(newNode);
                });
              });
              var previousSiblings = dom.getPreviousSiblings(parentNode);
              if (previousSiblings.length) {
                var leftParagraph = goog.dom.createDom("div", null, previousSiblings);
                goog.dom.insertSiblingBefore(leftParagraph, parentNode);
              }
              var nextSiblings = dom.getNextSiblings(parentNode);
              if (nextSiblings.length) {
                var rightParagraph = goog.dom.createDom("div", null, nextSiblings);
                goog.dom.insertSiblingAfter(rightParagraph, parentNode);
              }
              if (!parentNode.childNodes.length) {
                goog.dom.removeNode(parentNode);
              } else {
                goog.dom.flattenElement(parentNode);
              }
            }
          } else {
            node = parentNode;
          }
        }
      }
      util.styles.mergeAttributes(dumbParentNode, node, true);
    });
  };
  util.normalize.normalizeParagraphStructure = function(paragraph) {
    if (dom.isP(paragraph)) {
      paragraph = dom.changeTagName(paragraph, "div");
      if (paragraph.style.marginBottom.length === 0 && paragraph.style.marginTop.length === 0) {
        dom.setStyleValue(paragraph, "-en-paragraph", "true");
        dom.setStyleValue(paragraph, "margin-top", "1em");
        dom.setStyleValue(paragraph, "margin-bottom", "1em");
      }
    }
    return paragraph;
  };
  util.normalize.inlineNodes = function(root, options) {
    var paragraphs = util.paragraph.all(root);
    var dumbNode = goog.dom.createDom("div");
    if (!paragraphs.length && dom.isElementNode(root)) {
      paragraphs = [root];
    }
    goog.array.forEach(paragraphs, function(paragraph) {
      paragraph = util.normalize.normalizeParagraphStructure(paragraph);
      if (dom.isBlockNode(paragraph.firstChild)) {
        return;
      }
      var deepestNodes = util.dom.getNodeLeaves(paragraph, dom.inlineObjects);
      var nodes = [];
      deepestNodes.forEach(function(node) {
        var link = false;
        var element = node;
        while (element !== paragraph) {
          if (element.attributes && element.getAttribute("href")) {
            link = element;
            break;
          }
          element = element.parentNode;
        }
        if (dom.isTextNode(node)) {
          var currentNode = node;
          node = goog.dom.createDom("span", null, node.textContent);
          if (!options.removeFormat) {
            while (dom.isInlineNode(currentNode) && currentNode.parentNode) {
              util.styles.mergeAttributes(currentNode.parentNode, node, false, {disallowedStyles:"align.*|animation.*|flex.*|float|grid.*|justify.*|left|list.*|margin.*|padding.*|shape.*|text-align|transition.*", allowedAttrs:"data-.*|title|class"});
              currentNode = currentNode.parentNode;
            }
          }
          if (!node.hasAttributes()) {
            node = node.firstChild;
          }
        }
        if (link) {
          var href = link.getAttribute("href");
          if (dom.isSpan(node) || dom.isTextNode(node)) {
            var anchor = goog.dom.createDom("a", {href:href}, node.textContent);
            goog.array.forEach(node.attributes || [], function(attr) {
              anchor.setAttribute(attr.name, attr.value);
            });
            if (link.getAttribute("rev")) {
              anchor.setAttribute("rev", link.getAttribute("rev"));
            }
            node = anchor;
          } else {
            if (dom.isImg(node) || util.resource.isImage(node)) {
              node = goog.dom.createDom("a", {href:href}, node);
            }
          }
        }
        nodes.push(node);
      });
      if (nodes.length) {
        while (paragraph.firstChild) {
          paragraph.removeChild(paragraph.firstChild);
        }
        var mergeOptions = {allowedStyles:".*", disallowedStyles:options.removeFormat ? ".*" : "", disallowedAttrs:options.externalContent ? "name|id|data-.*|bgcolor|class" : "bgcolor"};
        util.styles.mergeAttributes(dumbNode, paragraph, false, mergeOptions);
        nodes.forEach(function(node) {
          paragraph.appendChild(node);
          if (dom.isInlineNode(paragraph) && !paragraph.hasAttributes()) {
            goog.dom.flattenElement(paragraph);
          }
        });
      }
    });
  };
  util.normalize.removeUnsupportedNodes = function(frag) {
    var iterator = frag.ownerDocument.createNodeIterator(frag, 8 | 128, null, false);
    var element;
    var nodeList = [];
    while (element = iterator.nextNode()) {
      nodeList.push(element);
    }
    for (var i = nodeList.length - 1; i >= 0; i--) {
      var node = nodeList[i];
      var nodeType = node.nodeType;
      if (nodeType === Node.COMMENT_NODE) {
        if (node.data.indexOf("[CDATA[") === 0) {
          var nextSibling = node.nextSibling;
          var textNode = document.createTextNode(node.data.substr(7));
          goog.dom.replaceNode(textNode, node);
          node = textNode;
          if (node.data.lastIndexOf("]]") !== node.data.length - 2 && nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {
            nextSibling.data = nextSibling.data.replace(/^(.*?)\]\]\>(.*?)$/gi, "$1$2");
            node.data += ">";
          } else {
            node.data = node.data.replace(/^(.*?)\]\](.*?)$/gi, "$1$2");
          }
        } else {
          node.parentNode.removeChild(node);
        }
      } else {
        goog.dom.replaceNode(document.createTextNode(node.data), node);
      }
    }
  };
  util.normalize.removeExcessiveEmptyLinesInHtml = function(html) {
    return html.replace(/(<li[^>]*>(?:(?!<\/li).)*?)(?:<div><br\s?\/><\/div>){6,}/g, "$1<div><br /></div>");
  };
  util.normalize.removeRichLinkFormat = function(frag) {
    goog.array.forEach(util.richlink.all(frag), function(link) {
      var parent = link.parentNode;
      if (util.dom.isA(parent)) {
        parent.innerHTML = parent.href;
      }
    });
  };
})();
goog.provide("uno.util.n3");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.list");
goog.require("uno.util.table");
goog.require("uno.util.paragraph");
goog.require("uno.util.styles");
goog.require("uno.util.normalize");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.functions");
(function() {
  var util = uno.util;
  var dom = util.dom;
  util.n3.normalizeNode = function(node, options) {
    start("util.normalize.normalizeNode");
    options = options || {};
    if (dom.isTextNode(node)) {
      node = node.parentNode;
    }
    var savedCursor = null;
    var endCursor = null;
    if (options.cleanUX && options.editor) {
      options.editor.cleanUX();
    }
    if (options.range) {
      savedCursor = util.range.saveCursor(options.range);
    }
    node.innerHTML = util.normalize.normalizeHtml(node.innerHTML);
    util.n3.normalizeDom(node, options);
    if (savedCursor) {
      endCursor = node.querySelector("#" + savedCursor.endCaretId_);
      if (options.range.isCollapsed() && endCursor && !dom.isBr(endCursor.nextSibling) && endCursor.parentNode.childNodes === 2) {
        goog.dom.insertSiblingAfter(document.createElement("br"), endCursor);
      }
      savedCursor.restore();
    }
    if (options.cleanUX && options.editor) {
      options.editor.restoreUX();
    }
    stop("util.normalize.normalizeNode");
    return node;
  };
  util.n3.normalizeDom = function(root, options) {
    start("util.n3.normalizeDom");
    options = options || {};
    var strictMode = options.editor && options.editor.strictMode;
    root.normalize();
    if (dom.isTextNode(root)) {
      stop("util.n3.normalizeDom");
      return;
    }
    util.normalize.removeUnsupportedNodes(root);
    util.normalize.removeUnsupportedTags(root);
    if (options.simplifyFormat) {
      removeTags(root, ["blockquote", 'div[style*="-en-codeblock:"]']);
    }
    if (strictMode) {
      convertBlockquoteToParagraphMargin(root);
    }
    util.normalize.replaceBrsByParagraphs(root.querySelectorAll("br"));
    util.normalize.removeEmptyNodes(root);
    util.list.normalize(root);
    util.table.normalize(root, options.ignoreTableStyles);
    normalizeInlineNodes(root, options);
    if (strictMode) {
      wrapTopLevelChunksInParagraphs(root.querySelectorAll("li"));
    } else {
      util.list.convertParagraphsToBrs(root);
    }
    stop("util.n3.normalizeDom");
  };
  function normalizeInlineNodes(root, options) {
    start("util.normalize.normalizeDom normalizeInlineNodes");
    options = options || {};
    var parents = [root];
    var walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, {acceptNode:function(node) {
      if (node.firstChild == null || isOpaqueElement(node)) {
        return NodeFilter.FILTER_REJECT;
      } else {
        parents.push(node);
        return NodeFilter.FILTER_ACCEPT;
      }
    }});
    while (walker.nextNode()) {
    }
    goog.array.forEachRight(parents, function(parent, index) {
      if (parent.tagName === "SPAN" && !parent.getAttribute("style")) {
        goog.dom.flattenElement(parent);
      } else {
        parent = replacePtagWithDiv(parent);
        parent = matchTagNameToDisplayProperty(parent);
        ensureChildrenAreAllBlocksOrAllInline(parent);
      }
    });
    var elementsAndStyles = findContentParentsAndStyles(root, options);
    var elements = elementsAndStyles.nodes;
    var styles = elementsAndStyles.styles;
    normalizeFormatting(elements, styles, options);
    stop("util.normalize.normalizeDom normalizeInlineNodes");
  }
  function replacePtagWithDiv(el) {
    if (el.tagName === "P") {
      el = dom.changeTagName(el, "div");
      if (el.style.marginBottom.length === 0 && el.style.marginTop.length === 0) {
        dom.setStyleValue(el, "-en-paragraph", "true");
        dom.setStyleValue(el, "margin-top", "1em");
        dom.setStyleValue(el, "margin-bottom", "1em");
      }
    }
    return el;
  }
  function matchTagNameToDisplayProperty(node) {
    if (dom.isBlockNode(node) && node.style && node.style.display === "inline") {
      node = dom.changeTagName(node, "span");
      node.style.display = "";
    } else {
      if (!dom.isBlockNode(node) && node.style && node.style.display === "block") {
        node = dom.changeTagName(node, "div");
        node.style.display = "";
      }
    }
    return node;
  }
  function ensureChildrenAreAllBlocksOrAllInline(parent) {
    if (parent.childNodes.length < 2) {
      return;
    }
    if (isOpaqueElement(parent)) {
      return;
    }
    var curCluster = {nodes:[], hasBlock:null};
    var clusters = [curCluster];
    var childrenShouldBeBlocks = false;
    goog.array.forEach(parent.childNodes, function(child) {
      var hasBlock = isBlockLayout(child);
      childrenShouldBeBlocks = childrenShouldBeBlocks || hasBlock;
      if (curCluster.hasBlock == null || hasBlock === curCluster.hasBlock) {
        curCluster.nodes.push(child);
        curCluster.hasBlock = hasBlock;
      } else {
        curCluster = {nodes:[child], hasBlock:hasBlock};
        clusters.push(curCluster);
      }
    });
    if (clusters.length > 1 && childrenShouldBeBlocks) {
      goog.array.forEach(clusters, function(cluster) {
        if (!cluster.hasBlock) {
          var container = document.createElement("div");
          goog.dom.replaceNode(container, cluster.nodes[0]);
          goog.array.forEach(cluster.nodes, function(child) {
            container.appendChild(child);
          });
        }
      });
    }
  }
  function findContentParentsAndStyles(root, options) {
    var parents = [];
    var parent;
    var parentStyles = [];
    var parentStyle;
    var children = [];
    var child;
    var childStyles = [];
    var resultNodes = [];
    var resultStyles = [];
    var redundantNodes = [];
    var i;
    var hasContentChild;
    var isRedundantDiv;
    var isRedundantInline;
    var temp1, temp2;
    parents.push(root);
    parentStyles.push(combinedStyle(root, {}, options));
    while (parents.length > 0) {
      parent = parents.pop();
      parentStyle = parentStyles.pop();
      if (!isOpaqueElement(parent)) {
        hasContentChild = false;
        isRedundantDiv = parent.tagName === "DIV" && !util.styles.hasLayoutStyle(parent);
        isRedundantInline = !dom.isBlockNode(parent) && !util.styles.hasLayoutStyle(parent);
        for (i = parent.childNodes.length - 1; i > -1; i--) {
          child = parent.childNodes[i];
          if (child.firstChild != null) {
            children.push(child);
            childStyles.push(combinedStyle(child, parentStyle, options));
          }
          if (isRedundantDiv && child.tagName !== "DIV") {
            isRedundantDiv = false;
          }
          if (!hasContentChild && (child.nodeType === Node.TEXT_NODE || child.tagName === "IMG" || util.resource.isImage(child))) {
            hasContentChild = true;
          }
        }
        if (hasContentChild && Object.keys(parentStyle).length > 0) {
          resultNodes.push(parent);
          resultStyles.push(parentStyle);
        } else {
          if (isRedundantDiv || isRedundantInline) {
            redundantNodes.push(parent);
          }
        }
      }
      if (parents.length === 0) {
        temp1 = parents;
        temp2 = parentStyles;
        parents = children;
        parentStyles = childStyles;
        children = temp1;
        childStyles = temp2;
      }
    }
    goog.array.forEach(redundantNodes, dom.flattenElement);
    return {nodes:resultNodes, styles:resultStyles};
  }
  function normalizeFormatting(contentParents, styles, options) {
    options = options || {};
    goog.array.forEachRight(contentParents, function(parent, index) {
      var style = styles[index];
      var wrappers;
      var clusters = [];
      var cluster;
      goog.array.forEach(parent.childNodes, function(child) {
        if (child.nodeType === Node.TEXT_NODE || child.tagName === "IMG" || child.tagName === "BR" || util.resource.isResource(child)) {
          if (cluster == null) {
            cluster = [];
            clusters.push(cluster);
          }
          cluster.push(child);
        } else {
          cluster = null;
        }
      });
      if (style.href != null) {
        if (parent.tagName !== "A") {
          wrappers = clusters.map(function() {
            return document.createElement("a");
          });
        }
      } else {
        if (parent.tagName !== "SPAN" || clusters.length > 1) {
          wrappers = clusters.map(function() {
            return document.createElement("span");
          });
        }
      }
      if (wrappers) {
        wrappers.forEach(function(wrapper, idx) {
          goog.dom.replaceNode(wrapper, clusters[idx][0]);
          clusters[idx].forEach(function(node) {
            wrapper.appendChild(node);
          });
          if (!dom.isBlockNode(parent)) {
            Object.keys(parent.style).forEach(function(key) {
              if (isNaN(key) && parent.style[key] != null && parent.style[key] !== "" && style[key] == null && key !== "cssText") {
                style[key] = parent.style[key];
              }
            });
            dom.flattenElement(parent);
          }
        });
      } else {
        wrappers = [parent];
      }
      wrappers.forEach(function(wrapper) {
        applyStyle(style, wrapper, options.simplifyFormat);
      });
    });
  }
  var TAGS_TO_STYLES = {B:{name:"fontWeight", value:"bold"}, EM:{name:"fontStyle", value:"italic"}, I:{name:"fontStyle", value:"italic"}, STRIKE:{name:"textDecoration", value:"line-through"}, STRONG:{name:"fontWeight", value:"bold"}, SUB:{name:"verticalAlign", value:"sub"}, SUP:{name:"verticalAlign", value:"super"}, U:{name:"textDecoration", value:"underline"}};
  var COMPOUND_STYLES = ["textDecoration"];
  function isBlockLayout(node) {
    return dom.isBlockNode(node) && node.style.float !== "left" && node.style.float !== "right" && node.style.display !== "inline" && node.style.display !== "inline-block";
  }
  function combinedStyle(node, parentStyle, options) {
    options = options || {};
    if (options.removeFormat) {
      return parentStyle;
    }
    var fontSize;
    var style = {};
    var declaration = node.style;
    if (declaration == null) {
      return style;
    }
    goog.object.extend(style, parentStyle);
    var styleFromTag = TAGS_TO_STYLES[node.tagName];
    if (styleFromTag) {
      if (COMPOUND_STYLES.indexOf(styleFromTag.name) !== -1 && style[styleFromTag.name] != null) {
        style[styleFromTag.name] += " " + styleFromTag.value;
      } else {
        style[styleFromTag.name] = styleFromTag.value;
      }
    } else {
      if (node.tagName === "FONT" && !options.simplifyFormat) {
        if (node.getAttribute("color")) {
          style.color = node.getAttribute("color");
        }
        if (node.getAttribute("face")) {
          style.fontFamily = node.getAttribute("face");
        }
        if (node.getAttribute("size") && declaration.fontSize === "") {
          if (isRelativeValue(node.getAttribute("size")) && isRelativeValue(style.fontSize)) {
            style.fontSize = combineRelativeValues(node.getAttribute("size"), style.fontSize);
          } else {
            style.fontSize = node.getAttribute("size");
          }
        }
      } else {
        if (node.tagName === "A") {
          if (style.color) {
            delete style.color;
          }
          if (node.getAttribute("href")) {
            style.href = node.getAttribute("href");
          }
        }
      }
    }
    var styleNames = options.simplifyFormat ? SIMPLIFY_FORMAT_STYLES : util.styles.inlineStyles;
    styleNames.forEach(function(name) {
      var value = declaration[name];
      if (value != null && value !== "" && value !== "inherit") {
        style[name] = value;
      }
    });
    if (options.simplifyFormat) {
      node.removeAttribute("style");
    } else {
      styleNames.forEach(function(name) {
        if (name !== "backgroundColor" && name !== "fontSize") {
          declaration[name] = null;
        }
      });
    }
    if (style.backgroundColor && !declaration.backgroundColor && dom.isBlockNode(node)) {
      declaration.backgroundColor = null;
    }
    if (node.getAttribute("style") === "") {
      node.removeAttribute("style");
    }
    return style;
  }
  function stripStyles(node, styleNames) {
    var declaration = node.style;
    styleNames.forEach(function(name) {
      if (declaration[name] !== "") {
        declaration[name] = "";
      }
    });
  }
  function applyStyle(style, el, simplifyFormat) {
    if (simplifyFormat) {
      el.removeAttribute("style");
    }
    Object.keys(style).filter(function(key) {
      return key === "href" ? !el.href : el.style[key] === "";
    }).forEach(function(key) {
      if (key === "href") {
        el.href = style.href;
      } else {
        el.style[key] = style[key];
      }
    });
  }
  function isRelativeValue(value) {
    return false;
  }
  function combineRelativeValues(v1, v2) {
    return v1;
  }
  function removeTags(root, tagNames) {
    if (!tagNames) {
      return;
    }
    if (typeof tagNames === "string") {
      tagNames = [tagNames];
    }
    var selector = tagNames.join(",");
    goog.array.forEach(root.querySelectorAll(selector), dom.flattenElement);
  }
  var SIMPLIFY_FORMAT_STYLES = ["fontStyle", "fontWeight", "textDecoration"];
  function wrapTopLevelChunksInParagraphs(origins) {
    goog.array.forEach(origins, function(origin) {
      var inlineNodes = [];
      var p;
      goog.array.forEachRight(origin.childNodes, function(child) {
        if (!util.dom.isBlockNode(child)) {
          inlineNodes.push(child);
        } else {
          if (inlineNodes.length > 0) {
            p = goog.dom.createDom("div", null, inlineNodes.reverse());
            goog.dom.insertSiblingAfter(p, child);
            inlineNodes = [];
          }
        }
      });
      if (inlineNodes.length > 0) {
        p = goog.dom.createDom("div", null, inlineNodes.reverse());
        goog.dom.insertChildAt(origin, p, 0);
      }
    });
  }
  function convertBlockquoteToParagraphMargin(frag) {
    var blockquotes = frag.querySelectorAll("blockquote");
    var hierarchy = [];
    var marginIncrement = 40;
    goog.array.forEach(blockquotes, function(blockquote) {
      var paragraphs = blockquote.querySelectorAll("div");
      goog.array.forEach(paragraphs, function(p) {
        var left = parseInt(p.style.marginLeft, 10) || 0;
        left += marginIncrement;
        p.style.marginLeft = left + "px";
      });
      goog.dom.flattenElement(blockquote);
    });
  }
  var opaqueTagNames = ["EN-CRYPT", "EN-MEDIA", "EMBED", "OBJECT"];
  function isOpaqueElement(el) {
    return el != null && opaqueTagNames.indexOf(el.tagName) !== -1;
  }
})();
goog.provide("uno.util.paste");
goog.require("goog.editor.range");
goog.require("goog.editor.node");
goog.require("goog.dom.Range");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("uno.util.paragraph");
goog.require("uno.util.dom");
goog.require("uno.util.font");
goog.require("uno.util.range");
goog.require("uno.util.table");
goog.require("uno.util.n3");
(function() {
  var util = uno.util;
  var dom = util.dom;
  util.paste.paste = function(clipboardContent, range, options) {
    options = options || {};
    var pasteTarget = util.paste.getTarget(range);
    if (!pasteTarget) {
      return false;
    }
    var paragraphs = [];
    var pastingInLi = goog.dom.getAncestor(pasteTarget, dom.isLi, true);
    var pastingInTable = goog.dom.getAncestor(pasteTarget, dom.isTable, true);
    var pastingInCodeBlock = goog.dom.getAncestor(pasteTarget, dom.isCodeBlock, true);
    var pastingInCrypt = goog.dom.getAncestor(pasteTarget, dom.isRevealedCrypt, true);
    var pastingInTodo = util.paragraph.startsWithTodo(pasteTarget);
    options.cursorPosition = getCursorPosition(range);
    options.alignment = pasteTarget.style.textAlign;
    setStyles(clipboardContent, options);
    if (pastingInTable && (clipboardContent.childNodes.length > 1 || !dom.isEntable(clipboardContent.firstChild))) {
      var tables = clipboardContent.querySelectorAll("en-table");
      goog.array.forEach(tables, plainifyTable);
    }
    goog.array.forEach(clipboardContent.childNodes, function(child, index) {
      if (pastingInLi && (dom.isUl(child) || dom.isOl(child))) {
        goog.array.forEach(child.childNodes, function(li) {
          paragraphs.push(li);
        });
      } else {
        if ((pastingInCodeBlock || pastingInCrypt) && dom.isCodeBlock(child)) {
          paragraphs = paragraphs.concat(plainifyCodeBlock(child));
        } else {
          if (dom.isRevealedCrypt(child)) {
            paragraphs = paragraphs.concat(plainifyCrypt(child));
          } else {
            if (options.alignment) {
              child.style.textAlign = options.alignment;
            }
            if (pastingInTodo) {
              if (index === 0) {
                var todo = util.paragraph.getLeadingTodo(child);
                if (todo && !options.cursorPosition.beginingOfLine) {
                  goog.dom.removeNode(todo);
                }
              } else {
                if (!util.paragraph.startsWithTodo(child)) {
                  util.todo.addTodoToParagraph(child);
                }
              }
            }
            paragraphs.push(child);
          }
        }
      }
    });
    if (pastingInTable && paragraphs.length === 1 && dom.isEntable(paragraphs[0])) {
      var table = paragraphs[0].querySelector("table");
      return mergeTables(pasteTarget, table, range);
    }
    return mergeContent(pasteTarget, paragraphs, range, options);
  };
  util.paste.getTarget = function(range) {
    if (!range) {
      return false;
    }
    var node = util.range.boundary(range.getStartNode(), range.getStartOffset()) || range.getStartNode();
    if (dom.isEnnote(node)) {
      return false;
    }
    var paragraph = goog.dom.getAncestor(node, dom.isBlockNode, true);
    if (dom.isEnnote(paragraph) || dom.isHr(paragraph)) {
      var siblings = dom.contiguousInlineSiblings(node);
      paragraph = goog.dom.createDom("div");
      goog.dom.insertSiblingBefore(paragraph, node);
      siblings.forEach(function(sibling) {
        paragraph.appendChild(sibling);
      });
    }
    return paragraph;
  };
  function plainifyCodeBlock(node) {
    return goog.array.toArray(node.childNodes);
  }
  function plainifyCrypt(node) {
    return goog.array.toArray(node.childNodes);
  }
  function plainifyTable(table) {
    if (!table) {
      return;
    }
    var trs = goog.array.toArray(table.querySelectorAll("tr"));
    var content = goog.dom.createDom("div");
    goog.array.forEach(trs, function(tr) {
      var tds = tr.querySelectorAll("td");
      goog.array.forEach(tds, function(td) {
        goog.array.forEach(td.childNodes, function(paragraph) {
          if (paragraph.innerHTML === "<br>") {
            return;
          }
          content.appendChild(paragraph);
        });
      });
      var blankLine = goog.dom.createDom("div");
      blankLine.innerHTML = "<br>";
      content.appendChild(blankLine);
    });
    goog.dom.replaceNode(content, table);
    goog.dom.flattenElement(content);
  }
  function getCursorPosition(range) {
    var node = range.getStartNode();
    var offset = range.getStartOffset();
    var position = {beginingOfLine:false};
    if (dom.isTextNode(node)) {
      if (!node.parentNode.previousSibling && offset === 0) {
        position.beginingOfLine = true;
      }
    } else {
      if (offset === 0) {
        position.beginingOfLine = true;
      }
    }
    return position;
  }
  function isObject(node) {
    return dom.isEntable(node) || dom.isHeader(node) || dom.isTable(node) || dom.isCodeBlock(node) || dom.isBlockquote(node) || dom.isRevealedCrypt(node) || dom.isUl(node) || dom.isOl(node);
  }
  function stripStyles(clipboardContent) {
    goog.array.forEach(clipboardContent.querySelectorAll("*"), function(node) {
      if (node.removeAttribute) {
        node.removeAttribute("style");
      }
      if (node.tagName.match(/h[1-9]{1}/i)) {
        dom.changeTagName(node, "div");
      }
    });
  }
  function setStyles(clipboardContent, options) {
    if (options.matchStyle) {
      stripStyles(clipboardContent);
    }
    var currentStyles = util.styles.toStyleObject(options.currentStyles, options.defaultStyles);
    var paragraphs = util.paragraph.all(clipboardContent);
    goog.array.forEach(paragraphs, function(paragraph) {
      goog.array.forEach(paragraph.childNodes, function(child) {
        if (util.table.for(child)) {
          return;
        }
        var sourceStyle = {};
        if (!options.matchStyle) {
          sourceStyle = util.styles.getNodeStyle(child);
        }
        if (!options.enclipboard) {
        }
        Object.keys(currentStyles).forEach(function(key) {
          var value = currentStyles[key];
          if (value && (options.matchStyle || !options.enclipboard && !sourceStyle[key])) {
            sourceStyle[key] = value;
          }
        });
        var styles = util.styles.getStyleString(sourceStyle);
        if (styles) {
          if (dom.isTextNode(child)) {
            var node = goog.dom.createDom("span", null, child.textContent);
            child.parentNode.replaceChild(node, child);
            child = node;
          }
          child.setAttribute("style", styles);
        } else {
          if (!dom.isTextNode(child)) {
            child.removeAttribute("style");
          }
        }
      });
    });
  }
  function mergeContent(pasteTarget, paragraphs, range, options) {
    if (!paragraphs.length) {
      return false;
    }
    var shouldSplit = !!(paragraphs.length > 1 || isObject(paragraphs[0]));
    var pastingInList = goog.dom.getAncestor(pasteTarget, dom.isLi, true);
    var firstParagraph = paragraphs.shift();
    var lastParagraph = paragraphs.length ? paragraphs.pop() : null;
    var lastWord = dom.getLastParagraphItem(lastParagraph || firstParagraph);
    var placeholder = goog.dom.createTextNode("");
    if (dom.isEmpty(pasteTarget)) {
      pasteTarget.innerHTML = "";
      pasteTarget.appendChild(placeholder);
    } else {
      var targetLastWord = dom.getLastParagraphItem(pasteTarget);
      if (dom.isBr(targetLastWord)) {
        goog.dom.removeNode(targetLastWord);
      }
      range.insertNode(placeholder);
      if (!goog.dom.contains(pasteTarget, placeholder)) {
        if (options.cursorPosition.beginingOfLine) {
          goog.dom.insertChildAt(pasteTarget, placeholder, 0);
        } else {
          pasteTarget.appendChild(placeholder);
        }
      }
    }
    if (shouldSplit) {
      var restOfParagraph = goog.editor.node.splitDomTreeAt(placeholder, null, pasteTarget);
      var lastItemInserted = pasteTarget;
      if (isObject(firstParagraph)) {
        goog.dom.insertSiblingAfter(firstParagraph, pasteTarget);
        goog.dom.removeNode(placeholder);
        lastItemInserted = firstParagraph;
        if (dom.isEmpty(pasteTarget)) {
          goog.dom.removeNode(pasteTarget);
        }
      } else {
        goog.dom.insertSiblingAfter(firstParagraph, placeholder);
        goog.dom.flattenElement(firstParagraph);
        goog.dom.removeNode(placeholder);
      }
      if (lastParagraph) {
        if (isObject(lastParagraph)) {
          goog.dom.insertSiblingAfter(lastParagraph, lastItemInserted);
          if (!dom.isEmpty(restOfParagraph)) {
            goog.dom.insertSiblingAfter(restOfParagraph, lastParagraph);
          }
        } else {
          goog.dom.insertSiblingAfter(restOfParagraph, lastItemInserted);
          if (dom.isEmpty(restOfParagraph)) {
            restOfParagraph.appendChild(lastParagraph);
          } else {
            goog.dom.insertSiblingBefore(lastParagraph, restOfParagraph.firstChild);
          }
          goog.dom.flattenElement(lastParagraph);
        }
      } else {
        if (!dom.isEmpty(restOfParagraph)) {
          goog.dom.insertSiblingAfter(restOfParagraph, lastItemInserted);
        }
      }
      while (paragraphs.length) {
        var node = paragraphs.shift();
        if (pastingInList && dom.isDiv(node)) {
          node = dom.changeTagName(node, "li");
        }
        goog.dom.insertSiblingAfter(node, lastItemInserted);
        lastItemInserted = node;
      }
      if (lastWord && lastWord.parentNode) {
        goog.editor.range.placeCursorNextTo(lastWord);
      }
    } else {
      goog.dom.replaceNode(firstParagraph, placeholder);
      goog.dom.flattenElement(firstParagraph);
    }
    if (lastWord && lastWord.parentNode) {
      return goog.editor.range.placeCursorNextTo(lastWord);
    }
    return false;
  }
  function mergeTables(pasteTarget, clipboardTable) {
    var td = goog.dom.getAncestor(pasteTarget, dom.isTd, true);
    var table = goog.dom.getAncestor(td, dom.isTable);
    var enTable = goog.dom.getAncestor(table, dom.isEntable);
    if (!enTable || !td) {
      return null;
    }
    var clipMatrix = util.table.matrix(clipboardTable);
    var matrix = util.table.matrix(table);
    var startRowIndex = util.table.rowIndex(td, false, matrix);
    var startColIndex = util.table.colIndex(td, false, matrix);
    var endRowIndex = startRowIndex + clipMatrix.length - 1;
    var endColIndex = startColIndex + clipMatrix[0].length - 1;
    var rowAddCount = Math.max(0, endRowIndex - (matrix.length - 1));
    var colAddCount = Math.max(0, endColIndex - (matrix[0].length - 1));
    var unmerged = false;
    var needfill = false;
    if (rowAddCount || colAddCount) {
      if (rowAddCount) {
        util.table.insertRows(enTable, matrix.length, rowAddCount);
      }
      if (colAddCount) {
        util.table.insertColumns(enTable, matrix[0].length, colAddCount);
      }
      matrix = util.table.matrix(table);
    }
    for (var r = endRowIndex; r >= startRowIndex; r--) {
      for (var c = endColIndex; c >= startColIndex; c--) {
        var info = matrix[r][c].info;
        var node = info.node;
        if (info.startRowIndex === r && info.startColIndex === c) {
          util.table.splitCell(node, matrix);
          unmerged = true;
          continue;
        }
        if (info.startRowIndex !== r && r === startRowIndex) {
          util.table.setRowSpan(node, r - info.startRowIndex);
          unmerged = true;
          needfill = true;
        }
        if (info.startColIndex !== c && c === startColIndex) {
          util.table.setColSpan(node, c - info.startColIndex);
          unmerged = true;
          needfill = true;
        }
      }
    }
    if (needfill) {
      matrix = util.table.matrix(table);
      matrix.forEach(function(row, rowIndex) {
        for (var colIndex = 0; colIndex < matrix[0].length; colIndex++) {
          if (row[colIndex] === undefined) {
            util.table.insertTd(util.table.createEmptyTd(), rowIndex, colIndex, table, matrix);
          }
        }
      });
    }
    if (unmerged) {
      matrix = util.table.matrix(table);
    }
    goog.array.forEachRight(clipMatrix, function(row, rowIndex) {
      goog.array.forEachRight(row, function(obj, colIndex) {
        var info = obj.info;
        if (info.startRowIndex !== rowIndex || info.startColIndex !== colIndex) {
          return;
        }
        var relativeRowIndex = rowIndex + startRowIndex;
        var relativeColIndex = colIndex + startColIndex;
        var targetTd;
        if (info.state & util.table.State.MERGED) {
          var rowOffset = info.endRowIndex - info.startRowIndex;
          var colOffset = info.endColIndex - info.startColIndex;
          var nodes = [];
          for (var r = relativeRowIndex; r <= relativeRowIndex + rowOffset; r++) {
            for (var c = relativeColIndex; c <= relativeColIndex + colOffset; c++) {
              nodes.push(matrix[r][c].info.node);
            }
          }
          targetTd = util.table.mergeCells(nodes);
        } else {
          targetTd = matrix[rowIndex + startRowIndex][colIndex + startColIndex].info.node;
        }
        targetTd.innerHTML = info.node.innerHTML;
        targetTd.style.backgroundColor = info.node.style.backgroundColor;
      });
    });
    var leaf = dom.getLastParagraphItem(matrix[endRowIndex][endColIndex].info.node);
    if (leaf) {
      goog.editor.range.placeCursorNextTo(leaf);
    }
    return goog.dom.Range.createFromNodes(enTable, 0, enTable, enTable.childNodes.length);
  }
})();
goog.provide("uno.util.paste.plain");
(function() {
  var util = uno.util;
  util.paste.plain.getContent = function(content) {
    return content.split("\n").map(function(line) {
      var value = goog.string.htmlEscape(line).replace(/\t/gi, uno.defs.tab.CHARACTER_SEQUENCE).replace(/[ \t]{2,}/gi, function(match) {
        var nbsp = String.fromCharCode(160);
        var result = "";
        for (var i = 0; i < match.length; i++) {
          result += nbsp;
        }
        return result;
      });
      if (!value) {
        value = "<br>";
      }
      return "<div>" + value + "</div>";
    }).join("");
  };
})();
goog.provide("uno.commands.Paste");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.img");
goog.require("uno.util.paste");
goog.require("uno.util.paste.plain");
goog.require("uno.util.table.selection");
goog.require("uno.util.normalize");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Paste");
  var util = uno.util;
  var dom = util.dom;
  var Paste = uno.commands.Paste = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Paste, uno.BasePlugin);
  Paste.prototype.isSupportedCommand = function(command) {
    return command === "paste" || command === "pasteplain";
  };
  Paste.prototype.queryCommandValue = function() {
    return true;
  };
  Paste.prototype.execCommand = function(command, opt) {
    var editor = this.editor;
    var range = editor.getRange();
    if (!editor.multirange.isEmpty()) {
      var pasteCell = util.table.selection.getPasteCell();
      if (!pasteCell) {
        return false;
      }
      util.table.selection.clear();
      pasteCell.innerHTML = uno.defs.table.CELL_HTML;
      goog.editor.range.selectNodeStart(pasteCell);
    }
    if (!range) {
      editor.placeCursorAtEnd();
      range = editor.getRange();
      if (!range) {
        return false;
      }
    }
    if (!range.isCollapsed()) {
      editor.execCommand("delete", "selection", {smart:false});
      range = editor.getRange();
    }
    var options = goog.isObject(opt) ? opt : {value:goog.isString(opt) ? opt : "", type:"html", matchStyle:false, resources:[]};
    editor.context.format = uno.defs.format.CLIPBOARD;
    if (!options.value) {
      return false;
    }
    (options.resources || []).forEach(function(res) {
      editor.context.resources[res.id] = res;
    });
    editor.dispatchBeforeChange();
    if (options.type === "plain") {
      options.value = util.paste.plain.getContent(options.value);
    }
    var matchStyle = options.matchStyle === true;
    var clipboardRegex = /-en-clipboard:\s*true;/g;
    var enclipboard = clipboardRegex.test(options.value);
    var value = "<div>" + options.value.replace(clipboardRegex, "") + "</div>";
    var variantSelectorRegex = /[\uFE00-\uFE0F]/g;
    value = value.replace(variantSelectorRegex, "");
    editor.context.copyPaste.externalContent = !enclipboard;
    var cleanedContent = editor.prepareContentsHtml.call(editor, value, {});
    var clipboardContent = dom.nodeFromHtml(cleanedContent);
    var currentStyles = {};
    goog.object.extend(currentStyles, editor.context.style.state, editor.context.style.value);
    var pasteRange = util.paste.paste(clipboardContent, editor.getRange(), {editor:editor, enclipboard:enclipboard, matchStyle:matchStyle, currentStyles:currentStyles, defaultStyles:{richTextFont:editor.config.defaults.richTextFont, fontName:editor.config.defaults.fontFamily, fontSize:editor.config.defaults.fontSize, fontColor:editor.config.defaults.foreColor}});
    editor.field.normalize();
    editor.dispatchChange();
    util.range.scrollSelectionIntoView(editor);
    if (pasteRange) {
      this.dispatchEvent({type:uno.Editor.EventType.DOM_UPDATE, range:pasteRange, paste:true});
    }
    return true;
  };
})();
goog.provide("uno.commands.PlainText");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.PlainText");
  var PlainText = uno.commands.PlainText = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(PlainText, uno.BasePlugin);
  PlainText.prototype.isSupportedCommand = function(command) {
    return command === "plaintext";
  };
  PlainText.prototype.activeOnUneditableFields = goog.functions.TRUE;
  PlainText.prototype.execCommandInternal = function() {
    this.editor.enterEditMode(true);
    this.editor.execCommand("selectall");
    var copyResults = this.editor.queryCommandValue("copy");
    this.editor.field.innerHTML = "";
    var plainText = goog.string.htmlEscape(copyResults.plain).replace(/  /g, " &nbsp;").split("\n").map(function(line) {
      return "<div>" + (line.trim() ? line : "<br>") + "</div>";
    }).join("\n");
    this.editor.setHtml(false, plainText);
    this.editor.execCommand("selectall");
    this.editor.execCommand("fontname", this.editor.config.defaults.plainTextFont);
    this.editor.placeCursorAtEnd();
    return true;
  };
})();
goog.provide("uno.commands.PrintPreview");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.classlist");
goog.require("goog.functions");
goog.require("goog.object");
goog.require("goog.array");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.todo");
(function() {
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.commands.PrintPreview");
  var previousPreviewContainer;
  var PrintPreview = uno.commands.PrintPreview = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(PrintPreview, uno.BasePlugin);
  PrintPreview.CONTAINER_ID = "print-container";
  PrintPreview.HEADER_TITLE_ID = "header-title";
  PrintPreview.HEADER_TABLE_ID = "header-table";
  PrintPreview.HEADER_LABEL_CLASS = "header-table-label";
  PrintPreview.HEADER_TEXT_CLASS = "header-table-text";
  PrintPreview.PRINT_INSERT_CLASS = "en-print";
  PrintPreview.CHECKBOX_CLASS = "checkbox";
  PrintPreview.CHECKED_CLASS = "checked";
  PrintPreview.PDF_CLASS = "pdf";
  PrintPreview.AUDIO_CLASS = "audio";
  PrintPreview.GENERIC_ATTACHMENT_CLASS = "generic-attachment";
  PrintPreview.prototype.isSupportedCommand = function(command) {
    return command === "printpreview";
  };
  PrintPreview.prototype.activeOnUneditableFields = goog.functions.TRUE;
  PrintPreview.prototype.execCommand = function(command, localization, options) {
    var previewContainer = goog.dom.createDom("div", {id:PrintPreview.CONTAINER_ID, class:PrintPreview.PRINT_INSERT_CLASS});
    var parsedLocalization = parseLocalization(localization);
    var parsedOptions = options && parseOptions(options);
    var addMetadata = !!parsedOptions && Object.keys(parsedOptions).some(function(key) {
      return key !== "title" && parsedOptions[key] != null;
    });
    if (addMetadata) {
      var metaDataHeader = generateMetadataHeader(parsedOptions, parsedLocalization);
      previewContainer.appendChild(metaDataHeader);
      var hr = goog.dom.createDom("hr");
      previewContainer.appendChild(hr);
      previewContainer.appendChild(createGap());
    }
    var titleText = parsedOptions && parsedOptions.title;
    if (titleText) {
      var title = createTitle(titleText);
      previewContainer.appendChild(title);
      previewContainer.appendChild(createGap());
    }
    var note = copyNote(this.editor.field);
    replaceEmbeds(note, parsedLocalization);
    replaceTodos(note);
    previewContainer.innerHTML = previewContainer.innerHTML + note.innerHTML;
    goog.dom.replaceNode(previewContainer, previousPreviewContainer || this.editor.field);
    previousPreviewContainer = previewContainer;
    this.editor.dispatchEvent("printReady");
    return true;
  };
  PrintPreview.prototype.queryCommandValue = function() {
  };
  function generateMetadataHeader(options, localization) {
    var table, tr, td, row, col, toInsert, tds, span1, span2;
    table = goog.dom.createDom("table", {id:PrintPreview.HEADER_TABLE_ID, class:PrintPreview.PRINT_INSERT_CLASS});
    for (row = 0; row < 4; row++) {
      tr = goog.dom.createDom("tr");
      table.appendChild(tr);
      for (col = 0; col < 2; col++) {
        td = goog.dom.createDom("td");
        tr.appendChild(td);
      }
    }
    toInsert = [[localization.author, "author"], [localization.notebook, "notebook"], [localization.created, "created"], [localization.tags, "tags"], [localization.updated, "updated"], [localization.url, "url"], [localization.deleted, "deleted"], [localization.location, "location"]];
    tds = table.querySelectorAll("td");
    toInsert.forEach(function(data, i) {
      if (options[data[1]] === null) {
        return;
      }
      tds[i].innerHTML = "";
      span1 = goog.dom.createDom("span", {class:PrintPreview.HEADER_LABEL_CLASS});
      span1.textContent = data[0];
      span2 = goog.dom.createDom("span", {class:PrintPreview.HEADER_TEXT_CLASS});
      span2.textContent = " " + options[data[1]];
      tds[i].appendChild(span1);
      tds[i].appendChild(span2);
    });
    return table;
  }
  function parseOptions(options) {
    var defaultOptions = {title:null, notebook:null, created:null, updated:null, deleted:null, author:null, location:null, tags:null, url:null};
    var parsedOptions = goog.object.clone(options || {});
    goog.object.extend(defaultOptions, parsedOptions);
    return defaultOptions;
  }
  function parseLocalization(localization) {
    var defaultLocalization = {notebook:"Notebook:", created:"Created:", updated:"Updated:", deleted:"Deleted:", author:"Author:", location:"Location:", tags:"Tags:", url:"Source:", pdf_file:"PDF File", audio_file:"Audio File", generic_file:"Generic File"};
    var parsedLocalization = goog.object.clone(localization || {});
    goog.object.extend(defaultLocalization, parsedLocalization);
    return defaultLocalization;
  }
  function createGap() {
    return goog.dom.createDom("br", {class:PrintPreview.PRINT_INSERT_CLASS});
  }
  function createTitle(title) {
    var header = goog.dom.createDom("div", {id:PrintPreview.HEADER_TITLE_ID, class:PrintPreview.PRINT_INSERT_CLASS});
    header.textContent = title;
    return header;
  }
  function copyNote(noteElement) {
    if (!noteElement) {
      log.warning("Could not find note!");
      return document.createElement("div");
    }
    goog.array.forEach(noteElement.childNodes, function(node) {
      if (node.nodeType !== Node.TEXT_NODE) {
        goog.dom.classlist.add(node, PrintPreview.PRINT_INSERT_CLASS);
      }
    });
    return noteElement;
  }
  function replaceEmbeds(note, localization) {
    goog.array.forEach(note.querySelectorAll("embed"), function(embed) {
      var replacement = goog.dom.createDom("div", {class:PrintPreview.PRINT_INSERT_CLASS});
      switch(embed.getAttribute("type")) {
        case "evernote/x-pdf":
          goog.dom.classlist.add(replacement, PrintPreview.PDF_CLASS);
          replacement.textContent = localization.pdf_file;
          break;
        case "evernote/x-attachment":
          var id = embed.getAttribute("id");
          if (id && id.match(/.*en-media:audio.*/)) {
            goog.dom.classlist.add(replacement, PrintPreview.AUDIO_CLASS);
            replacement.textContent = localization.audio_file;
          } else {
            goog.dom.classlist.add(replacement, PrintPreview.GENERIC_ATTACHMENT_CLASS);
            replacement.textContent = localization.generic_file;
          }
          break;
        default:
          log.warning("Found <embed> with unknown type! " + embed);
          goog.dom.classlist.add(replacement, PrintPreview.GENERIC_ATTACHMENT_CLASS);
          replacement.textContent = localization.generic_file;
      }
      goog.dom.replaceNode(replacement, embed);
    });
  }
  function replaceTodos(note) {
    goog.array.forEach(util.todo.all(note), function(todo) {
      var replacement = goog.dom.createDom("div", {class:PrintPreview.PRINT_INSERT_CLASS + " " + PrintPreview.CHECKBOX_CLASS});
      if (util.todo.isChecked(todo)) {
        goog.dom.classlist.add(replacement, PrintPreview.CHECKED_CLASS);
      }
      goog.dom.replaceNode(replacement, todo);
    });
  }
})();
goog.provide("uno.commands.Redo");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Redo");
  var Redo = uno.commands.Redo = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Redo, uno.BasePlugin);
  Redo.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Redo.prototype.isSupportedCommand = function(command) {
    return command === "redo";
  };
  Redo.prototype.execCommand = function() {
    return this.editor.execCommand(goog.editor.Command.REDO);
  };
  Redo.prototype.queryCommandValue = function() {
    return !!this.editor.queryCommandValue(goog.editor.Command.REDO);
  };
})();
goog.provide("uno.commands.RemoveFormat");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.normalize");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.RemoveFormat");
  var util = uno.util;
  var RemoveFormat = uno.commands.RemoveFormat = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(RemoveFormat, uno.BasePlugin);
  RemoveFormat.prototype.isSupportedCommand = function(command) {
    return command === "removeformat";
  };
  RemoveFormat.prototype.activeOnUneditableFields = goog.functions.TRUE;
  RemoveFormat.prototype.execCommandInternal = function() {
    var editor = this.editor;
    var range = editor.getRange();
    var container = (!range || range.isCollapsed()) && editor.multirange.isEmpty() ? editor.field : range.getContainer();
    if (util.dom.isTextNode(container)) {
      container = container.parentNode;
    }
    if (range && !range.isCollapsed() && container === editor.field) {
      goog.array.forEachRight(container.childNodes, function(child) {
        if (range.containsNode(child, true)) {
          if (util.dom.isTextNode(child)) {
            child = child.parentNode;
          }
          util.normalize.normalizeNode(child, {cleanUX:true, editor:editor, removeFormat:true});
        }
      });
    } else {
      util.normalize.normalizeNode(container, {cleanUX:true, editor:editor, removeFormat:true});
    }
    return true;
  };
})();
goog.provide("uno.commands.Resources");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.img");
goog.require("uno.util.resource");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Resources");
  var util = uno.util;
  var Resources = uno.commands.Resources = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Resources, uno.BasePlugin);
  Resources.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Resources.prototype.isSupportedCommand = function(command) {
    return command === "resources";
  };
  Resources.prototype.execCommand = function(command, value) {
    var me = this;
    var editor = this.editor;
    var startedInEditMode = editor.inEditMode();
    var hasChanges;
    var hasInserts = false;
    if (!goog.isArray(value)) {
      value = [value];
    }
    hasChanges = value.some(function(dict) {
      if (dict.action === "insert" || dict.action === "delete") {
        return true;
      } else {
        if (dict.action === "update") {
          return goog.array.some(me.findElementsForDict(dict), function(el) {
            var existing = util.resource.dictFromElement(el);
            return dict.filename != null && dict.filename !== existing.filename || dict.filesize != null && dict.filesize !== existing.filesize || dict.hash != null && dict.hash !== existing.hash || dict.mime != null && dict.mime !== existing.mime || dict.url != null && dict.url !== existing.url;
          });
        }
      }
    });
    hasInserts = value.some(function(dict) {
      return dict.action === "insert";
    });
    if (hasChanges) {
      editor.dispatchBeforeChange();
    }
    if (!startedInEditMode && hasInserts) {
      editor.enterEditMode(true);
    }
    var additions = [];
    value.forEach(function(dict) {
      if (dict.action === "insert") {
        if (dict.pos === "bottom") {
          editor.placeCursorAtEnd();
        }
        additions.push(me.add(dict));
      } else {
        if (dict.action === "update") {
          me.update(dict);
        } else {
          if (dict.action === "delete") {
            me.remove(dict);
          }
        }
      }
    });
    if (additions.length > 0) {
      var scrollTarget = additions[additions.length - 1];
      var scrollAfterLoad = util.resource.isImage(scrollTarget);
      var promises = additions.filter(util.resource.isImage).map(util.img.ratioResizeIfNeeded);
      Promise.all(promises).then(function(resizes) {
        if (resizes.indexOf(true) > -1) {
          editor.dispatchChange();
        }
        if (scrollAfterLoad) {
          goog.editor.range.placeCursorNextTo(scrollTarget);
          scrollTarget.scrollIntoView();
        }
      });
      if (!scrollAfterLoad) {
        goog.editor.range.placeCursorNextTo(scrollTarget);
        scrollTarget.scrollIntoView();
      }
    }
    if (!startedInEditMode && hasInserts) {
      editor.blur();
    }
    if (hasChanges) {
      editor.dispatchChange();
    }
    return hasChanges;
  };
  Resources.prototype.add = function(dict) {
    var editor = this.editor;
    var enmedia = util.resource.createMediaFromDict(dict);
    var slug = util.resource.convertMediaToSlug(enmedia, dict, editor);
    var range = editor.getRange();
    var ref = dict.beforeRef || dict.afterRef;
    var refNode = dict.beforeRef || dict.afterRef ? util.resource.findByRef(ref, editor.field) : null;
    if (refNode) {
      if (dict.beforeRef) {
        goog.dom.insertSiblingBefore(slug, refNode);
      } else {
        goog.dom.insertSiblingAfter(slug, refNode);
      }
    } else {
      if (range && !util.dom.isEmpty(util.paragraph.for(range.getStartNode()))) {
        editor.execCommand("insertparagraph");
      }
      switch(dict.justify) {
        case "left":
        case "center":
        case "right":
          editor.execCommand("justify" + dict.justify);
          break;
        default:
      }
      range = editor.getRange();
      range.insertNode(slug);
    }
    return slug;
  };
  Resources.prototype.update = function(dict) {
    var elements;
    var enmedia;
    var slug;
    var editor = this.editor;
    elements = this.findElementsForDict(dict);
    goog.array.forEach(elements, function(el) {
      var combodict = {};
      goog.object.extend(combodict, util.resource.dictFromElement(el), dict);
      enmedia = util.resource.createMediaFromDict(combodict);
      slug = util.resource.convertMediaToSlug(enmedia, combodict, editor);
      goog.dom.replaceNode(slug, el);
    });
  };
  Resources.prototype.remove = function(dict) {
    var elements = this.findElementsForDict(dict);
    goog.array.forEach(elements, function(el) {
      var par = util.paragraph.for(el);
      goog.dom.removeNode(el);
      if (util.dom.isEmpty(par)) {
        par.innerHTML = "<br>";
      }
    });
  };
  Resources.prototype.findElementsForDict = function(dict) {
    var elements;
    var el;
    if (dict.reference) {
      el = util.resource.findByRef(dict.reference, this.editor.field);
      elements = [];
      if (el) {
        elements.push(el);
      }
    } else {
      if (dict.originalURL) {
        elements = util.resource.findByURL(dict.originalURL, this.editor.field);
      } else {
        elements = util.resource.findByHash(dict.hash, this.editor.field);
      }
    }
    return elements;
  };
  Resources.prototype.queryCommandValue = function(command, opt) {
    var editor = this.editor;
    var range = editor.getRange();
    var sibling;
    var list = goog.array.map(util.resource.all(editor.field), function(el) {
      var dict = util.resource.toDict(el, range);
      if (opt === "neighbors") {
        sibling = el.previousElementSibling;
        if (util.resource.isResource(sibling)) {
          dict.prevNeighbour = util.resource.toDict(sibling, range);
        }
        sibling = el.nextElementSibling;
        if (util.resource.isResource(sibling)) {
          dict.nextNeighbour = util.resource.toDict(sibling, range);
        }
      }
      return dict;
    });
    return list;
  };
})();
goog.provide("uno.commands.RichlinksConvert");
goog.require("uno.BasePlugin");
goog.require("uno.util.richlink");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.RichlinksConvert");
  var RichlinksConvert = uno.commands.RichlinksConvert = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(RichlinksConvert, uno.BasePlugin);
  RichlinksConvert.prototype.isSupportedCommand = function(command) {
    return command === "richlinks.convert";
  };
  RichlinksConvert.prototype.execCommandInternal = function() {
    uno.util.dom.queryReverse(uno.defs.richlink.ANCHOR_ELEMENT_SELECTOR, document.body).forEach(function(node) {
      uno.util.richlink.handleLink(node, true);
      RichlinksConvert.editor.dispatchEvent({type:uno.Editor.EventType.DELAYEDCHANGE});
    });
  };
})();
goog.provide("uno.commands.RichlinksRefresh");
goog.require("uno.BasePlugin");
goog.require("uno.util.richlink");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.RichlinksRefresh");
  var RichlinksRefresh = uno.commands.RichlinksRefresh = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(RichlinksRefresh, uno.BasePlugin);
  RichlinksRefresh.prototype.isSupportedCommand = function(command) {
    return command === "richlinks.refresh";
  };
  RichlinksRefresh.prototype.execCommandInternal = function() {
  };
})();
goog.provide("uno.commands.SelectAll");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.Range");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.SelectAll");
  var SelectAll = uno.commands.SelectAll = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(SelectAll, uno.BasePlugin);
  SelectAll.SELECTOR = "en-note";
  SelectAll.prototype.isSupportedCommand = function(command) {
    return command === "selectall";
  };
  SelectAll.prototype.activeOnUneditableFields = goog.functions.TRUE;
  SelectAll.prototype.execCommand = function() {
    var contentElement = goog.dom.getElement(SelectAll.SELECTOR);
    var range = goog.dom.Range.createFromNodeContents(contentElement);
    range.select();
    return true;
  };
  SelectAll.prototype.queryCommandValue = function() {
  };
})();
goog.provide("uno.commands.Selection");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Selection");
  var util = uno.util;
  var Selection = uno.commands.Selection = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Selection, uno.BasePlugin);
  Selection.prototype.isSupportedCommand = function(command) {
    return command === "selection";
  };
  Selection.prototype.execCommand = function(command, selectionPath) {
    try {
      var path = selectionPath;
      var startNode = getNodeFromPath(this.editor.field, path.startNode);
      var endNode = getNodeFromPath(this.editor.field, path.endNode);
      var range = goog.dom.Range.createFromNodes(startNode, path.startOffset, endNode, path.endOffset);
      this.editor.restoreRange(range);
      return true;
    } catch (err$11) {
      log.warning("could not restore the range");
      log.fine(err$11.stack || err$11);
      return false;
    }
  };
  Selection.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    if (range) {
      var path = {startNode:getNodePath(range.getStartNode()), endNode:getNodePath(range.getEndNode()), startOffset:range.getStartOffset(), endOffset:range.getEndOffset(), collapsed:range.isCollapsed()};
      return path;
    }
    return "";
  };
  function getNodePath(node) {
    var path = [];
    goog.dom.getAncestor(node, function(element) {
      if (util.dom.isEnnote(element)) {
        return true;
      }
      path.unshift(util.dom.index(element));
      return false;
    }, true);
    return path;
  }
  function getNodeFromPath(root, path) {
    var node = root;
    path.forEach(function(index) {
      if (node.childNodes) {
        node = node.childNodes[index];
      }
    });
    return node;
  }
})();
goog.provide("uno.commands.SimpleText");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.functions");
goog.require("goog.editor.range");
goog.require("goog.style");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.n3");
goog.require("uno.util.range");
goog.require("uno.util.table.selection");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.SimpleText");
  var util = uno.util;
  var SimpleText = uno.commands.SimpleText = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(SimpleText, uno.BasePlugin);
  SimpleText.prototype.isSupportedCommand = function(command) {
    return command === "simpletext";
  };
  SimpleText.prototype.activeOnUneditableFields = goog.functions.TRUE;
  SimpleText.prototype.execCommandInternal = function() {
    var editor = this.editor;
    var range = editor.getRange();
    var container = (!range || range.isCollapsed()) && editor.multirange.isEmpty() ? editor.field : range.getContainer();
    if (util.dom.isTextNode(container)) {
      container = container.parentNode;
    }
    uno.util.table.selection.clear();
    if (range && !range.isCollapsed() && container === editor.field) {
      goog.array.forEachRight(container.childNodes, function(child) {
        if (range.containsNode(child, true)) {
          if (util.dom.isTextNode(child)) {
            child = child.parentNode;
          }
          util.n3.normalizeNode(child, {cleanUX:true, editor:editor, simplifyFormat:true});
        }
      });
    } else {
      util.n3.normalizeNode(container, {cleanUX:true, editor:editor, simplifyFormat:true});
    }
    return true;
  };
})();
goog.provide("uno.util.link");
goog.require("goog.debug.Logger");
(function() {
  var util = uno.util;
  util.link.all = function(root) {
    return root.querySelectorAll("a[href]");
  };
})();
goog.provide("uno.commands.Stats");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.link");
goog.require("uno.util.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Stats");
  var util = uno.util;
  var Stats = uno.commands.Stats = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Stats, uno.BasePlugin);
  Stats.prototype.isSupportedCommand = function(command) {
    return command === "stats";
  };
  Stats.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Stats.prototype.queryCommandEnabled = goog.functions.TRUE;
  Stats.prototype.queryCommandValue = function() {
    var stats = {};
    stats.isEmpty = util.dom.isEmpty(this.editor.field);
    stats.isDirty = this.editor.queryCommandValue("changes");
    stats.isReadOnly = this.editor.readOnly;
    stats.isEditable = this.editor.inEditMode();
    stats.hasFocus = this.editor.isFocused();
    stats.todo = util.todo.all(this.editor.field).length;
    stats.link = util.link.all(this.editor.field).length;
    stats.firstLine = this.editor.field.innerText.trim().split("\n").shift();
    stats.selection = this.editor.queryCommandValue("selection");
    stats.lastSelection = null;
    return stats;
  };
})();
goog.provide("uno.commands.Strikethrough");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.range");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Strikethrough");
  var Strikethrough = uno.commands.Strikethrough = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(Strikethrough, uno.BasePlugin);
  Strikethrough.prototype.isSupportedCommand = function(command) {
    return command === "strikethrough";
  };
  Strikethrough.prototype.execCommand = function() {
    var range = this.editor.getRange();
    var underlined = this.editor.context.style.state.underline;
    if (!range.isCollapsed()) {
      var result = this.editor.execCommand(goog.editor.Command.STRIKE_THROUGH);
      this.editor.dispatchChange();
      return result;
    }
    if (underlined) {
      document.execCommand("insertText", null, uno.defs.unicode.ZERO_WIDTH_SPACE);
      var updatedRange = this.editor.getRange();
      var node = updatedRange.getStartNode();
      var startOffset = updatedRange.getStartOffset();
      var newRange = goog.dom.Range.createFromNodes(node, startOffset - 1, node, startOffset);
      newRange.select();
      this.editor.execCommand(goog.editor.Command.STRIKE_THROUGH);
      newRange.collapse();
      newRange.select();
    } else {
      var currentState = this.editor.context.style.state.strikethrough;
      this.editor.execCommand(goog.editor.Command.STRIKE_THROUGH);
      this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:{state:{strikethrough:!currentState, underline:underlined}, value:{}, enabled:{}}});
    }
    return true;
  };
  Strikethrough.prototype.queryCommandValue = function() {
    return this.editor.queryCommandValue(goog.editor.Command.STRIKE_THROUGH);
  };
})();
goog.provide("uno.commands.Tab");
goog.require("goog.debug.Logger");
goog.require("goog.events.BrowserEvent");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Tab");
  var Tab = uno.commands.Tab = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Tab, uno.BasePlugin);
  Tab.prototype.isSupportedCommand = function(command) {
    return command === "tab";
  };
  Tab.prototype.execCommandInternal = function(command, options) {
    var event = document.createEvent("Event");
    var browserEvent = new goog.events.BrowserEvent(event);
    browserEvent.shiftKey = options === true;
    browserEvent.keyCode = goog.events.KeyCodes.TAB;
    this.editor.handleKeyDown_(browserEvent);
  };
  Tab.prototype.queryCommandValue = function() {
    return null;
  };
  Tab.prototype.queryCommandEnabled = function() {
    return true;
  };
})();
goog.provide("uno.commands.Underline");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.EditorMultiRange");
goog.require("uno.util.range");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Underline");
  var Underline = uno.commands.Underline = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(Underline, uno.BasePlugin);
  Underline.prototype.isSupportedCommand = function(command) {
    return command === "underline";
  };
  Underline.prototype.execCommand = function() {
    var range = this.editor.getRange();
    var strikethrough = this.editor.context.style.state.strikethrough;
    if (!range.isCollapsed()) {
      var result = this.editor.execCommand(goog.editor.Command.UNDERLINE);
      this.editor.dispatchChange();
      return result;
    }
    if (strikethrough) {
      document.execCommand("insertText", null, uno.defs.unicode.ZERO_WIDTH_SPACE);
      var updatedRange = this.editor.getRange();
      var node = updatedRange.getStartNode();
      var startOffset = updatedRange.getStartOffset();
      var newRange = goog.dom.Range.createFromNodes(node, startOffset - 1, node, startOffset);
      newRange.select();
      this.editor.execCommand(goog.editor.Command.UNDERLINE);
      newRange.collapse();
      newRange.select();
    } else {
      var currentState = this.editor.context.style.state.underline;
      this.editor.execCommand(goog.editor.Command.UNDERLINE);
      this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:{state:{underline:!currentState, strikethrough:strikethrough}, value:{}, enabled:{}}});
    }
    return true;
  };
  Underline.prototype.queryCommandValue = function() {
    return this.editor.queryCommandValue(goog.editor.Command.UNDERLINE);
  };
})();
goog.provide("uno.commands.Undo");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Undo");
  var Undo = uno.commands.Undo = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Undo, uno.BasePlugin);
  Undo.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Undo.prototype.isSupportedCommand = function(command) {
    return command === "undo";
  };
  Undo.prototype.execCommand = function() {
    return this.editor.execCommand(goog.editor.Command.UNDO);
  };
  Undo.prototype.queryCommandValue = function() {
    return !!this.editor.queryCommandValue(goog.editor.Command.UNDO);
  };
})();
goog.provide("goog.editor.plugins.UndoRedoState");
goog.require("goog.events.EventTarget");
goog.editor.plugins.UndoRedoState = function(asynchronous) {
  goog.editor.plugins.UndoRedoState.base(this, "constructor");
  this.asynchronous_ = asynchronous;
};
goog.inherits(goog.editor.plugins.UndoRedoState, goog.events.EventTarget);
goog.editor.plugins.UndoRedoState.ACTION_COMPLETED = "action_completed";
goog.editor.plugins.UndoRedoState.prototype.isAsynchronous = function() {
  return this.asynchronous_;
};
goog.editor.plugins.UndoRedoState.prototype.undo = goog.abstractMethod;
goog.editor.plugins.UndoRedoState.prototype.redo = goog.abstractMethod;
goog.editor.plugins.UndoRedoState.prototype.equals = goog.abstractMethod;
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");
goog.editor.plugins.UndoRedoManager = function() {
  goog.events.EventTarget.call(this);
  this.maxUndoDepth_ = 100;
  this.undoStack_ = [];
  this.redoStack_ = [];
  this.pendingActions_ = [];
};
goog.inherits(goog.editor.plugins.UndoRedoManager, goog.events.EventTarget);
goog.editor.plugins.UndoRedoManager.EventType = {STATE_CHANGE:"state_change", STATE_ADDED:"state_added", BEFORE_UNDO:"before_undo", BEFORE_REDO:"before_redo"};
goog.editor.plugins.UndoRedoManager.prototype.inProgressActionKey_ = null;
goog.editor.plugins.UndoRedoManager.prototype.setMaxUndoDepth = function(depth) {
  this.maxUndoDepth_ = depth;
};
goog.editor.plugins.UndoRedoManager.prototype.addState = function(state) {
  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();
    }
    var redoLength = this.redoStack_.length;
    this.redoStack_.length = 0;
    this.dispatchEvent({type:goog.editor.plugins.UndoRedoManager.EventType.STATE_ADDED, state:state});
    if (this.undoStack_.length == 1 || redoLength) {
      this.dispatchStateChange_();
    }
  }
};
goog.editor.plugins.UndoRedoManager.prototype.dispatchStateChange_ = function() {
  this.dispatchEvent(goog.editor.plugins.UndoRedoManager.EventType.STATE_CHANGE);
};
goog.editor.plugins.UndoRedoManager.prototype.undo = function() {
  this.shiftState_(this.undoStack_, this.redoStack_);
};
goog.editor.plugins.UndoRedoManager.prototype.redo = function() {
  this.shiftState_(this.redoStack_, this.undoStack_);
};
goog.editor.plugins.UndoRedoManager.prototype.hasUndoState = function() {
  return this.undoStack_.length > 0;
};
goog.editor.plugins.UndoRedoManager.prototype.hasRedoState = function() {
  return this.redoStack_.length > 0;
};
goog.editor.plugins.UndoRedoManager.prototype.shiftState_ = function(fromStack, toStack) {
  if (fromStack.length) {
    var state = fromStack.pop();
    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 (fromStack.length == 0 || toStack.length == 1) {
      this.dispatchStateChange_();
    }
  }
};
goog.editor.plugins.UndoRedoManager.prototype.addAction_ = function(action) {
  this.pendingActions_.push(action);
  if (this.pendingActions_.length == 1) {
    this.doAction_();
  }
};
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_();
    }
  }
};
goog.editor.plugins.UndoRedoManager.prototype.finishAction_ = function() {
  goog.events.unlistenByKey(this.inProgressActionKey_);
  this.inProgressActionKey_ = null;
  this.doAction_();
};
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_();
  }
};
goog.editor.plugins.UndoRedoManager.prototype.undoPeek = function() {
  return this.undoStack_[this.undoStack_.length - 1];
};
goog.editor.plugins.UndoRedoManager.prototype.redoPeek = function() {
  return this.redoStack_[this.redoStack_.length - 1];
};
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");
goog.editor.plugins.UndoRedo = function(opt_manager) {
  goog.editor.Plugin.call(this);
  this.setUndoRedoManager(opt_manager || new goog.editor.plugins.UndoRedoManager);
  this.eventHandlers_ = {};
  this.currentStates_ = {};
  this.initialFieldChange_ = null;
  this.boundRestoreState_ = goog.bind(this.restoreState, this);
};
goog.inherits(goog.editor.plugins.UndoRedo, goog.editor.Plugin);
goog.editor.plugins.UndoRedo.prototype.logger = goog.log.getLogger("goog.editor.plugins.UndoRedo");
goog.editor.plugins.UndoRedo.prototype.inProgressUndo_ = null;
goog.editor.plugins.UndoRedo.prototype.undoManager_;
goog.editor.plugins.UndoRedo.prototype.managerStateChangeKey_;
goog.editor.plugins.UndoRedo.COMMAND = {UNDO:"+undo", REDO:"+redo"};
goog.editor.plugins.UndoRedo.SUPPORTED_COMMANDS_ = goog.object.transpose(goog.editor.plugins.UndoRedo.COMMAND);
goog.editor.plugins.UndoRedo.prototype.setMaxUndoDepth = function(depth) {
  this.undoManager_.setMaxUndoDepth(depth);
};
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);
};
goog.editor.plugins.UndoRedo.prototype.isSupportedCommand = function(command) {
  return command in goog.editor.plugins.UndoRedo.SUPPORTED_COMMANDS_;
};
goog.editor.plugins.UndoRedo.prototype.unregisterFieldObject = function(fieldObject) {
  this.disable(fieldObject);
  this.setFieldObject(null);
};
goog.editor.plugins.UndoRedo.prototype.getCurrentFieldObject = function() {
  return this.getFieldObject();
};
goog.editor.plugins.UndoRedo.prototype.getFieldObjectForHash = function(fieldHashCode) {
  return this.getFieldObject();
};
goog.editor.plugins.UndoRedo.prototype.getCurrentEventTarget = function() {
  return this.getFieldObject();
};
goog.editor.plugins.UndoRedo.prototype.enable = function(fieldObject) {
  if (this.isEnabled(fieldObject)) {
    return;
  }
  fieldObject.clearDelayedChange();
  var eventHandler = new goog.events.EventHandler(this);
  if (!goog.editor.BrowserFeature.USE_MUTATION_EVENTS) {
    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;
  this.updateCurrentState_(fieldObject);
};
goog.editor.plugins.UndoRedo.prototype.disable = function(fieldObject) {
  fieldObject.clearDelayedChange();
  var eventHandler = this.eventHandlers_[fieldObject.getHashCode()];
  if (eventHandler) {
    eventHandler.dispose();
    delete this.eventHandlers_[fieldObject.getHashCode()];
  }
  if (this.currentStates_[fieldObject.getHashCode()]) {
    delete this.currentStates_[fieldObject.getHashCode()];
  }
};
goog.editor.plugins.UndoRedo.prototype.isEnabled = function(fieldObject) {
  return !!this.eventHandlers_[fieldObject.getHashCode()];
};
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_;
  }
};
goog.editor.plugins.UndoRedo.prototype.getTrogClassId = function() {
  return "UndoRedo";
};
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();
    }
  }
};
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;
};
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]});
};
goog.editor.plugins.UndoRedo.prototype.restoreState = function(state, content, cursorPosition) {
  var fieldObj = this.getFieldObjectForHash(state.fieldHashCode);
  if (!fieldObj) {
    return;
  }
  fieldObj.stopChangeEvents(true, true);
  try {
    fieldObj.dispatchBeforeChange();
    fieldObj.execCommand(goog.editor.Command.CLEAR_LOREM, true);
    goog.editor.node.replaceInnerHtml(fieldObj.getElement(), content);
    if (cursorPosition) {
      cursorPosition.select();
    }
    var previousFieldObject = this.getCurrentFieldObject();
    fieldObj.focus();
    if (previousFieldObject && previousFieldObject.getHashCode() != state.fieldHashCode) {
      previousFieldObject.execCommand(goog.editor.Command.UPDATE_LOREM);
    }
    this.currentStates_[state.fieldHashCode].setUndoState(content, cursorPosition);
  } catch (e) {
    goog.log.error(this.logger, "Error while restoring undo state", e);
  } finally {
    this.inProgressUndo_ = state;
    fieldObj.dispatchChange();
    fieldObj.dispatchSelectionChangeEvent();
  }
};
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) {
      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;
};
goog.editor.plugins.UndoRedo.prototype.clearHistory = function() {
  this.getFieldObject().stopChangeEvents(true, true);
  this.undoManager_.clearHistory();
  this.getFieldObject().startChangeEvents();
};
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);
  }
};
goog.editor.plugins.UndoRedo.prototype.handleBeforeChange_ = function(e) {
  if (this.inProgressUndo_) {
    return;
  }
  var fieldObj = e.target;
  var fieldHashCode = fieldObj.getHashCode();
  if (this.initialFieldChange_ != fieldHashCode) {
    this.initialFieldChange_ = fieldHashCode;
    this.updateCurrentState_(fieldObj);
  }
};
goog.editor.plugins.UndoRedo.prototype.handleDelayedChange_ = function(e) {
  if (this.inProgressUndo_) {
    var state = this.inProgressUndo_;
    this.inProgressUndo_ = null;
    state.dispatchEvent(goog.editor.plugins.UndoRedoState.ACTION_COMPLETED);
    return;
  }
  this.updateCurrentState_(e.target);
};
goog.editor.plugins.UndoRedo.prototype.handleBlur_ = function(e) {
  var fieldObj = e.target;
  if (fieldObj) {
    fieldObj.clearDelayedChange();
  }
};
goog.editor.plugins.UndoRedo.prototype.getCursorPosition_ = function(fieldObj) {
  var cursorPos = new goog.editor.plugins.UndoRedo.CursorPosition_(fieldObj);
  if (!cursorPos.isValid()) {
    return null;
  }
  return cursorPos;
};
goog.editor.plugins.UndoRedo.prototype.updateCurrentState_ = function(fieldObj) {
  var fieldHashCode = fieldObj.getHashCode();
  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) {
    if (currentState.undoContent_ == content) {
      return;
    } else {
      if (content == "" || currentState.undoContent_ == "") {
        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_);
};
goog.editor.plugins.UndoRedo.UndoState_ = function(fieldHashCode, content, cursorPosition, restore) {
  goog.editor.plugins.UndoRedoState.call(this, true);
  this.fieldHashCode = fieldHashCode;
  this.restore_ = restore;
  this.setUndoState(content, cursorPosition);
};
goog.inherits(goog.editor.plugins.UndoRedo.UndoState_, goog.editor.plugins.UndoRedoState);
goog.editor.plugins.UndoRedo.UndoState_.prototype.undoContent_;
goog.editor.plugins.UndoRedo.UndoState_.prototype.undoCursorPosition_;
goog.editor.plugins.UndoRedo.UndoState_.prototype.redoContent_;
goog.editor.plugins.UndoRedo.UndoState_.prototype.redoCursorPosition_;
goog.editor.plugins.UndoRedo.UndoState_.prototype.undo = function() {
  this.restore_(this, this.undoContent_, this.undoCursorPosition_);
};
goog.editor.plugins.UndoRedo.UndoState_.prototype.redo = function() {
  this.restore_(this, this.redoContent_, this.redoCursorPosition_);
};
goog.editor.plugins.UndoRedo.UndoState_.prototype.setUndoState = function(content, cursorPosition) {
  this.undoContent_ = content;
  this.undoCursorPosition_ = cursorPosition;
};
goog.editor.plugins.UndoRedo.UndoState_.prototype.setRedoState = function(content, cursorPosition) {
  this.redoContent_ = content;
  this.redoCursorPosition_ = cursorPosition;
};
goog.editor.plugins.UndoRedo.UndoState_.prototype.equals = function(rhs) {
  return this.fieldHashCode == rhs.fieldHashCode && this.undoContent_ == rhs.undoContent_ && this.redoContent_ == rhs.redoContent_;
};
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);
    }
  }
};
goog.editor.plugins.UndoRedo.CursorPosition_.prototype.initW3C_ = function(range) {
  this.isValid_ = false;
  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());
  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;
};
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;
  }
  var contentEditableRange = this.field_.getEditableDomHelper().getDocument().body.createTextRange();
  contentEditableRange.moveToElementText(this.field_.getElement());
  var startMarker = ieRange.duplicate();
  startMarker.collapse(true);
  startMarker.setEndPoint("StartToStart", contentEditableRange);
  this.startOffset_ = goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_(startMarker);
  var endMarker = ieRange.duplicate();
  endMarker.setEndPoint("StartToStart", contentEditableRange);
  this.endOffset_ = goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_(endMarker);
  this.isValid_ = true;
};
goog.editor.plugins.UndoRedo.CursorPosition_.prototype.isValid = function() {
  return this.isValid_;
};
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_;
};
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();
  }
};
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;
    }
    return goog.dom.Range.createFromNodes(startNode, this.startChildOffset_, endNode, this.endChildOffset_).getBrowserRangeObject();
  }
  var sel = baseNode.ownerDocument.body.createTextRange();
  sel.moveToElementText(baseNode);
  sel.collapse(true);
  sel.moveEnd("character", this.endOffset_);
  sel.moveStart("character", this.startOffset_);
  return sel;
};
goog.editor.plugins.UndoRedo.CursorPosition_.computeEndOffsetIE_ = function(range) {
  var testRange = range.duplicate();
  var text = range.text;
  var guess = text.length;
  testRange.collapse(true);
  testRange.moveEnd("character", guess);
  var diff;
  var numTries = 10;
  while (diff = testRange.compareEndPoints("EndToEnd", range)) {
    guess -= diff;
    testRange.moveEnd("character", -diff);
    --numTries;
    if (0 == numTries) {
      break;
    }
  }
  var offset = 0;
  var pos = text.indexOf("\n\r");
  while (pos != -1) {
    ++offset;
    pos = text.indexOf("\n\r", pos + 1);
  }
  return guess + offset;
};
goog.provide("uno.commands.UndoRedo");
goog.require("goog.editor.plugins.UndoRedo");
goog.require("goog.functions");
(function() {
  var UndoRedo = uno.commands.UndoRedo = function(optManager) {
    goog.editor.plugins.UndoRedo.call(this, optManager);
  };
  goog.inherits(UndoRedo, goog.editor.plugins.UndoRedo);
  UndoRedo.prototype.activeOnUneditableFields = goog.functions.TRUE;
})();
goog.provide("uno.commands.Unlink");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Unlink");
  var Unlink = uno.commands.Unlink = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Unlink, uno.BasePlugin);
  Unlink.prototype.isSupportedCommand = function(command) {
    return command === "unlink";
  };
  Unlink.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Unlink.prototype.execCommand = function() {
    var range = this.editor.getRange();
    var link = goog.dom.getAncestorByTagNameAndClass(range.getContainer(), "a");
    if (!link) {
      return false;
    }
    this.editor.dispatchBeforeChange();
    goog.dom.flattenElement(link);
    this.editor.dispatchChange();
    return true;
  };
  Unlink.prototype.queryCommandEnabled = function() {
    var range = this.editor.getRange();
    var link = range && goog.dom.getAncestorByTagNameAndClass(range.getContainer(), "a");
    return link != null;
  };
  Unlink.prototype.queryCommandValue = function(command) {
    return this.queryCommandEnabled(command);
  };
})();
goog.provide("uno.commands.Uppercase");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.Uppercase");
  var util = uno.util;
  var Uppercase = uno.commands.Uppercase = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multiRangeMode = uno.EditorMultiRange.Mode.ALL;
  };
  goog.inherits(Uppercase, uno.BasePlugin);
  Uppercase.prototype.isSupportedCommand = function(command) {
    return command === "uppercase";
  };
  Uppercase.prototype.execCommandInternal = function() {
    var range = this.editor.getRange();
    var savedRange = range.saveUsingDom();
    util.range.forEachWord(range, function(word, wordRange) {
      var container = wordRange.startContainer;
      var text = container.nodeValue;
      container.nodeValue = text.slice(0, wordRange.startOffset) + word.toLocaleUpperCase() + text.slice(wordRange.endOffset);
    });
    savedRange.restore().select();
    return true;
  };
})();
goog.provide("uno.commands.ZoomScale");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.img");
goog.require("uno.util.preview");
goog.require("uno.util.zoomscale");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.ZoomScale");
  var util = uno.util;
  var MIN_ZOOM_SCALE = 0.75;
  var MAX_ZOOM_SCALE = 2.0;
  function boundedZoomScale(zoomScale) {
    return Math.min(Math.max(zoomScale, MIN_ZOOM_SCALE), MAX_ZOOM_SCALE);
  }
  function zoomInFrom(fromZoomScale) {
    var toZoomScale = 1.0;
    if (Math.abs(fromZoomScale - 0.5) < 0.01 || fromZoomScale < 0.5) {
      toZoomScale = 0.67;
    } else {
      if (Math.abs(fromZoomScale - 0.67) < 0.01 || fromZoomScale < 0.67) {
        toZoomScale = 0.75;
      } else {
        if (Math.abs(fromZoomScale - 0.75) < 0.01 || fromZoomScale < 0.75) {
          toZoomScale = 0.9;
        } else {
          if (Math.abs(fromZoomScale - 0.9) < 0.01 || fromZoomScale < 0.9) {
            toZoomScale = 1.0;
          } else {
            if (Math.abs(fromZoomScale - 1.0) < 0.01 || fromZoomScale < 1.0) {
              toZoomScale = 1.1;
            } else {
              if (Math.abs(fromZoomScale - 1.1) < 0.01 || fromZoomScale < 1.1) {
                toZoomScale = 1.25;
              } else {
                if (Math.abs(fromZoomScale - 1.25) < 0.01 || fromZoomScale < 1.25) {
                  toZoomScale = 1.5;
                } else {
                  if (Math.abs(fromZoomScale - 1.5) < 0.01 || fromZoomScale < 1.5) {
                    toZoomScale = 1.75;
                  } else {
                    if (Math.abs(fromZoomScale - 1.75) < 0.01 || fromZoomScale < 1.75) {
                      toZoomScale = 2.0;
                    } else {
                      if (Math.abs(fromZoomScale - 2.0) < 0.01 || fromZoomScale < 2.0) {
                        toZoomScale = 2.5;
                      } else {
                        if (Math.abs(fromZoomScale - 2.5) < 0.01 || fromZoomScale < 2.5) {
                          toZoomScale = 3.0;
                        } else {
                          toZoomScale = 3.0;
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    return boundedZoomScale(toZoomScale);
  }
  function zoomOutFrom(fromZoomScale) {
    var toZoomScale = 1.0;
    if (Math.abs(fromZoomScale - 0.5) < 0.01 || fromZoomScale < 0.5) {
      toZoomScale = 0.5;
    } else {
      if (Math.abs(fromZoomScale - 0.67) < 0.01 || fromZoomScale < 0.67) {
        toZoomScale = 0.5;
      } else {
        if (Math.abs(fromZoomScale - 0.75) < 0.01 || fromZoomScale < 0.75) {
          toZoomScale = 0.67;
        } else {
          if (Math.abs(fromZoomScale - 0.9) < 0.01 || fromZoomScale < 0.9) {
            toZoomScale = 0.75;
          } else {
            if (Math.abs(fromZoomScale - 1.0) < 0.01 || fromZoomScale < 1.0) {
              toZoomScale = 0.9;
            } else {
              if (Math.abs(fromZoomScale - 1.1) < 0.01 || fromZoomScale < 1.1) {
                toZoomScale = 1.0;
              } else {
                if (Math.abs(fromZoomScale - 1.25) < 0.01 || fromZoomScale < 1.25) {
                  toZoomScale = 1.1;
                } else {
                  if (Math.abs(fromZoomScale - 1.5) < 0.01 || fromZoomScale < 1.5) {
                    toZoomScale = 1.25;
                  } else {
                    if (Math.abs(fromZoomScale - 1.75) < 0.01 || fromZoomScale < 1.75) {
                      toZoomScale = 1.5;
                    } else {
                      if (Math.abs(fromZoomScale - 2.0) < 0.01 || fromZoomScale < 2.0) {
                        toZoomScale = 1.75;
                      } else {
                        if (Math.abs(fromZoomScale - 2.5) < 0.01 || fromZoomScale < 2.5) {
                          toZoomScale = 2.0;
                        } else {
                          if (Math.abs(fromZoomScale - 3.0) < 0.01 || fromZoomScale < 3.0) {
                            toZoomScale = 2.5;
                          } else {
                            toZoomScale = 3.0;
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
    return boundedZoomScale(toZoomScale);
  }
  var ZoomScale = uno.commands.ZoomScale = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ZoomScale, uno.BasePlugin);
  ZoomScale.prototype.isSupportedCommand = function(command) {
    return command === "zoomscale";
  };
  ZoomScale.prototype.activeOnUneditableFields = goog.functions.TRUE;
  ZoomScale.prototype.execCommand = function(command, value) {
    if (uno.util.preview.isVisible() || uno.util.preview.isPending()) {
      return false;
    }
    var zoomScale = 0;
    if (value === "+") {
      zoomScale = zoomInFrom(uno.util.zoomscale.getZoom());
    } else {
      if (value === "-") {
        zoomScale = zoomOutFrom(uno.util.zoomscale.getZoom());
      } else {
        zoomScale = parseFloat(value);
      }
    }
    if (zoomScale > 0 && zoomScale < 10.0) {
      var editorBody = this.editor.field;
      if (editorBody) {
        editorBody.style.zoom = zoomScale;
        util.img.layoutResizer();
        util.img.layoutToolbar();
      }
      return true;
    }
    return false;
  };
  ZoomScale.prototype.queryCommandValue = function() {
    return uno.util.zoomscale.getZoom();
  };
})();
goog.provide("uno.model.origin");
goog.require("goog.debug.Logger");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.origin");
  var model = uno.model;
  var TAGS = ["EN-NOTE", "EN-CODEBLOCK", "LI", "TD"];
  model.origin.for = function(node) {
    if (node == null) {
      return;
    }
    while (!model.origin.is(node) && node.parentElement != null) {
      node = node.parentElement;
    }
    if (model.origin.is(node)) {
      return node;
    }
  };
  model.origin.is = function(node) {
    return node != null && TAGS.indexOf(node.tagName) !== -1;
  };
  model.origin.firstSection = function(origin) {
    return origin && origin.firstChild;
  };
  model.origin.lastSection = function(origin) {
    return origin && origin.lastChild;
  };
  model.origin.sections = function(origin) {
    return origin && origin.childNodes;
  };
  model.origin.placeCursorAtStart = function(origin) {
    var section = model.origin.firstSection(origin);
    model.section.placeCursorAtStart(section);
  };
  model.origin.placeCursorAtEnd = function(origin) {
    var section = model.origin.lastSection(origin);
    model.section.placeCursorAtEnd(section);
  };
  model.origin.rangeInfoForStart = function(origin) {
    var section = model.origin.firstSection(origin);
    return model.section.rangeInfoForStart(section);
  };
  model.origin.rangeInfoForEnd = function(origin) {
    var section = model.origin.lastSection(origin);
    return model.section.rangeInfoForEnd(section);
  };
  model.origin.isRangeInfoForStart = function(container, offset, origin) {
    var result = false;
    var info = model.origin.rangeInfoForStart(origin);
    if (info != null) {
      result = info.container === container && info.offset === offset;
    }
    return result;
  };
  model.origin.isRangeInfoForEnd = function(container, offset, origin) {
    var result = false;
    var info = model.origin.rangeInfoForEnd(origin);
    if (info != null) {
      result = info.container === container && info.offset === offset;
    }
    return result;
  };
})();
goog.provide("uno.model.chunk");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.model.origin");
goog.require("uno.util.dom");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.chunk");
  var util = uno.util;
  var model = uno.model;
  model.chunk.is = function(node) {
    return node != null && (node.nodeType === Node.TEXT_NODE || !util.dom.isBlockNode(node));
  };
  model.chunk.equals = function(chunk1, chunk2) {
    return model.chunk.firstLeaf(chunk1) === model.chunk.firstLeaf(chunk2);
  };
  model.chunk.previousChunk = function(chunk) {
    return model.chunk.root(chunk).previousSibling;
  };
  model.chunk.nextChunk = function(chunk) {
    return model.chunk.root(chunk).nextSibling;
  };
  model.chunk.previousChunks = function(chunk) {
    var result = [];
    var node = model.chunk.root(chunk);
    while (node = node.previousSibling) {
      result.unshift(node);
    }
    return result;
  };
  model.chunk.nextChunks = function(chunk) {
    var result = [];
    var node = model.chunk.root(chunk);
    while (node = node.nextSibling) {
      result.push(node);
    }
    return result;
  };
  model.chunk.root = function(chunk) {
    if (chunk == null) {
      return;
    }
    while (chunk.parentElement != null && !model.p.is(chunk.parentElement) && !model.origin.is(chunk.parentElement)) {
      chunk = chunk.parentElement;
    }
    return chunk;
  };
  model.chunk.firstLeaf = function(chunk) {
    var firstLeaf = chunk;
    while (firstLeaf != null && firstLeaf.firstChild != null) {
      firstLeaf = firstLeaf.firstChild;
    }
    return firstLeaf;
  };
  model.chunk.lastLeaf = function(chunk) {
    var leaves = model.chunk.leaves(chunk);
    if (leaves.length > 0) {
      return leaves[leaves.length - 1];
    }
  };
  model.chunk.leaves = function(chunk) {
    var firstLeaf = model.chunk.firstLeaf(chunk);
    if (firstLeaf == null) {
      return [];
    }
    var wrapper = model.fmt.wrapperOrNull(chunk);
    if (wrapper == null) {
      return [firstLeaf];
    } else {
      return firstLeaf.parentNode.childNodes;
    }
  };
  model.chunk.leafInfoForOffset = function(offset, chunk) {
    var len = 0;
    var leaf = model.chunk.firstLeaf(chunk);
    var leafOffset = len;
    while (len < offset && leaf != null) {
      leafOffset = len;
      len += leaf.nodeType === Node.TEXT_NODE ? leaf.data.length : 1;
      if (len < offset) {
        leaf = leaf.nextSibling;
      }
    }
    return {leaf:leaf, offset:offset - leafOffset};
  };
  model.chunk.length = function(chunk) {
    var leaves = model.chunk.leaves(chunk);
    var result = goog.array.reduce(leaves, function(len, leaf) {
      len += leaf.nodeType === Node.TEXT_NODE ? leaf.data.length : 1;
      return len;
    }, 0);
    return result;
  };
  model.chunk.paragraphNeverNull = function(chunk) {
    var root = model.chunk.root(chunk);
    if (root.parentElement) {
      return root.parentElement;
    } else {
      return goog.dom.createDom("div", null, root);
    }
  };
  model.chunk.insertBefore = function(newChunk, refChunk) {
    var newNode = model.chunk.root(newChunk);
    var refNode = model.chunk.root(refChunk);
    goog.dom.insertSiblingBefore(newNode, refNode);
  };
  model.chunk.insertAfter = function(newChunk, refChunk) {
    var newNode = model.chunk.root(newChunk);
    var refNode = model.chunk.root(refChunk);
    goog.dom.insertSiblingBefore(newNode, refNode);
  };
  model.chunk.insertAt = function(newChunk, refChunk, offset) {
    var refInfo = model.chunk.leafInfoForOffset(offset, refChunk);
    var refLeaf = refInfo.leaf;
    var refOffset = refInfo.offset;
    if (model.chunk.canSplitLeaf(refLeaf, refOffset)) {
      refLeaf = model.chunk.split(refLeaf, refOffset);
      refOffset = 0;
    }
    if (offset === 0 || offset == null) {
      goog.array.forEach(model.chunk.leaves(newChunk), function(newLeaf) {
        goog.dom.insertSiblingBefore(newLeaf, refLeaf);
      });
    } else {
      goog.array.forEachRight(model.chunk.leaves(newChunk), function(newLeaf) {
        goog.dom.insertSiblingAfter(newLeaf, refLeaf);
      });
    }
  };
  model.chunk.bounds = function(range) {
    var start;
    var startOffset;
    var end;
    var endOffset;
    if (range.getStartNode().nodeType === Node.TEXT_NODE) {
      start = range.getStartNode();
      startOffset = range.getStartOffset();
    } else {
      start = model.chunk.fromContainer(range.getStartNode(), range.getStartOffset());
      startOffset = 0;
    }
    if (start != null) {
      if (range.getEndNode().nodeType === Node.TEXT_NODE) {
        end = range.getEndNode();
        endOffset = range.getEndOffset();
      } else {
        end = model.chunk.fromContainer(range.getEndNode(), range.getEndOffset());
        endOffset = 0;
      }
    }
    return {start:start, startOffset:startOffset, end:end, endOffset:endOffset};
  };
  model.chunk.fromContainer = function(container, offset) {
    if (container.childNodes.length > 0) {
      if (offset === container.childNodes.length) {
        offset--;
      }
      return container.childNodes[offset];
    }
  };
  model.chunk.allFromRange = function(range) {
    var results = [];
    if (range == null) {
      return results;
    }
    var bounds = model.chunk.bounds(range);
    var start = bounds.start;
    var end = bounds.end;
    if (start != null) {
      results.push(start);
      if (!model.chunk.equals(start, end)) {
        var middle = model.chunk.allBetween(bounds.start, bounds.end);
        middle.forEach(function(chunk) {
          results.push(chunk);
        });
        results.push(end);
      }
    }
    return results;
  };
  model.chunk.allBetween = function(start, end) {
    var results = [];
    if (!model.chunk.equals(start, end)) {
      walker = new util.dom.TreeWalker(start, goog.dom.findCommonAncestor(start, end));
      while ((node = walker.next()) && node !== end) {
        if ((node.nodeType === Node.TEXT_NODE || node.nodeType === Node.ELEMENT_NODE) && node.firstChild == null && !util.dom.isBlockNode(node)) {
          results.push(node);
        }
      }
    }
    return results;
  };
  model.chunk.firstFromRange = function(range) {
    return model.chunk.bounds(range).start;
  };
  model.chunk.lastFromRange = function(range) {
    return model.chunk.bounds(range).end;
  };
  model.chunk.addressForRange = function(range) {
    var bounds = model.chunk.bounds(range);
    startAddress = addressForChunkContent(bounds.start, bounds.startOffset);
    endAddress = addressForChunkContent(bounds.end, bounds.endOffset);
    return {startParagraph:startAddress.paragraph, startIndex:startAddress.index, endParagraph:endAddress.paragraph, endIndex:endAddress.index};
  };
  function addressForChunkContent(chunk, offset) {
    var root = model.chunk.root(chunk);
    var p = model.chunk.paragraphNeverNull(root);
    var index = 0;
    goog.array.some(p.childNodes, function(node) {
      if (node !== root) {
        index += model.chunk.length(node);
      } else {
        index += offset;
        return true;
      }
    });
    return {paragraph:p, index:index};
  }
  model.chunk.rangeForAddress = function(address) {
    var startInfo = rangeInfoForAddress(address.startParagraph, address.startIndex, true);
    var endInfo = rangeInfoForAddress(address.endParagraph, address.endIndex);
    return goog.dom.Range.createFromNodes(startInfo.container, startInfo.offset, endInfo.container, endInfo.offset);
  };
  function rangeInfoForAddress(p, index, isStart) {
    var container;
    var offset;
    var count = 0;
    goog.array.some(p.childNodes, function(chunk) {
      var len = model.chunk.length(chunk);
      if (count + len < index) {
        count += len;
      } else {
        if (count + len === index && isStart && model.chunk.nextChunk(chunk)) {
          count += len;
        } else {
          var leafInfo = model.chunk.leafInfoForOffset(index - count, chunk);
          var leaf = leafInfo.leaf;
          if (leaf.nodeType === Node.TEXT_NODE) {
            container = leaf;
            offset = leafInfo.offset;
          } else {
            container = leaf.parentElement;
            offset = util.dom.index(leaf) + leafInfo.offset;
          }
          return true;
        }
      }
    });
    return {container:container, offset:offset};
  }
  model.chunk.rangeInfoForStart = function(chunk) {
    var leaf = model.chunk.firstLeaf(chunk);
    var container = leaf;
    var offset = 0;
    if (leaf.nodeType === Node.ELEMENT_NODE) {
      container = leaf.parentElement || model.chunk.paragraphNeverNull(leaf);
      offset = util.dom.index(leaf);
    }
    return {container:container, offset:offset};
  };
  model.chunk.rangeInfoForEnd = function(chunk) {
    var leaf = model.chunk.lastLeaf(chunk);
    var container;
    var offset;
    if (leaf.nodeType === Node.TEXT_NODE) {
      container = leaf;
      offset = leaf.data.length;
    } else {
      if (leaf.nodeType === Node.ELEMENT_NODE) {
        container = leaf.parentElement || model.chunk.paragraphNeverNull(leaf);
        offset = util.dom.index(leaf);
        if (leaf.tagName !== "BR") {
          offset++;
        }
      }
    }
    return {container:container, offset:offset};
  };
  model.chunk.placeCursorAtStart = function(chunk) {
    util.range.selectFromInfo(model.chunk.rangeInfoForStart(chunk));
  };
  model.chunk.placeCursorAtEnd = function(chunk) {
    util.range.selectFromInfo(model.chunk.rangeInfoForEnd(chunk));
  };
  model.chunk.placeCursorAt = function(offset, chunk) {
    var leafInfo = model.chunk.leafInfoForOffset(offset, chunk);
    var leaf = leafInfo.leaf;
    var container;
    var containerOffset;
    if (leaf.nodeType === Node.TEXT_NODE) {
      container = leaf;
      containerOffset = leafInfo.offset;
    } else {
      container = leaf.parentNode;
      containerOffset = util.dom.index(leaf) + leafInfo.offset;
    }
    var range = goog.dom.Range.createFromNodes(container, containerOffset, container, containerOffset);
    range.select();
  };
  model.chunk.fromText = function(text, format) {
    var chunk = document.createTextNode(text);
    if (format != null) {
      model.fmt.applyFormatting(format, chunk);
    }
    return chunk;
  };
  model.chunk.fromTagName = function(tag, format) {
    var chunk = document.createElement(tag);
    if (format != null) {
      model.fmt.applyFormatting(format, chunk);
    }
    return chunk;
  };
  model.chunk.text = function(chunk) {
    var leaves = model.chunk.leaves(chunk);
    var result = goog.array.reduce(leaves, function(text, leaf) {
      if (leaf.nodeType === Node.TEXT_NODE) {
        text += leaf.data;
      }
      return text;
    }, "");
    return result;
  };
  model.chunk.canSplit = function(chunk, start, end) {
    var len = model.chunk.length(chunk);
    if (end > 0 && model.chunk.length(chunk) > end) {
      return true;
    }
    if (start != 0 && start != end && start < len) {
      return true;
    }
    return false;
  };
  model.chunk.canSplitLeaf = function(leaf, start, end) {
    if (leaf == null || leaf.nodeType !== Node.TEXT_NODE) {
      return false;
    }
    if (end > 0 && leaf.data.length > end) {
      return true;
    }
    if (start != 0 && start != end && start < leaf.data.length) {
      return true;
    }
    return false;
  };
  model.chunk.split = function(chunk, start, end) {
    var rightEdgeInfo = model.chunk.leafInfoForOffset(end, chunk);
    var rightEdgeLeaf = rightEdgeInfo.leaf;
    if (end && model.chunk.canSplitLeaf(rightEdgeLeaf, rightEdgeInfo.offset)) {
      model.chunk.splitLeafAt(rightEdgeLeaf, rightEdgeInfo.offset);
    }
    var leftEdgeInfo = model.chunk.leafInfoForOffset(start, chunk);
    var leftEdgeLeaf = leftEdgeInfo.leaf;
    var rightAndLeftAreSame = rightEdgeLeaf === leftEdgeLeaf;
    if (start && model.chunk.canSplitLeaf(leftEdgeLeaf, leftEdgeInfo.offset)) {
      leftEdgeLeaf = model.chunk.splitLeafAt(leftEdgeLeaf, leftEdgeInfo.offset);
      if (rightAndLeftAreSame) {
        rightEdgeLeaf = leftEdgeLeaf;
      }
    }
    var root = model.chunk.root(chunk);
    var firstLeaf = model.chunk.firstLeaf(chunk);
    var lastLeaf = model.chunk.lastLeaf(chunk);
    if (root !== firstLeaf) {
      var rootClone;
      var leafParent;
      if (lastLeaf !== rightEdgeLeaf) {
        rootClone = root.cloneNode(true);
        parentClone = model.chunk.firstLeaf(rootClone).parentNode;
        goog.dom.removeChildren(parentClone);
        while (rightEdgeLeaf.nextSibling != null) {
          parentClone.appendChild(rightEdgeLeaf.nextSibling);
        }
        goog.dom.insertSiblingAfter(rootClone, root);
      }
      if (firstLeaf !== leftEdgeLeaf) {
        rootClone = root.cloneNode(true);
        parentClone = model.chunk.firstLeaf(rootClone).parentNode;
        goog.dom.removeChildren(parentClone);
        while (rightEdgeLeaf.previousSibling != null) {
          parentClone.appendChild(rightEdgeLeaf.parentNode.firstChild);
        }
        goog.dom.insertSiblingBefore(rootClone, root);
      }
    }
    return leftEdgeLeaf;
  };
  model.chunk.splitLeafAt = function(leaf, offset) {
    if (leaf == null) {
      return leaf;
    }
    if (leaf.nodeType !== Node.TEXT_NODE) {
      throw Error("Cannot split content leaf that is not text");
    }
    return leaf.splitText(offset);
  };
  model.chunk.replaceText = function(text, chunk) {
    var leaves = model.chunk.leaves(chunk);
    var firstTextNode;
    var node;
    goog.array.some(model.chunk.leaves(chunk), function(leaf) {
      if (leaf.nodeType === Node.TEXT_NODE) {
        firstTextNode = leaf;
        return true;
      }
    });
    if (firstTextNode == null) {
      model.chunk.insertText(text, 0, chunk);
    } else {
      var replacementNode = model.chunk.fromText(text);
      goog.dom.replaceNode(replacementNode, firstTextNode);
      firstTextNode = replacementNode;
    }
    node = firstTextNode.nextSibling;
    while (node != null) {
      if (node.nodeType === Node.TEXT_NODE) {
        goog.dom.removeNode(node);
      }
      node = node.nextSibling;
    }
    var lastLeaf = model.chunk.lastLeaf(chunk);
    if (lastLeaf.tagName === "BR") {
      goog.dom.removeNode(lastLeaf);
    }
    return firstTextNode;
  };
  model.chunk.insertText = function(text, chunk, offset) {
    var leafInfo = model.chunk.leafInfoForOffset(offset, chunk);
    var leaf = leafInfo.leaf;
    var index = leafInfo.offset;
    var result;
    if (leaf.nodeType === Node.TEXT_NODE) {
      var leftText = leaf.data.substring(0, index);
      var rightText = leaf.data.substring(index);
      leaf.data = leftText + text + rightText;
      result = chunk;
    } else {
      var textNode = model.chunk.fromText(text);
      if (index < 1) {
        goog.dom.insertSiblingBefore(textNode, leaf);
        if (leaf.tagName === "BR") {
          goog.dom.removeNode(leaf);
        }
      } else {
        goog.dom.insertSiblingAfter(textNode, leaf);
      }
      result = textNode;
    }
    return result;
  };
  model.chunk.removeLeaf = function(leaf) {
    var root = model.chunk.root(leaf);
    var nextChunk = model.chunk.nextChunk(root);
    var p = model.p.for(root);
    if (model.chunk.leaves(root).length === 1) {
      goog.dom.removeNode(root);
      if (nextChunk != null) {
        model.fmt.normalizeLeft(nextChunk);
      }
    } else {
      goog.dom.removeNode(leaf);
    }
    if (model.p.chunks(p).length === 0) {
      model.p.append(model.chunk.fromTagName("br"));
    }
  };
  model.chunk.insertSiblingBefore = function(chunks, refChunk) {
    var root = model.chunk.root(refChunk);
    if (root == null || root.parentElement == null) {
      return;
    }
    chunks = chunks || [];
    if (!goog.isArrayLike(chunks)) {
      chunks = [chunks];
    }
    goog.array.forEachRight(chunks, function(chunk) {
      goog.dom.insertSiblingBefore(model.chunk.root(chunk), refChunk);
    });
  };
  model.chunk.insertSiblingAfter = function(chunks, refChunk) {
    var root = model.chunk.root(refChunk);
    if (root == null || root.parentElement == null) {
      return;
    }
    chunks = chunks || [];
    if (!goog.isArrayLike(chunks)) {
      chunks = [chunks];
    }
    goog.array.forEachRight(chunks, function(chunk) {
      goog.dom.insertSiblingAfter(model.chunk.root(chunk), refChunk);
    });
  };
  model.chunk.remove = function(chunk) {
    var root = model.chunk.root(chunk);
    if (root == null || root.parentElement == null) {
      return;
    }
    goog.dom.removeNode(root);
  };
})();
goog.provide("uno.model.fmt");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.defs");
goog.require("uno.model.chunk");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.fmt");
  var model = uno.model;
  var util = uno.util;
  var HIGHLIGHT_COLOR = uno.defs.highlight.COLOR;
  var HIGHLIGHT_REGEX = uno.defs.highlight.regex;
  model.fmt.isSegment = function(chunk, start, end) {
    return start > 0 && start != end || end && end <= model.chunk.length(chunk);
  };
  model.fmt.isZeroLengthSegment = function(chunk, start, end) {
    var len = model.chunk.length(chunk);
    return start != null && (start === end || start === len);
  };
  model.fmt.wrapperOrNull = function(chunk) {
    var root = model.chunk.root(chunk);
    var leaf = model.chunk.firstLeaf(chunk);
    return root === leaf ? null : root;
  };
  model.fmt.wrapperNeverNull = function(chunk, start, end, tag) {
    if (model.fmt.isSegment(chunk, start, end)) {
      chunk = model.chunk.split(chunk, start, end);
    }
    var root = model.chunk.root(chunk);
    var wrapper = root;
    tag = tag && tag.toUpperCase() || "SPAN";
    if (root.firstChild == null || model.fmt.findTag(tag, root) == null) {
      wrapper = document.createElement(tag);
      if (root.parentElement != null) {
        goog.dom.replaceNode(wrapper, root);
      }
      wrapper.appendChild(root);
    }
    return wrapper;
  };
  model.fmt.addStyle = function(name, value, chunk, start, end) {
    if (!model.fmt.isZeroLengthSegment(chunk, start, end)) {
      var wrapper = model.fmt.wrapperNeverNull(chunk, start, end);
      var values = wrapper.style[name].split(" ");
      if (values.indexOf(value) === -1) {
        wrapper.style[name] = values.concat(value).join(" ");
      }
    }
    chunk = model.fmt.normalizeLeft(chunk);
    return chunk;
  };
  model.fmt.removeStyle = function(name, value, chunk, start, end) {
    var result = chunk;
    if (!model.fmt.isZeroLengthSegment(chunk, start, end)) {
      var wrapper = model.fmt.wrapperOrNull(chunk);
      if (wrapper != null) {
        result = wrapper;
        wrapper = model.fmt.wrapperNeverNull(chunk, start, end);
        var values = wrapper.style[name].split(" ");
        if (values.indexOf(value) !== -1) {
          values.splice(values.indexOf(value), 1);
          wrapper.style[name] = values.join(" ");
          result = model.fmt.normalizeLeft(wrapper);
        }
      }
    }
    return result;
  };
  model.fmt.compact = function(chunk) {
    var wrapper;
    var leaf = model.chunk.firstLeaf(chunk);
    while ((wrapper = model.fmt.wrapperOrNull(leaf)) && model.fmt.isTombstone(wrapper)) {
      goog.dom.flattenElement(wrapper);
    }
    return leaf;
  };
  model.fmt.setStyle = function(name, value, chunk, start, end) {
    if (model.fmt.styleValue(name, chunk) !== value) {
      if (!model.fmt.isZeroLengthSegment(chunk, start, end)) {
        var wrapper = model.fmt.wrapperNeverNull(chunk, start, end);
        wrapper.style[name] = value;
      }
    }
    return model.fmt.normalizeLeft(wrapper || chunk);
  };
  model.fmt.clearStyle = function(name, chunk, start, end) {
    if (!model.fmt.isZeroLengthSegment(chunk, start, end)) {
      var wrapper = model.fmt.wrapperOrNull(chunk);
      if (wrapper != null) {
        wrapper = model.fmt.wrapperNeverNull(chunk, start, end);
        wrapper.style[name] = "";
      }
    }
    return model.fmt.normalizeLeft(wrapper || chunk);
  };
  model.fmt.styleValue = function(name, chunk) {
    var result;
    var node = model.chunk.root(chunk);
    while (node && node.firstChild != null) {
      if (node.style != null && node.style[name] != null && node.style[name] !== "") {
        result = node.style[name];
      }
      node = node.firstChild;
    }
    return result;
  };
  model.fmt.addTag = function(name, attr, chunk, start, end) {
    if (!model.fmt.isZeroLengthSegment(chunk, start, end)) {
      var leaf = model.chunk.firstLeaf(chunk);
      var wrapper = model.fmt.wrapperNeverNull(chunk, start, end, name);
      var el = model.fmt.findTag(name, chunk);
      if (el == null) {
        el = document.createElement(name);
      }
      if (attr != null) {
        Object.keys(attr).forEach(function(key) {
          el.setAttribute(key, attr[key]);
        });
      }
      if (el.firstChild == null) {
        goog.dom.replaceNode(el, leaf);
        el.appendChild(leaf);
      }
    }
    return model.fmt.normalizeLeft(chunk);
  };
  model.fmt.removeTag = function(name, chunk, start, end) {
    var leaf;
    if (!model.fmt.isZeroLengthSegment(chunk, start, end)) {
      var wrapper = model.fmt.wrapperOrNull(chunk);
      if (wrapper != null) {
        var el = model.fmt.findTag(name, chunk);
        if (el != null) {
          wrapper = model.fmt.wrapperNeverNull(chunk, start, end, name);
          leaf = model.chunk.firstLeaf(chunk);
          el = model.fmt.findTag(name, wrapper);
          goog.dom.flattenElement(el);
        }
      }
    }
    return model.fmt.normalizeLeft(leaf || chunk);
  };
  model.fmt.findTag = function(name, chunk) {
    var wrapper = model.fmt.wrapperOrNull(chunk);
    if (wrapper != null) {
      return util.dom.compareTagName(wrapper, name) ? wrapper : wrapper.querySelector(name);
    }
  };
  model.fmt.hasFormatting = function(chunk) {
    var result = false;
    var node = model.fmt.root(chunk);
    while (result === false && node.firstChild != null) {
      result = !model.fmt.isTombstone(node);
      node = node.firstChild;
    }
    return result;
  };
  model.fmt.isTombstone = function(wrapper) {
    return wrapper != null && wrapper.tagName === "SPAN" && wrapper.style.cssText === "";
  };
  model.fmt.getFormatting = function(chunk) {
    var fontname;
    var fontsize;
    var forecolor;
    var bgcolor;
    var hyperlink;
    var result = {};
    if (model.fmt.boldValue(chunk)) {
      result.bold = true;
    }
    if (model.fmt.highlightValue(chunk)) {
      result.highlight = true;
    }
    if (model.fmt.italicValue(chunk)) {
      result.italic = true;
    }
    if (model.fmt.strikethroughValue(chunk)) {
      result.strikethrough = true;
    }
    if (model.fmt.subscriptValue(chunk)) {
      result.subscript = true;
    }
    if (model.fmt.superscriptValue(chunk)) {
      result.superscript = true;
    }
    if (model.fmt.underlineValue(chunk)) {
      result.underline = true;
    }
    fontname = model.fmt.fontnameValue(chunk);
    if (fontname != null) {
      result.fontname = fontname;
    }
    fontsize = model.fmt.fontsizeValue(chunk);
    if (fontsize != null) {
      result.fontsize = fontsize;
    }
    forecolor = model.fmt.forecolorValue(chunk);
    if (forecolor != null) {
      result.forecolor = forecolor;
    }
    if (!result.highlight) {
      bgcolor = model.fmt.bgcolorValue(chunk);
      if (bgcolor != null) {
        result.bgcolor = bgcolor;
      }
    }
    hyperlink = model.fmt.hyperlinkValue(chunk);
    if (hyperlink != null) {
      result.hyperlink = hyperlink;
    }
    return result;
  };
  model.fmt.applyFormatting = function(formatting, chunk, start, end) {
    if (model.fmt.isZeroLengthSegment(chunk, start, end)) {
      return chunk;
    }
    var result = Object.keys(formatting).reduce(function(formattedChunk, f) {
      return model.fmt.formatChunk(f, formatting[f], formattedChunk, start, end);
    }, chunk);
    return result;
  };
  model.fmt.formatRange = function(name, value, range) {
    var bounds = model.chunk.bounds(range);
    if (bounds.start != null) {
      var end = bounds.end;
      if (bounds.start === bounds.end) {
        model.fmt.formatChunk(name, value, bounds.start, bounds.startOffset, bounds.endOffset);
      } else {
        model.fmt.formatChunk(name, value, bounds.start, bounds.startOffset);
        var middle = model.chunk.allBetween(bounds.start, bounds.end);
        middle.forEach(function(chunk) {
          model.fmt.formatChunk(name, value, chunk);
        });
        end = model.fmt.formatChunk(name, value, bounds.end, 0, bounds.endOffset);
      }
      model.fmt.normalizeRight(end);
    }
  };
  model.fmt.formatChunk = function(name, value, chunk, start, end) {
    return model.fmt[name](value, chunk, start, end);
  };
  model.fmt.formatValue = function(name, chunk) {
    return model.fmt[name + "Value"](chunk);
  };
  model.fmt.isFormatIdentical = function(chunk1, chunk2) {
    var f1 = model.fmt.getFormatting(chunk1);
    var f2 = model.fmt.getFormatting(chunk2);
    return goog.object.equals(f1, f2);
  };
  model.fmt.removeAllFormatting = function(chunk, start, end) {
    var leaf = model.chunk.firstLeaf(chunk);
    if (!model.fmt.isZeroLengthSegment(chunk, start, end)) {
      var wrapper = model.fmt.wrapperOrNull(chunk);
      if (wrapper != null) {
        var node = model.fmt.wrapperNeverNull(chunk, start, end).firstChild;
        leaf = model.chunk.firstLeaf(node);
        while (node != null) {
          goog.dom.flattenElement(node.parentElement);
          node = node.firstChild;
        }
      }
    }
    return model.fmt.normalizeLeft(leaf);
  };
  model.fmt.queryValue = function(name, chunk) {
    return model.fmt[name](name, chunk);
  };
  model.fmt.queryState = function(name, chunk) {
    return model.fmt[name](name, chunk) != null;
  };
  model.fmt.normalizeLeft = function(chunk) {
    chunk = model.fmt.compact(chunk);
    var result = chunk;
    var root = model.chunk.root(chunk);
    var sib = root.previousSibling;
    var sibLeaf = model.chunk.lastLeaf(sib);
    if (root === model.chunk.firstLeaf(chunk)) {
      root = null;
    }
    if (sibLeaf != null && model.fmt.isFormatIdentical(chunk, sib)) {
      goog.array.forEachRight(model.chunk.leaves(chunk), function(leaf) {
        goog.dom.insertSiblingAfter(leaf, sibLeaf);
      });
      if (root != null) {
        goog.dom.removeNode(root);
      }
      result = sib;
    }
    result.normalize();
    return result;
  };
  model.fmt.normalizeRight = function(chunk) {
    chunk = model.fmt.compact(chunk);
    var result = chunk;
    var root = model.chunk.root(chunk);
    var sib = root.nextSibling;
    var sibLeaf = model.chunk.firstLeaf(sib);
    if (root === model.chunk.firstLeaf(chunk)) {
      root = null;
    }
    if (sibLeaf != null && model.fmt.isFormatIdentical(chunk, sib)) {
      goog.array.forEachRight(model.chunk.leaves(chunk), function(leaf) {
        goog.dom.insertSiblingBefore(leaf, sibLeaf);
      });
      if (root != null) {
        goog.dom.removeNode(root);
      }
      result = sib;
    }
    result.normalize();
    return result;
  };
  model.fmt.bgcolor = function(color, chunk, start, end) {
    if (!!color) {
      return model.fmt.setStyle("background-color", color, chunk, start, end);
    } else {
      return model.fmt.clearStyle("background-color", chunk, start, end);
    }
  };
  model.fmt.bgcolorValue = function(chunk) {
    return model.fmt.styleValue("background-color", chunk);
  };
  model.fmt.bold = function(enable, chunk, start, end) {
    if (enable) {
      return model.fmt.setStyle("fontWeight", "bold", chunk, start, end);
    } else {
      return model.fmt.clearStyle("fontWeight", chunk, start, end);
    }
  };
  model.fmt.boldValue = function(chunk) {
    return model.fmt.styleValue("fontWeight", chunk) === "bold";
  };
  model.fmt.fontname = function(name, chunk, start, end) {
    if (!!name) {
      return model.fmt.setStyle("fontFamily", name, chunk, start, end);
    } else {
      return model.fmt.clearStyle("fontFamily", chunk, start, end);
    }
  };
  model.fmt.fontnameValue = function(chunk) {
    return model.fmt.styleValue("fontFamily", chunk);
  };
  model.fmt.fontsize = function(size, chunk, start, end) {
    if (!!size) {
      return model.fmt.setStyle("fontSize", size, chunk, start, end);
    } else {
      return model.fmt.clearStyle("fontSize", chunk, start, end);
    }
  };
  model.fmt.fontsizeValue = function(chunk) {
    return model.fmt.styleValue("fontSize", chunk);
  };
  model.fmt.forecolor = function(color, chunk, start, end) {
    if (!!color) {
      return model.fmt.setStyle("color", color, chunk, start, end);
    } else {
      return model.fmt.clearStyle("color", chunk, start, end);
    }
  };
  model.fmt.forecolorValue = function(chunk) {
    return model.fmt.styleValue("color", chunk);
  };
  model.fmt.highlight = function(enable, chunk, start, end) {
    if (enable) {
      return model.fmt.setStyle("backgroundColor", HIGHLIGHT_COLOR, chunk, start, end);
    } else {
      return model.fmt.clearStyle("backgroundColor", chunk, start, end);
    }
  };
  model.fmt.highlightValue = function(chunk) {
    var val = model.fmt.styleValue("backgroundColor", chunk);
    return HIGHLIGHT_REGEX.test(val);
  };
  model.fmt.hyperlink = function(urlOrProps, chunk, start, end) {
    if (!!urlOrProps) {
      var props = typeof urlOrProps === "string" ? {href:urlOrProps} : urlOrProps;
      return model.fmt.addTag("a", props, chunk, start, end);
    } else {
      return model.fmt.removeTag("a", chunk, start, end);
    }
  };
  model.fmt.hyperlinkValue = function(chunk) {
    var a = model.fmt.findTag("a", chunk);
    return a ? {href:a.getAttribute("href")} : null;
  };
  model.fmt.italic = function(enable, chunk, start, end) {
    if (enable) {
      return model.fmt.setStyle("fontStyle", "italic", chunk, start, end);
    } else {
      return model.fmt.clearStyle("fontStyle", chunk, start, end);
    }
  };
  model.fmt.italicValue = function(chunk) {
    return model.fmt.styleValue("fontStyle", chunk) === "italic";
  };
  model.fmt.strikethrough = function(enable, chunk, start, end) {
    if (enable) {
      return model.fmt.addStyle("textDecoration", "line-through", chunk, start, end);
    } else {
      return model.fmt.removeStyle("textDecoration", "line-through", chunk, start, end);
    }
  };
  model.fmt.strikethroughValue = function(chunk) {
    var val = model.fmt.styleValue("textDecoration", chunk);
    return val != null && val.indexOf("line-through") !== -1;
  };
  model.fmt.subscript = function(enable, chunk, start, end) {
    if (enable) {
      return model.fmt.addTag("sub", null, chunk, start, end);
    } else {
      return model.fmt.removeTag("sub", chunk, start, end);
    }
  };
  model.fmt.subscriptValue = function(chunk) {
    return model.fmt.findTag("sub", chunk) != null;
  };
  model.fmt.superscript = function(enable, chunk, start, end) {
    if (enable) {
      return model.fmt.addTag("sup", null, chunk, start, end);
    } else {
      return model.fmt.removeTag("sup", chunk, start, end);
    }
  };
  model.fmt.superscriptValue = function(chunk) {
    return model.fmt.findTag("sup", chunk) != null;
  };
  model.fmt.underline = function(enable, chunk, start, end) {
    if (enable) {
      return model.fmt.addStyle("textDecoration", "underline", chunk, start, end);
    } else {
      return model.fmt.removeStyle("textDecoration", "underline", chunk, start, end);
    }
  };
  model.fmt.underlineValue = function(chunk) {
    var val = model.fmt.styleValue("textDecoration", chunk);
    return val != null && val.indexOf("underline") !== -1;
  };
})();
goog.provide("uno.commands.strict.BasicTextFormatter");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.BasicTextFormatter");
  var model = uno.model;
  var util = uno.util;
  var BasicTextFormatter = uno.commands.strict.BasicTextFormatter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(BasicTextFormatter, uno.BasePlugin);
  BasicTextFormatter.GOOG_COMMAND = {bold:goog.editor.Command.BOLD, italic:goog.editor.Command.ITALIC, strikethrough:goog.editor.Command.STRIKE_THROUGH, subscript:goog.editor.Command.SUBSCRIPT, superscript:goog.editor.Command.SUPERSCRIPT, underline:goog.editor.Command.UNDERLINE};
  BasicTextFormatter.COMMANDS = ["bold", "highlight", "italic", "strikethrough", "subscript", "superscript", "underline"];
  BasicTextFormatter.prototype.isSupportedCommand = function(command) {
    return BasicTextFormatter.COMMANDS.indexOf(command) > -1;
  };
  BasicTextFormatter.prototype.activeOnUneditableFields = goog.functions.TRUE;
  BasicTextFormatter.prototype.execCommand = function(command, value) {
    var currentState = this.editor.context.style.state[command];
    var range = this.editor.getRange();
    if (value == null || value == "") {
      value = !currentState;
    }
    if (range.isCollapsed()) {
      util.styles.addTempState(this.editor, command, value);
    } else {
      this.editor.dispatchBeforeChange();
      var address = model.chunk.addressForRange(range);
      model.fmt.formatRange(command, value, range);
      range = model.chunk.rangeForAddress(address);
      range.select();
      this.editor.dispatchChange();
    }
    this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:this.editor.context.tempStyles});
    return true;
  };
  BasicTextFormatter.prototype.queryCommandValue = function(command) {
    var result;
    if (BasicTextFormatter.GOOG_COMMAND[command] != null) {
      result = this.editor.queryCommandValue(BasicTextFormatter.GOOG_COMMAND[command]);
    } else {
      var chunks = model.chunk.allFromRange(this.editor.getRange());
      result = goog.array.every(chunks, function(chunk) {
        return !!model.fmt.formatValue(command, chunk);
      });
    }
    return result;
  };
  BasicTextFormatter.prototype.queryCommandEnabled = goog.functions.TRUE;
})();
goog.provide("uno.model.section");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.model.origin");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.section");
  var model = uno.model;
  var util = uno.util;
  var TAGS = ["div", "en-codeblock", "hr", "ol", "table", "ul"];
  model.section.types = [];
  model.section.is = function(node) {
    if (node == null) {
      return false;
    }
    return model.section.typeFor(node) != null;
  };
  model.section.typeFor = function(node) {
    var result;
    if (node != null) {
      model.section.types.some(function(type) {
        if (type.is(node)) {
          result = type;
          return true;
        }
      });
    }
    return result;
  };
  model.section.for = function(node) {
    var type;
    if (node == null) {
      return result;
    }
    while (!(type = model.section.typeFor(node)) && !model.origin.is(node) && node.parentElement != null) {
      node = node.parentElement;
    }
    if (type != null) {
      return node;
    }
  };
  model.section.parent = function(section) {
    if (section == null) {
      return null;
    }
    var foundRoot = false;
    var parent = goog.dom.getAncestor(section, function(node) {
      if (node.tagName === "EN-NOTE") {
        foundRoot = true;
      }
      return !foundRoot && TAGS.indexOf(node.tagName) !== -1;
    });
    return parent;
  };
  model.section.allFromRange = function(range) {
    var elements;
    var container;
    var results = [];
    var start = model.section.firstFromRange(range);
    var end = model.section.lastFromRange(range);
    if (range == null) {
      return;
    }
    if (start !== end) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll(TAGS.join(","));
      results = goog.array.filter(elements, function(el) {
        return el !== start && el !== end && range.containsNode(el) && model.section.parent(el) == null;
      });
    }
    if (start != null) {
      results.unshift(start);
    }
    if (start !== end) {
      results.push(end);
    }
    return results;
  };
  model.section.firstFromRange = function(range) {
    var node;
    if (range == null) {
      return;
    }
    if (range.getStartNode().nodeType === Node.ELEMENT_NODE) {
      node = range.getStartNode().childNodes[range.getStartOffset()];
    } else {
      node = range.getStartNode();
    }
    return model.section.for(node);
  };
  model.section.lastFromRange = function(range) {
    var node;
    if (range == null) {
      return;
    }
    if (range.getEndNode().nodeType === Node.ELEMENT_NODE) {
      node = range.getEndNode().childNodes[range.getEndOffset()];
    } else {
      node = range.getEndNode();
    }
    return model.section.for(node);
  };
  model.section.selectAll = function(sections) {
    if (sections.length === 0) {
      return;
    }
    var first = sections[0];
    var last = sections[sections.length - 1];
    util.range.selectFromInfo(model.section.rangeInfoForStart(first), model.section.rangeInfoForEnd(last));
  };
  model.section.insertSiblingBefore = function(section, ref) {
    goog.dom.insertSiblingBefore(section, ref);
  };
  model.section.insertSiblingAfter = function(section, ref) {
    goog.dom.insertSiblingAfter(section, ref);
  };
  model.section.previousSection = function(section) {
    if (section != null && section.previousElementSibling != null) {
      return model.section.for(section.previousElementSibling);
    }
  };
  model.section.nextSection = function(section) {
    if (section != null && section.nextElementSibling != null) {
      return model.section.for(section.nextElementSibling);
    }
  };
  model.section.replace = function(section, ref) {
    goog.dom.replaceNode(section, ref);
  };
  model.section.remove = function(section) {
    goog.dom.removeNode(section);
  };
  model.section.rangeInfoForStart = function(section) {
    var type = model.section.typeFor(section);
    return type && type.rangeInfoForStart(section);
  };
  model.section.rangeInfoForEnd = function(section) {
    var type = model.section.typeFor(section);
    return type && type.rangeInfoForEnd(section);
  };
  model.section.placeCursorAtStart = function(section) {
    var type = model.section.typeFor(section);
    return type && type.placeCursorAtStart(section);
  };
  model.section.placeCursorAtEnd = function(section) {
    var type = model.section.typeFor(section);
    return type && type.placeCursorAtEnd(section);
  };
  model.section.isRangeInfoForStart = function(container, offset, section) {
    var result = false;
    var info = model.section.rangeInfoForStart(section);
    if (info != null) {
      result = info.container === container && info.offset === offset;
    }
    return result;
  };
  model.section.isRangeInfoForEnd = function(container, offset, section) {
    var result = false;
    var info = model.section.rangeInfoForEnd(section);
    if (info != null) {
      result = info.container === container && info.offset === offset;
    }
    return result;
  };
  model.section.contains = function(content, section) {
    if (section == null || content == null) {
      return false;
    }
    return section.contains(content);
  };
})();
goog.provide("uno.model.todo");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.todo");
  var model = uno.model;
  var TRANSPARENT_IMAGE_DATA_URL = uno.defs.image.TRANSPARENT_IMAGE_DATA_URL;
  model.todo.create = function(checked) {
    var todo = new Image;
    todo.src = TRANSPARENT_IMAGE_DATA_URL;
    goog.dom.classes.add(todo, "en-todo");
    if (checked) {
      model.todo.toggle(todo);
    }
    return todo;
  };
  model.todo.is = function(node) {
    return node != null && node.tagName === "IMG" && goog.dom.classlist.contains(node, "en-todo");
  };
  model.todo.toggle = function(todo) {
    if (model.todo.is(todo)) {
      model.todo.setChecked(!model.todo.isChecked(todo), todo);
    }
  };
  model.todo.toggleByRange = function(range) {
    if (range == null) {
      return;
    }
    var node = range.getStartNode();
    var prevNode;
    while ((prevNode = goog.dom.getPreviousElementSibling(node)) || (prevNode = model.chunk.lastLeaf(model.chunk.previousChunk(model.chunk.for(node))))) {
      node = prevNode;
      if (model.todo.isTodo(node)) {
        model.todo.toggle(node);
        return true;
      }
    }
  };
  model.todo.isChecked = function(todo) {
    return model.todo.is(todo) && todo.getAttribute("checked") === "true";
  };
  model.todo.setChecked = function(checked, todo) {
    if (model.todo.is(todo)) {
      if (checked) {
        todo.setAttribute("checked", checked);
      } else {
        todo.removeAttribute("checked");
      }
    }
  };
  model.todo.all = function(origin) {
    if (origin == null) {
      return [];
    }
    return origin.querySelectorAll("img.en-todo");
  };
  model.todo.allFromRange = function(range) {
    if (range == null) {
      return [];
    }
    var container = range.getContainerElement();
    var all = container.querySelectorAll("img.en-todo");
    var todos = goog.array.toArray(all).filter(function(todo) {
      return range.containsNode(todo, true);
    });
    return todos;
  };
})();
goog.provide("uno.model.p");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.defs");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
goog.require("uno.model.origin");
goog.require("uno.model.section");
goog.require("uno.model.todo");
goog.require("uno.util.dom");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.p");
  var model = uno.model;
  var util = uno.util;
  var TAG = "DIV";
  var SELECTOR = TAG;
  model.section.types.push(model.p);
  model.p.create = function(chunks) {
    var p = goog.dom.createDom(TAG, null, document.createElement("br"));
    if (chunks) {
      model.p.append(chunks, p);
    }
    return p;
  };
  model.p.is = function(node) {
    return node != null && node.tagName === TAG;
  };
  model.p.for = function(node) {
    if (node == null) {
      return;
    }
    if (node.nodeType === Node.TEXT_NODE && node.parentElement == null) {
      return;
    }
    var el = node.nodeType != Node.ELEMENT_NODE ? node.parentElement : node;
    while (!model.p.is(el) && !model.origin.is(el) && el.parentElement != null) {
      el = el.parentElement;
    }
    if (model.p.is(el)) {
      return el;
    }
  };
  model.p.all = function(root) {
    if (root == null) {
      return [];
    }
    return root.querySelectorAll(SELECTOR);
  };
  model.p.firstParagraph = function(container) {
    var el = container;
    if (el != null && !model.p.is(el)) {
      el = container.querySelector(SELECTOR);
    }
    if (model.p.is(el)) {
      return el;
    }
  };
  model.p.lastParagraph = function(container) {
    var el = container;
    if (el != null && !model.p.is(el)) {
      nodes = container.querySelectorAll(SELECTOR);
      if (nodes.length > 0) {
        el = nodes[nodes.length - 1];
      }
    }
    if (model.p.is(el)) {
      return el;
    }
  };
  model.p.allFromRange = function(range) {
    var elements;
    var results = [];
    var start = model.p.firstFromRange(range);
    var end = model.p.lastFromRange(range);
    var container = range.getContainer();
    if (container.nodeType !== Node.ELEMENT_NODE) {
      container = container.parentElement;
    }
    elements = container.querySelectorAll(SELECTOR);
    results = goog.array.filter(elements, function(el) {
      return el !== start && el !== end && range.containsNode(el);
    });
    if (start != null) {
      results.unshift(start);
    }
    if (start !== end) {
      results.push(end);
    }
    return results;
  };
  model.p.firstFromRange = function(range) {
    var result;
    var container;
    var elements;
    if (range == null) {
      return;
    }
    if (range.getStartNode().nodeType === Node.ELEMENT_NODE) {
      result = model.p.for(range.getStartNode().childNodes[range.getStartOffset()]);
    } else {
      result = model.p.for(range.getStartNode());
    }
    if (result == null) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll(SELECTOR);
      result = goog.array.find(elements, function(el) {
        return range.containsNode(el);
      });
    }
    return result;
  };
  model.p.lastFromRange = function(range) {
    var result;
    var container;
    var elements;
    if (range == null) {
      return;
    }
    if (range.getEndNode().nodeType === Node.ELEMENT_NODE) {
      result = model.p.for(range.getEndOffset() < range.getEndNode().childNodes.length ? range.getEndNode().childNodes[range.getEndOffset()] : range.getEndNode().childNodes[range.getEndOffset() - 1]);
    } else {
      result = model.p.for(range.getEndNode());
    }
    if (result == null) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll(SELECTOR);
      result = goog.array.findRight(elements, function(el) {
        return range.containsNode(el);
      });
    }
    return result;
  };
  model.p.clear = function(p) {
    if (!model.p.isEmpty(p)) {
      goog.dom.removeChildren(p);
    }
    if (p.childNodes.length === 0) {
      p.appendChild(document.createElement("br"));
    }
  };
  model.p.chunks = function(p) {
    return p.childNodes;
  };
  model.p.firstChunk = function(p) {
    return p && p.firstChild;
  };
  model.p.lastChunk = function(p) {
    return p && p.lastChild;
  };
  model.p.prepend = function(chunks, p) {
    chunks = chunks.nodeType || typeof chunks === "string" ? [chunks] : chunks;
    if (chunks.length > 0) {
      if (p.childNodes.length === 1 && p.firstChild.tagName === "BR") {
        goog.dom.removeNode(p.firstChild);
      }
      goog.array.forEachRight(chunks, function(chunk) {
        if (typeof chunk === "string") {
          chunk = txt.fromText(chunk);
        }
        p.insertBefore(model.chunk.root(chunk), p.firstChild);
      });
    }
  };
  model.p.append = function(chunks, p) {
    if (p == null) {
      return;
    }
    chunks = chunks.nodeType || typeof chunks === "string" ? [chunks] : chunks;
    if (chunks.length > 0) {
      if (p.childNodes.length === 1 && p.firstChild.tagName === "BR") {
        goog.dom.removeNode(p.firstChild);
      }
      goog.array.forEach(chunks, function(chunk) {
        if (typeof chunk === "string") {
          chunk = model.chunk.fromText(chunk);
        }
        var root = model.chunk.root(chunk);
        var leafCount = goog.array.reduce(model.chunk.leaves(chunk), function(count, leaf) {
          if (leaf.nodeType === Node.TEXT_NODE && leaf.data.length === 0) {
            if (leaf.parentElement != null) {
              goog.dom.removeNode(leaf);
            }
          } else {
            count++;
          }
          return count;
        }, 0);
        if (leafCount > 0) {
          p.appendChild(model.chunk.root(chunk));
        }
      });
      if (p.childNodes.length === 0) {
        p.appendChild(document.createElement("br"));
      }
    }
  };
  model.p.removeAllFormatting = function(p) {
    p.removeAttribute("style");
  };
  model.p.setStyle = function(name, value, p) {
    if (p == null) {
      return;
    }
    p.style[name] = value;
  };
  model.p.clearStyle = function(name, p) {
    if (p == null) {
      return;
    }
    p.style[name] = "";
    if (p.style.cssText === "") {
      p.removeAttribute("style");
    }
  };
  model.p.justify = function(alignment, p) {
    if (model.p["justify" + alignment]) {
      model.p["justify" + alignment](p);
    }
  };
  model.p.justifyleft = function(p) {
    model.p.clearStyle("text-align", p);
  };
  model.p.justifycenter = function(p) {
    model.p.setStyle("text-align", "center", p);
  };
  model.p.justifyright = function(p) {
    model.p.setStyle("text-align", "right", p);
  };
  model.p.justifyfull = function(p) {
    model.p.setStyle("text-align", "justify", p);
  };
  model.p.justifyValue = function(p) {
    if (p == null) {
      return;
    }
    var result = p.style.textAlign;
    if (result === "") {
      result = "left";
    }
    return result;
  };
  model.p.indent = function(p) {
    var margin = parseFloat(p.style.marginLeft) || 0;
    p.style.marginLeft = margin + uno.defs.paragraph.indent + "px";
  };
  model.p.indentLevel = function(p) {
    var margin = parseFloat(p.style.marginLeft) || 0;
    return margin / uno.defs.paragraph.indent;
  };
  model.p.outdent = function(p) {
    var margin = parseFloat(p.style.marginLeft) || 0;
    if (margin > uno.defs.paragraph.indent) {
      p.style.marginLeft = margin - uno.defs.paragraph.indent + "px";
    } else {
      if (margin === uno.defs.paragraph.indent) {
        p.style.marginLeft = "";
        if (p.style.cssText === "") {
          p.removeAttribute("style");
        }
      }
    }
  };
  model.p.rangeInfoForStart = function(p) {
    var offset;
    var chunk;
    if (p.childNodes.length === 0) {
      return {container:p.parentElement, offset:util.dom.index(p)};
    } else {
      chunk = p.firstChild;
      return model.chunk.rangeInfoForStart(chunk);
    }
  };
  model.p.rangeInfoForEnd = function(p) {
    var offset;
    var chunk;
    if (p.childNodes.length === 0) {
      p.appendChild(document.createElement("br"));
    }
    chunk = p.lastChild;
    return model.chunk.rangeInfoForEnd(chunk);
  };
  model.p.placeCursorAtStart = function(p) {
    util.range.selectFromInfo(model.p.rangeInfoForStart(p));
  };
  model.p.placeCursorAtEnd = function(p) {
    util.range.selectFromInfo(model.p.rangeInfoForEnd(p));
  };
  model.p.isEmpty = function(p) {
    if (p == null) {
      return;
    }
    var nodes = p.childNodes;
    if (nodes.length === 0) {
      return true;
    }
    return !goog.array.some(nodes, function(node) {
      return node.tagName !== "BR" && node.data !== "";
    });
  };
  model.p.getEndingFormat = function(p) {
    var chunk;
    if (p.childNodes.length === 0) {
      return {};
    }
    if (p.lastChild.tagName === "BR" && p.childNodes.length > 1) {
      chunk = p.childNodes[p.childNodes.length - 2];
    } else {
      chunk = p.lastChild;
    }
    return model.fmt.getFormatting(chunk);
  };
  model.p.splitAt = function(container, offset, p) {
    var newP;
    var chunks;
    var boundary = util.range.boundary(container, offset);
    var chunk = boundary;
    if (offset === 0) {
      chunks = [chunk].concat(model.chunk.nextChunks(chunk));
    } else {
      if (model.chunk.canSplit(chunk, offset, offset)) {
        chunk = model.chunk.split(chunk, offset, offset);
      }
      chunks = model.chunk.nextChunks(chunk);
      if (chunks.length === 0) {
        chunks.push(document.createElement("br"));
        model.fmt.applyFormatting(model.fmt.getFormatting(chunk), chunks[0]);
      }
    }
    newP = model.p.create(chunks);
    goog.dom.insertSiblingAfter(newP, p);
    if (p.childNodes.length === 0) {
      p.appendChild(document.createElement("br"));
    }
    return newP;
  };
  model.p.isStartPos = function(container, offset, p) {
    var boundary = util.range.boundary(container, offset);
    var result = false;
    if (offset === 0) {
      result = boundary === p || p.firstChild === model.chunk.root(boundary);
    }
    return result;
  };
  model.p.addTodo = function(p) {
    if (p == null) {
      return;
    }
    var todo = model.todo.create();
    model.p.prepend(todo, p);
    return todo;
  };
  model.p.removeTodo = function(p) {
    var todo = model.p.getTodo(p);
    model.chunk.removeLeaf(todo);
    if (p.firstChild == null) {
      p.appendChild(document.createElement("br"));
    }
  };
  model.p.getTodo = function(p) {
    if (p == null) {
      return;
    }
    var chunk = model.p.firstChunk(p);
    var firstLeaf = chunk && model.chunk.firstLeaf(chunk);
    if (model.todo.is(firstLeaf)) {
      return firstLeaf;
    }
  };
  model.p.startsWithTodo = function(p) {
    return model.p.getTodo(p) != null;
  };
  model.p.toggleTodo = function(p) {
    var todo = model.p.getTodo(p);
    model.todo.toggle(todo);
  };
  model.p.hasVisibleContent = function(p, opt) {
    var contentTags = "en-media,embed,img,object";
    var result;
    if (!p) {
      log.warning("hasVisibleContent p is null");
      return false;
    }
    opt = opt || {};
    result = goog.array.some(p.querySelectorAll(contentTags), function(el) {
      return el !== opt.excluding;
    });
    if (!result) {
      result = !goog.string.isEmptyOrWhitespace(p.innerText);
    }
    return result;
  };
})();
goog.provide("uno.model.codeblock");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.model.p");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.codeblock");
  var model = uno.model;
  var util = uno.util;
  model.section.types.push(model.codeblock);
  model.codeblock.create = function(paragraphs) {
    if (paragraphs == null) {
      paragraphs = [];
    }
    if (paragraphs.length === 0) {
      paragraphs.push(model.p.create());
    }
    var codeblock = goog.dom.createDom("en-codeblock", null, paragraphs);
    return codeblock;
  };
  model.codeblock.is = function(node) {
    return node != null && node.tagName === "EN-CODEBLOCK";
  };
  model.codeblock.for = function(node) {
    var type;
    if (node == null) {
      return null;
    }
    while (!model.codeblock.is(node) && !model.origin.is(node) && node.parentElement != null) {
      node = node.parentElement;
    }
    if (model.codeblock.is(node)) {
      return node;
    }
  };
  model.codeblock.wrap = function(paragraphs) {
    var codeblock = model.codeblock.create();
    paragraphs = paragraphs || [];
    if (!Array.isArray(paragraphs)) {
      paragraphs = [paragraphs];
    }
    if (paragraphs.length != 0) {
      goog.dom.removeChildren(codeblock);
      goog.dom.replaceNode(codeblock, paragraphs[0]);
    }
    goog.array.forEach(paragraphs, function(p) {
      codeblock.appendChild(p);
    });
    return codeblock;
  };
  model.codeblock.unwrap = function(codeblock) {
    goog.dom.flattenElement(codeblock);
  };
  model.codeblock.all = function(root) {
    return root.querySelectorAll("en-codeblock");
  };
  model.codeblock.allFromRange = function(range) {
    var results = [];
    var start = model.codeblock.firstFromRange(range);
    if (start != null) {
      results.push(start);
    }
    results = results.concat(util.range.queryTagNamesAll("en-codeblock", range));
    return results;
  };
  model.codeblock.firstFromRange = function(range) {
    if (range == null) {
      return;
    }
    var start = util.range.boundary(range.getStartNode(), range.getStartOffset());
    var result = model.codeblock.for(start);
    if (result == null) {
      result = util.range.queryTagNames("en-codeblock", range);
    }
    return result;
  };
  model.codeblock.lastFromRange = function(range) {
    if (range == null) {
      return;
    }
    var end = util.range.boundary(range.getEndNode(), range.getEndOffset());
    var result = model.codeblock.for(end);
    if (result == null) {
      var codeblocks = util.range.queryTagNamesAll("en-codeblock", range);
      if (codeblocks.length > 0) {
        result = codeblocks[codeblocks.length - 1];
      }
    }
    return result;
  };
  model.codeblock.rangeInfoForStart = function(codeblock) {
    var section;
    var info;
    if (model.codeblock.is(codeblock)) {
      section = uno.model.origin.firstSection(codeblock);
      info = uno.model.section.rangeInfoForStart(section);
    }
    return info;
  };
  model.codeblock.rangeInfoForEnd = function(codeblock) {
    var section;
    var info;
    if (model.codeblock.is(codeblock)) {
      section = uno.model.origin.lastSection(codeblock);
      info = uno.model.section.rangeInfoForEnd(section);
    }
    return info;
  };
  model.codeblock.placeCursorAtStart = function(codeblock) {
    var section;
    if (model.codeblock.is(codeblock)) {
      section = uno.model.origin.firstSection(codeblock);
      uno.model.section.placeCursorAtStart(section);
    }
  };
  model.codeblock.placeCursorAtEnd = function(codeblock) {
    var section;
    if (model.codeblock.is(codeblock)) {
      section = uno.model.origin.lastSection(codeblock);
      uno.model.section.placeCursorAtEnd(section);
    }
  };
  model.codeblock.isEmpty = function(codeblock) {
    var section;
    var result = false;
    if (model.codeblock.is(codeblock)) {
      section = model.origin.firstSection(codeblock);
      if (section == null) {
        result = true;
      } else {
        if (model.p.is(section) && model.p.isEmpty(section)) {
          result = true;
        }
      }
    }
    return result;
  };
})();
goog.provide("uno.util.strict.range");
goog.require("goog.dom.Range");
goog.require("uno.model.chunk");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.util.range");
(function() {
  var model = uno.model;
  var util = uno.util;
  util.strict.range.tighten = function(range) {
    var tightRange = range;
    if (range != null && !range.isCollapsed()) {
      var p = model.p.for(range.getEndNode());
      if (p != null) {
        var firstChunk = model.p.firstChunk(p);
        var firstRoot = model.chunk.root(firstChunk);
        var firstLeaf = model.chunk.firstLeaf(firstChunk);
        if (range.getEndOffset() === 0 && (range.getEndNode() === p || range.getEndNode() === firstLeaf || range.getEndNode() === firstLeaf.parentElement)) {
          var prevSection = model.section.previousSection(p);
          if (prevSection != null) {
            var endInfo = model.section.rangeInfoForEnd(prevSection);
            var endBoundary = util.range.boundary(endInfo.container, endInfo.offset);
            if (range.containsNode(endBoundary)) {
              tightRange = goog.dom.Range.createFromNodes(range.getStartNode(), range.getStartOffset(), endInfo.container, endInfo.offset);
            }
          }
        }
      }
    }
    return tightRange;
  };
})();
goog.provide("uno.commands.strict.CodeBlock");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.codeblock");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.util.range");
goog.require("uno.util.strict.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.CodeBlock");
  var Chunk = uno.model.Chunk;
  var model = uno.model;
  var util = uno.util;
  var CodeBlock = uno.commands.strict.CodeBlock = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CodeBlock, uno.BasePlugin);
  CodeBlock.prototype.isSupportedCommand = function(command) {
    return command === "codeblock";
  };
  CodeBlock.prototype.execCommandInternal = function(command, value) {
    var paragraphs;
    var remove;
    var refSection;
    var range = this.editor.getRange();
    var tightRange = util.strict.range.tighten(range);
    if (tightRange) {
      remove = this.queryCommandValue();
      if (remove) {
        codeblocks = model.codeblock.allFromRange(tightRange);
        goog.array.forEachRight(codeblocks, function(codeblock) {
          model.codeblock.unwrap(codeblock);
        });
      } else {
        paragraphs = model.p.allFromRange(tightRange);
        codeblock = model.codeblock.wrap(paragraphs);
        model.codeblock.placeCursorAtEnd(codeblock);
        if (model.section.nextSection(codeblock) == null) {
          model.section.insertSiblingAfter(model.p.create(), codeblock);
        }
      }
    }
    return true;
  };
  CodeBlock.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    return model.codeblock.allFromRange(range).length > 0;
  };
  CodeBlock.prototype.queryCommandEnabled = function() {
    var range = this.editor.getRange();
    var hasForbiddenTags = !!util.range.queryTagNames(["hr", "ol", "ul", "table", "td", "tr"], range);
    var start = util.range.boundary(range.getStartNode(), range.getStartOffset());
    return !hasForbiddenTags && util.dom.getFirstAncestor(start, ["td"]) == null;
  };
})();
goog.provide("uno.commands.strict.ControlTodos");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.model.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.ControlTodos");
  var model = uno.model;
  var ControlTodos = uno.commands.strict.ControlTodos = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ControlTodos, uno.BasePlugin);
  ControlTodos.prototype.isSupportedCommand = function(command) {
    return command === "controltodos";
  };
  ControlTodos.prototype.execCommandInternal = function(command, state) {
    var todos = model.todo.all(this.editor.field);
    var range = this.editor.getRange();
    if (!range.isCollapsed()) {
      todos = goog.array.filter(todos, function(todo) {
        return range.containsNode(todo, true);
      });
    }
    goog.array.forEach(todos, function(todo) {
      if (state === "on") {
        model.todo.setChecked(true, todo);
      } else {
        if (state === "off") {
          model.todo.setChecked(false, todo);
        } else {
          model.todo.toggle(todo);
        }
      }
    });
  };
})();
goog.provide("uno.model.item");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.Range");
goog.require("uno.model.origin");
goog.require("uno.model.p");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.item");
  var Chunk = uno.model.Chunk;
  var model = uno.model;
  var util = uno.util;
  model.item.create = function(paragraphs) {
    if (paragraphs == null) {
      paragraphs = model.p.create();
    }
    if (!goog.isArrayLike(paragraphs)) {
      paragraphs = [paragraphs];
    }
    if (paragraphs.length === 0) {
      paragraphs = [model.p.create()];
    }
    return goog.dom.createDom("li", null, paragraphs);
  };
  model.item.is = function(node) {
    return node != null && node.tagName === "LI";
  };
  model.item.for = function(node) {
    if (node == null) {
      return;
    }
    if (node.nodeType === Node.TEXT_NODE && node.parentElement == null) {
      return;
    }
    var el = node.nodeType != Node.ELEMENT_NODE ? node.parentElement : node;
    while (!model.item.is(el) && !model.origin.is(el) && el.parentElement != null) {
      el = el.parentElement;
    }
    if (model.item.is(el)) {
      return el;
    }
  };
  model.item.toListItem = function(p) {
    var result = document.createElement("li");
    result.appendChild(p);
    return result;
  };
  model.item.allFromRange = function(range) {
    if (range == null) {
      return;
    }
    var elements;
    var results = [];
    var start = model.item.firstFromRange(range);
    var end = model.item.lastFromRange(range);
    var container = range.getContainer();
    if (container.nodeType !== Node.ELEMENT_NODE) {
      container = container.parentElement;
    }
    elements = container.querySelectorAll("li");
    results = goog.array.filter(elements, function(el) {
      return el !== start && el !== end && range.containsNode(el);
    });
    if (start != null) {
      results.unshift(start);
    }
    if (start !== end) {
      results.push(end);
    }
    return results;
  };
  model.item.firstFromRange = function(range) {
    var result;
    var container;
    var elements;
    if (range == null) {
      return;
    }
    if (range.getStartNode().nodeType === Node.ELEMENT_NODE) {
      result = model.item.for(range.getStartNode().childNodes[range.getStartOffset()]);
    } else {
      result = model.item.for(range.getStartNode());
    }
    if (result == null) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll("li");
      result = goog.array.find(elements, function(el) {
        return range.containsNode(el);
      });
    }
    return result;
  };
  model.item.lastFromRange = function(range) {
    var result;
    var container;
    var elements;
    if (range == null) {
      return;
    }
    if (range.getEndNode().nodeType === Node.ELEMENT_NODE) {
      result = model.item.for(range.getEndNode().childNodes[range.getEndOffset()]);
    } else {
      result = model.item.for(range.getEndNode());
    }
    if (result == null) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll("li");
      result = goog.array.findRight(elements, function(el) {
        return range.containsNode(el);
      });
    }
    return result;
  };
  model.item.indent = function(item) {
    var list = model.list.for(item);
    var prevSib = item.previousElementSibling;
    var nextSib = item.nextElementSibling;
    if (model.list.is(prevSib)) {
      prevSib.appendChild(item);
      if (nextSib && prevSib.tagName === nextSib.tagName) {
        model.list.join(prevSib, nextSib);
      }
    } else {
      if (model.list.is(nextSib)) {
        nextSib.insertBefore(item, nextSib.firstChild);
        if (prevSib && prevSib.tagName === nextSib.tagName) {
          model.list.join(prevSib, nextSib);
        }
      } else {
        var targetList = model.list.create(model.list.type(list));
        model.list.clear(targetList);
        model.section.insertSiblingAfter(targetList, item);
        targetList.appendChild(item);
      }
    }
  };
  model.item.outdent = function(item) {
    var precedingList;
    var trailingList;
    var sections;
    var list = model.list.for(item);
    if (item.nextElementSibling != null) {
      trailingList = model.list.splitBefore(item.nextElementSibling);
      goog.dom.insertSiblingAfter(trailingList, item);
    }
    if (item.previousElementSibling != null) {
      precedingList = list;
      list = model.list.splitBefore(item);
      goog.dom.insertSiblingAfter(list, precedingList);
    }
    goog.dom.flattenElement(list);
    if (!model.list.for(item)) {
      goog.dom.flattenElement(item);
    }
  };
  model.item.previousItem = function(item) {
    var el;
    if (item == null) {
      return;
    }
    el = item.previousElementSibling;
    if (el != null && el.tagName === "LI") {
      return el;
    }
  };
  model.item.nextItem = function(item) {
    var el;
    if (item == null) {
      return;
    }
    el = item.nextElementSibling;
    if (el != null && el.tagName === "LI") {
      return el;
    }
  };
  model.item.insertSiblingBefore = function(item, ref) {
    goog.dom.insertSiblingBefore(item, ref);
  };
  model.item.insertSiblingAfter = function(item, ref) {
    goog.dom.insertSiblingAfter(item, ref);
  };
  model.item.isEmpty = function(item) {
    var result = false;
    if (item != null && item.childNodes.length === 1) {
      result = model.p.is(item.firstChild) && model.p.isEmpty(item.firstChild);
    }
    return result;
  };
  model.item.remove = function(item) {
    if (item != null) {
      goog.dom.removeNode(item);
    }
  };
  model.item.updateEmpty = function(item) {
    if (item == null) {
      return;
    }
    goog.array.forEachRight(item.childNodes, function(node) {
      if (node.tagName === "BR") {
        goog.dom.replaceNode(model.p.create(), node);
      }
    });
    if (item.firstChild == null) {
      item.appendChild(model.p.create());
    }
  };
})();
goog.provide("uno.model.list");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.model.item");
goog.require("uno.model.origin");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.list");
  var model = uno.model;
  var util = uno.util;
  var LIST_TYPES = {ordered:{tagName:"OL"}, unordered:{tagName:"UL"}, todo:{tagName:"UL", className:"en-todo-list"}};
  var TAGS = Object.keys(LIST_TYPES).reduce(function(array, key) {
    if (array.indexOf(LIST_TYPES[key].tagName) === -1) {
      array.push(LIST_TYPES[key].tagName);
    }
    return array;
  }, []);
  var CLASSES = Object.keys(LIST_TYPES).reduce(function(array, key) {
    if (array.indexOf(LIST_TYPES[key].className) === -1) {
      array.push(LIST_TYPES[key].className);
    }
    return array;
  }, []);
  model.section.types.push(model.list);
  model.list.create = function(type) {
    if (type == null) {
      type = "ordered";
    }
    var el = goog.dom.createDom(LIST_TYPES[type].tagName, LIST_TYPES[type].className, model.item.create());
    return el;
  };
  model.list.is = function(node) {
    return node && TAGS.indexOf(node.tagName) !== -1;
  };
  model.list.isListType = function(type, node) {
    var result = node && node.tagName === LIST_TYPES[type].tagName;
    if (result && LIST_TYPES[type].className != null) {
      result = node.classList.contains(LIST_TYPES[type].className);
    }
    return result;
  };
  model.list.for = function(node) {
    if (node == null) {
      return;
    }
    if (node.nodeType === Node.TEXT_NODE && node.parentElement == null) {
      return;
    }
    var el = node.nodeType != Node.ELEMENT_NODE ? node.parentElement : node;
    while (!model.list.is(el) && (model.item.is(el) || !model.origin.is(el)) && el.parentElement != null) {
      el = el.parentElement;
    }
    if (model.list.is(el)) {
      return el;
    }
  };
  model.list.allFromRange = function(range) {
    if (range == null) {
      return;
    }
    var elements;
    var results = [];
    var start = model.list.firstFromRange(range);
    var end = model.list.lastFromRange(range);
    var container = range.getContainer();
    if (container.nodeType !== Node.ELEMENT_NODE) {
      container = container.parentElement;
    }
    elements = container.querySelectorAll(TAGS.join(","));
    results = goog.array.filter(elements, function(el) {
      return el !== start && el !== end && range.containsNode(el);
    });
    if (start != null) {
      results.unshift(start);
    }
    if (start !== end) {
      results.push(end);
    }
    return results;
  };
  model.list.firstFromRange = function(range) {
    var result;
    var container;
    var elements;
    if (range == null) {
      return;
    }
    if (range.getStartNode().nodeType === Node.ELEMENT_NODE) {
      result = model.list.for(range.getStartNode().childNodes[range.getStartOffset()]);
    } else {
      result = model.list.for(range.getStartNode());
    }
    if (result == null) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll(TAGS.join(","));
      result = goog.array.find(elements, function(el) {
        return range.containsNode(el);
      });
    }
    return result;
  };
  model.list.lastFromRange = function(range) {
    var result;
    var container;
    var elements;
    if (range == null) {
      return;
    }
    if (range.getEndNode().nodeType === Node.ELEMENT_NODE) {
      result = model.list.for(range.getEndNode().childNodes[range.getEndOffset()]);
    } else {
      result = model.list.for(range.getEndNode());
    }
    if (result == null) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll(TAGS.join(","));
      result = goog.array.findRight(elements, function(el) {
        return range.containsNode(el);
      });
    }
    return result;
  };
  model.list.type = function(listNode) {
    var result;
    var tagName = listNode.tagName;
    Object.keys(LIST_TYPES).some(function(type) {
      if (LIST_TYPES[type].tagName === tagName) {
        if (LIST_TYPES[type].className != null) {
          if (listNode.classList.contains(LIST_TYPES[type].className)) {
            result = type;
          }
        } else {
          if (!CLASSES.some(function(classname) {
            return listNode.classList.contains(classname);
          })) {
            result = type;
          }
        }
        return result != null;
      }
    });
    return result;
  };
  model.list.setType = function(type, list) {
    var newList;
    var className = LIST_TYPES[type].className;
    if (list == null || !model.list.is(list)) {
      return;
    }
    if (!model.list.isListType(type, list)) {
      if (list.tagName !== LIST_TYPES[type].tagName) {
        newList = model.list.create(type);
        model.list.clear(newList);
        util.dom.replaceContainer(list, newList);
        list = newList;
      }
      goog.dom.classlist.removeAll(list, CLASSES);
      if (className != null) {
        goog.dom.classlist.add(list, className);
      }
    }
  };
  model.list.splitBefore = function(itemOrList) {
    var list;
    var newList;
    if (itemOrList == null || !model.item.is(itemOrList) && !model.list.is(itemOrList)) {
      return;
    }
    if (model.item.is(itemOrList)) {
      list = model.list.for(itemOrList);
    } else {
      list = model.list.for(itemOrList.parentElement);
    }
    newList = model.list.create(model.list.type(list));
    model.list.clear(newList);
    while (itemOrList.nextSibling != null) {
      newList.appendChild(itemOrList.nextSibling);
    }
    newList.insertBefore(itemOrList, newList.firstChild);
    model.section.insertSiblingAfter(newList, list);
    return newList;
  };
  model.list.join = function(listA, listB) {
    util.dom.moveChildren(listB, listA);
    goog.dom.removeNode(listB);
  };
  model.list.itemCount = function(listNode) {
    return goog.array.reduce(listNode.querySelectorAll("li"), function(sum, li) {
      if (li.parentElement === listNode) {
        sum++;
      }
      return sum;
    }, 0);
  };
  model.list.rangeInfoForStart = function(listNode) {
    if (listNode.childNodes.length === 0) {
      listNode.appendChild(model.item.create());
    }
    return {container:listNode.querySelector("li"), offset:0};
  };
  model.list.rangeInfoForEnd = function(listNode) {
    if (listNode.childNodes.length === 0) {
      listNode.appendChild(model.item.create());
    }
    var nodes = listNode.querySelectorAll("li");
    var li = nodes[nodes.length - 1];
    return model.origin.rangeInfoForEnd(li);
  };
  model.list.placeCursorAtStart = function(listNode) {
    var li = model.list.firstItem(listNode);
    model.origin.placeCursorAtStart(li);
  };
  model.list.placeCursorAtEnd = function(listNode) {
    var li = model.list.lastItem(listNode);
    model.origin.placeCursorAtEnd(li);
  };
  model.list.children = function(list) {
    if (list == null) {
      return [];
    }
    return list.children;
  };
  model.list.items = function(list) {
    if (list == null) {
      return;
    }
    var items = goog.array.filter(list.children, function(child) {
      return child.tagName === "LI";
    });
    return items;
  };
  model.list.firstItem = function(list) {
    if (list == null) {
      return;
    }
    var node = list.firstChild;
    while (node != null && node.tagName !== "LI") {
      node = node.nextSibling;
    }
    return node;
  };
  model.list.lastItem = function(list) {
    if (list == null) {
      return;
    }
    var node = list.lastChild;
    while (node != null && node.tagName !== "LI") {
      node = node.previousSibling;
    }
    return node;
  };
  model.list.clear = function(list) {
    goog.dom.removeChildren(list);
  };
  model.list.appendItem = function(item, list) {
    list.appendChild(item);
  };
  model.list.appendList = function(list, refListNode) {
    util.dom.moveChildren(list, refListNode);
    model.section.remove(list);
  };
  model.list.startAt = function(number, list) {
    if (number != 1 || list.hasAttribute("start")) {
      list.setAttribute("start", number);
    }
  };
  model.list.parentListCount = function(list) {
    var count = 0;
    var el = list;
    while (el != null && el.tagName !== "EN-NOTE") {
      el = el.parentElement;
      if (TAGS.indexOf(el.tagName) !== -1) {
        count++;
      }
    }
    return count;
  };
  model.list.flatten = function(list) {
    goog.array.forEachRight(model.list.items(list), function(item) {
      goog.dom.flattenElement(item);
    });
    goog.dom.flattenElement(list);
  };
})();
goog.provide("uno.model.resource.generic");
goog.require("uno.util.canvas");
goog.require("uno.util.img");
(function() {
  var model = uno.model;
  var generic = uno.model.resource.generic;
  var util = uno.util;
  var resourceFillStyle = "#8E8E93";
  var resourceFontStyle = '12px "Helvetica Neue", Helvetica, Arial, sans';
  generic.findResourcesInClientHtml = function() {
    return [];
  };
  generic.findResourcesInClipboardHtml = function() {
    return [];
  };
  generic.convertMediaToSlug = function(enmedia, props, editor) {
    var slug;
    if (model.resource.isImage(props.type)) {
      slug = util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      slug = convertMediaToImage(enmedia, props, editor);
    }
    return slug;
  };
  function convertMediaToImage(enmedia, props, editor) {
    var img = model.resource.findByRef(props.reference, editor.field);
    if (img == null) {
      img = new Image;
      img.width = 160;
      img.height = 120;
      img.style.width = "160px";
      img.style.height = "120px";
      img.dataset.hash = props.hash;
      img.dataset.type = props.type;
    }
    var canvas = util.canvas.getScratchCanvas(img.width, img.height);
    var ctx = canvas.getContext("2d");
    var padding = 10;
    if (props.state === "unloaded") {
      renderUnloadedResource(ctx, img, props, padding);
    } else {
      if (props.state === "loading") {
        renderLoadingResource(ctx, img, props, padding);
      } else {
        if (props.state === "loaded" || props.state == null) {
          renderFilename(ctx, img, props, padding);
          if (props.thumbnailURL != null) {
            var thumbnail = new Image;
            thumbnail.src = props.thumbnailURL;
            editor.eventRegister.listenOnce(thumbnail, "load", function() {
              var newCanvas = util.canvas.getScratchCanvas(img.width, img.height);
              var newCtx = newCanvas.getContext("2d");
              var image = util.resource.findByRef(props.reference, editor.field);
              renderLoadedResource(newCtx, img, props, padding, thumbnail);
              image.src = newCanvas.toDataURL();
            });
          }
        }
      }
    }
    img.src = canvas.toDataURL();
    return img;
  }
  function renderLoadedResource(ctx, img, props, padding, thumbnail) {
    var dHeight = Math.min(thumbnail.height, 48);
    var dWidth = dHeight / thumbnail.height * thumbnail.width;
    ctx.drawImage(thumbnail, (img.width - dWidth) / 2, padding, dWidth, dHeight);
    renderFilename(ctx, img, props, padding);
  }
  function renderFilename(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.filename != null) {
      var filename = props.filename;
      var len = filename.length - 4;
      var metrics = ctx.measureText(filename);
      while (metrics.width > img.width - padding * 2 && len > 0) {
        filename = props.filename.substring(0, len) + "...";
        len--;
        metrics = ctx.measureText(filename);
      }
      ctx.fillText(filename, img.width / 2, img.height * 0.75);
    }
    ctx.restore();
  }
  function renderUnloadedResource(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.title != null) {
      ctx.save();
      ctx.fillStyle = "#167EFB";
      ctx.font = '700 14px "Helvetica Neue", Helvetica, Arial, sans';
      ctx.textAlign = "center";
      ctx.fillText(props.title, img.width / 2, img.height * 0.25);
      ctx.restore();
    }
    if (props.filesize != null) {
      ctx.fillText(props.filesize, img.width / 2, img.height * 0.75 + 15);
    }
    ctx.restore();
    renderFilename(ctx, img, props, padding);
  }
  function renderLoadingResource(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.downloaded != null) {
      ctx.fillText(props.downloaded, img.width / 2, img.height * 0.75 + 15);
    }
    var progress = Math.max(Math.min(1, props.progress), 0);
    var cx = img.width / 2;
    var cy = img.height * 0.25;
    var radius = 25;
    ctx.lineWidth = 3;
    ctx.strokeStyle = "#dedede";
    ctx.beginPath();
    ctx.arc(cx, cy, radius, 0, 2 * Math.PI, false);
    ctx.stroke();
    ctx.fillStyle = "#dedede";
    ctx.beginPath();
    ctx.arc(cx, cy, radius, util.canvas.rad(360 * progress - 90), util.canvas.rad(270), false);
    ctx.lineTo(cx, cy);
    ctx.closePath();
    ctx.fill();
    ctx.restore();
    renderFilename(ctx, img, props, padding);
  }
  generic.formatForExport = function(html) {
    return html;
  };
  generic.dictFromElement = function() {
    return {};
  };
  generic.dictFromClipboardElement = function() {
    return {};
  };
  generic.convertClientElementToSlug = function(el) {
    return el;
  };
  generic.convertSlugToClientElement = function(el) {
    return el;
  };
  generic.convertSlugToClipboardElement = function(slug) {
    return slug;
  };
  generic.toggleObjectsInRange = function(range, dict) {
    return false;
  };
})();
goog.provide("uno.model.resource.android");
goog.require("uno.model.resource.generic");
goog.require("uno.util.canvas");
goog.require("uno.util.img");
(function() {
  var model = uno.model;
  var android = model.resource.android;
  var generic = model.resource.generic;
  var util = uno.util;
  android.findResourcesInClientHtml = function(root) {
    return [];
  };
  android.findResourcesInClipboardHtml = function(root) {
    return [];
  };
  android.convertMediaToSlug = function(enmedia, props, editor) {
    var slug;
    if (model.resource.isImage(props.type)) {
      slug = util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      slug = convertMediaToImage(enmedia, props, editor);
    }
    return slug;
  };
  function convertMediaToImage(enmedia, props, editor) {
    var img = model.resource.findByRef(props.reference, editor.field);
    if (img == null) {
      img = new Image;
      img.width = 320;
      img.height = 40;
      img.style.width = "320px";
      img.style.height = "40px";
      img.dataset.hash = props.hash;
      img.dataset.type = props.type;
    }
    var canvas = util.canvas.getScratchCanvas(img.width, img.height);
    var ctx = canvas.getContext("2d");
    ctx.save();
    ctx.fillStyle = "#8E8E93";
    ctx.font = '12px "Helvetica Neue", Helvetica, Arial, sans';
    ctx.textAlign = "center";
    ctx.fillText(props.filename || "resource", img.width / 2, img.height / 2);
    ctx.restore();
    img.src = canvas.toDataURL();
    return img;
  }
  android.dictFromElement = function(el) {
    return {};
  };
  android.dictFromClipboardElement = function(el, context) {
    return {};
  };
  android.formatForExport = function(html) {
    return html;
  };
  android.convertClientElementToSlug = function(el) {
    return el;
  };
  android.convertSlugToClientElement = function(el) {
    return el;
  };
  android.convertSlugToClipboardElement = function(slug) {
    return slug;
  };
  android.toggleObjectsInRange = function(range, clonedObjects) {
    return false;
  };
})();
goog.provide("uno.model.resource.ios");
goog.require("uno.model.resource.generic");
goog.require("uno.util.dom");
goog.require("uno.util.img");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.resource.ios");
  var model = uno.model;
  var util = uno.util;
  var ios = model.resource.ios;
  var generic = model.resource.generic;
  var resourceFillStyle = "#8E8E93";
  var resourceFontStyle = '12px "Helvetica Neue", Helvetica, Arial, sans';
  ios.findResourcesInClientHtml = function(root) {
    return [];
  };
  ios.findResourcesInClipboardHtml = function(root) {
    return root.querySelectorAll("img:not(.en-todo):not(.en-crypt):not(.en-richlink)");
  };
  ios.convertMediaToSlug = function(enmedia, props, editor) {
    var slug;
    if (model.resource.isImage(props.type)) {
      slug = util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      slug = convertMediaToImage(enmedia, props, editor);
    }
    return slug;
  };
  function convertMediaToImage(enmedia, props, editor) {
    var img = model.resource.findByRef(props.reference, editor.field);
    if (img == null) {
      img = new Image;
      img.width = 160;
      img.height = 120;
      img.style.width = "160px";
      img.style.height = "120px";
      img.dataset.hash = props.hash;
      img.dataset.type = props.type;
    }
    var canvas = util.canvas.getScratchCanvas(img.width, img.height);
    var ctx = canvas.getContext("2d");
    var padding = 10;
    if (props.state === "unloaded") {
      renderUnloadedResource(ctx, img, props, padding);
    } else {
      if (props.state === "loading") {
        renderLoadingResource(ctx, img, props, padding);
      } else {
        if (props.state === "loaded" || props.state == null) {
          renderFilename(ctx, img, props, padding);
          if (props.thumbnailURL != null) {
            var thumbnail = new Image;
            thumbnail.src = props.thumbnailURL;
            editor.eventRegister.listenOnce(thumbnail, "load", function() {
              var canvas = util.canvas.getScratchCanvas(img.width, img.height);
              var ctx = canvas.getContext("2d");
              var image = util.resource.findByRef(props.reference, editor.field);
              renderLoadedResource(ctx, img, props, padding, thumbnail);
              image.src = canvas.toDataURL();
            });
          }
        }
      }
    }
    img.src = canvas.toDataURL();
    return img;
  }
  function renderUnloadedResource(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.title != null) {
      ctx.save();
      ctx.fillStyle = "#167EFB";
      ctx.font = '700 14px "Helvetica Neue", Helvetica, Arial, sans';
      ctx.textAlign = "center";
      ctx.fillText(props.title, img.width / 2, img.height * .25);
      ctx.restore();
    }
    if (props.filesize != null) {
      ctx.fillText(props.filesize, img.width / 2, img.height * .75 + 15);
    }
    ctx.restore();
    renderFilename(ctx, img, props, padding);
  }
  function renderLoadingResource(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.downloaded != null) {
      ctx.fillText(props.downloaded, img.width / 2, img.height * .75 + 15);
    }
    var progress = Math.max(Math.min(1, props.progress), 0);
    var cx = img.width / 2;
    var cy = img.height * .25;
    var radius = 25;
    ctx.lineWidth = 3;
    ctx.strokeStyle = "#dedede";
    ctx.beginPath();
    ctx.arc(cx, cy, radius, 0, 2 * Math.PI, false);
    ctx.stroke();
    ctx.fillStyle = "#dedede";
    ctx.beginPath();
    ctx.arc(cx, cy, radius, util.canvas.rad(360 * progress - 90), util.canvas.rad(270), false);
    ctx.lineTo(cx, cy);
    ctx.closePath();
    ctx.fill();
    ctx.restore();
    renderFilename(ctx, img, props, padding);
  }
  function renderLoadedResource(ctx, img, props, padding, thumbnail) {
    var dHeight = Math.min(thumbnail.height, 48);
    var dWidth = dHeight / thumbnail.height * thumbnail.width;
    ctx.drawImage(thumbnail, (img.width - dWidth) / 2, padding, dWidth, dHeight);
    renderFilename(ctx, img, props, padding);
  }
  function renderFilename(ctx, img, props, padding) {
    ctx.save();
    ctx.fillStyle = resourceFillStyle;
    ctx.font = resourceFontStyle;
    ctx.textAlign = "center";
    if (props.filename != null) {
      var filename = props.filename;
      var len = filename.length - 4;
      var metrics = ctx.measureText(filename);
      while (metrics.width > img.width - padding * 2 && len > 0) {
        filename = props.filename.substring(0, len) + "...";
        len--;
        metrics = ctx.measureText(filename);
      }
      ctx.fillText(filename, img.width / 2, img.height * .75);
    }
    ctx.restore();
  }
  ios.decorateMedia = function(enmedia, props) {
    enmedia.dataset.url = props.url;
    goog.dom.append(enmedia, goog.dom.createDom("en-ux", {}, [goog.dom.createDom("span", {class:"en-resource-progress"}, goog.dom.createDom("span", {class:"en-resource-progress-fill"}, goog.dom.createDom("span", {class:"en-resource-progress-mask"}))), goog.dom.createDom("span", {class:"en-resource-icon"}, goog.dom.createDom("img", {src:props.thumbnailURL})), goog.dom.createDom("span", {class:"en-resource-title"}, props.title), goog.dom.createDom("span", {class:"en-resource-name"}, props.filename), 
    goog.dom.createDom("span", {class:"en-resource-value"}, props.state == "loading" ? props.downloaded : props.filesize)]));
    if (props.state) {
      goog.dom.classes.add(enmedia, props.state);
    }
    if (props.state === "loading") {
      var value = Math.max(Math.min(1, props.progress), 0);
      var halfValue = value > 0.5 ? value - 0.5 : value;
      var progressFill = enmedia.querySelector(".en-resource-progress-fill");
      goog.style.setStyle(progressFill, "-webkit-transform", "rotate(" + 360 * value + "deg)");
      var progressMask = progressFill.children[0];
      goog.style.setStyle(progressMask, "-webkit-transform", "rotate(" + -180 * halfValue * 2 + "deg)");
      goog.style.setStyle(progressMask, "background", value * 2 <= 1 ? "#fff" : "#dedede");
    }
    if (props.overlayOpacity > 0) {
      goog.dom.classes.add(enmedia, "overlayed");
      var overlay = goog.dom.createDom("span", {class:"en-resource-overlay"});
      overlay.style.backgroundColor = "rgba(0, 0, 0, " + props.overlayOpacity + ")";
      enmedia.appendChild(overlay);
    }
    return enmedia;
  };
  ios.dictFromElement = function(el) {
    return {};
  };
  ios.dictFromClipboardElement = function(el, context) {
    var dict;
    if (util.dom.compareTagName(el, "img")) {
      dict = context.resources[el.getAttribute("src")];
    } else {
      log.severe("ios resource from clipboard is not an img");
      if (el) {
        log.info("ios.dictFromClipboardElement received " + el.tagName);
      }
    }
    return dict;
  };
  ios.formatForExport = function(html) {
    return html;
  };
  ios.convertClientElementToSlug = function(el) {
    return el;
  };
  ios.convertSlugToClientElement = function(el) {
    return el;
  };
  ios.convertSlugToClipboardElement = function(el) {
    return el;
  };
  ios.toggleObjectsInRange = function(range, clonedObjects) {
    return false;
  };
})();
goog.provide("uno.model.resource.mac");
goog.require("uno.util.img");
(function() {
  var model = uno.model;
  var mac = uno.model.resource.mac;
  var util = uno.util;
  var rxEmbedImplicitVoidTags = /<embed([^>]*[^/]\s*)>/g;
  mac.findResourcesInClientHtml = function(root) {
    return goog.array.filter(root.querySelectorAll('img:not(.en-todo):not(.en-crypt):not(.en-richlink),embed[id^="en-media"]'), function(el) {
      return el;
    });
  };
  mac.findResourcesInClipboardHtml = function(root) {
    return mac.findResourcesInClientHtml(root);
  };
  mac.convertMediaToSlug = function(enmedia, props, editor) {
    var slug;
    if (model.resource.isImage(props.type)) {
      slug = util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      if (model.resource.isPdf(props.type)) {
        slug = convertPdfMediaToSlug(enmedia, props);
      } else {
        slug = convertFileMediaToSlug(enmedia, props);
      }
    }
    if (props.elementId) {
      slug.id = props.elementId;
    }
    return slug;
  };
  mac.dictFromElement = function(el) {
    var hash = el.dataset.hash;
    var mime = el.dataset.type;
    var url = el.dataset.url;
    var elementId = "en-media:\u200b" + mime + ":" + hash + ":\u200bnone:\u200bnone";
    var width = el.getAttribute("width");
    var dict;
    if (mime && hash && url && url.indexOf("evernotecid") > -1) {
      dict = {url:url, mime:mime || util.dom.compareTagName(el, "img") && "image/unknown", hash:hash, elementId:elementId};
    } else {
      var data = (el.getAttribute("id") || ":::").split(":");
      dict = {url:el.src, mime:data[1] || util.dom.compareTagName(el, "img") && "image/unknown", hash:data[2], elementId:el.getAttribute("id")};
    }
    if (width != null && width != "") {
      dict.width = width;
    }
    return dict;
  };
  mac.dictFromClipboardElement = function(el, context) {
    return mac.dictFromElement(el);
  };
  mac.formatForExport = function(html) {
    if (html == null) {
      return html;
    }
    return html.replace(rxEmbedImplicitVoidTags, "<embed $1 />");
  };
  function convertPdfMediaToSlug(enmedia, props) {
    var attr = {src:props.url, type:"evernote/x-pdf", id:"en-media:application/pdf:" + props.hash};
    ["style", "width", "height"].forEach(function(name) {
      if (props[name]) {
        attr[name] = props[name];
      }
    });
    return goog.dom.createDom("embed", attr);
  }
  function convertFileMediaToSlug(enmedia, props) {
    var attr = {src:props.url, type:"evernote/x-attachment", id:"en-media:evernote/x-attachment:" + props.hash};
    ["style", "width", "height", "id"].forEach(function(name) {
      if (props[name]) {
        attr[name] = props[name];
      }
    });
    return goog.dom.createDom("embed", attr);
  }
  mac.convertClientElementToSlug = function(el, props, editor) {
    if (util.resource.isImage(props.type)) {
      return util.img.convertClientElementToSlug(el, props, editor);
    }
    return el;
  };
  mac.convertSlugToClientElement = function(el) {
    return el;
  };
  mac.convertSlugToClipboardElement = function(slug) {
    return slug;
  };
  mac.toggleObjectsInRange = function(range, clonedObjects) {
    return false;
  };
})();
goog.provide("uno.model.resource.win");
goog.require("goog.array");
goog.require("uno.util.dom");
goog.require("uno.util.img");
(function() {
  var model = uno.model;
  var win = model.resource.win;
  var util = uno.util;
  win.findResourcesInClientHtml = function(root) {
    return goog.array.filter(root.querySelectorAll('img:not(.en-todo):not(.en-crypt):not(.en-richlink):not([src^="en-resource://database/pprotect:"]), object'), function(el) {
      return util.dom.compareTagName(el, "object") || !/\/check/i.test(el.src);
    });
  };
  win.findResourcesInClipboardHtml = function(root) {
    return win.findResourcesInClientHtml(root);
  };
  win.convertMediaToSlug = function(enmedia, props, editor) {
    if (model.resource.isImage(props.type)) {
      return util.img.convertMediaToSlug(enmedia, props, editor);
    } else {
      return createFileSlug(enmedia, props);
    }
  };
  function createFileSlug(enmedia, props) {
    var slug = goog.dom.createDom("object", {data:props.url, type:props.type}, goog.dom.createDom("param", {name:"filename", value:props.filename}));
    if (props.width != null) {
      slug.setAttribute("width", props.width);
    }
    if (props.height != null) {
      slug.setAttribute("height", props.height);
    }
    if (props.style != null) {
      slug.setAttribute("style", props.style);
    }
    return slug;
  }
  win.dictFromElement = function(el) {
    var mime = el.getAttribute("type");
    var url = el.getAttribute("data");
    var style = el.getAttribute("style");
    var width = el.getAttribute("width");
    var height = el.getAttribute("height");
    var paramFilename = el.querySelector("param[name=filename]");
    var paramUrl = el.querySelector("param[name=data]");
    if (paramFilename) {
      paramFilename = paramFilename.value;
    }
    if (!url && paramUrl) {
      url = paramUrl.value;
    }
    var dict;
    if (url && url.indexOf("en-resource") > -1) {
      dict = {url:url, mime:mime || util.dom.compareTagName(el, "img") && "image/unknown"};
    } else {
      dict = {url:el.src, mime:el.getAttribute("type") || util.dom.compareTagName(el, "img") && "image/unknown"};
    }
    if (style) {
      dict.style = style;
    }
    if (width) {
      dict.width = width;
    }
    if (height && dict.mime.indexOf("image/") < 0) {
      dict.height = height;
    }
    if (paramFilename) {
      dict.filename = paramFilename;
    }
    return dict;
  };
  win.dictFromClipboardElement = function(el) {
    return win.dictFromElement(el);
  };
  win.formatForExport = function(html) {
    return html;
  };
  win.convertClientElementToSlug = function(el) {
    return el;
  };
  win.convertSlugToClientElement = function(el) {
    return el;
  };
  win.convertSlugToClipboardElement = function(slug) {
    return slug;
  };
  win.toggleObjectsInRange = function(range, clonedObjects) {
    clonedObjects = clonedObjects || [];
    var containerNode;
    if (range.isCollapsed()) {
      containerNode = range.getStartNode();
    } else {
      containerNode = range.getContainerElement();
    }
    if (util.dom.isTextNode(containerNode)) {
      return false;
    }
    var objects = containerNode.querySelectorAll("object");
    if (!!clonedObjects.length) {
      goog.array.forEach(objects, function(brokenObject) {
        var brokenObjectNodeAttrs = util.dom.attributes(brokenObject);
        goog.array.forEach(clonedObjects, function(clonedObject) {
          var clonedObjectAttrs = util.dom.attributes(clonedObject);
          if (brokenObjectNodeAttrs["data-reference"] === clonedObjectAttrs["data-reference"] && brokenObjectNodeAttrs["data-filename"] === clonedObjectAttrs["data-filename"] && brokenObjectNodeAttrs["data-url"] === clonedObjectAttrs["data-url"]) {
            brokenObject.parentNode.replaceChild(clonedObject, brokenObject);
          }
        });
      });
    } else {
      goog.array.forEach(objects, function(brokenObject) {
        clonedObjects.push(brokenObject.cloneNode(true));
      });
      return clonedObjects;
    }
    return false;
  };
})();
goog.provide("uno.model.resource");
goog.require("goog.debug.Logger");
goog.require("uno.model.chunk");
goog.require("uno.model.resource.android");
goog.require("uno.model.resource.generic");
goog.require("uno.model.resource.ios");
goog.require("uno.model.resource.mac");
goog.require("uno.model.resource.win");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.resource");
  var model = uno.model;
  model.resource.counter = 0;
  var client = uno.model.resource.generic;
  model.resource.all = function(root) {
    if (root == null) {
      return [];
    }
    return root.querySelectorAll("en-media");
  };
  model.resource.setClient = function(clientName) {
    client = uno.model.resource[clientName] || client;
  };
  model.resource.fromClientDict = function(dict, editor) {
    var enmedia = goog.dom.createElement("en-media");
    enmedia.setAttribute("type", dict.mime);
    enmedia.setAttribute("hash", dict.hash);
    if (dict.style) {
      enmedia.setAttribute("style", dict.style);
    }
    if (dict.width) {
      enmedia.setAttribute("width", dict.width);
    }
    if (dict.height) {
      enmedia.setAttribute("height", dict.height);
    }
    return model.resource.fromMedia(enmedia, dict, editor);
  };
  model.resource.fromMedia = function(enmedia, dict, editor) {
    var props = {};
    var enmlProps = propsFromEnml(enmedia);
    Object.keys(enmlProps).forEach(function(key) {
      if (enmlProps[key] == null) {
        delete enmlProps[key];
      }
    });
    goog.object.extend(props, propsFromDict(dict), enmlProps);
    props.reference = props.reference || enmedia.dataset.reference || createUid();
    var slug = client.convertMediaToSlug(enmedia, props, editor);
    if (model.resource.isImage(props.type)) {
      slug.removeAttribute("height");
    }
    addMetaData(slug, props);
    if (props.style != null) {
      var style = slug.getAttribute("style") || "";
      slug.setAttribute("style", style + props.style);
    }
    if (props.hidden === true) {
      goog.style.setStyle(slug, "display", "none");
    }
    addCssClasses(slug, props.type);
    return slug;
  };
  function propsFromEnml(enmedia) {
    if (!enmedia) {
      return {};
    }
    return {hash:enmedia.getAttribute("hash"), type:enmedia.getAttribute("type"), width:enmedia.getAttribute("width"), height:enmedia.getAttribute("height"), style:enmedia.getAttribute("style"), align:enmedia.getAttribute("align"), alt:enmedia.getAttribute("alt"), longdesc:enmedia.getAttribute("longdesc"), title:enmedia.getAttribute("title"), lang:enmedia.getAttribute("lang"), dir:enmedia.getAttribute("dir"), border:enmedia.getAttribute("border"), hspace:enmedia.getAttribute("hspace"), vspace:enmedia.getAttribute("vspace"), 
    usemap:enmedia.getAttribute("usemap")};
  }
  function propsFromDict(dict) {
    if (!dict) {
      return {};
    }
    return {contextURL:dict.contextURL, defaultActionURL:dict.defaultActionURL, downloaded:dict.downloaded, dpi:dict.dpi, filename:dict.filename, filesize:dict.filesize, hash:dict.hash, height:dict.height, hidden:dict.hidden === true, elementId:dict.elementId, overlayImageURL:dict.overlayImageURL, overlayColor:dict.overlayColor, overlayOpacity:dict.overlayOpacity, progress:dict.progress, reference:dict.reference, state:dict.state, thumbnailURL:dict.thumbnailURL, title:dict.title, type:dict.mime.toLowerCase(), 
    url:dict.url, width:dict.width};
  }
  function addMetaData(el, props) {
    if (props.reference != null) {
      el.dataset.reference = props.reference;
    }
    if (props.hash != null) {
      el.dataset.hash = props.hash;
    }
    if (props.type != null) {
      el.dataset.type = props.type;
    }
    if (props.filename != null) {
      el.dataset.filename = props.filename;
    }
    if (props.filesize != null) {
      el.dataset.filesize = props.filesize;
    }
    if (props.thumbnailURL != null) {
      el.dataset.thumbnailUrl = props.thumbnailURL;
    }
    if (props.title != null) {
      el.dataset.title = props.title;
    }
    if (props.url != null) {
      el.dataset.url = props.url;
    }
    if (props.dpi != null) {
      el.dataset.dpi = props.dpi;
    }
  }
  function addCssClasses(el, type) {
    goog.dom.classlist.add(el, "en-media");
    if (model.resource.isImage(type)) {
      goog.dom.classlist.add(el, "en-media-image");
    } else {
      goog.dom.classlist.add(el, "en-media-file");
      if (model.resource.isPdf(type)) {
        goog.dom.classlist.add(el, "en-media-pdf");
      }
    }
  }
  model.resource.dictFromResource = function(res) {
    if (!res) {
      return {};
    }
    return {filename:res.dataset.filename, filesize:res.dataset.filesize, hash:res.getAttribute("hash") || res.dataset.hash, reference:res.dataset.reference, thumbnailURL:res.dataset.thumbnailUrl, title:res.dataset.title, mime:res.getAttribute("type") || res.dataset.type, url:res.dataset.url, dpi:res.dataset.dpi};
  };
  model.resource.isImage = function(elOrMime) {
    var mime = (parseMime(elOrMime) || "").toLowerCase();
    var isImage = mime.indexOf("image/") === 0;
    var isPsd = mime === "image/vnd.adobe.photoshop";
    var isXcf = mime === "image/x-xcf";
    var isInk = mime === "application/vnd.evernote.ink";
    return isInk || isImage && !isPsd && !isXcf;
  };
  model.resource.isPdf = function(elOrMime) {
    var mimes = ["application/pdf", "evernote/x-pdf", "application/x-evernote-pdf"];
    var mime = util.resource.parseMime(elOrMime);
    return mime && mimes.indexOf(mime.toLowerCase()) != -1;
  };
  model.resource.isFileUI = function(el) {
    return goog.dom.classes.has(el, "en-media-file");
  };
  model.resource.mimeTypeFor = function(el) {
    return el.getAttribute("type") || el.getAttribute("data-type");
  };
  function parseMime(elOrMime) {
    var mime;
    if (elOrMime.getAttribute) {
      mime = model.resource.mimeTypeFor(elOrMime);
    } else {
      if (typeof elOrMime === "string") {
        mime = elOrMime;
      }
    }
    return mime;
  }
  model.resource.slug = function(res) {
    var root = model.chunk.root(res);
    return root && root.querySelector(".en-media");
  };
  model.resource.scrollIntoView = function(res) {
    var slug = model.resource.slug(res);
    if (slug === null) {
      return;
    }
    if (!slug.naturalHeight) {
      slug.onload = function() {
        slug.onload = null;
        slug.scrollIntoView();
      };
    } else {
      slug.scrollIntoView();
    }
  };
  function createUid() {
    return "resource-" + model.resource.counter++;
  }
  model.resource.findByRef = function(ref, node) {
    var selector = '.en-media[data-reference="' + ref + '"]';
    var el = node.querySelector(selector);
    return el;
  };
  model.resource.findByURL = function(url, node) {
    var selector = '.en-media[data-url="' + url + '"]';
    return node.querySelectorAll(selector);
  };
  model.resource.findByHash = function(hash, node) {
    var selector = '.en-media[data-hash="' + hash + '"]';
    return node.querySelectorAll(selector);
  };
  model.resource.replace = function(newRes, refRes) {
    goog.dom.replaceNode(newRes, refRes);
  };
  model.resource.remove = function(res) {
    model.chunk.removeLeaf(res);
  };
})();
goog.provide("uno.util.strict.copy.plain");
goog.require("uno.model.fmt");
goog.require("uno.model.list");
goog.require("uno.model.resource");
goog.require("uno.model.todo");
(function() {
  var model = uno.model;
  var util = uno.util;
  util.strict.copy.plain.copy = function(root) {
    var resources = model.resource.all(root);
    goog.array.forEach(resources, function(res) {
      model.resource.remove(res);
    });
    var a = root.querySelectorAll("a");
    goog.array.forEach(a, function(chunk) {
      model.fmt.hyperlink(false, chunk);
    });
    var todos = model.todo.all(root);
    goog.array.forEach(todos, function(todo) {
      var txt = document.createTextNode(model.todo.isChecked(todo) ? "[x] " : "[ ] ");
      goog.dom.replaceNode(txt, todo);
    });
    plainifyLists(root, 0);
    var entools = document.querySelector("en-tools");
    entools.appendChild(root);
    var n, walk = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, null, false);
    while (n = walk.nextNode()) {
      n.data = n.data.replace(/ /g, "\u00a0");
    }
    var plainText = root.innerText;
    goog.dom.removeNode(root);
    plainText = plainText.replace(/<br>/g, "\n").replace(/-----PLACEHOLDER_TAB-----/g, "    ").replace(/\u00A0/g, " ");
    return plainText;
  };
  function plainifyLists(node) {
    var lists = [];
    if (model.list.is(node)) {
      lists.push(node);
    } else {
      if (util.dom.isElementNode(node)) {
        lists = node.querySelectorAll("ul, ol");
      }
    }
    goog.array.forEach(lists, function(list) {
      var isOL = model.list.isListType("ordered", list);
      var count = parseInt(list.getAttribute("start"), 10) || 1;
      var tabsCount = getTabCounts(list);
      goog.array.forEach(model.list.items, function(item) {
        if (item.firstChild) {
          var prefix = goog.dom.createTextNode(insertTabs(tabsCount) + (isOL ? count + ". " : "* "));
          goog.dom.insertSiblingBefore(prefix, item.firstChild);
          count++;
        }
      });
    });
  }
  function getTabCounts(node) {
    var tabsCount = 0;
    goog.dom.getAncestor(node, function(element) {
      if (util.dom.isUl(element) || util.dom.isOl(element)) {
        tabsCount++;
      }
      return !!util.dom.isEnnote(element);
    });
    return tabsCount;
  }
  function insertTabs(count) {
    var placeholder = "";
    for (var i = 0; i < count; i++) {
      placeholder += "-----PLACEHOLDER_TAB-----";
    }
    return placeholder;
  }
})();
goog.provide("uno.util.strict.copy");
goog.require("goog.dom");
goog.require("uno.util.dom");
goog.require("uno.util.copy.table");
goog.require("uno.util.copy.rich");
goog.require("uno.util.copy.resources");
goog.require("uno.util.strict.copy.plain");
(function() {
  var util = uno.util;
  var dom = util.dom;
  var model = uno.model;
  util.strict.copy.copy = function(editor, options, range) {
    range = range || editor.getRange();
    var pastableHtml = "";
    if (!editor.multirange.isEmpty()) {
      pastableHtml = util.strict.copy.table.getPastableHtml(editor.multirange.getTextRanges());
    } else {
      if (range && !range.isCollapsed()) {
        pastableHtml = range.getPastableHtml();
      } else {
        return {plain:"", html:"", resources:[]};
      }
    }
    var root = dom.nodeFromHtml("<div>" + pastableHtml + "</div>");
    var resourcesNode = dom.nodeFromHtml(pastableHtml);
    addContext(root.firstChild, range, editor);
    pastableHtml = editor.getClipboardContent(root);
    var richNode = dom.nodeFromHtml(pastableHtml);
    var plainNode = dom.nodeFromHtml(pastableHtml);
    if (options.addMarker || typeof options.addMarker === "undefined") {
      var clipboardMarker = richNode.firstElementChild;
      if (clipboardMarker) {
        util.dom.setStyleValue(clipboardMarker, "-en-clipboard", "true");
      }
    }
    return {resources:options.resources ? util.copy.resources.copy(resourcesNode) : [], html:options.html ? util.copy.rich.copy(richNode) : "", plain:options.plain ? util.strict.copy.plain.copy(plainNode) : ""};
  };
  function addContext(root, range, editor) {
    if (!editor.multirange.isEmpty()) {
      return;
    }
    if (model.chunk.is(root.firstChild)) {
      var startNode = util.range.boundary(range.getStartNode(), range.getStartOffset());
      if (model.chunk.is(startNode)) {
        var formatting = model.fmt.getFormatting(startNode);
        model.fmt.applyFormatting(formatting, root.firstChild);
      }
    }
  }
})();
goog.provide("uno.commands.strict.Copy");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.strict.copy");
goog.require("uno.util.objects");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.Copy");
  var defs = uno.defs;
  var util = uno.util;
  var Copy = uno.commands.strict.Copy = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Copy, uno.BasePlugin);
  Copy.prototype.isSupportedCommand = function(command) {
    return command === "copy";
  };
  Copy.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Copy.prototype.execCommand = function() {
    return false;
  };
  Copy.prototype.queryCommandValue = function(command, opt) {
    var options = getOptions(opt);
    this.editor.context.format = defs.format.CLIPBOARD;
    return util.strict.copy.copy(this.editor, options);
  };
  function getOptions(options) {
    return util.objects.mergeOptions(options, {html:true, resources:true, plain:true});
  }
})();
goog.provide("uno.commands.strict.CreateLink");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.CreateLink");
  var model = uno.model;
  var util = uno.util;
  var CreateLink = uno.commands.strict.CreateLink = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CreateLink, uno.BasePlugin);
  CreateLink.prototype.isSupportedCommand = function(command) {
    return command === "createlink";
  };
  CreateLink.prototype.activeOnUneditableFields = goog.functions.TRUE;
  CreateLink.prototype.execCommandInternal = function(command, value) {
    var chunks;
    var range = this.editor.getRange();
    if (range && !range.isCollapsed()) {
      var address = model.chunk.addressForRange(range);
      model.fmt.formatRange("hyperlink", value, range);
      range = model.chunk.rangeForAddress(address);
      range.select();
    }
    return true;
  };
  CreateLink.prototype.queryCommandValue = function() {
    var anchor;
    var range = this.editor.getRange();
    if (range && (range.isCollapsed() || range.getContainer() === range.getStartNode())) {
      anchor = goog.dom.getAncestorByTagNameAndClass(range.getStartNode(), "a");
      if (anchor && anchor.hasAttribute("href")) {
        return anchor.getAttribute("href");
      }
    }
    return null;
  };
  CreateLink.prototype.queryCommandEnabled = function(command) {
    return !!this.editor.getRange();
  };
})();
goog.provide("uno.model.cell");
goog.require("goog.debug.Logger");
goog.require("uno.model.origin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.cell");
  var model = uno.model;
  var util = uno.util;
  model.cell.is = function(node) {
    return node != null && node.tagName === "TD";
  };
  model.cell.for = function(node) {
    var origin = model.origin.for(node);
    if (model.cell.is(origin)) {
      return origin;
    }
  };
  model.cell.isStartPos = function(container, offset) {
    var p = model.p.for(container);
    var cell = model.cell.for(container);
    if (offset === 0) {
      if (model.cell.is(container)) {
        return true;
      }
      if (cell && model.origin.firstSection(cell) === p) {
        return true;
      }
    }
    return false;
  };
  model.cell.allFromRange = function(range) {
    var elements;
    var results = [];
    var start = model.cell.firstFromRange(range);
    var end = model.cell.lastFromRange(range);
    var container = range.getContainer();
    if (container.nodeType !== Node.ELEMENT_NODE) {
      container = container.parentElement;
    }
    elements = container.querySelectorAll("td");
    results = goog.array.filter(elements, function(el) {
      return el !== start && el !== end && range.containsNode(el);
    });
    if (start != null) {
      results.unshift(start);
    }
    if (start !== end) {
      results.push(end);
    }
    return results;
  };
  model.cell.firstFromRange = function(range) {
    var result;
    var container;
    var elements;
    if (range == null) {
      return;
    }
    if (range.getStartNode().nodeType === Node.ELEMENT_NODE) {
      result = model.cell.for(range.getStartNode().childNodes[range.getStartOffset()]);
    } else {
      result = model.cell.for(range.getStartNode());
    }
    if (result == null) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll("td");
      result = goog.array.find(elements, function(el) {
        return range.containsNode(el);
      });
    }
    return result;
  };
  model.cell.lastFromRange = function(range) {
    var result;
    var container;
    var elements;
    if (range == null) {
      return;
    }
    if (range.getEndNode().nodeType === Node.ELEMENT_NODE) {
      result = model.cell.for(range.getEndNode().childNodes[range.getEndOffset()]);
    } else {
      result = model.cell.for(range.getEndNode());
    }
    if (result == null) {
      container = range.getContainer();
      if (container.nodeType !== Node.ELEMENT_NODE) {
        container = container.parentElement;
      }
      elements = container.querySelectorAll("td");
      result = goog.array.findRight(elements, function(el) {
        return range.containsNode(el);
      });
    }
    return result;
  };
  model.cell.isEmpty = function(cell) {
    var result = false;
    if (cell != null && cell.childNodes.length === 1) {
      result = model.p.is(cell.firstChild) && model.p.isEmpty(cell.firstChild);
    }
    return result;
  };
  model.cell.clear = function(cell) {
    if (!model.cell.is(cell)) {
      return;
    }
    if (!model.cell.isEmpty(cell)) {
      goog.dom.removeChildren(cell);
    }
    if (cell.childNodes.length === 0) {
      cell.appendChild(model.p.create());
    }
  };
})();
goog.provide("uno.model.table");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.model.origin");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.table");
  var model = uno.model;
  var util = uno.util;
  model.section.types.push(model.table);
  model.table.create = function(options) {
    var i;
    var j;
    var row;
    if (options == null) {
      options = {};
    }
    var opt = {rows:options.rows || 1, columns:options.columns || 1, align:options.align || "left", borderColor:options.borderColor || null, borderWidth:options.borderWidth || 1, cellColor:options.cellColor || null, style:options.style};
    var tbody = document.createElement("tbody");
    var table = goog.dom.createDom("table", null, tbody);
    for (i = 0; i < opt.rows; i++) {
      row = document.createElement("tr");
      for (j = 0; j < opt.columns; j++) {
        row.appendChild(goog.dom.createDom("td", {style:"border-width: 1px;"}, uno.model.p.create()));
      }
      tbody.appendChild(row);
    }
    var style = opt.style;
    table.style.width = style.table.width;
    table.style.borderCollapse = style.table.borderCollapse;
    table.style.tableLayout = style.table.tableLayout;
    if (["left", "right", "center"].indexOf(options.align) > 0) {
      model.table["align" + options.align](table, true);
    }
    var firstRow = table.querySelector("tr");
    var cellWidth = 100 / firstRow.querySelectorAll("td").length + "%";
    var tds = table.querySelectorAll("td");
    goog.array.forEach(tds, function(td) {
      td.style.borderColor = options.borderColor || style.table.cell.borderColor;
      td.style.borderWidth = options.borderWidth + "px" || style.table.cell.borderWidth;
      td.style.borderStyle = style.table.cell.borderStyle;
      if (options.cellColor) {
        td.style.background = options.cellColor;
      }
      td.style.padding = style.table.cell.padding;
      td.style.margin = style.table.cell.margin;
      td.style.width = td.parentNode === firstRow ? cellWidth : "";
    });
    return table;
  };
  model.table.is = function(node) {
    return node != null && node.tagName === "TABLE";
  };
  model.table.for = function(node) {
    if (node == null) {
      return;
    }
    while (!model.table.is(node) && node.tagName !== "EN-NOTE" && node.parentElement != null) {
      node = node.parentElement;
    }
    if (model.table.is(node)) {
      return node;
    }
  };
  model.table.firstCell = function(table) {
    if (table == null) {
      return;
    }
    return table.querySelector("td");
  };
  model.table.lastCell = function(table) {
    var result;
    var cells;
    cells = model.table.allCells(table);
    if (cells.length !== 0) {
      result = cells[cells.length - 1];
    }
    return result;
  };
  model.table.allCells = function(table) {
    if (table == null) {
      return [];
    }
    return table.querySelectorAll("td");
  };
  model.table.alignleft = function(table, enable) {
    if (enable != null) {
      if (enable) {
        table.style.marginLeft = "";
        table.style.marginRight = "auto";
      } else {
        table.style.marginLeft = "";
        table.style.marginRight = "";
      }
      return enable;
    } else {
      return table.style.marginLeft === "" && table.style.marginRight === "auto";
    }
  };
  model.table.aligncenter = function(table, enable) {
    if (enable != null) {
      if (enable) {
        table.style.marginLeft = "auto";
        table.style.marginRight = "auto";
      } else {
        table.style.marginLeft = "";
        table.style.marginRight = "";
      }
      return enable;
    } else {
      return table.style.marginLeft === "auto" && table.style.marginRight === "auto";
    }
  };
  model.table.alignright = function(enable) {
    if (enable != null) {
      if (enable) {
        table.style.marginLeft = "auto";
        table.style.marginRight = "";
      } else {
        table.style.marginLeft = "";
        table.style.marginRight = "";
      }
      return enable;
    } else {
      return table.style.marginLeft === "auto" && table.style.marginRight === "";
    }
  };
  model.table.rangeInfoForStart = function(table) {
    var origin = model.table.firstCell(table);
    var section = model.origin.firstSection(origin);
    return section && model.section.rangeInfoForStart(section);
  };
  model.table.rangeInfoForEnd = function(table) {
    var origin = model.table.firstCell(table);
    var section = model.origin.lastSection(origin);
    return section && model.section.rangeInfoForEnd(section);
  };
  model.table.placeCursorAtStart = function(table) {
    var origin = model.table.firstCell(table);
    var section = origin && model.origin.firstSection(origin);
    return section && model.section.placeCursorAtStart(section);
  };
  model.table.placeCursorAtEnd = function(table) {
    var origin = model.table.lastCell(table);
    var section = origin && model.origin.lastSection(origin);
    return section && model.section.placeCursorAtEnd(section);
  };
  model.table.isImmediatelyAfter = function(container, offset) {
    if (offset > 0) {
      return false;
    }
    var section = model.section.for(node);
    var prev = model.section.previousSection(section);
    if (prev != null) {
      if (model.table.is(prev)) {
        return true;
      }
    }
    return false;
  };
  model.table.select = function(table) {
    util.range.selectNode(table);
  };
})();
goog.provide("uno.commands.strict.Delete");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.iter");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.model.cell");
goog.require("uno.model.codeblock");
goog.require("uno.model.item");
goog.require("uno.model.origin");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.model.table");
goog.require("uno.util.dom");
goog.require("uno.util.range");
(function() {
  var model = uno.model;
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.commands.strict.Delete");
  var Delete = uno.commands.strict.Delete = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Delete, uno.BasePlugin);
  Delete.WORD = "word";
  Delete.SELECTION = "selection";
  Delete.prototype.isSupportedCommand = function(command) {
    return command === "delete";
  };
  Delete.prototype.queryCommandValue = function(command) {
    return document.queryCommandValue(command);
  };
  Delete.prototype.execCommand = function(command, value, options) {
    if (options && options.smart === false) {
      clearBaseAndExtent();
    }
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var forward = options ? options.forward : false;
    var native = options ? options.native : false;
    var savedRange = range.saveUsingDom();
    var focusNode = range.getFocusNode();
    var focusOffset = range.getFocusOffset();
    if (value === Delete.SELECTION && range.isCollapsed()) {
      return false;
    }
    if (value === Delete.WORD) {
      var wordRange = getWordRange(range, forward);
      worRange.select();
      range = this.editor.getRange();
      value = 1;
    }
    this.editor.dispatchBeforeChange();
    var result;
    var count = parseInt(value, 10);
    count = isNaN(count) ? 1 : count;
    for (var i = 0; i < count; i++) {
      var currentNode = focusNode.childNodes && focusNode.childNodes[focusOffset - 1];
      if (isAtStartOfTableCell(focusNode, focusOffset) && range.isCollapsed()) {
        result = true;
      } else {
        if (isImmediatelyAfterTable(focusNode, focusOffset) && range.isCollapsed() && !forward) {
          result = selectTableBeforeNode(focusNode);
        } else {
          if (isCursorOnTable(focusNode, currentNode) && !forward) {
            result = deleteTable(currentNode);
          } else {
            if (!range.isCollapsed() && isCursorWithinTable(range, currentNode)) {
              result = emptyTableCells(range);
            } else {
              if (isCursorImmediatelyAfterCodeBlock(focusNode, focusOffset) && range.isCollapsed()) {
                result = moveCursorToEndOfPrevCodeBlock(focusNode, this.editor);
              } else {
                if (isCursorAtBeginningOfCodeBlock(focusNode, focusOffset) && range.isCollapsed()) {
                  result = moveFirstLineOutOfCodeBlock(focusNode, this.editor);
                } else {
                  if (isCursorAtBeginningOfListItem(focusNode, focusOffset) && range.isCollapsed() && !forward) {
                    result = this.editor.execCommand("outdent");
                  } else {
                    if (isCursorInListItem(focusNode, focusOffset)) {
                      deleteSelection(forward);
                      result = true;
                    } else {
                      if (isCursorAtBeginningOfIndentedParagraph(focusNode, focusOffset) && range.isCollapsed() && !forward) {
                        result = this.editor.execCommand("outdent");
                      } else {
                        if (isEditorDefaultEmpty(this.editor)) {
                          result = true;
                        } else {
                          if (range.isCollapsed() && isEmptyParagraph(focusNode) && !isCursorAtBeginningOfNote(focusNode, focusOffset, this.editor)) {
                            result = removeParagraph(focusNode);
                          }
                        }
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
      if (typeof result !== "undefined") {
        if (result === true) {
          this.editor.dispatchChange();
        }
        return result;
      } else {
        if (native) {
          return false;
        }
      }
      deleteSelection(forward);
    }
    this.editor.dispatchChange();
    return true;
  };
  function isCursorInListItem(node, offset) {
    var boundary = util.range.boundary(node, offset);
    return model.item.for(boundary);
  }
  function isEditorDefaultEmpty(editor) {
    return editor.field.innerHTML === editor.config.defaults.html;
  }
  function isCursorAtBeginningOfNote(node, offset, editor) {
    if (offset === 0 && editor.field) {
      return model.origin.isRangeInfoForStart(node, offset, editor.field);
    }
    return false;
  }
  function removeParagraph(node) {
    var result = false;
    var p = model.p.for(node);
    var sib;
    if (p != null) {
      if (sib = model.section.previousSection(p)) {
        model.section.placeCursorAtEnd(sib);
      } else {
        if (sib = model.section.nextSection(p)) {
          model.section.placeCursorAtStart(sib);
        }
      }
      model.section.remove(p);
      result = true;
    }
    return result;
  }
  function clearBaseAndExtent() {
    var sel = window.getSelection();
    if (!sel || sel.setBaseAndExtent === undefined || sel.baseNode === undefined) {
      return;
    }
    var clear = sel.type === "Range" && (sel.anchorNode !== sel.baseNode || sel.anchorOffset !== sel.baseOffset || sel.extentNode !== sel.focusNode || sel.extentOffset !== sel.focusOffset);
    if (clear) {
      sel.setBaseAndExtent(sel.anchorNode, sel.anchorOffset, sel.focusNode, sel.focusOffset);
    }
  }
  function deleteSelection(forward) {
    var commandName = forward ? "forwarddelete" : "delete";
    var result = document.execCommand(commandName);
  }
  function getWordRange(currentRange, offset, forward) {
    var wordRange = currentRange;
    var wordNode = currentRange.getContainer();
    if (offset && wordNode && wordNode.nodeType === Node.TEXT_NODE) {
      var found = false;
      var index = 0;
      wordNode.nodeValue.split(" ").forEach(function(word, i, arr) {
        var oldIndex = index;
        index += word.length;
        if (i < arr.length - 1) {
          index++;
        }
        if (!found) {
          if (forward && (offset === oldIndex || offset === oldIndex - 1)) {
            found = true;
          } else {
            if (!forward && (offset === index || offset === index - 1)) {
              found = true;
            } else {
              if (offset > oldIndex && offset < index) {
                found = true;
              }
            }
          }
          if (found) {
            wordRange = goog.dom.Range.createFromNodes(wordNode, oldIndex, wordNode, index);
          }
        }
      });
    }
    return wordRange;
  }
  function isAtStartOfTableCell(container, offset) {
    var node = util.range.boundary(container, offset);
    var origin = model.origin.for(node);
    var result = model.cell.is(origin) && model.origin.isRangeInfoForStart(container, offset, origin);
  }
  function isCursorOnTable(node, currentNode) {
    return util.dom.isElementNode(node) && util.dom.isTable(currentNode);
  }
  function isCursorWithinTable(range) {
    var startTable = model.table.for(range.getStartNode());
    var endTable = model.table.for(range.getEndNode());
    return startTable && startTable === endTable;
  }
  function isImmediatelyAfterTable(node, offset) {
    var section = model.section.for(node);
    var prev = model.section.previousSection(section);
    var result = model.table.is(prev) && model.section.isRangeInfoForStart(node, offset, section);
    return result;
  }
  function isEmptyParagraph(node) {
    var p = model.p.for(node);
    return model.p.isEmpty(p);
  }
  function isCursorAtBeginningOfListItem(node, offset) {
    var item = model.item.for(node);
    return model.origin.isRangeInfoForStart(node, offset, item);
  }
  function isCursorAtBeginningOfIndentedParagraph(node, offset) {
    var result = false;
    var p = model.p.for(node);
    if (p != null) {
      result = model.p.indentLevel(p) > 0 && model.section.isRangeInfoForStart(node, offset, p);
    }
    return result;
  }
  function getParagraphBeforeNode(type, node) {
    var currentPar = model.p.for(node);
    var prevPar = model.p.for(model.section.previousSibling(currentPar));
    return prevPar;
  }
  function isCursorAtBeginningOfCodeBlock(node, offset) {
    var codeblock = model.codeblock.for(node);
    return model.origin.isRangeInfoForStart(node, offset, codeblock);
  }
  function moveFirstLineOutOfCodeBlock(node) {
    var p = model.p.for(node);
    var codeblock = model.codeblock.for(node);
    model.section.insertSiblingBefore(p, codeblock);
    model.p.placeCursorAtStart(p);
    if (model.codeblock.isEmpty(codeblock)) {
      model.section.remove(codeblock);
    }
    return true;
  }
  function getPrevCodeBlock(node) {
    var codeblock;
    var section = model.section.for(node);
    var prev = model.section.previousSection(section);
    if (prev != null) {
      if (model.codeblock.is(prev)) {
        codeblock = prev;
      }
    }
    return codeblock;
  }
  function moveCursorToEndOfPrevCodeBlock(node, editor) {
    var section = model.section.for(node);
    var prev = model.section.previousSection(section);
    if (model.codeblock.is(prev)) {
      model.section.placeCursorAtEnd(prev);
      return true;
    }
  }
  function isCursorImmediatelyAfterCodeBlock(node, offset) {
    var codeblock = getPrevCodeBlock(node);
    return codeblock != null;
  }
  function isAfterResource(node, offset, forward) {
    if (node.nodeType === Node.TEXT_NODE) {
      if (forward && (node.length === offset || node.textContent === ZERO_WIDTH_SPACE)) {
        node = node.nextSibling;
      } else {
        if (offset === 0 || node.textContent === ZERO_WIDTH_SPACE) {
          node = node.previousSibling;
        }
      }
    }
    if (util.dom.isEnmedia(node)) {
      return true;
    }
    return false;
  }
  function getRangeOfTableBeforeNode(node) {
    var previousParagraph = getParagraphBeforeNode(node);
    if (previousParagraph) {
      var table = previousParagraph.querySelector("table") || util.dom.isTable(previousParagraph);
      if (table) {
        var tableRange = goog.dom.Range.createFromNodes(table, 0, table, table.childNodes.length);
        return tableRange;
      }
    }
    return false;
  }
  function selectTableBeforeNode(node, forward) {
    if (forward) {
      return false;
    }
    var section = model.section.for(node);
    var prev = model.section.previousSection(section);
    if (model.table.is(prev)) {
      util.range.selectNode(prev);
      return true;
    }
    return false;
  }
  function deleteTable(node, forward) {
    var table = model.table.for(node);
    var prev = model.section.previousSection(table);
    var next = model.section.nextSection(table);
    if (table != null) {
      if (prev != null) {
        model.section.placeCursorAtEnd(prev);
      } else {
        if (next != null) {
          model.section.placeCursorAtStart(next);
        }
      }
      model.section.remove(table);
      return true;
    }
    return false;
  }
  function emptyTableCells(range) {
    var newRange;
    var result = false;
    var cells = model.cell.allFromRange(range);
    var isAtStart = false;
    var isAtEnd = false;
    if (cells.length > 0) {
      isAtStart = model.origin.isRangeInfoForStart(range.getStartNode(), range.getStartOffset(), cells[0]);
      isAtEnd = model.origin.isRangeInfoForEnd(range.getEndNode(), range.getEndOffset(), cells[cells.length - 1]);
      if (isAtStart && isAtEnd) {
        goog.array.forEach(cells, function(cell) {
          model.cell.clear(cell);
        });
        rangeInfo = model.origin.rangeInfoForStart(cells[0]);
        newRange = goog.dom.Range.createFromNodes(rangeInfo.container, rangeInfo.offset, rangeInfo.container, rangeInfo.offset);
        newRange.select();
        result = true;
      }
    }
    return result;
  }
  function removeResource(node, isCursorCollapsed, forward) {
    var enMedia = node;
    if (node.nodeType === Node.TEXT_NODE) {
      var sibling = forward ? node.nextSibling : node.previousSibling;
      if (sibling && sibling.tagName && sibling.tagName.toLowerCase() === "en-media") {
        enMedia = sibling;
      }
    }
    var previousSibling = enMedia.previousSibling;
    var nextSibling = enMedia.nextSibling;
    var startNode = enMedia.parentNode;
    var startOffset = util.dom.index(enMedia);
    if (previousSibling && previousSibling.textContent === ZERO_WIDTH_SPACE) {
      startNode = previousSibling;
      startOffset = 0;
    }
    var endNode = enMedia.parentNode;
    var endOffset = util.dom.index(enMedia) + 1;
    if (nextSibling && nextSibling.textContent === ZERO_WIDTH_SPACE) {
      endNode = nextSibling;
      endOffset = 1;
    }
    var range = goog.dom.Range.createFromNodes(startNode, startOffset, endNode, endOffset);
    if (isCursorCollapsed) {
      range.select();
    } else {
      deleteSelection(forward);
    }
    return true;
  }
})();
goog.provide("uno.commands.strict.FontName");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.FontName");
  var model = uno.model;
  var util = uno.util;
  var FontName = uno.commands.strict.FontName = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(FontName, uno.BasePlugin);
  FontName.prototype.isSupportedCommand = function(command) {
    return command === "fontname";
  };
  FontName.prototype.activeOnUneditableFields = goog.functions.TRUE;
  FontName.prototype.execCommandInternal = function(command, name) {
    var range = this.editor.getRange();
    var defaultFontname = this.editor.config.defaults.richTextFont;
    if (range) {
      if (range.isCollapsed()) {
        this.setFontNameCollapsed(name, defaultFontname);
      } else {
        this.setFontNameExpanded(name, range, defaultFontname);
      }
    }
    return true;
  };
  FontName.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    if (range && range.isCollapsed() && this.editor.context.tempStyles.value.fontname) {
      return this.editor.context.tempStyles.value.fontname;
    }
    var defaultFontname = this.editor.config.defaults.richTextFont;
    var chunks = model.chunk.allFromRange(range);
    var fontname = chunks.length ? model.fmt.fontnameValue(chunks[0]) || defaultFontname : "";
    var consistentFont = chunks.every(function(chunk) {
      var chunkFontName = model.fmt.fontnameValue(chunk) || defaultFontname;
      return chunkFontName === fontname;
    });
    if (consistentFont) {
      return fontname.replace(/^'(.+)'$/, "$1");
    }
    return "";
  };
  FontName.prototype.setFontNameCollapsed = function(name, defaultFontname) {
    if (defaultFontname === name) {
      name = "";
    }
    util.styles.addTempValue(this.editor, "fontname", name);
    this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:this.editor.context.tempStyles});
  };
  FontName.prototype.setFontNameExpanded = function(name, range, defaultFontname) {
    var enable = defaultFontname !== name;
    var address = model.chunk.addressForRange(range);
    model.fmt.formatRange("fontname", name, range);
    range = model.chunk.rangeForAddress(address);
    range.select();
  };
})();
goog.provide("uno.commands.strict.FontSize");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.FontSize");
  var model = uno.model;
  var util = uno.util;
  var FontSize = uno.commands.strict.FontSize = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(FontSize, uno.BasePlugin);
  FontSize.prototype.isSupportedCommand = function(command) {
    return command === "fontsize";
  };
  FontSize.prototype.activeOnUneditableFields = goog.functions.TRUE;
  FontSize.prototype.execCommandInternal = function(command, size) {
    var range = this.editor.getRange();
    var sizeValue = util.font.prepareSize(size);
    if (range) {
      if (range.isCollapsed()) {
        this.setFontSizeCollapsed(sizeValue, range);
      } else {
        this.setFontSizeExpanded(sizeValue, range);
      }
    }
    return true;
  };
  FontSize.prototype.queryCommandValue = function() {
    var chunks;
    var node;
    var result;
    var range = this.editor.getRange();
    if (!range) {
      return "";
    }
    chunks = model.chunk.allFromRange(range);
    if (chunks.length > 0) {
      node = model.chunk.root(chunks[0]);
      if (node.nodeType === Node.TEXT_NODE) {
        node = node.parentElement;
      }
      result = util.font.getSize(node).toString();
    }
    return result;
  };
  FontSize.prototype.setFontSizeCollapsed = function(size, range) {
    util.styles.addTempValue(this.editor, "fontsize", size);
    this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:this.editor.context.tempStyles});
  };
  FontSize.prototype.setFontSizeExpanded = function(size, range) {
    var address = model.chunk.addressForRange(range);
    model.fmt.formatRange("fontsize", size, range);
    range = model.chunk.rangeForAddress(address);
    range.select();
  };
})();
goog.provide("uno.commands.strict.ForeColor");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.ForeColor");
  var model = uno.model;
  var util = uno.util;
  var ForeColor = uno.commands.strict.ForeColor = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ForeColor, uno.BasePlugin);
  ForeColor.prototype.isSupportedCommand = function(command) {
    return command === "forecolor";
  };
  ForeColor.prototype.activeOnUneditableFields = goog.functions.TRUE;
  ForeColor.prototype.execCommandInternal = function(command, color) {
    var range = this.editor.getRange();
    if (range) {
      if (range.isCollapsed()) {
        this.setForeColorCollapsed(color, range);
      } else {
        this.setForeColorExpanded(color, range);
      }
    }
    return true;
  };
  ForeColor.prototype.queryCommandValue = function() {
    return this.editor.queryCommandValue(goog.editor.Command.FONT_COLOR);
  };
  ForeColor.prototype.setForeColorCollapsed = function(color, range) {
    util.styles.addTempValue(this.editor, "forecolor", color);
    this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:this.editor.context.tempStyles});
  };
  ForeColor.prototype.setForeColorExpanded = function(color, range) {
    var address = model.chunk.addressForRange(range);
    model.fmt.formatRange("forecolor", color, range);
    range = model.chunk.rangeForAddress(address);
    range.select();
  };
})();
goog.provide("uno.commands.strict.Indent");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.item");
goog.require("uno.model.origin");
goog.require("uno.model.p");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.Indent");
  var model = uno.model;
  var util = uno.util;
  var Indent = uno.commands.strict.Indent = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Indent, uno.BasePlugin);
  Indent.prototype.isSupportedCommand = function(command) {
    return command === "indent";
  };
  Indent.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Indent.prototype.execCommandInternal = function() {
    var items;
    var paragraphs;
    var savedRange;
    var range = this.editor.getRange();
    if (range) {
      savedRange = range.saveUsingDom();
      items = model.item.allFromRange(range);
      if (items.length > 0) {
        items.forEach(function(item) {
          model.item.indent(item);
        });
      } else {
        paragraphs = model.p.allFromRange(range);
        paragraphs.forEach(function(p) {
          model.p.indent(p);
        });
      }
      savedRange.restore().select();
    }
    return true;
  };
})();
goog.provide("uno.model.hr");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.classlist");
goog.require("uno.model.section");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.model.hr");
  var model = uno.model;
  var util = uno.util;
  model.section.types.push(model.hr);
  model.hr.create = function() {
    return document.createElement("hr");
  };
  model.hr.is = function(node) {
    return node != null && node.tagName === "HR";
  };
  model.hr.select = function(node) {
    if (node != null) {
      node.classList.add("selected");
    }
  };
  model.hr.unselect = function(node) {
    if (node != null) {
      node.classList.remove("selected");
    }
  };
  model.hr.toggleSelected = function(node) {
    return goog.dom.classlist.toggle(node, "selected");
  };
  model.hr.rangeInfoForStart = function(node) {
    return {container:node, offset:0};
  };
  model.hr.rangeInfoForEnd = function(node) {
    return {container:node, offset:0};
  };
  model.hr.placeCursorAtStart = function(node) {
    util.range.selectNode(node);
  };
  model.hr.placeCursorAtEnd = function(node) {
    model.hr.placeCursorAtStart(node);
  };
  model.hr.isStartPos = function(container, offset, hr) {
    var boundary = util.range.boundary(container, offset);
    return boundary === hr;
  };
})();
goog.provide("uno.commands.strict.InsertHorizontalRule");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.hr");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.InsertHorizontalRule");
  var model = uno.model;
  var util = uno.util;
  var InsertHorizontalRule = uno.commands.strict.InsertHorizontalRule = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertHorizontalRule, uno.BasePlugin);
  InsertHorizontalRule.prototype.isSupportedCommand = function(command) {
    return command === "inserthorizontalrule";
  };
  InsertHorizontalRule.prototype.activeOnUneditableFields = goog.functions.TRUE;
  InsertHorizontalRule.prototype.execCommandInternal = function() {
    var refSection;
    var hr;
    var prev;
    var next;
    var range = this.editor.getRange();
    if (range) {
      if (!range.isCollapsed()) {
        this.editor.execCommand("delete");
        range = this.editor.getRange();
      }
      refSection = model.section.for(range.getEndNode());
      prev = model.section.previousSection(refSection);
      if (prev != null && model.hr.is(prev)) {
        refSection = prev;
      }
      hr = model.hr.create();
      model.section.insertSiblingAfter(hr, refSection);
      next = model.section.nextSection(hr);
      if (next == null || model.hr.is(next)) {
        model.section.insertSiblingAfter(model.p.create(), hr);
        next = model.section.nextSection(hr);
      }
      model.section.placeCursorAtStart(next);
    }
    return true;
  };
  InsertHorizontalRule.prototype.queryCommandValue = function() {
    return this.editor.queryCommandValue(goog.editor.Command.HORIZONTAL_RULE);
  };
})();
goog.provide("uno.commands.strict.InsertList");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.item");
goog.require("uno.model.list");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.util.range");
goog.require("uno.util.strict.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.InsertList");
  var model = uno.model;
  var util = uno.util;
  var COMMANDS = ["insertorderedlist", "insertunorderedlist"];
  var InsertList = uno.commands.strict.InsertList = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertList, uno.BasePlugin);
  InsertList.prototype.isSupportedCommand = function(command) {
    return COMMANDS.indexOf(command) !== -1;
  };
  InsertList.prototype.activeOnUneditableFields = goog.functions.TRUE;
  InsertList.prototype.execCommandInternal = function(command) {
    var type;
    var range = this.editor.getRange();
    var tightRange = util.strict.range.tighten(range);
    var value = this.queryCommandValueByRange(tightRange);
    var remove = false;
    var changeType = false;
    if (command === "insertorderedlist") {
      type = "ordered";
    } else {
      if (command === "insertunorderedlist") {
        type = "unordered";
      }
    }
    if (value != "none") {
      if (command === "insertunorderedlist" && value === "ul") {
        remove = true;
      } else {
        if (command === "insertorderedlist" && value === "ol") {
          remove = true;
        }
      }
      changeType = !remove;
    }
    if (tightRange) {
      if (changeType) {
        this.changeListType(tightRange, type);
      } else {
        if (remove) {
          this.removeList(tightRange);
        } else {
          this.insertList(tightRange, type);
        }
      }
    }
    return true;
  };
  InsertList.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    return this.queryCommandValueByRange(range);
  };
  InsertList.prototype.queryCommandValueByRange = function(range) {
    var list;
    var result = "none";
    if (range != null) {
      list = model.list.for(range.getContainer());
      if (list != null) {
        switch(model.list.type(list)) {
          case "ordered":
            result = "ol";
            break;
          case "unordered":
            result = "ul";
            break;
        }
      }
    }
    return result;
  };
  InsertList.prototype.changeListType = function(range, type) {
    var savedRange = range.saveUsingDom();
    var lists = model.list.allFromRange(range);
    lists.forEach(function(list) {
      model.list.setType(type, list);
    });
    savedRange.restore().select();
  };
  InsertList.prototype.insertList = function(range, type) {
    var section;
    var list;
    var paragraphs = [];
    var savedRange = range.saveUsingDom();
    var sections = model.section.allFromRange(range);
    if (sections.length === 0) {
      return;
    }
    var firstSection = sections[0];
    if (model.list.isListType(type, model.section.previousSection(firstSection))) {
      list = model.section.previousSection(section);
    } else {
      if (model.list.for(firstSection) != null) {
        list = model.list.for(firstSection);
      } else {
        list = model.list.create(type);
        model.list.clear(list);
        model.section.insertSiblingBefore(list, firstSection);
      }
    }
    sections.forEach(function(section) {
      if (!model.section.contains(section, list)) {
        if (model.list.is(section)) {
          model.list.appendList(section, list);
        } else {
          model.list.appendItem(model.item.create(section), list);
        }
      }
    });
    if (model.list.isListType(type, model.section.nextSection(list))) {
      model.list.appendList(model.section.nextSection(list), list);
    }
    savedRange.restore().select();
  };
  InsertList.prototype.removeList = function(range) {
    var lists = [];
    var savedRange = range.saveUsingDom();
    if (!range.isCollapsed()) {
      lists = model.list.allFromRange(range);
    } else {
      lists.push(model.list.for(range.getStartNode()));
    }
    lists.forEach(function(list) {
      model.list.flatten(list);
    });
    savedRange.restore().select();
  };
})();
goog.provide("uno.commands.strict.InsertTable");
goog.require("goog.debug.Logger");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.model.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.InsertTable");
  var model = uno.model;
  var util = uno.util;
  var InsertTable = uno.commands.strict.InsertTable = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertTable, uno.BasePlugin);
  InsertTable.prototype.isSupportedCommand = function(command) {
    return command === "inserttable";
  };
  InsertTable.prototype.activeOnUneditableFields = goog.functions.TRUE;
  InsertTable.prototype.execCommandInternal = function(command, options) {
    options = options || {};
    options.style = this.editor.config.style;
    var table = model.table.create(options);
    var range = this.editor.getRange();
    var section = model.section.lastFromRange(range);
    if (model.p.is(section) && model.p.isEmpty(section)) {
      model.section.replace(table, section);
    } else {
      model.section.insertSiblingAfter(table, section);
    }
    model.table.placeCursorAtStart(table);
    if (model.section.nextSection(table) == null) {
      model.section.insertSiblingAfter(model.p.create(), table);
    }
    return true;
  };
  InsertTable.prototype.queryCommandEnabled = function() {
    var range = this.editor.getRange();
    if (range == null) {
      return false;
    }
    var startTable = util.table.for(range.getStartNode());
    var endTable = util.table.for(range.getEndNode());
    if (startTable == null && endTable == null) {
      return true;
    }
    return false;
  };
})();
goog.provide("uno.commands.strict.InsertTodo");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.editor.range");
goog.require("uno.BasePlugin");
goog.require("uno.model.p");
goog.require("uno.model.todo");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.InsertTodo");
  var model = uno.model;
  var util = uno.util;
  var InsertTodo = uno.commands.strict.InsertTodo = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(InsertTodo, uno.BasePlugin);
  InsertTodo.prototype.isSupportedCommand = function(command) {
    return command === "inserttodo";
  };
  InsertTodo.prototype.execCommandInternal = function(command, value) {
    var toggle = value === "toggle";
    var range = this.editor.getRange();
    var paragraphs = model.p.allFromRange(range);
    var remove;
    if (range) {
      if (toggle) {
        model.todo.toggleByRange(range);
      } else {
        if (range.isCollapsed()) {
          var todo = model.todo.create();
          range.insertNode(todo);
          var p = model.p.for(todo);
          var lastLeaf = model.chunk.lastLeaf(model.p.lastChunk(p));
          if (lastLeaf && lastLeaf.tagName === "BR") {
            model.chunk.removeLeaf(lastLeaf);
          }
          goog.editor.range.placeCursorNextTo(todo);
        } else {
          var existing = model.todo.allFromRange(range);
          if (existing.length > 0) {
            existing.forEach(model.chunk.removeLeaf);
            var p = model.p.firstFromRange(range);
            if (model.p.startsWithTodo(p)) {
              model.p.removeTodo(p);
            }
          } else {
            var paragraphs = model.p.allFromRange(range);
            paragraphs = goog.array.filter(paragraphs, model.p.hasVisibleContent);
            paragraphs = goog.array.filter(paragraphs, function(p) {
              return !model.p.startsWithTodo(p);
            });
            if (paragraphs.length > 0) {
              goog.array.forEach(paragraphs, model.p.addTodo);
            }
          }
        }
      }
    }
    return true;
  };
})();
goog.provide("uno.commands.strict.Justify");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.p");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.Justify");
  var model = uno.model;
  var util = uno.util;
  var COMMANDS = ["justifyleft", "justifycenter", "justifyright", "justifyfull"];
  var Justify = uno.commands.strict.Justify = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Justify, uno.BasePlugin);
  Justify.prototype.isSupportedCommand = function(command) {
    return COMMANDS.indexOf(command) !== -1;
  };
  Justify.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Justify.prototype.execCommandInternal = function(command) {
    var range = this.editor.getRange();
    if (range) {
      var paragraphs = model.p.allFromRange(range);
      paragraphs.forEach(function(p) {
        model.p[command](p);
      });
    }
    return true;
  };
  Justify.prototype.queryCommandValue = function(command) {
    if (this.editor.queryCommandValue(goog.editor.Command.JUSTIFY_LEFT) !== false) {
      return "left";
    } else {
      if (this.editor.queryCommandValue(goog.editor.Command.JUSTIFY_CENTER) !== false) {
        return "center";
      } else {
        if (this.editor.queryCommandValue(goog.editor.Command.JUSTIFY_RIGHT) !== false) {
          return "right";
        } else {
          if (this.editor.queryCommandValue(goog.editor.Command.JUSTIFY_FULL) !== false) {
            return "justify";
          }
        }
      }
    }
  };
})();
goog.provide("uno.commands.strict.Outdent");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.p");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.Outdent");
  var model = uno.model;
  var util = uno.util;
  var Outdent = uno.commands.strict.Outdent = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Outdent, uno.BasePlugin);
  Outdent.prototype.isSupportedCommand = function(command) {
    return command === "outdent";
  };
  Outdent.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Outdent.prototype.execCommandInternal = function() {
    var items;
    var paragraphs;
    var savedRange;
    var range = this.editor.getRange();
    if (range) {
      savedRange = range.saveUsingDom();
      items = model.item.allFromRange(range);
      if (items.length > 0) {
        items.forEach(function(item) {
          model.item.outdent(item);
        });
      } else {
        paragraphs = model.p.allFromRange(range);
        paragraphs.forEach(function(p) {
          model.p.outdent(p);
        });
      }
      savedRange.restore().select();
    }
    return true;
  };
})();
goog.provide("uno.util.strict.paste");
goog.require("goog.editor.range");
goog.require("goog.editor.node");
goog.require("goog.dom.Range");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("uno.model.cell");
goog.require("uno.model.chunk");
goog.require("uno.model.codeblock");
goog.require("uno.model.fmt");
goog.require("uno.model.item");
goog.require("uno.model.list");
goog.require("uno.model.origin");
goog.require("uno.model.p");
goog.require("uno.model.table");
goog.require("uno.util.range");
(function() {
  var util = uno.util;
  var dom = util.dom;
  var model = uno.model;
  var fmt = uno.model.fmt;
  util.strict.paste.paste = function(clipboardContent, range, options) {
    options = options || {};
    var startNode = range.getStartNode();
    var pasteTarget = model.p.for(startNode);
    var sections = [];
    var pastingInTable = model.cell.for(pasteTarget);
    var pastingInCodeBlock = model.codeblock.for(pasteTarget);
    var pastingInCrypt = false;
    options.cursorPosition = {beginingOfLine:model.p.isStartPos(range.getStartNode(), range.getStartOffset(), pasteTarget)};
    options.alignment = model.p.justifyValue(pasteTarget);
    util.strict.paste.setStyles(clipboardContent, startNode, options);
    if (pastingInTable && (clipboardContent.childNodes.length > 1 || !dom.isEntable(clipboardContent.firstChild))) {
      var tables = clipboardContent.querySelectorAll("en-table");
      goog.array.forEach(tables, util.strict.paste.plainifyTable);
    }
    goog.array.forEach(model.origin.sections(clipboardContent), function(section, index) {
      if ((pastingInCodeBlock || pastingInCrypt) && model.codeblock.is(section)) {
        sections = sections.concat(util.strict.paste.plainifyCodeBlock(section));
      } else {
        if (dom.isRevealedCrypt(section)) {
          sections = sections.concat(util.strict.paste.plainifyCrypt(section));
        } else {
          if (model.p.is(section)) {
            model.p.justify(options.alignment, section);
          }
          sections.push(section);
        }
      }
    });
    if (pastingInTable && sections.length === 1 && dom.isEntable(sections[0])) {
      var table = sections[0].querySelector("table");
      return util.strict.paste.mergeTables(pasteTarget, table, range);
    }
    return util.strict.paste.mergeContent(pasteTarget, sections, range, options);
  };
  util.strict.paste.getTarget = function(range) {
    if (!range || !range.isCollapsed()) {
      return null;
    }
    var startNode = range.getStartNode();
    var ancestor = goog.dom.getAncestor(startNode, util.dom.isBlockNode, true);
    if (util.dom.isEnnote(ancestor)) {
      var childNode = null;
      var siblings = null;
      var savedRange = range.saveUsingCarets();
      if (startNode !== ancestor) {
        siblings = util.dom.contiguousInlineSiblings(startNode);
      } else {
        childNode = startNode.childNodes[range.getStartOffset()];
        siblings = util.dom.contiguousInlineSiblings(childNode);
      }
      var blockWrapper = goog.dom.createDom("div");
      goog.dom.insertSiblingBefore(blockWrapper, siblings[0]);
      siblings.forEach(function(sibling) {
        blockWrapper.appendChild(sibling);
      });
      savedRange.restore().select();
      return blockWrapper;
    }
    return ancestor;
  };
  util.strict.paste.mergeContent = function(pasteTarget, sections, range, options) {
    var paste = util.strict.paste;
    var startNode = range.getStartNode();
    var startOffset = range.getStartOffset();
    var listItem = model.item.for(pasteTarget);
    if (model.section.isRangeInfoForStart(startNode, startOffset, pasteTarget)) {
      fn = listItem ? paste.mergeAtStartInList : paste.mergeAtStart;
    } else {
      if (model.section.isRangeInfoForEnd(startNode, startOffset, pasteTarget)) {
        fn = listItem ? paste.mergeAtEndInList : paste.mergeAtEnd;
      } else {
        fn = listItem ? paste.mergeAtMiddleInList : paste.mergeAtMiddle;
      }
    }
    var range = fn(pasteTarget, sections, range, options);
    util.normalize.normalizeNode(pasteTarget.parentElement, {editor:{strictMode:true}});
  };
  util.strict.paste.mergeAtStart = function(pasteTarget, sections, range, options) {
    var lastSection = sections[sections.length - 1];
    goog.array.forEach(sections, function(section) {
      if (section !== lastSection) {
        model.section.insertSiblingBefore(section, pasteTarget);
      }
    });
    if (model.p.is(lastSection)) {
      var lastChunk = model.p.lastChunk(lastSection);
      model.p.prepend(model.p.chunks(lastSection), pasteTarget);
      model.chunk.placeCursorAtEnd(lastChunk);
    } else {
      model.section.insertSiblingBefore(lastSection, pasteTarget);
      model.section.placeCursorAtEnd(lastSection);
    }
  };
  util.strict.paste.mergeAtStartInList = function(pasteTarget, sections, range, options) {
    var lastSection = sections[sections.length - 1];
    var targetItem = model.item.for(pasteTarget);
    goog.array.forEach(sections, function(section) {
      if (section !== lastSection) {
        if (!model.list.is(section)) {
          section = model.item.create(section);
        }
        model.section.insertSiblingBefore(section, targetItem);
        if (model.list.is(section)) {
          goog.dom.flattenElement(section);
        }
      }
    });
    if (model.p.is(lastSection)) {
      var lastChunk = model.p.lastChunk(lastSection);
      model.p.prepend(model.p.chunks(lastSection), pasteTarget);
      model.chunk.placeCursorAtEnd(lastChunk);
    } else {
      if (!model.list.is(lastSection)) {
        lastSection = model.item.create(lastSection);
      }
      model.section.insertSiblingBefore(lastSection, targetItem);
      if (model.list.is(lastSection)) {
        goog.dom.flattenElement(lastSection);
      }
    }
  };
  util.strict.paste.mergeAtMiddle = function(pasteTarget, sections, range, options) {
    var firstSection = sections[0];
    var lastSection = sections[sections.length - 1];
    if (sections.length === 1 && model.p.is(firstSection)) {
      range.insertNode(firstSection);
      model.section.placeCursorAtEnd(firstSection);
      goog.dom.flattenElement(firstSection);
    } else {
      var placeholder = model.chunk.fromText("");
      range.insertNode(placeholder);
      var rightSection = goog.editor.node.splitDomTreeAt(placeholder, null, pasteTarget);
      model.section.insertSiblingAfter(rightSection, pasteTarget);
      if (model.p.is(firstSection)) {
        var leftSection = model.p.for(placeholder);
        model.p.append(model.p.chunks(firstSection), leftSection);
      } else {
        model.section.insertSiblingAfter(firstSection, leftSection);
      }
      goog.dom.removeNode(placeholder);
      goog.array.forEachRight(sections, function(section) {
        if (section !== firstSection && section !== lastSection) {
          model.section.insertSiblingAfter(section, leftSection);
        }
      });
      if (model.p.is(lastSection)) {
        model.p.prepend(model.p.chunks(lastSection), rightSection);
      } else {
        model.section.insertSiblingBefore(lastSection, rightSection);
      }
    }
  };
  util.strict.paste.mergeAtMiddleInList = function(pasteTarget, sections, range, options) {
    var firstSection = sections[0];
    var lastSection = sections[sections.length - 1];
    var targetItem = model.item.for(pasteTarget);
    if (sections.length === 1 && model.p.is(firstSection)) {
      range.insertNode(firstSection);
      model.section.placeCursorAtEnd(firstSection);
      goog.dom.flattenElement(firstSection);
    } else {
      var placeholder = model.chunk.fromText("");
      range.insertNode(placeholder);
      var rightItem = goog.editor.node.splitDomTreeAt(placeholder, null, targetItem);
      model.section.insertSiblingAfter(rightItem, targetItem);
      if (model.p.is(firstSection)) {
        var leftSection = model.p.for(placeholder);
        model.p.append(model.p.chunks(firstSection), leftSection);
      } else {
        if (!model.list.is(firstSection)) {
          firstSection = model.item.create(firstSection);
        }
        model.section.insertSiblingAfter(firstSection, targetItem);
        if (model.list.is(firstSection)) {
          goog.dom.flattenElement(firstSection);
        }
      }
      goog.dom.removeNode(placeholder);
      goog.array.forEachRight(sections, function(section) {
        if (section !== firstSection && section !== lastSection) {
          if (!model.list.is(section)) {
            section = model.item.create(section);
          }
          model.section.insertSiblingAfter(section, targetItem);
          if (model.list.is(section)) {
            goog.dom.flattenElement(section);
          }
        }
      });
      if (model.p.is(lastSection)) {
        model.p.prepend(model.p.chunks(lastSection), model.origin.firstSection(rightItem));
      } else {
        if (!model.list.is(lastSection)) {
          lastSection = model.item.create(lastSection);
        }
        model.section.insertSiblingBefore(lastSection, rightItem);
        if (model.list.is(lastSection)) {
          goog.dom.flattenElement(lastSection);
        }
      }
    }
  };
  util.strict.paste.mergeAtEnd = function(pasteTarget, sections, range, options) {
    var firstSection = sections[0];
    var lastSection = sections[sections.length - 1];
    goog.array.forEachRight(sections, function(section) {
      if (section !== firstSection) {
        model.section.insertSiblingAfter(section, pasteTarget);
      }
    });
    if (model.p.is(firstSection)) {
      model.p.append(model.p.chunks(firstSection), pasteTarget);
    } else {
      model.section.insertSiblingAfter(firstSection, pasteTarget);
    }
    model.section.placeCursorAtEnd(lastSection);
  };
  util.strict.paste.mergeAtEndInList = function(pasteTarget, sections, range, options) {
    var firstSection = sections[0];
    var lastSection = sections[sections.length - 1];
    var targetItem = model.item.for(pasteTarget);
    goog.array.forEachRight(sections, function(section) {
      if (section !== firstSection) {
        if (!model.list.is(section)) {
          section = model.item.create(section);
        }
        model.section.insertSiblingAfter(section, targetItem);
        if (model.list.is(section)) {
          goog.dom.flattenElement(section);
        }
      }
    });
    if (model.p.is(firstSection)) {
      model.p.append(model.p.chunks(firstSection), pasteTarget);
    } else {
      if (!model.list.is(firstSection)) {
        firstSection = model.item.create(firstSection);
      }
      model.section.insertSiblingAfter(firstSection, targetItem);
      if (model.list.is(firstSection)) {
        goog.dom.flattenElement(firstSection);
      }
    }
    model.section.placeCursorAtEnd(lastSection);
  };
  util.strict.paste.mergeTables = function(pasteTarget, clipboardTable) {
    var td = goog.dom.getAncestor(pasteTarget, dom.isTd, true);
    var targetTable = goog.dom.getAncestor(td, dom.isTable, true);
    if (!td) {
      return null;
    }
    var cellIndex = td.cellIndex;
    var rowIndex = td.parentNode.rowIndex;
    var numberOfColumnsToAdd = clipboardTable.rows[0].cells.length - (targetTable.rows[0].cells.length - cellIndex);
    var numberOfRowsToAdd = clipboardTable.rows.length - (targetTable.rows.length - rowIndex);
    var cellToClone;
    if (numberOfColumnsToAdd) {
      var firstTr = targetTable.querySelectorAll("tr")[0];
      cellToClone = firstTr.lastChild;
      goog.array.forEach(targetTable.querySelectorAll("tr"), function(tr) {
        for (var i = 0; i < numberOfColumnsToAdd; i++) {
          var cell = cellToClone.cloneNode();
          cell.innerHTML = "<div><br></div>";
          tr.appendChild(cell);
        }
      });
    }
    if (numberOfRowsToAdd) {
      var lastTr = goog.array.last(targetTable.querySelectorAll("tr"));
      cellToClone = lastTr.firstChild;
      var tbody = targetTable.querySelector("tbody");
      for (var i = 0; i < numberOfRowsToAdd; i++) {
        var tr = goog.dom.createDom("tr");
        for (var j = 0; j < targetTable.rows[0].cells.length; j++) {
          var cell = cellToClone.cloneNode();
          cell.innerHTML = "<div><br></div>";
          tr.appendChild(cell);
        }
        tbody.appendChild(tr);
      }
    }
    var trs = clipboardTable.querySelectorAll("tr");
    goog.array.forEach(trs, function(tr, i) {
      goog.array.forEach(tr.querySelectorAll("td"), function(td, j) {
        var cell = targetTable.rows[rowIndex + i].cells[cellIndex + j];
        if (cell) {
          cell.innerHTML = td.innerHTML;
        }
      });
    });
    var lastCellIndex = clipboardTable.rows[0].cells.length - 1 + cellIndex;
    var lastRowIndex = clipboardTable.rows.length - 1 + rowIndex;
    var lastCell = targetTable.rows[lastRowIndex].cells[lastCellIndex];
    var lastWord = dom.getLastParagraphItem(lastCell);
    if (lastWord && lastWord.parentNode) {
      goog.editor.range.placeCursorNextTo(lastWord);
      return goog.dom.Range.createFromNodes(td, 0, lastWord.parentNode, lastWord.parentNode.childNodes.length);
    }
    return null;
  };
  util.strict.paste.plainifyTable = function(table) {
    if (!table) {
      return;
    }
    var trs = goog.array.toArray(table.querySelectorAll("tr"));
    var content = goog.dom.createDom("div");
    goog.array.forEach(trs, function(tr) {
      var tds = tr.querySelectorAll("td");
      goog.array.forEach(tds, function(td) {
        goog.array.forEach(td.childNodes, function(paragraph) {
          if (paragraph.innerHTML === "<br>") {
            return;
          }
          content.appendChild(paragraph);
        });
      });
      var blankLine = goog.dom.createDom("div");
      blankLine.innerHTML = "<br>";
      content.appendChild(blankLine);
    });
    goog.dom.replaceNode(content, table);
    goog.dom.flattenElement(content);
  };
  util.strict.paste.plainifyCodeBlock = function(node) {
    return goog.array.toArray(node.childNodes);
  };
  util.strict.paste.plainifyCrypt = function(node) {
    return goog.array.toArray(node.childNodes);
  };
  util.strict.paste.getCursorPosition = function(range) {
    var node = range.getStartNode();
    var offset = range.getStartOffset();
    var position = {beginingOfLine:false};
    if (dom.isTextNode(node)) {
      if (!node.parentNode.previousSibling && offset === 0) {
        position.beginingOfLine = true;
      }
    } else {
      if (offset === 0) {
        position.beginingOfLine = true;
      }
    }
    return position;
  };
  util.strict.paste.setStyles = function(clipboardContent, startNode, options) {
    var targetFormatting = fmt.getFormatting(startNode);
    var tempFormatting = {};
    var paragraphs = model.p.all(clipboardContent);
    var beginingOfLine = options.cursorPosition.beginingOfLine;
    var editor = options && options.editor;
    if (editor && editor.context.hasTempStyles) {
      tempFormatting = util.styles.formattingForTempStyles(editor);
      util.styles.clearTempStyles(editor);
    }
    goog.array.forEach(paragraphs, function(p) {
      goog.array.forEach(model.p.chunks(p), function(chunk) {
        var sourceFormatting = {};
        if (!options.matchStyle) {
          sourceFormatting = fmt.getFormatting(chunk);
        }
        Object.keys(tempFormatting).forEach(function(key) {
          if (tempFormatting[key] && !sourceFormatting[key]) {
            sourceFormatting[key] = tempFormatting[key];
          }
        });
        if (options.defaultFontColor === sourceFormatting.forecolor) {
          delete sourceFormatting.forecolor;
        }
        if (options.defaultFontName === sourceFormatting.fontname) {
          delete sourceFormatting.fontname;
        }
        if (options.defaultFontSize === sourceFormatting.fontsize) {
          delete sourceFormatting.fontsize;
        }
        Object.keys(targetFormatting).forEach(function(key) {
          var value = targetFormatting[key];
          if (value != null && value !== false && (options.matchStyle || !options.enclipboard && !sourceFormatting[key])) {
            sourceFormatting[key] = value;
          }
        });
        if (options.matchStyle) {
          chunk = fmt.removeAllFormatting(chunk);
        }
        fmt.applyFormatting(sourceFormatting, chunk);
      });
    });
  };
})();
goog.provide("uno.commands.strict.Paste");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.model.p");
goog.require("uno.util.dom");
goog.require("uno.util.paste.plain");
goog.require("uno.util.strict.paste");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.Paste");
  var model = uno.model;
  var util = uno.util;
  var Paste = uno.commands.strict.Paste = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Paste, uno.BasePlugin);
  Paste.prototype.isSupportedCommand = function(command) {
    return command === "paste" || command === "pasteplain";
  };
  Paste.prototype.queryCommandValue = function() {
    return true;
  };
  Paste.prototype.execCommand = function(command, opt) {
    var editor = this.editor;
    if (!editor.multirange.isEmpty()) {
      return false;
    }
    var range = editor.getRange();
    if (!range) {
      editor.placeCursorAtEnd();
      range = editor.getRange();
      if (!range) {
        return false;
      }
    }
    if (!range.isCollapsed()) {
      editor.execCommand("delete", "selection", {smart:false});
      range = editor.getRange();
    }
    var options = goog.isObject(opt) ? opt : {value:goog.isString(opt) ? opt : "", type:"html", matchStyle:false, resources:[]};
    editor.context.format = uno.defs.format.CLIPBOARD;
    if (!options.value) {
      return false;
    }
    (options.resources || []).forEach(function(res) {
      editor.context.resources[res.id] = res;
    });
    editor.dispatchBeforeChange();
    if (options.type === "plain") {
      options.value = util.paste.plain.getContent(options.value);
    }
    var matchStyle = options.matchStyle === true;
    var rxClipboard = /\-en\-clipboard:\s*true;/g;
    var enclipboard = rxClipboard.test(options.value);
    var value = "<div>" + options.value.replace(rxClipboard, "") + "</div>";
    var cleanedContent = editor.prepareContentsHtml.call(editor, value, {});
    var clipboardContent = util.dom.nodeFromHtml(cleanedContent);
    range = editor.getRange();
    var pasteTarget = model.p.for(range.getStartNode());
    var pasteRange = util.strict.paste.paste(clipboardContent, editor.getRange(), {enclipboard:enclipboard, matchStyle:matchStyle, editor:editor, defaultFontName:editor.config.defaults.richTextFont, defaultFontSize:editor.config.defaults.fontSize, defaultFontColor:editor.config.defaults.foreColor});
    editor.dispatchChange();
    util.range.scrollSelectionIntoView(editor);
    if (pasteRange) {
      this.dispatchEvent({type:uno.Editor.EventType.DOM_UPDATE, range:pasteRange, paste:true});
    }
    return true;
  };
})();
goog.provide("uno.commands.strict.RemoveFormat");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.p");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.RemoveFormat");
  var Chunk = uno.model.Chunk;
  var model = uno.model;
  var util = uno.util;
  var RemoveFormat = uno.commands.strict.RemoveFormat = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(RemoveFormat, uno.BasePlugin);
  RemoveFormat.prototype.isSupportedCommand = function(command) {
    return command === "removeformat";
  };
  RemoveFormat.prototype.activeOnUneditableFields = goog.functions.TRUE;
  RemoveFormat.prototype.execCommandInternal = function() {
    var chunks;
    var paragraphs;
    var range = this.editor.getRange();
    if (range && !range.isCollapsed()) {
      paragraphs = model.p.allFromRange(range);
      chunks = Chunk.allFromRange(range);
      paragraphs.forEach(function(p) {
        model.p.removeAllFormatting(p);
      });
      chunks.forEach(function(chunk) {
        chunk.removeAllFormatting();
      });
      chunks[0].normalizeRight();
      Chunk.selectChunks(chunks);
    }
    return true;
  };
})();
goog.provide("uno.commands.strict.Resources");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
goog.require("uno.model.p");
goog.require("uno.model.resource");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.Resources");
  var model = uno.model;
  var util = uno.util;
  var Resources = uno.commands.strict.Resources = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Resources, uno.BasePlugin);
  Resources.prototype.isSupportedCommand = function(command) {
    return command === "resources";
  };
  Resources.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Resources.prototype.execCommand = function(command, value) {
    var me = this;
    var editor = this.editor;
    var startedInEditMode = editor.inEditMode();
    var hasChanges;
    var hasInserts = false;
    if (!goog.isArray(value)) {
      value = [value];
    }
    hasChanges = value.some(function(dict) {
      if (dict.action === "insert" || dict.action === "delete") {
        return true;
      } else {
        if (dict.action === "update") {
          return goog.array.some(me.findResourcesForDict(dict), function(res) {
            var existing = model.resource.dictFromResource(res);
            return dict.filename != null && dict.filename !== existing.filename || dict.filesize != null && dict.filesize !== existing.filesize || dict.hash != null && dict.hash !== existing.hash || dict.mime != null && dict.mime !== existing.mime || dict.url != null && dict.url !== existing.url;
          });
        }
      }
    });
    hasInserts = value.some(function(dict) {
      return dict.action === "insert";
    });
    if (hasChanges) {
      editor.dispatchBeforeChange();
    }
    if (!startedInEditMode && hasInserts) {
      editor.enterEditMode(true);
    }
    value.forEach(function(dict) {
      if (dict.action === "insert") {
        if (dict.pos === "bottom") {
          editor.placeCursorAtEnd();
        }
        me.add(dict);
      } else {
        if (dict.action === "update") {
          me.update(dict);
        } else {
          if (dict.action === "delete") {
            me.remove(dict);
          }
        }
      }
    });
    if (!startedInEditMode && hasInserts) {
      editor.blur();
    }
    if (hasChanges) {
      editor.dispatchChange();
    }
    return hasChanges;
  };
  Resources.prototype.add = function(dict) {
    var editor = this.editor;
    var res = model.resource.fromClientDict(dict, editor);
    var range = editor.getRange();
    var p = model.p.firstFromRange(range);
    var ref = dict.beforeRef || dict.afterRef;
    var refResource = ref && model.chunk.root(model.resource.findByRef(ref, editor.field));
    if (refResource) {
      model.fmt.applyFormatting(model.fmt.getFormatting(refResource), res);
      if (dict.beforeRef) {
        model.chunk.insertBefore(refResource, res);
      } else {
        model.chunk.insertAfter(refResource, res);
      }
    } else {
      if (range && !model.p.isEmpty(p)) {
        var newP = model.p.splitAt(range.getStartNode(), range.getStartOffset(), p);
        model.p.placeCursorAtStart(newP);
        range = editor.getRange();
      }
      var bounds = model.chunk.bounds(range);
      model.chunk.insertAt(res, bounds.start, bounds.startOffset);
    }
    if (model.p["justify" + dict.justify]) {
      model.p["justify" + dict.justify](model.p.for(res));
    }
    model.chunk.placeCursorAt(bounds.startOffset + 1, res);
    model.resource.scrollIntoView(res);
  };
  Resources.prototype.update = function(dict) {
    var enmedia;
    var slug;
    var editor = this.editor;
    var resources = this.findResourcesForDict(dict);
    goog.array.forEach(resources, function(existingRes) {
      var combodict = {};
      goog.object.extend(combodict, model.resource.dictFromResource(existingRes), dict);
      var updatedRes = model.resource.fromClientDict(combodict, editor);
      model.resource.replace(updatedRes, existingRes);
    });
  };
  Resources.prototype.remove = function(dict) {
    var resources = this.findResourcesForDict(dict);
    var editor = this.editor;
    goog.array.forEach(resources, function(res) {
      var range = editor.getRange();
      var bounds = model.chunk.bounds(range);
      var address;
      if (range.isCollapsed() && (bounds.start === res || bounds.start.previousSibling === res || bounds.end === res || bounds.end.previousSibling === res)) {
        address = model.chunk.addressForRange(range);
        address.startIndex--;
        address.endIndex--;
      }
      model.resource.remove(res);
      if (address != null) {
        model.chunk.rangeForAddress(address).select();
      }
    });
  };
  Resources.prototype.findResourcesForDict = function(dict) {
    var resources;
    var res;
    if (dict.reference) {
      res = model.resource.findByRef(dict.reference, this.editor.field);
      resources = [];
      if (res) {
        resources.push(res);
      }
    } else {
      if (dict.originalURL) {
        resources = model.resource.findByURL(dict.originalURL, this.editor.field);
      } else {
        resources = model.resource.findByHash(dict.hash, this.editor.field);
      }
    }
    return resources;
  };
  Resources.prototype.queryCommandValue = function(command, opt) {
    var editor = this.editor;
    var range = editor.getRange();
    var sibling;
    var list = goog.array.map(util.resource.all(editor.field), function(el) {
      var dict = util.resource.toDict(el, range);
      if (opt === "neighbors") {
        sibling = el.previousElementSibling;
        if (util.resource.isResource(sibling)) {
          dict.prevNeighbour = util.resource.toDict(sibling, range);
        }
        sibling = el.nextElementSibling;
        if (util.resource.isResource(sibling)) {
          dict.nextNeighbour = util.resource.toDict(sibling, range);
        }
      }
      return dict;
    });
    return list;
  };
})();
goog.provide("uno.commands.strict.Unlink");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
goog.require("uno.util.styles");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.strict.Unlink");
  var model = uno.model;
  var util = uno.util;
  var Unlink = uno.commands.strict.Unlink = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Unlink, uno.BasePlugin);
  Unlink.prototype.isSupportedCommand = function(command) {
    return command === "unlink";
  };
  Unlink.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Unlink.prototype.execCommandInternal = function() {
    var chunks;
    var range = this.editor.getRange();
    if (range && !range.isCollapsed()) {
      var address = model.chunk.addressForRange(range);
      model.fmt.formatRange("hyperlink", false, range);
      range = model.chunk.rangeForAddress(address);
      range.select();
    }
    return true;
  };
  Unlink.prototype.queryCommandValue = function() {
    var range = this.editor.getRange();
    var link = range && goog.dom.getAncestorByTagNameAndClass(range.getStartNode(), "a");
    return link != null;
  };
  Unlink.prototype.queryCommandEnabled = function(command) {
    return this.queryCommandValue(command);
  };
})();
goog.provide("uno.filters.CodeBlockFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.CodeBlockFilter");
  var util = uno.util;
  var dom = util.dom;
  var CodeBlockFilter = uno.filters.CodeBlockFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CodeBlockFilter, uno.BasePlugin);
  CodeBlockFilter.prototype.prepareContentsDom = function(frag) {
    var codeblocks = frag.querySelectorAll('[style*="-en-codeblock"]');
    goog.array.forEach(codeblocks, function(codeblock) {
      codeblock.removeAttribute("style");
      codeblock.classList.add("en-code");
    });
  };
  CodeBlockFilter.prototype.cleanContentsDom = function(frag) {
    var codeblocks = frag.querySelectorAll(".en-code");
    goog.array.forEach(codeblocks, function(codeblock) {
      codeblock.setAttribute("style", uno.defs.codeblock.style);
      dom.setStyleValue(codeblock, "-en-codeblock", "true");
    });
  };
})();
goog.provide("uno.filters.cryptfilter.win");
goog.require("goog.dom.classlist");
goog.require("uno.defs");
goog.require("uno.util.crypto");
(function() {
  var win = uno.filters.cryptfilter.win;
  var util = uno.util;
  var CRYPT_CLASS = uno.defs.crypto.CRYPT_CLASS;
  win.importHTML = function(fragment, context) {
    var cryptElements = fragment.querySelectorAll('img[src^="en-resource://database/pprotect:"]');
    Array.prototype.forEach.call(cryptElements, function(node) {
      node.setAttribute("id", "crypt-" + context.crypt.incrementUniqueId());
      node.setAttribute("data-src", node.src);
      goog.dom.classlist.add(node, CRYPT_CLASS);
    });
    return fragment;
  };
  win.exportHTML = function(fragment) {
    var cryptElements = util.crypto.all(fragment);
    Array.prototype.forEach.call(cryptElements, function(node) {
      if (util.crypto.isOpen(node)) {
        var newNode = document.createElement("img");
        newNode.setAttribute("id", node.getAttribute("id"));
        newNode.setAttribute("class", node.getAttribute("class"));
        newNode.setAttribute("src", node.getAttribute("data-src"));
        newNode.setAttribute("data-length", node.getAttribute("data-length"));
        newNode.setAttribute("data-cipher", node.getAttribute("data-cipher"));
        newNode.setAttribute("data-hint", node.getAttribute("data-hint"));
        newNode.setAttribute("data-ciphertext", node.getAttribute("data-ciphertext"));
        node.parentNode.replaceChild(newNode, node);
      } else {
        node.setAttribute("src", node.getAttribute("data-src"));
        node.removeAttribute("data-src");
      }
    });
  };
})();
goog.provide("uno.filters.CryptFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.filters.cryptfilter.win");
goog.require("uno.util.crypto");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.CryptFilter");
  var util = uno.util;
  var CryptFilter = uno.filters.CryptFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CryptFilter, uno.BasePlugin);
  CryptFilter.prototype.prepareContentsDom = function(fragment) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.ENML) {
      if (this.client.importENML) {
        this.client.importENML(fragment, context);
      } else {
        Array.prototype.forEach.call(fragment.querySelectorAll("en-crypt"), function(node) {
          var newId = context.crypt.incrementUniqueId();
          var cryptInfo = {id:"crypt-" + newId};
          cryptInfo.cipherText = node.textContent;
          cryptInfo.length = node.getAttribute("length");
          cryptInfo.cipher = node.getAttribute("cipher");
          cryptInfo.hint = node.getAttribute("hint");
          var newNode = util.crypto.createCryptoPlaceholder(cryptInfo);
          goog.dom.replaceNode(newNode, node);
        });
      }
    } else {
      if (context.format === uno.defs.format.CLIENT_HTML) {
        if (this.client.importHTML) {
          this.client.importHTML(fragment, context);
        }
      } else {
        if (context.format === uno.defs.format.CLIPBOARD) {
          if (this.client.importHTML) {
            this.client.importHTML(fragment, context);
          }
        }
      }
    }
  };
  CryptFilter.prototype.cleanContentsDom = function(fragment) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.ENML) {
      if (this.client.exportENML) {
        this.client.exportENML(fragment);
      } else {
        Array.prototype.forEach.call(util.crypto.all(fragment), function(node) {
          var newNode = goog.dom.createDom("en-crypt");
          newNode.setAttribute("cipher", node.getAttribute("data-cipher") || "AES");
          newNode.setAttribute("length", node.getAttribute("data-length") || "128");
          newNode.setAttribute("hint", node.getAttribute("data-hint") || "");
          newNode.innerHTML = node.getAttribute("data-ciphertext") || "";
          goog.dom.replaceNode(newNode, node);
        });
      }
    } else {
      if (context.format === uno.defs.format.CLIENT_HTML) {
        if (this.client.exportHTML) {
          this.client.exportHTML(fragment);
        }
      } else {
        if (context.format === uno.defs.format.CLIPBOARD) {
          Array.prototype.forEach.call(util.crypto.all(fragment), function(node) {
            var newId = "crypt-" + context.crypt.incrementUniqueId();
            node.id = newId;
          });
        }
      }
    }
  };
})();
goog.provide("uno.filters.EnmlFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.EnmlFilter");
  var util = uno.util;
  var rxDocType = /^<!DOCTYPE[^>]*>\n?/g;
  var rxXhtmlNs = / +xmlns="(http:\/\/www.w3.org\/1999\/xhtml)?"/g;
  var rxInvalidHtmlChars = new RegExp(uno.defs.regex.INVALID_HTML_CHARS, "g");
  var rxEnNoteOpening = /<\s*en-note[^>]*>/;
  var rxEnNoteClosing = /<\/\s*en-note\s*>/;
  var rxEnNoteVoid = /<\s*en-note\s*\/\s*>/;
  var rxEnTodoNonVoid = /<en-todo([^>]*?)>.*?<\/en-todo>/g;
  var rxEnMediaNonVoid = /<en-media([^>]*?)>.*?<\/en-media>/g;
  var EnmlFilter = uno.filters.EnmlFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(EnmlFilter, uno.BasePlugin);
  EnmlFilter.prototype.prepareContentsHtml = function(html) {
    var openingMatch;
    var closingMatch;
    if (!html) {
      return html;
    }
    openingMatch = html.match(rxEnNoteOpening);
    closingMatch = html.match(rxEnNoteClosing);
    voidMatch = html.match(rxEnNoteVoid);
    if (voidMatch) {
      html = "";
    } else {
      if (openingMatch && closingMatch) {
        html = html.substring(openingMatch.index + openingMatch[0].length, closingMatch.index);
      } else {
        if (this.editor.context.format === uno.defs.format.ENML) {
          log.info("html:");
          log.info(html);
          log.severe("Cannot find en-note node in ENML");
        }
      }
    }
    return html;
  };
  EnmlFilter.prototype.cleanContentsHtml = function(html) {
    if (this.editor.context.format !== uno.defs.format.ENML) {
      return html;
    }
    var liveRoot = this.editor.field;
    var enmlDTD = document.implementation.createDocumentType("en-note", "", "http://xml.evernote.com/pub/enml2.dtd");
    var enmlDocument = document.implementation.createDocument("http://www.w3.org/1999/xhtml", "en-note", enmlDTD);
    var enmlNode = enmlDocument.documentElement;
    var legalNoteAttributes = ["style", "bgcolor", "title", "lang", "dir", "text"];
    var zwsRegex = new RegExp(uno.defs.unicode.ZERO_WIDTH_SPACE, "g");
    html = html.replace(zwsRegex, "");
    var frag = util.dom.fragFromString(html);
    if (liveRoot.hasAttributes()) {
      goog.array.forEach(liveRoot.attributes, function(a) {
        if (goog.array.contains(legalNoteAttributes, a.name)) {
          enmlNode.setAttribute(a.name.toLowerCase(), a.value);
        }
      });
    }
    var treeWalker = document.createTreeWalker(frag, NodeFilter.SHOW_ELEMENT);
    while (treeWalker.nextNode()) {
      var currentNode = treeWalker.currentNode;
      if (currentNode.tagName === "EN-CURSOR") {
        currentNode.remove();
        continue;
      }
      currentNode.removeAttribute("id");
      currentNode.removeAttribute("class");
      for (var key in currentNode.dataset) {
        delete currentNode.dataset[key];
      }
    }
    goog.array.forEachRight(frag.querySelectorAll('*[style*="-en-clipboard"]'), function(el) {
      util.dom.removeStyleValue(el, "-en-clipboard");
    });
    var clonedNode = enmlDocument.importNode(frag, true);
    var ennote = enmlDocument.querySelector("en-note");
    util.dom.removeStyleValue(ennote, "display");
    util.dom.removeStyleValue(ennote, "margin");
    util.dom.removeStyleValue(ennote, "padding");
    ennote.appendChild(clonedNode);
    var xmlString = (new XMLSerializer).serializeToString(enmlDocument);
    xmlString = xmlString.replace(rxInvalidHtmlChars, "").replace(rxDocType, '<!DOCTYPE en-note SYSTEM "http://xml.evernote.com/pub/enml2.dtd">').replace(rxXhtmlNs, "").replace(rxEnTodoNonVoid, "<en-todo$1 />").replace(rxEnMediaNonVoid, "<en-media$1 />");
    return xmlString;
  };
})();
goog.provide("uno.filters.FontSizeFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.FontSizeFilter");
  var FontSizeFilter = uno.filters.FontSizeFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(FontSizeFilter, uno.BasePlugin);
  FontSizeFilter.prototype.cleanContentsHtml = function(html) {
    return html.replace(uno.defs.unicode.ZERO_WIDTH_SPACE, "");
  };
})();
goog.provide("uno.filters.NormalizeFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.normalize");
goog.require("uno.util.n3");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.NormalizeFilter");
  var util = uno.util;
  var NormalizeFilter = uno.filters.NormalizeFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(NormalizeFilter, uno.BasePlugin);
  NormalizeFilter.prototype.prepareContentsHtml = function(html) {
    return util.normalize.normalizeHtml(html);
  };
  NormalizeFilter.prototype.prepareContentsDom = function(frag) {
    var context = this.editor.context;
    var HTML = uno.defs.format.CLIENT_HTML;
    var ENML = uno.defs.format.ENML;
    if ((context.format === ENML || context.format === HTML) && !this.editor.config.noNormalize) {
      util.n3.normalizeDom(frag, {editor:this.editor});
    } else {
      if (context.format === uno.defs.format.CLIPBOARD) {
        util.normalize.normalizeDom(frag, {editor:this.editor, externalContent:context.copyPaste.externalContent});
      }
    }
  };
  NormalizeFilter.prototype.cleanContentsDom = function(frag) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.CLIPBOARD) {
      util.normalize.normalizeDom(frag, {ignoreTableStyles:true});
    }
  };
  NormalizeFilter.prototype.cleanContentsHtml = function(html) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.CLIPBOARD) {
      return util.normalize.normalizeHtml(html);
    }
    return html;
  };
})();
goog.provide("uno.filters.PasteFilter");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.array");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.PasteFilter");
  var util = uno.util;
  var PasteFilter = uno.filters.PasteFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(PasteFilter, uno.BasePlugin);
  PasteFilter.prototype.prepareContentsDom = function(frag) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.CLIPBOARD) {
      transformURLs(frag);
    }
  };
  function transformURLs(frag) {
    var urlRegex = new RegExp("(" + uno.defs.regex.SIMPLE_URL + ")", "gi");
    var emailRegex = new RegExp("(" + uno.defs.regex.SIMPLE_EMAIL + ")", "gi");
    goog.array.forEachRight(util.dom.getNodeLeaves(frag), function(node) {
      var isTextNode = util.dom.isTextNode(node);
      var isLinked = !!goog.dom.getAncestor(node, function(ancestor) {
        return !!ancestor.hasAttribute && ancestor.hasAttribute("href");
      });
      if (isTextNode && !isLinked) {
        var text = goog.string.htmlEscape(node.textContent);
        var html;
        if (emailRegex.test(text)) {
          html = text.replace(emailRegex, '<a href="mailto:$1">$1</a>');
        } else {
          if (urlRegex.test(text)) {
            html = text.replace(urlRegex, function(match) {
              var href = /http(s?):\/\//i.test(match) ? match : "http://" + match;
              return '<a href="' + href + '">' + match + "</a>";
            });
          }
        }
        if (html) {
          node.parentNode.replaceChild(util.dom.fragFromString(html), node);
        }
      }
    });
  }
})();
goog.provide("uno.filters.PrePasteFilter");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.array");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.PrePasteFilter");
  var util = uno.util;
  var PrePasteFilter = uno.filters.PrePasteFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(PrePasteFilter, uno.BasePlugin);
  PrePasteFilter.prototype.prepareContentsDom = function(frag) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.CLIPBOARD) {
      transformMicrosoftWordListsWithMap(frag);
    }
  };
  function transformMicrosoftWordListsWithMap(frag) {
    var queue = [];
    goog.array.forEach(frag.querySelectorAll("p"), function(node) {
      if (util.dom.getNodeLength(node) === 1 && util.dom.getTagName(node.firstChild) === "o:p") {
        goog.dom.removeNode(node.firstChild);
        node.appendChild(goog.dom.createDom("br"));
        util.dom.changeTagName(node, "div");
      }
    });
    goog.array.forEach(frag.querySelectorAll('div[style*="mso-line-break-override"]'), function(node) {
      var results = node.querySelectorAll('span[style*="mso-special-format"]');
      if (results.length > 0) {
        var listType = "ul";
        if (util.dom.getStyleValue(results[0], "mso-special-format").toLowerCase() !== "bullet") {
          listType = "ol";
        }
        if (util.dom.getNodeLength(results[0].parentNode) === 1) {
          goog.dom.removeNode(results[0].parentNode);
        } else {
          goog.dom.removeNode(results[0]);
        }
        appendListItem(node, queue, 1, listType);
      }
    });
    var rxLevel = /level([0-9]+)/;
    var rxMsoIgnore = /ignore/i;
    goog.array.forEach(frag.querySelectorAll("div[style*=mso]"), function(node) {
      var listMso = (util.dom.getStyleValue(node, "mso-list") || "").toLowerCase().match(rxLevel);
      if (listMso) {
        var level = parseInt(listMso.pop(), 10);
        var levelKey = listMso.pop();
        if (!isNaN(level)) {
          var listType = "ul";
          var spanMso = node.querySelectorAll('span[style*="mso-list:"]');
          if (spanMso) {
            goog.array.forEach(spanMso, function() {
              var span = spanMso[0];
              var spanMsoType = util.dom.getStyleValue(span, "mso-list").toLowerCase().match(rxMsoIgnore);
              if (spanMsoType) {
                if (span.textContent.match(/[0-9a-z]+.*/g)) {
                  listType = "ol";
                }
                if (util.dom.matches(span.parentNode, "span") && util.dom.getNodeLength(span.parentNode) === 1) {
                  goog.dom.removeNode(span.parentNode);
                } else {
                  goog.dom.removeNode(span);
                }
              }
            });
          }
          appendListItem(node, queue, level, listType);
        }
      } else {
        appendListItem(node, queue);
      }
    });
  }
  function getList(node, queue, level, listType) {
    if (level === undefined) {
      return queue.slice(-1).pop();
    }
    var list = null;
    while (!list && queue.length) {
      list = queue.pop();
      if (list.level === level) {
        if (util.dom.matches(list, listType)) {
          queue.push(list);
        } else {
          var parent = list.parentNode;
          list = goog.dom.createDom(listType);
          list.level = level;
          queue.push(list);
          parent.appendChild(list);
        }
      } else {
        if (list.level < level) {
          queue.push(list);
          var parent = list;
          list = goog.dom.createDom(listType);
          list.level = level;
          queue.push(list);
          parent.appendChild(list);
        } else {
          list = null;
        }
      }
    }
    if (!list) {
      list = goog.dom.createDom(listType);
      list.level = level;
      queue.push(list);
      node.parentNode.insertBefore(list, node);
    }
    return list;
  }
  function appendListItem(node, queue, level, listType) {
    var list = getList(node, queue, level, listType);
    goog.array.forEach(node.getElementsByTagName("o:p"), function(elem) {
      goog.dom.removeNode(elem);
    });
    if (!list || !node.getAttribute("style")) {
      node.removeAttribute("style");
      return;
    }
    util.dom.detachNode(node);
    var listItem = node;
    if (util.dom.getStyleValue(node, "mso-list")) {
      node = util.dom.changeTagName(node, "div");
      listItem = goog.dom.createDom("li");
      listItem.appendChild(node);
    } else {
      list = list.lastElementChild;
    }
    node.removeAttribute("style");
    list.appendChild(listItem);
  }
})();
goog.provide("uno.filters.ResourceFilter");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.resource");
goog.require("uno.util.img");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.ResourceFilter");
  var defs = uno.defs;
  var util = uno.util;
  var ResourceFilter = uno.filters.ResourceFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ResourceFilter, uno.BasePlugin);
  ResourceFilter.prototype.prepareContentsDom = function(frag) {
    var editor = this.editor;
    var context = this.editor.context;
    var dict;
    if (context.format === defs.format.ENML) {
      goog.array.forEach(frag.querySelectorAll("en-media"), function(enmedia) {
        var hash = enmedia.getAttribute("hash");
        if (hash) {
          hash = hash.toLowerCase();
          enmedia.setAttribute("hash", hash);
        }
        dict = context.resources[hash];
        util.resource.convertMediaToSlug(enmedia, dict, editor);
      });
    } else {
      if (context.format === defs.format.CLIENT_HTML) {
        goog.array.forEach(util.resource.findResourcesInClientHtml(frag), function(el) {
          if (util.dom.compareTagName(el, "en-media")) {
            dict = context.resources[el.getAttribute("hash")];
            util.resource.convertMediaToSlug(el, dict, editor);
          } else {
            util.resource.convertClientElementToSlug(el, editor);
          }
        });
      } else {
        if (context.format === defs.format.CLIPBOARD) {
          goog.array.forEach(util.resource.findResourcesInClipboardHtml(frag), function(el) {
            util.resource.convertClipboardElementToSlug(el, context, editor);
          });
        }
      }
    }
  };
  ResourceFilter.prototype.cleanContentsDom = function(frag) {
    var context = this.editor.context;
    if (context.format === defs.format.ENML) {
      goog.array.forEachRight(util.resource.all(frag), function(el) {
        util.resource.convertSlugToMedia(el);
      });
    } else {
      if (context.format === defs.format.CLIENT_HTML) {
        goog.array.forEachRight(util.resource.all(frag), function(el) {
          util.resource.convertSlugToClientElement(el);
        });
      } else {
        if (context.format === defs.format.CLIPBOARD) {
          goog.array.forEachRight(util.resource.all(frag), function(el) {
            util.resource.convertSlugToClientElement(el);
          });
        }
      }
    }
  };
  ResourceFilter.prototype.cleanContentsHtml = function(html) {
    if (this.editor.context.format === defs.format.CLIENT_HTML) {
      html = util.resource.formatClientHtmlForExport(html);
      html = html.replace(uno.defs.unicode.ZERO_WIDTH_SPACE, "");
    }
    return html;
  };
  ResourceFilter.prototype.handleDomUpdate = function(event) {
    if (event.paste) {
      var images = [];
      var editor = this.editor;
      goog.iter.forEach(event.range, function(node, _, iter) {
        if (iter.isStartTag() && util.dom.isImg(node)) {
          images.push(node);
        }
      });
      Promise.all(goog.array.map(images, util.img.ratioResizeIfNeeded)).then(function(resizes) {
        if (resizes.indexOf(true) > -1) {
          editor.dispatchChange();
        }
      });
    }
  };
})();
goog.provide("uno.filters.RichlinkFilter");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.richlink");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.RichlinkFilter");
  var util = uno.util;
  var RICHLINK_CONVERT_DELAY = 400;
  var RichlinkFilter = uno.filters.RichlinkFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(RichlinkFilter, uno.BasePlugin);
  RichlinkFilter.prototype.prepareContentsDom = function(frag, styles) {
    var editor = this.editor;
    var links;
    var fromClipboard = editor.context.format === uno.defs.format.CLIPBOARD;
    if (!editor.config.richlinks.enabled) {
      return;
    }
    if (fromClipboard) {
      links = util.richlink.allPlain(frag);
    } else {
      links = util.richlink.allUndecorated(frag);
    }
    if (links.length > 0) {
      goog.array.forEach(links, function(link) {
        if (util.richlink.canDecorate(link, editor)) {
          util.richlink.setPending(link, true);
        }
      });
      setTimeout(function() {
        var pendingLinks = util.richlink.allPending(editor.field);
        goog.array.forEach(pendingLinks, function(link) {
          if (util.richlink.canDecorate(link, editor)) {
            util.richlink.setPending(link, false);
            if (fromClipboard) {
              editor.plugins_.UndoRedo.updateCurrentState_(editor);
            }
            util.richlink.decorate(link, editor);
          }
        });
      }, fromClipboard ? RICHLINK_CONVERT_DELAY : 0);
    }
  };
  RichlinkFilter.prototype.cleanContentsDom = function(frag) {
    var editor = this.editor;
    if (editor.config.richlinks.enabled) {
      goog.array.forEach(util.richlink.all(frag), function(link) {
        util.richlink.undecorate(link, editor);
      });
    }
  };
})();
goog.provide("uno.filters.SectionBreakFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.SectionBreakFilter");
  var util = uno.util;
  var SectionBreakFilter = uno.filters.SectionBreakFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(SectionBreakFilter, uno.BasePlugin);
  SectionBreakFilter.prototype.cleanContentsDom = function(frag) {
    var sectionbreaks = frag.querySelectorAll('[style*="-evernote-encp-section-break"]');
    goog.array.forEach(sectionbreaks, function(sectionbreak) {
      sectionbreak.style.display = "none";
      util.dom.setStyleValue(sectionbreak, "-evernote-encp-section-break", true);
    });
  };
})();
goog.provide("uno.filters.TableFilter");
goog.require("goog.debug.Logger");
goog.require("goog.array");
goog.require("goog.iter");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.TableFilter");
  var defs = uno.defs;
  var util = uno.util;
  var TableFilter = uno.filters.TableFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TableFilter, uno.BasePlugin);
  TableFilter.prototype.prepareContentsDom = function(frag) {
    var isClipboard = this.editor.context.format === defs.format.CLIPBOARD;
    goog.array.forEach(frag.querySelectorAll("table"), function(table) {
      var enTable = util.table.attachAdornments(table);
      if (!isClipboard && enTable) {
        util.table.normalizeDOMPlacement(enTable);
      }
    });
  };
  TableFilter.prototype.cleanContentsDom = function(frag) {
    var isClipboard = this.editor.context.format === defs.format.CLIPBOARD;
    goog.array.forEach(frag.querySelectorAll("en-table"), function(enTable) {
      util.table.clearAdornments(enTable, !isClipboard);
    });
  };
  TableFilter.prototype.handleDomUpdate = function(event) {
    start("TableFilter.prototype.handleDomUpdate");
    var range = event.range;
    var enTable = goog.dom.getAncestor(range.getStartNode(), util.dom.isEntable, true);
    if (enTable) {
      start("table.layout");
      util.table.layout(enTable);
      stop("table.layout");
    } else {
      goog.iter.forEach(range, function(node, _, iter) {
        if (iter.isStartTag() && util.dom.isEntable(node)) {
          util.table.layout(node);
        }
      });
    }
    stop("TableFilter.prototype.handleDomUpdate");
  };
  TableFilter.prototype.restoreUX = function(frag) {
    goog.array.forEach(frag.querySelectorAll("table"), util.table.attachAdornments);
  };
  TableFilter.prototype.cleanUX = function(frag) {
    goog.array.forEach(frag.querySelectorAll("en-table"), util.table.clearAdornments);
  };
})();
goog.provide("uno.filters.TodoFilter");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.TodoFilter");
  var defs = uno.defs;
  var util = uno.util;
  var TodoFilter = uno.filters.TodoFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TodoFilter, uno.BasePlugin);
  TodoFilter.prototype.prepareContentsDom = function(frag) {
    var context = this.editor.context;
    if (context.format === defs.format.ENML) {
      goog.array.forEach(util.todo.allEnmlTodos(frag), function(entodo) {
        util.todo.decorate(entodo);
      });
    } else {
      if (context.format === defs.format.CLIPBOARD) {
        var todos = util.todo.all(frag);
        Array.prototype.forEach.call(todos, function(todo) {
          var newTodo = util.todo.convertTodoInClipboard(todo);
          if (newTodo) {
            goog.dom.replaceNode(newTodo, todo);
          }
        });
      } else {
        goog.array.forEach(util.todo.findTodosInClientHtml(frag), function(el) {
          util.todo.convertClientElementToTodo(el);
        });
      }
    }
  };
  TodoFilter.prototype.cleanContentsDom = function(frag) {
    var context = this.editor.context;
    if (context.format === defs.format.ENML) {
      goog.array.forEach(util.todo.all(frag), function(entodo) {
        util.todo.undecorate(entodo);
      });
    } else {
      if (context.format === defs.format.CLIPBOARD) {
        var todos = util.todo.all(frag);
        Array.prototype.forEach.call(todos, function(todo) {
          var newTodo = util.todo.convertTodoToClipboardElement(todo);
          if (newTodo) {
            goog.dom.replaceNode(newTodo, todo);
          }
        });
      } else {
        goog.array.forEachRight(util.todo.all(frag), function(entodo) {
          util.todo.convertTodoToClientElement(entodo);
        });
      }
    }
  };
})();
goog.provide("uno.filters.BasicTextFormatterFilter");
goog.require("goog.debug.Logger");
goog.require("goog.iter");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.BasicTextFormatterFilter");
  var highlightBackgroundColor = uno.defs.highlight.COLOR;
  var util = uno.util;
  var CLIENT_HTML = uno.defs.format.CLIENT_HTML;
  var ENML = uno.defs.format.ENML;
  var BasicTextFormatterFilter = uno.filters.BasicTextFormatterFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(BasicTextFormatterFilter, uno.BasePlugin);
  BasicTextFormatterFilter.prototype.prepareContentsDom = function(frag) {
    var context = this.editor.context;
    if ([ENML, CLIENT_HTML].indexOf(context.format) > -1) {
      var nodes = frag.querySelectorAll('[style*="background-color"],[style*="' + uno.defs.highlight.STYLE + '"]');
      Array.prototype.forEach.call(nodes, function(node) {
        var bgColor = node.style.backgroundColor.toString();
        if (!bgColor || uno.defs.highlight.regex.test(bgColor)) {
          node.style.backgroundColor = highlightBackgroundColor;
          uno.util.dom.removeStyleValue(node, uno.defs.highlight.STYLE);
        }
      });
    }
  };
  BasicTextFormatterFilter.prototype.cleanContentsDom = function(frag) {
    var context = this.editor.context;
    if ([ENML, CLIENT_HTML].indexOf(context.format) > -1 && frag.querySelectorAll != null) {
      var nodes = frag.querySelectorAll('[style*="background-color"]');
      goog.iter.forEach(nodes, function(node) {
        if (node.attributes.style) {
          var bgColor = node.style.backgroundColor.toString();
          if (uno.defs.highlight.regex.test(bgColor)) {
            util.dom.setStyleValue(node, uno.defs.highlight.STYLE, "true");
          }
        }
      });
    }
  };
})();
goog.provide("uno.filters.ZoomScaleFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.ZoomScaleFilter");
  var ZoomScaleFilter = uno.filters.ZoomScaleFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ZoomScaleFilter, uno.BasePlugin);
  ZoomScaleFilter.prototype.cleanContentsDom = function(frag) {
    frag.firstElementChild && frag.firstElementChild.style.removeProperty("zoom");
  };
})();
goog.provide("uno.filters.CopyFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.crypto");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.CopyFilter");
  var util = uno.util;
  var CopyFilter = uno.filters.CopyFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CopyFilter, uno.BasePlugin);
  CopyFilter.prototype.cleanContentsDom = function(frag) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.CLIPBOARD) {
    }
  };
  CopyFilter.prototype.cleanContentsHtml = function(html) {
    return html;
  };
})();
goog.provide("uno.filters.strict.CodeBlockFilter");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.model.codeblock");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.strict.CodeBlockFilter");
  var util = uno.util;
  var model = uno.model;
  var CodeBlockFilter = uno.filters.strict.CodeBlockFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CodeBlockFilter, uno.BasePlugin);
  CodeBlockFilter.prototype.prepareContentsDom = function(frag) {
    var codeblocks = frag.querySelectorAll('[style*="-en-codeblock"]');
    goog.array.forEachRight(codeblocks, function(enmlCodeblock) {
      var codeblock = model.codeblock.create(enmlCodeblock.childNodes);
      goog.dom.replaceNode(codeblock, enmlCodeblock);
    });
  };
  CodeBlockFilter.prototype.cleanContentsDom = function(frag) {
    var codeblocks = model.codeblock.all(frag);
    goog.array.forEachRight(codeblocks, function(codeblock) {
      var enmlCodeblock = goog.dom.createDom("div", {style:uno.defs.codeblock.style}, codeblock.childNodes);
      util.dom.setStyleValue(enmlCodeblock, "-en-codeblock", "true");
      goog.dom.replaceNode(enmlCodeblock, codeblock);
    });
  };
})();
goog.provide("uno.listeners.AccentuateListener");
goog.require("goog.debug.Logger");
goog.require("goog.iter");
goog.require("goog.dom");
goog.require("goog.events.KeyCodes");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.img");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.AccentuateListener");
  var util = uno.util;
  var AccentuateListener = uno.listeners.AccentuateListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(AccentuateListener, uno.BasePlugin);
  AccentuateListener.CONTAINER_CLASSNAME = ".accentuate-container";
  AccentuateListener.BOX_CLASSNAME = ".en-find-result";
  AccentuateListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  AccentuateListener.prototype.handleSelectionChange = function(event) {
    var config = this.editor.config.accentuate;
    if (config.clearOnClickSelector) {
      var range = this.editor.getRange();
      if (range) {
        var focusNode = range.getFocusNode();
        var selector = document.querySelector(config.clearOnClickSelector);
        var editor = this.editor;
        if (event && goog.dom.contains(selector, focusNode)) {
          editor.execCommand("accentuate", {clearFirst:true});
        }
        goog.array.forEach(util.img.all(this.editor.field), util.img.removeOverlay);
      }
    }
  };
})();
goog.provide("uno.listeners.AttachmentListener");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.resource");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.AttachmentListener");
  var util = uno.util;
  var AttachmentListener = uno.listeners.AttachmentListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(AttachmentListener, uno.BasePlugin);
  AttachmentListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  AttachmentListener.prototype.handleClick = function(e) {
    if (!util.resource.isFileUI(e.target) || !this.editor.config.resourceConfig.openLinkNotifications) {
      return false;
    }
    var target = e.target;
    var evt = {type:"linkclick", target:target, data:{action:undefined, eventType:"tap", hash:util.resource.hashFor(target), href:util.resource.urlFor(target), mime:util.resource.mimeTypeFor(target), module:"resource", reference:util.resource.referenceFor(target)}};
    if (util.resource.isDefaultContextButton(target)) {
      evt.data.action = "generic-default";
    } else {
      if (util.resource.isOverflowContextButton(target)) {
        evt.data.action = "generic-context";
      } else {
        evt.data.action = "open";
      }
    }
    this.editor.dispatchEvent(evt);
    return true;
  };
  AttachmentListener.prototype.handleMouseDown = function(e) {
    if (util.resource.isPdf(e.target)) {
      this.editor.field.blur();
    }
  };
})();
goog.provide("uno.listeners.AutoCorrectListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.AutoCorrectListener");
  var wordCharacterRegexp = new RegExp(uno.defs.regex.WORD_CHARACTER, "g");
  var lastCharacterIsAlphanum;
  var spellcheckOn = true;
  var AutoCorrectListener = uno.listeners.AutoCorrectListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(AutoCorrectListener, uno.BasePlugin);
  AutoCorrectListener.prototype.handleKeyPress = function(event) {
    wordCharacterRegexp.lastIndex = 0;
    var data = String.fromCharCode(event.keyCode);
    if (!wordCharacterRegexp.test(data)) {
      if (lastCharacterIsAlphanum) {
        var undoPlugin = this.editor.plugins_.UndoRedo;
        undoPlugin.updateCurrentState_(this.editor);
        lastCharacterIsAlphanum = false;
      }
    } else {
      lastCharacterIsAlphanum = true;
      if (!spellcheckOn) {
        this.editor.field.setAttribute("autocorrect", "on");
        this.editor.field.setAttribute("spellcheck", "true");
        spellcheckOn = true;
      }
    }
  };
  AutoCorrectListener.prototype.handleAfterExecCommand = function(event) {
    if (event.command === "undo") {
      if (spellcheckOn) {
        this.editor.field.setAttribute("autocorrect", "off");
        this.editor.field.setAttribute("spellcheck", "false");
        spellcheckOn = false;
      }
    }
  };
})();
goog.provide("uno.listeners.ChangeListener");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.img");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.ChangeListener");
  var ChangeListener = uno.listeners.ChangeListener = function() {
    uno.BasePlugin.call(this, log.getName());
    goog.editor.Field.isSpecialGeneratingKey_ = goog.functions.FALSE;
    goog.editor.Field.isGeneratingKey_ = goog.functions.FALSE;
  };
  goog.inherits(ChangeListener, uno.BasePlugin);
  ChangeListener.prototype.handleKeyPress = function() {
    this.editor.gotGeneratingKey_ = false;
    return false;
  };
})();
goog.provide("uno.util.codeblock");
goog.require("uno.defs");
goog.require("uno.util.dom");
(function() {
  var util = uno.util;
  util.codeblock.for = function(node) {
    return goog.dom.getAncestor(node, util.dom.isCodeBlock, true);
  };
  util.codeblock.updateEmpty = function(node) {
    if (!node) {
      return false;
    }
    var block = goog.dom.getAncestor(node, function(ancestor) {
      return util.dom.isCodeBlock(ancestor);
    }, true);
    if (block && block.childNodes && !util.dom.isDiv(block.childNodes[0])) {
      var innerContent = block.childNodes[0].cloneNode(true);
      var innerDiv = goog.dom.createDom("div", {}, innerContent);
      for (var i = 1; i < block.childNodes.length; i++) {
        innerDiv.appendChild(block.childNodes[i].cloneNode(true));
        block.childNodes[i].remove();
      }
      goog.dom.replaceNode(innerDiv, block.childNodes[0]);
      goog.editor.range.placeCursorNextTo(innerContent);
      return true;
    }
    return false;
  };
  util.codeblock.updateTopSpace = function(editor) {
    var firstChild = editor.field.childNodes[0];
    if (util.dom.isCodeBlock(firstChild)) {
      var innerDiv = goog.dom.createDom("div", {}, goog.dom.createDom("br"));
      editor.field.insertBefore(innerDiv, firstChild);
    }
  };
})();
goog.provide("uno.listeners.CodeBlockListener");
goog.require("uno.BasePlugin");
goog.require("uno.util.codeblock");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.CodeBlockListener");
  var util = uno.util;
  var CodeBlockListener = uno.listeners.CodeBlockListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CodeBlockListener, uno.BasePlugin);
  CodeBlockListener.prototype.handleAfterExecCommand = function() {
    var range = this.editor.getRange();
    if (range) {
      util.codeblock.updateEmpty(range.getStartNode());
    }
  };
})();
goog.provide("uno.listeners.CryptListener");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.defs");
goog.require("uno.BasePlugin");
goog.require("uno.util.crypto");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.CryptListener");
  var util = uno.util;
  var CryptListener = uno.listeners.CryptListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(CryptListener, uno.BasePlugin);
  CryptListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  CryptListener.prototype.handleClick = function(e) {
    var dispatchEvent = this.editor.dispatchEvent.bind(this);
    var readOnly = this.editor.config.crypt.readOnly;
    return util.crypto.handleClick(e.target, readOnly, dispatchEvent);
  };
  CryptListener.prototype.handleDoubleClick = function(e) {
    var el = event.target;
    if (util.crypto.isCrypt(el) && !util.crypto.isOpen(el)) {
      goog.editor.range.placeCursorNextTo(el);
      this.editor.dispatchEvent({type:"cryptdoubleclick", id:el.getAttribute("id"), src:el.getAttribute("src")});
      return true;
    }
  };
})();
goog.provide("uno.listeners.DeleteListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.codeblock");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.DeleteListener");
  var util = uno.util;
  var BACKSPACE = goog.events.KeyCodes.BACKSPACE;
  var kKey = goog.events.KeyCodes.K;
  var DeleteListener = uno.listeners.DeleteListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(DeleteListener, uno.BasePlugin);
  DeleteListener.prototype.handleKeyDown = function(event) {
    if (event.ctrlKey && event.keyCode === kKey) {
      this.editor.dispatchChange();
    }
    if (event.keyCode === BACKSPACE) {
      if (this.editor.execCommand("delete", null, {native:true}, true)) {
        event.preventDefault();
        return true;
      } else {
        setTimeout(this.editor.dispatchChange.bind(this.editor));
      }
    }
  };
  DeleteListener.prototype.handleAfterExecCommand = function(event) {
    if (event.command === "delete") {
      var range = this.editor.getRange();
      util.codeblock.updateTopSpace(this.editor);
      if (range) {
        util.codeblock.updateEmpty(range.getStartNode());
      }
    }
  };
})();
goog.provide("uno.listeners.NoteListener");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.paragraph");
goog.require("uno.util.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.NoteListener");
  var util = uno.util;
  var selectingLines = false;
  var DOWN = goog.events.KeyCodes.DOWN;
  var UP = goog.events.KeyCodes.UP;
  var LEFT = goog.events.KeyCodes.LEFT;
  var RIGHT = goog.events.KeyCodes.RIGHT;
  var NoteListener = uno.listeners.NoteListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(NoteListener, uno.BasePlugin);
  NoteListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  NoteListener.prototype.handleKeyDown = function(e) {
    if ([DOWN, UP, LEFT, RIGHT].indexOf(e.keyCode) > -1 && e.shiftKey && !selectingLines) {
      selectingLines = true;
    } else {
      selectingLines = false;
    }
  };
  NoteListener.prototype.handleNativeSelectionChange = function() {
    var range = this.editor.getRange();
    if (range && !range.isCollapsed() && !selectingLines) {
      var rx = "^(<br( ?\\/)?>\\s*)?" + "(<\\/[^>]+>\\s*)+" + "(<[^\\/>]+>\\s*)+" + "(<br( ?\\/)?>\\s*)?$";
      rx = new RegExp(rx, "i");
      if (rx.test(range.getHtmlFragment())) {
        range.collapse(true);
        range.select();
      }
    }
    selectingLines = false;
  };
  NoteListener.prototype.handleClick = function(e) {
    if (!this.editor.readOnly) {
      var isOutsideNote = !goog.dom.getAncestor(e.target, util.dom.isEnnote, true);
      var focus = this.editor.config.stayInEditMode ? isOutsideNote : true;
      this.editor.enterEditMode(focus);
    } else {
      this.editor.dispatchEvent({type:uno.Editor.EventType.ACTION_DENIED, reason:{readOnly:true}});
    }
  };
  NoteListener.prototype.handleDelayedChange = function() {
    var lastNode = goog.dom.getLastElementChild(this.editor.field);
    if (!lastNode) {
      return;
    }
    var addNewLine = goog.array.some(lastNode.childNodes, function(node) {
      return util.dom.isBlockNode(node) || util.dom.isImageLikeElement(node) && !util.todo.isTodo(node);
    });
    if (addNewLine) {
      var newDiv = goog.dom.createDom("div", {}, goog.dom.createDom("br"));
      this.editor.field.appendChild(newDiv);
    }
  };
})();
goog.provide("uno.listeners.ForwardDeleteListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.paragraph");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.ForwardDeleteListener");
  var DELETE = goog.events.KeyCodes.DELETE;
  var ForwardDeleteListener = uno.listeners.ForwardDeleteListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ForwardDeleteListener, uno.BasePlugin);
  ForwardDeleteListener.prototype.handleKeyDown = function(event) {
    if (event.keyCode === DELETE) {
      if (this.editor.execCommand("delete", null, {forward:true, native:true}, true)) {
        event.preventDefault();
        return true;
      } else {
        setTimeout(this.editor.dispatchChange.bind(this.editor));
      }
    }
  };
})();
goog.provide("uno.listeners.HighlightListener");
goog.require("goog.debug.Logger");
goog.require("uno.util.dom");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.HighlightListener");
  var util = uno.util;
  var HighlightListener = uno.listeners.HighlightListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(HighlightListener, uno.BasePlugin);
  HighlightListener.prototype.handleNativeSelectionChange = function() {
    var range = this.editor.getRange();
    if (range) {
      var node = range.getStartNode();
      if (node && node.nodeType === Node.TEXT_NODE) {
        node = node.parentNode;
      }
      if (util.dom.isElementNode(node)) {
        var style = window.getComputedStyle(node);
        if (style.backgroundColor === "rgb(255, 255, 255)") {
          node.style.backgroundColor = "";
        }
      }
    }
  };
})();
goog.provide("uno.listeners.imglistener.generic");
goog.require("goog.events");
goog.require("goog.events.KeyCodes");
goog.require("goog.functions");
goog.require("uno.util.img");
goog.require("uno.util.preview");
goog.require("uno.util.resource");
(function() {
  var generic = uno.listeners.imglistener.generic;
  var util = uno.util;
  generic.handleImgResourceClick = function(event, editor) {
    var target = event.target;
    if (editor.readOnly || !util.img.isResource(target)) {
      return false;
    }
    if (util.img.isSelected(target)) {
      util.preview.requestOpen(target);
    } else {
      util.img.setSelected(target);
    }
    editor.dispatchEvent({type:uno.Editor.EventType.IMAGE_CLICK, name:"", src:util.resource.urlFor(target), tagname:"img", reference:target.dataset.reference || ""});
    return true;
  };
  generic.handleImgResourceKeyDown = function(evt) {
    var img = util.img.getSelectedImage();
    if (img && evt.keyCode === goog.events.KeyCodes.SPACE) {
      evt.preventDefault();
      util.preview.requestOpen(img);
      return true;
    }
    return false;
  };
})();
goog.provide("uno.listeners.imglistener.ios");
goog.require("uno.util.img");
goog.require("uno.util.resource");
(function() {
  var ios = uno.listeners.imglistener.ios;
  var util = uno.util;
  ios.handleImgResourceClick = function(event, editor) {
    var target = event.target;
    if (!util.img.isResource(target)) {
      return false;
    }
    var a;
    var target = event.target;
    var offsetX = event.offsetX;
    var horizontalThreshold = editor.config.images.horizontalThreshold;
    var thresholdWidth = horizontalThreshold * 3;
    if (target.width > thresholdWidth && (offsetX < horizontalThreshold || offsetX > target.offsetWidth - horizontalThreshold)) {
      if (editor.inEditMode()) {
        setTimeout(function() {
          goog.editor.range.placeCursorNextTo(target, offsetX < horizontalThreshold);
        });
      } else {
        var parent = target.parentElement;
        var offset = offsetX < horizontalThreshold ? 0 : 1;
        var index = util.dom.index(target) + offset;
        var newRange = goog.dom.Range.createFromNodes(parent, index, parent, index);
        editor.enterEditMode(newRange);
      }
    } else {
      a = goog.dom.getAncestorByTagNameAndClass(target, "a");
      editor.dispatchEvent({type:"linkclick", target:event.target, data:{action:"open", eventType:"tap", hash:util.resource.hashFor(target), href:util.resource.urlFor(target), mime:util.resource.mimeTypeFor(target), module:"resource", reference:util.resource.referenceFor(target), anchorHref:a && a.href || undefined}});
    }
    return true;
  };
  ios.handleImgResourceKeyDown = goog.functions.FALSE;
})();
goog.provide("uno.listeners.imglistener.mac");
goog.require("uno.util.img");
(function() {
  var mac = uno.listeners.imglistener.mac;
  var generic = uno.listeners.imglistener.generic;
  var util = uno.util;
  mac.handleImgResourceClick = generic.handleImgResourceClick;
  mac.handleImgResourceKeyDown = function(evt) {
    var img = util.img.getSelectedImage();
    if (img && evt.keyCode === goog.events.KeyCodes.SPACE) {
      evt.preventDefault();
      setTimeout(function() {
        util.preview.requestOpen(img);
      }, 250);
      return true;
    }
    return false;
  };
})();
goog.provide("uno.listeners.ImgListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.style");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.listeners.imglistener.generic");
goog.require("uno.listeners.imglistener.ios");
goog.require("uno.listeners.imglistener.mac");
goog.require("uno.util.img");
goog.require("uno.util.resource");
goog.require("uno.util.zoomscale");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.ImgListener");
  var util = uno.util;
  var ImgListener = uno.listeners.ImgListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ImgListener, uno.BasePlugin);
  ImgListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  ImgListener.prototype.handleClick = function(event) {
    if (event.metaKey || event.ctrlKey || event.altKey || event.shiftKey) {
      return false;
    }
    return this.client.handleImgResourceClick(event, this.editor);
  };
  ImgListener.prototype.handleNativeSelectionChange = function() {
    if (!util.img.isSelected(this.editor.getRange())) {
      util.img.setSelected(null);
    }
  };
  ImgListener.prototype.handleKeyDown = function(event) {
    return this.client.handleImgResourceKeyDown(event);
  };
  ImgListener.prototype.handleMouseOver = function(event) {
    if (util.img.isResource(event.target)) {
      util.img.setToolbar(event.target, handleToolbarButtonClick.bind(this));
    } else {
      if (!util.img.isToolbarButton(event.target)) {
        util.img.setToolbar(null);
      }
    }
  };
  ImgListener.prototype.handleScroll = function(event) {
    util.img.hideToolsOnScrollIfNeeded(event.target);
  };
  function handleToolbarButtonClick(img, name) {
    this.editor.dispatchEvent({type:name, module:"ui-img-buttons", src:util.resource.urlFor(img)});
  }
})();
goog.provide("uno.listeners.linklistener.web");
(function() {
  var web = uno.listeners.linklistener.web;
  web.handleClick = function(event) {
    event.preventDefault();
  };
})();
goog.provide("uno.listeners.LinkListener");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("goog.style");
goog.require("uno.BasePlugin");
goog.require("uno.listeners.linklistener.web");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.LinkListener");
  var util = uno.util;
  var LinkListener = uno.listeners.LinkListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(LinkListener, uno.BasePlugin);
  LinkListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  LinkListener.prototype.handleClick = function(event) {
    var bounds;
    var el = event.target;
    if (el != null) {
      var checkLink = function(node) {
        el = node;
        return util.dom.isA(node);
      };
      if (goog.dom.getAncestor(el, checkLink, true)) {
        var href = el.href;
        if (href != null && href.length > 0) {
          bounds = goog.style.getBounds(el);
          this.editor.dispatchEvent({type:"linkclick", target:el, data:{href:el.href, module:"link", left:bounds.left, top:bounds.top, width:bounds.width, height:bounds.height}});
        }
        if (this.client.handleClick) {
          this.client.handleClick(event);
        }
        return true;
      }
    }
  };
})();
goog.provide("uno.listeners.ListListener");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.editor.Command");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.list");
goog.require("uno.util.dom");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.ListListener");
  var util = uno.util;
  var KeyCodes = goog.events.KeyCodes;
  var ListListener = uno.listeners.ListListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ListListener, uno.BasePlugin);
  ListListener.prototype.handleKeyDown = function(event) {
    var range = this.editor.getRange();
    if (event.keyCode === KeyCodes.ENTER && event.shiftKey && util.list.for(range.getStartNode())) {
      event.preventDefault();
      var br = goog.dom.createDom("br");
      var zws = goog.dom.createTextNode(uno.defs.unicode.ZERO_WIDTH_SPACE);
      range.insertNode(zws);
      range.insertNode(br);
      goog.editor.range.placeCursorNextTo(zws);
      document.execCommand("delete");
      this.editor.dispatchChange();
      return true;
    } else {
      if (event.keyCode === KeyCodes.ENTER) {
        var node = util.list.itemFor(goog.editor.range.getDeepEndPoint(range, true).node);
        var sibling = node ? node.nextElementSibling : null;
        var siblingList = util.dom.isUl(sibling) || util.dom.isOl(sibling);
        if (siblingList && util.dom.isLi(node) && util.dom.isEmpty(node)) {
          event.stopPropagation();
          event.preventDefault();
          document.execCommand("outdent");
          return true;
        }
      } else {
        if (event.keyCode === KeyCodes.TAB) {
          if (util.dom.parent(range.getContainerElement(), "li") || goog.iter.some(range, util.dom.isLi)) {
            var fieldObject = this.getFieldObject();
            fieldObject.execCommand(event.shiftKey ? goog.editor.Command.OUTDENT : goog.editor.Command.INDENT);
            fieldObject.dispatchChange();
            event.preventDefault();
            return true;
          }
          return false;
        }
      }
    }
    return false;
  };
})();
goog.provide("uno.listeners.PasteListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.PasteListener");
  var PasteListener = uno.listeners.PasteListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(PasteListener, uno.BasePlugin);
  PasteListener.prototype.handlePaste = function(event) {
    event.preventDefault();
    return true;
  };
})();
goog.provide("uno.listeners.RichlinkListener");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.RichlinkListener");
  var util = uno.util;
  var RichlinkListener = uno.listeners.RichlinkListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(RichlinkListener, uno.BasePlugin);
  RichlinkListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  RichlinkListener.prototype.handleClick = function(event) {
    var el = util.richlink.componentElementFor(event.target);
    if (el) {
      return util.richlink.handleClick(el, event, this.editor);
    }
  };
  RichlinkListener.prototype.handleMouseMove = function(event) {
    var el = util.richlink.componentElementFor(event.target);
    if (el) {
      return util.richlink.handleMouseMove(el, event, this.editor);
    }
  };
  RichlinkListener.prototype.handleMouseOut = function(event) {
    var el = util.richlink.componentElementFor(event.target);
    if (el) {
      return util.richlink.handleMouseOut(el, event, this.editor);
    }
  };
})();
goog.provide("goog.editor.plugins.LinkShortcutPlugin");
goog.require("goog.editor.Command");
goog.require("goog.editor.Plugin");
goog.editor.plugins.LinkShortcutPlugin = function() {
  goog.editor.plugins.LinkShortcutPlugin.base(this, "constructor");
};
goog.inherits(goog.editor.plugins.LinkShortcutPlugin, goog.editor.Plugin);
goog.editor.plugins.LinkShortcutPlugin.prototype.getTrogClassId = function() {
  return "LinkShortcutPlugin";
};
goog.editor.plugins.LinkShortcutPlugin.prototype.handleKeyboardShortcut = function(e, key, isModifierPressed) {
  if (isModifierPressed && key == "k" && !e.shiftKey) {
    var link = this.getFieldObject().execCommand(goog.editor.Command.LINK);
    if (link) {
      link.finishLinkCreation(this.getFieldObject());
    }
    return true;
  }
  return false;
};
goog.provide("goog.editor.plugins.HeaderFormatter");
goog.require("goog.editor.Command");
goog.require("goog.editor.Plugin");
goog.require("goog.userAgent");
goog.editor.plugins.HeaderFormatter = function() {
  goog.editor.Plugin.call(this);
};
goog.inherits(goog.editor.plugins.HeaderFormatter, goog.editor.Plugin);
goog.editor.plugins.HeaderFormatter.prototype.getTrogClassId = function() {
  return "HeaderFormatter";
};
goog.editor.plugins.HeaderFormatter.HEADER_COMMAND = {H1:"H1", H2:"H2", H3:"H3", H4:"H4"};
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);
    if (goog.userAgent.GECKO) {
      e.stopPropagation();
    }
    return true;
  }
  return false;
};
goog.provide("uno.listeners.ShortcutListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.plugins.UndoRedo");
goog.require("goog.editor.plugins.RemoveFormatting");
goog.require("goog.editor.plugins.LinkShortcutPlugin");
goog.require("goog.editor.plugins.HeaderFormatter");
goog.require("goog.editor.plugins.BasicTextFormatter");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.ShortcutListener");
  var ShortcutListener = uno.listeners.ShortcutListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ShortcutListener, uno.BasePlugin);
  goog.editor.plugins.UndoRedo.prototype.handleKeyboardShortcut = goog.functions.FALSE;
  goog.editor.plugins.RemoveFormatting.prototype.handleKeyboardShortcut = goog.functions.FALSE;
  goog.editor.plugins.LinkShortcutPlugin.prototype.handleKeyboardShortcut = goog.functions.FALSE;
  goog.editor.plugins.HeaderFormatter.prototype.handleKeyboardShortcut = goog.functions.FALSE;
  goog.editor.plugins.BasicTextFormatter.prototype.handleKeyboardShortcut = goog.functions.FALSE;
})();
goog.provide("uno.listeners.SmartScrollListener");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.range");
goog.require("goog.events.KeyCodes");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.SmartScrollListener");
  var util = uno.util;
  var SmartScrollListener = uno.listeners.SmartScrollListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(SmartScrollListener, uno.BasePlugin);
  var delayedScrollTimerID = 0;
  SmartScrollListener.prototype._triggerDelayedScroll = function() {
    var editor = this.editor;
    if (delayedScrollTimerID) {
      clearTimeout(delayedScrollTimerID);
    }
    delayedScrollTimerID = setTimeout(function() {
      log.fine("  SmartScrollListener.prototype._triggerDelayedScroll");
      util.range.scrollSelectionIntoView(editor);
    });
  };
  SmartScrollListener.prototype.handleSelectionChange = function() {
    if (this.editor.config.smartScrollEnabled) {
      log.fine("SmartScrollListener.prototype.handleSelectionChange");
      this._triggerDelayedScroll();
    }
  };
  SmartScrollListener.prototype.handleNativeSelectionChange = function() {
    if (this.editor.config.smartScrollEnabled) {
      log.fine("  SmartScrollListener.prototype.handleNativeSelectionChange");
      var range = this.editor.getRange();
      if (range && range.isCollapsed()) {
        this._triggerDelayedScroll();
      }
    }
  };
  SmartScrollListener.prototype.handleWindowResize = function() {
    log.fine("SmartScrollListener.prototype.handleWindowResize");
    util.range.scrollSelectionIntoView(this.editor);
  };
})();
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");
goog.events.MouseWheelHandler = function(element, opt_capture) {
  goog.events.EventTarget.call(this);
  this.element_ = element;
  var rtlElement = goog.dom.isElement(this.element_) ? this.element_ : this.element_ ? this.element_.body : null;
  this.isRtl_ = !!rtlElement && goog.style.isRightToLeft(rtlElement);
  var type = goog.userAgent.GECKO ? "DOMMouseScroll" : "mousewheel";
  this.listenKey_ = goog.events.listen(this.element_, type, this, opt_capture);
};
goog.inherits(goog.events.MouseWheelHandler, goog.events.EventTarget);
goog.events.MouseWheelHandler.EventType = {MOUSEWHEEL:"mousewheel"};
goog.events.MouseWheelHandler.prototype.maxDeltaX_;
goog.events.MouseWheelHandler.prototype.maxDeltaY_;
goog.events.MouseWheelHandler.prototype.setMaxDeltaX = function(maxDeltaX) {
  this.maxDeltaX_ = maxDeltaX;
};
goog.events.MouseWheelHandler.prototype.setMaxDeltaY = function(maxDeltaY) {
  this.maxDeltaY_ = maxDeltaY;
};
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 = 40;
    detail = goog.events.MouseWheelHandler.smartScale_(-be.wheelDelta, wheelDeltaScaleFactor);
    if (goog.isDef(be.wheelDeltaX)) {
      deltaX = goog.events.MouseWheelHandler.smartScale_(-be.wheelDeltaX, wheelDeltaScaleFactor);
      deltaY = goog.events.MouseWheelHandler.smartScale_(-be.wheelDeltaY, wheelDeltaScaleFactor);
    } else {
      deltaY = detail;
    }
  } else {
    detail = be.detail;
    if (detail > 100) {
      detail = 3;
    } else {
      if (detail < -100) {
        detail = -3;
      }
    }
    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_);
  }
  if (this.isRtl_) {
    deltaX = -deltaX;
  }
  var newEvent = new goog.events.MouseWheelEvent(detail, be, deltaX, deltaY);
  this.dispatchEvent(newEvent);
};
goog.events.MouseWheelHandler.smartScale_ = function(mouseWheelDelta, scaleFactor) {
  if (goog.userAgent.WEBKIT && (goog.userAgent.MAC || goog.userAgent.LINUX) && mouseWheelDelta % scaleFactor != 0) {
    return mouseWheelDelta;
  } else {
    return mouseWheelDelta / scaleFactor;
  }
};
goog.events.MouseWheelHandler.prototype.disposeInternal = function() {
  goog.events.MouseWheelHandler.superClass_.disposeInternal.call(this);
  goog.events.unlistenByKey(this.listenKey_);
  this.listenKey_ = null;
};
goog.events.MouseWheelEvent = function(detail, browserEvent, deltaX, deltaY) {
  goog.events.BrowserEvent.call(this, browserEvent);
  this.type = goog.events.MouseWheelHandler.EventType.MOUSEWHEEL;
  this.detail = detail;
  this.deltaX = deltaX;
  this.deltaY = deltaY;
};
goog.inherits(goog.events.MouseWheelEvent, goog.events.BrowserEvent);
goog.provide("uno.listeners.tablelistener.generic");
goog.require("goog.events.KeyCodes");
(function() {
  var generic = uno.listeners.tablelistener.generic;
  generic.isToggleKey = function(event) {
    return event && event.metaKey;
  };
  generic.getDeltaX = function(event) {
    return event.deltaX * 0.5;
  };
})();
goog.provide("uno.listeners.tablelistener.win");
goog.require("goog.events.KeyCodes");
(function() {
  var win = uno.listeners.tablelistener.win;
  win.isToggleKey = function(event) {
    return event && event.ctrlKey;
  };
  win.getDeltaX = function(event) {
    return event.deltaX * 26;
  };
})();
goog.provide("uno.components.MenuAbstractItem");
goog.require("goog.dom");
(function() {
  uno.components.MenuAbstractItem = function() {
    this.focused_ = false;
    this.element = null;
  };
  uno.components.MenuAbstractItem.prototype.allowUserInteraction = true;
  uno.components.MenuAbstractItem.prototype.allowSubmenu = false;
  uno.components.MenuAbstractItem.prototype.setFocus = function(focused, sender) {
    if (this.allowUserInteraction) {
      this.focused_ = focused;
      this.element.classList.toggle("focused", focused);
    }
  };
  uno.components.MenuAbstractItem.prototype.getValue = function() {
    return null;
  };
  uno.components.MenuAbstractItem.prototype.handleMouseOver = function(evt) {
    return false;
  };
  uno.components.MenuAbstractItem.prototype.handleClick = function(evt) {
    return false;
  };
  uno.components.MenuAbstractItem.prototype.handleKey = function(keyCode) {
    return false;
  };
})();
goog.provide("uno.components.MenuColorPicker");
goog.require("goog.color");
goog.require("goog.dom");
goog.require("goog.events");
goog.require("goog.events.KeyCodes");
goog.require("uno.components.MenuAbstractItem");
(function() {
  uno.components.MenuColorPicker = function(text, defaultColor) {
    uno.components.MenuAbstractItem.call(this);
    if (typeof defaultColor === "string" && goog.color.isValidColor(defaultColor)) {
      defaultColor = goog.color.parse(defaultColor).hex;
    }
    this.colorPalette_ = ["#ffffff", "#eaeaea", "#d4d4d4", "#ddd1f3", "#f0d1f6", "#fbcfd6", "#fedec1", "#ffe697", "#cdedd8", "#cdeef0", "#cde6f9", "#ccd7ea", "#3f3f3f", "#737373", "#979797", "#8b65e0", "#c064d1", "#fc5356", "#fd7b39", "#ffc200", "#57b779", "#57bfc4", "#54a9e6", "#426bb3"];
    this.colorNodes_ = this.colorPalette_.map(function(code) {
      var cls = ["color"];
      if (code === "#ffffff") {
        cls.push("bordered");
      }
      if (code === defaultColor) {
        cls.push("default");
      }
      return goog.dom.createDom("div", {class:cls.join(" "), style:"background-color: " + code + ";", "data-color":code});
    });
    var titleNode = goog.dom.createDom("div", {class:"title"}, text);
    var container = goog.dom.createDom("div", {class:"colors"}, this.colorNodes_);
    var children = [titleNode, container];
    this.element = goog.dom.createDom("div", {class:"menu-colorpicker"}, children);
    this.defaultColorIndex_ = !!defaultColor ? this.colorPalette_.indexOf(defaultColor) : -1;
    this.focusedColorIndex_ = -1;
    this.cachedColorIndex_ = -1;
  };
  goog.inherits(uno.components.MenuColorPicker, uno.components.MenuAbstractItem);
  uno.components.MenuColorPicker.prototype.setColorFocus_ = function(index) {
    if (this.focusedColorIndex_ === index) {
      return;
    }
    if (this.focusedColorIndex_ > -1) {
      this.colorNodes_[this.focusedColorIndex_].classList.remove("selected");
    }
    if (index > -1) {
      this.colorNodes_[index].classList.add("selected");
      this.cachedColorIndex_ = index;
    }
    this.focusedColorIndex_ = index;
  };
  uno.components.MenuColorPicker.prototype.setFocus = function(focused, sender) {
    goog.base(this, "setFocus", focused);
    var KeyCodes = goog.events.KeyCodes;
    var cachedIndex = this.cachedColorIndex_;
    if (focused && [KeyCodes.DOWN, KeyCodes.RIGHT, KeyCodes.LEFT].indexOf(sender) > -1) {
      this.setColorFocus_(cachedIndex > -1 && cachedIndex < 6 ? cachedIndex : 0);
    } else {
      if (focused && sender === KeyCodes.UP) {
        this.setColorFocus_(cachedIndex >= this.colorPalette_.length - 6 ? cachedIndex : this.colorPalette_.length - 6);
      } else {
        if (focused) {
          this.cachedColorIndex_ = -1;
        } else {
          if (!focused) {
            this.setColorFocus_(-1);
          }
        }
      }
    }
  };
  uno.components.MenuColorPicker.prototype.getValue = function() {
    if (this.focusedColorIndex_ > -1) {
      return this.colorPalette_[this.focusedColorIndex_];
    } else {
      if (this.defaultColorIndex_ > -1) {
        return this.colorPalette_[this.defaultColorIndex_];
      }
    }
    return null;
  };
  uno.components.MenuColorPicker.prototype.handleClick = function(evt) {
    var index = this.colorNodes_.indexOf(evt.target);
    this.setColorFocus_(index);
    return index === -1;
  };
  uno.components.MenuColorPicker.prototype.handleKey = function(keyCode) {
    var KeyCodes = goog.events.KeyCodes;
    var columnCount = 6;
    var currentIndex = this.focusedColorIndex_;
    var cachedIndex = this.cachedColorIndex_;
    var index = -1;
    if (currentIndex === -1) {
      if (cachedIndex > -1 && [KeyCodes.RIGHT, KeyCodes.LEFT, KeyCodes.UP, KeyCodes.DOWN].indexOf(keyCode) > -1) {
        index = cachedIndex;
      } else {
        if ([KeyCodes.RIGHT, KeyCodes.DOWN].indexOf(keyCode) > -1) {
          index = 0;
        } else {
          if (keyCode === KeyCodes.LEFT) {
            index = columnCount - 1;
          } else {
            if (keyCode === KeyCodes.UP) {
              index = this.colorPalette_.length - columnCount;
            }
          }
        }
      }
      this.setColorFocus_(index);
      return index > -1;
    }
    if (keyCode === KeyCodes.RIGHT || keyCode === KeyCodes.LEFT) {
      var newIndex = currentIndex + (keyCode === KeyCodes.RIGHT ? 1 : -1);
      var newRow = Math.floor(newIndex / columnCount);
      var currentRow = Math.floor(currentIndex / columnCount);
      if (currentRow === newRow) {
        index = newIndex;
      }
    } else {
      if (keyCode === KeyCodes.UP && currentIndex - columnCount >= 0) {
        index = currentIndex - columnCount;
      } else {
        if (keyCode === KeyCodes.DOWN && currentIndex + columnCount <= this.colorPalette_.length - 1) {
          index = currentIndex + columnCount;
        }
      }
    }
    if (index > -1) {
      this.setColorFocus_(index);
      return true;
    }
    return false;
  };
  uno.components.MenuColorPicker.prototype.handleMouseOver = function(evt) {
    this.setColorFocus_(this.colorNodes_.indexOf(evt.target));
    return false;
  };
})();
goog.provide("uno.components.MenuItem");
goog.require("goog.dom");
goog.require("uno.components.MenuAbstractItem");
(function() {
  uno.components.MenuItem = function(text, disabled) {
    uno.components.MenuAbstractItem.call(this);
    this.element = goog.dom.createDom("div", {class:"menu-item"}, text);
    if (disabled === true) {
      this.element.classList.add("disabled");
      this.allowUserInteraction = false;
    }
  };
  goog.inherits(uno.components.MenuItem, uno.components.MenuAbstractItem);
  uno.components.MenuItem.prototype.allowSubmenu = true;
})();
goog.provide("uno.components.MenuOption");
goog.require("goog.dom");
goog.require("uno.components.MenuAbstractItem");
(function() {
  uno.components.MenuOption = function(text, checked) {
    uno.components.MenuAbstractItem.call(this);
    this.element = goog.dom.createDom("div", {class:"menu-item option" + (checked === true ? " checked" : "")}, text);
  };
  goog.inherits(uno.components.MenuOption, uno.components.MenuAbstractItem);
})();
goog.provide("uno.components.MenuSection");
goog.require("goog.dom");
goog.require("uno.components.MenuAbstractItem");
(function() {
  uno.components.MenuSection = function(text) {
    uno.components.MenuAbstractItem.call(this);
    this.element = goog.dom.createDom("div", {class:"menu-section"}, text);
  };
  goog.inherits(uno.components.MenuSection, uno.components.MenuAbstractItem);
  uno.components.MenuSection.prototype.allowUserInteraction = false;
})();
goog.provide("uno.components.MenuSeparator");
goog.require("goog.dom");
goog.require("uno.components.MenuAbstractItem");
(function() {
  uno.components.MenuSeparator = function() {
    uno.components.MenuAbstractItem.call(this);
    this.element = goog.dom.createDom("div", {class:"menu-separator"});
  };
  goog.inherits(uno.components.MenuSeparator, uno.components.MenuAbstractItem);
  uno.components.MenuSeparator.prototype.allowUserInteraction = false;
})();
goog.provide("uno.components.Menu");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.events");
goog.require("goog.events.KeyCodes");
goog.require("uno.util.dom");
goog.require("uno.util.tools");
goog.require("uno.components.MenuAbstractItem");
goog.require("uno.components.MenuColorPicker");
goog.require("uno.components.MenuItem");
goog.require("uno.components.MenuOption");
goog.require("uno.components.MenuSection");
goog.require("uno.components.MenuSeparator");
(function() {
  var Menu = uno.components.Menu = function(opt) {
    this.visible = false;
    this.scrollable_ = false;
    this.items_ = [];
    this.handlers_ = [];
    this.populators_ = [];
    this.originOverflowY_ = "";
    this.focusIndex_ = -1;
    this.dismissTimer_ = null;
    this.focusTimer_ = null;
    this.submenuTimer_ = null;
    this.submenu_ = null;
    opt = opt || {};
    this.onAction = typeof opt.onAction === "function" ? opt.onAction : null;
    this.onClose = typeof opt.onClose === "function" ? opt.onClose : null;
    this.actionClose_ = typeof opt.actionClose === "boolean" ? opt.actionClose : true;
    this.keyClose_ = typeof opt.keyClose === "boolean" ? opt.keyClose : true;
    this.blurClose_ = typeof opt.blurClose === "boolean" ? opt.blurClose : true;
    this.menuAutoFocused_ = typeof opt.menuAutoFocused === "boolean" ? opt.menuAutoFocused : true;
    this.itemAutoFocused_ = typeof opt.itemAutoFocused === "boolean" ? opt.itemAutoFocused : false;
    this.parentMenu_ = opt.parent || null;
    this.container_ = goog.dom.createDom("div", {class:"container"});
    this.element = goog.dom.createDom("div", {class:"en-menu", tabIndex:"-1"}, this.container_);
    goog.events.listen(this.element, "contextmenu", handleContextMenu);
    goog.events.listen(this.element, "keydown", handleKeyDown.bind(this), true);
    goog.events.listen(this.element, "mouseover", handleMouseOver.bind(this));
    goog.events.listen(this.element, "mouseout", handleMouseOut.bind(this));
    goog.events.listen(this.element, "click", handleClick.bind(this));
    goog.events.listen(this.element, "blur", handleBlur.bind(this), true);
  };
  Object.defineProperty(Menu.prototype, "focused", {get:function() {
    return this.element === document.activeElement;
  }});
  Menu.prototype.present = function(clientX, clientY) {
    if (this.visible) {
      return;
    }
    if (!this.parentMenu_) {
      this.originOverflowY_ = document.documentElement.style.overflowY;
      document.documentElement.style.overflowY = "hidden";
    }
    this.visible = true;
    uno.util.tools.append(this.element);
    var top = document.body.scrollTop;
    var vp = 4;
    var vh = window.innerHeight;
    var vw = window.innerWidth;
    var rect = this.element.getBoundingClientRect();
    var height = null;
    var y = clientY + top;
    var x = clientX + rect.width + vp > vw ? clientX - rect.width : clientX;
    x = Math.max(x, vp);
    if (rect.height + vp * 2 > vh) {
      y = top + vp;
      height = vh - vp * 2;
    } else {
      y = Math.max(y - 12, top + vp);
      if (y + rect.height > top + vh) {
        y = top + vh - rect.height - vp;
      }
    }
    this.element.style.top = y + "px";
    this.element.style.left = x + "px";
    this.element.style.height = height ? height + "px" : "";
    this.scrollable_ = !!height;
    if (this.menuAutoFocused_) {
      setTimeout(function() {
        this.element.focus();
        if (this.itemAutoFocused_) {
          this.setFocusAt_(this.getNextFocusIndex_());
        }
      }.bind(this), 10);
    }
  };
  Menu.prototype.dismiss = function() {
    if (!this.visible) {
      return;
    }
    this.visible = false;
    this.element.remove();
    if (this.parentMenu_) {
      this.parentMenu_.submenu_ = null;
      this.parentMenu_.element.focus();
      this.parentMenu_ = null;
    } else {
      if (this.submenu_) {
        this.submenu_.dismiss();
        this.submenu_ = null;
      }
      document.documentElement.style.overflowY = this.originOverflowY_;
      if (this.onClose) {
        this.onClose.call(this);
      }
    }
  };
  Menu.prototype.addItem = function(item, handler, populator) {
    if (item instanceof uno.components.MenuAbstractItem === false) {
      return;
    }
    var allowSubmenu = populator && item.allowSubmenu;
    var allowHandler = !allowSubmenu && handler && item.allowUserInteraction;
    this.items_.push(item);
    this.handlers_.push(allowHandler ? handler : null);
    this.populators_.push(allowSubmenu ? populator : null);
    if (allowSubmenu) {
      item.element.classList.add("submenu");
    }
    this.container_.appendChild(item.element);
  };
  Menu.prototype.addSubmenuItem = function(item, populator) {
    this.addItem(item, null, populator);
  };
  Menu.prototype.setFocusAt_ = function(index, sender) {
    clearTimeout(this.focusTimer_);
    if (this.focusIndex_ === index) {
      return;
    }
    clearTimeout(this.submenuTimer_);
    if (this.submenu_ && this.submenu_.index !== index) {
      this.submenu_.dismiss();
      this.submenu_ = null;
    } else {
      if (!sender && this.populators_[index]) {
        this.submenuTimer_ = setTimeout(function() {
          this.performActionAt_(index);
        }.bind(this), 200);
      }
    }
    if (this.focusIndex_ > -1) {
      var oldItem = this.items_[this.focusIndex_];
      if (oldItem) {
        oldItem.setFocus(false, sender);
      }
    }
    var item = this.items_[index];
    if (item && item.allowUserInteraction) {
      item.setFocus(true, sender);
      this.scrollItemIntoViewIfNeeded_(item);
      this.focusIndex_ = index;
      this.element.focus();
    } else {
      this.focusIndex_ = -1;
    }
  };
  Menu.prototype.scrollItemIntoViewIfNeeded_ = function(item) {
    if (!this.scrollable_) {
      return;
    }
    var rootRect = this.container_.getBoundingClientRect();
    var itemRect = item.element.getBoundingClientRect();
    if (itemRect.top < rootRect.top) {
      this.container_.scrollTop -= rootRect.top - itemRect.top;
    } else {
      if (itemRect.bottom > rootRect.bottom) {
        this.container_.scrollTop += itemRect.bottom - rootRect.bottom + 2;
      }
    }
  };
  Menu.prototype.getNextFocusIndex_ = function() {
    var index = -1;
    for (var i = this.focusIndex_ + 1, l = this.items_.length; i < l; i++) {
      if (this.items_[i].allowUserInteraction) {
        index = i;
        break;
      }
    }
    return index > -1 ? index : this.focusIndex_;
  };
  Menu.prototype.getPrevFocusIndex_ = function() {
    var index = -1;
    var startIndex = this.focusIndex_ > -1 ? this.focusIndex_ - 1 : this.items_.length - 1;
    for (var i = startIndex; i >= 0; i--) {
      if (this.items_[i].allowUserInteraction) {
        index = i;
        break;
      }
    }
    return index > -1 ? index : this.focusIndex_;
  };
  Menu.prototype.getItemIndex_ = function(item) {
    if (!item) {
      return -1;
    }
    if (uno.util.dom.isElementNode(item)) {
      var node = item;
      while (node.parentNode && node.parentNode !== this.container_) {
        node = node.parentNode;
      }
      return goog.array.findIndex(this.items_, function(i) {
        return i.element === node;
      });
    }
    return this.items_.indexOf(item);
  };
  Menu.prototype.performActionAt_ = function(index, sender) {
    var item = this.items_[index];
    var populator = this.populators_[index];
    if (this.submenu_ && this.submenu_.index === index) {
      this.submenu_.setFocusAt_(this.submenu_.getNextFocusIndex_(), sender);
    } else {
      if (item && populator) {
        var rect = item.element.getBoundingClientRect();
        var focused = !!sender;
        this.submenu_ = new Menu({parent:this, menuAutoFocused:focused, itemAutoFocused:focused});
        populator(this.submenu_);
        this.submenu_.index = index;
        this.submenu_.present(rect.left + rect.width, rect.top - 1);
      } else {
        if (item && item.allowUserInteraction) {
          var rootMenu = this.parentMenu_ || this;
          var handler = this.handlers_[index];
          var value = item.getValue();
          if (rootMenu.onAction) {
            var submenuIndex = this.parentMenu_ && this.index !== undefined ? this.index : -1;
            rootMenu.onAction.call(rootMenu, index, submenuIndex, value);
          }
          if (handler) {
            handler(value);
          }
          if (rootMenu.actionClose_) {
            rootMenu.dismiss();
          }
        }
      }
    }
  };
  Menu.prototype.addItemAt = function(item, n, handler) {
  };
  Menu.prototype.removeItem = function(item) {
  };
  Menu.prototype.removeItemAt = function(item, n) {
  };
  function handleKeyDown(evt) {
    var code = evt.keyCode;
    var item = this.items_[this.focusIndex_];
    if (item && item.handleKey(code)) {
      evt.preventDefault();
      evt.stopPropagation();
      return;
    }
    var KeyCodes = goog.events.KeyCodes;
    var rootMenu = this.parentMenu_ || this;
    var inSubmenu = this.parentMenu_ && this.focused;
    if (rootMenu.keyClose_ && code === KeyCodes.ESC) {
      rootMenu.dismiss();
    } else {
      if (code === KeyCodes.DOWN || !inSubmenu && this.focusIndex_ === -1 && [KeyCodes.RIGHT, KeyCodes.LEFT].indexOf(code) > -1) {
        this.setFocusAt_(this.getNextFocusIndex_(), code);
      } else {
        if (code === KeyCodes.UP) {
          this.setFocusAt_(this.getPrevFocusIndex_(), code);
        } else {
          if (code === KeyCodes.LEFT && !inSubmenu && this.submenu_) {
            this.submenu_.dismiss();
          } else {
            if (code === KeyCodes.LEFT && inSubmenu) {
              this.dismiss();
            } else {
              if (code === KeyCodes.RIGHT && !inSubmenu || this.focusIndex_ > -1 && [KeyCodes.ENTER, KeyCodes.SPACE].indexOf(code) > -1) {
                this.performActionAt_(this.focusIndex_, code);
              }
            }
          }
        }
      }
    }
    if (!evt.metaKey && !evt.ctrlKey && !evt.altKey && !evt.shiftKey) {
      evt.preventDefault();
      evt.stopPropagation();
    }
  }
  function handleMouseOver(evt) {
    var index = this.getItemIndex_(evt.target);
    var item = this.items_[index];
    if (item && !item.handleMouseOver(evt)) {
      this.setFocusAt_(index);
    }
  }
  function handleMouseOut() {
    clearTimeout(this.focusTimer_);
    this.focusTimer_ = setTimeout(function() {
      if (!this.submenu_ || this.submenu_.focusIndex_ === -1) {
        this.setFocusAt_(-1);
      }
    }.bind(this), 10);
  }
  function handleClick(evt) {
    var index = this.getItemIndex_(evt.target);
    var item = this.items_[index];
    if (this.submenu_ && this.submenu_.index === index && this.focusIndex_ === index && !this.focus && !this.submenu_.focus) {
      clearTimeout(this.dismissTimer_);
      this.element.focus();
      this.submenu_.setFocusAt_(-1);
    } else {
      if (item && !item.handleClick(evt) && !this.submenu_) {
        this.performActionAt_(index);
      }
    }
  }
  function handleBlur(evt) {
    if (this.parentMenu_ && this.parentMenu_.blurClose_ && this.visible && this.element === evt.target) {
      var context = this.parentMenu_;
      clearTimeout(context.dismissTimer_);
      context.dismissTimer_ = setTimeout(function() {
        context.dismiss();
      }, 10);
    } else {
      if (!this.parentMenu_ && this.blurClose_ && this.visible && !this.submenu_ && evt.target === this.element) {
        this.dismiss();
      }
    }
  }
  function handleContextMenu(evt) {
    evt.preventDefault();
    evt.stopPropagation();
  }
})();
goog.provide("uno.i18n.ar");
uno.i18n.ar.textEntries = {"Not available offline":"\u0644\u0627 \u064a\u062a\u0648\u0641\u0631 \u062f\u0648\u0646 \u0627\u062a\u0635\u0627\u0644 \u0628\u0627\u0644\u0625\u0646\u062a\u0631\u0646\u062a", "Not available":"\u063a\u064a\u0631 \u0645\u062a\u0627\u062d", "Tap to request access":"\u0627\u0636\u063a\u0637 \u0644\u0637\u0644\u0628 \u0627\u0644\u0648\u0635\u0648\u0644", "Click to request access":"\u0627\u0636\u063a\u0637 \u0644\u0637\u0644\u0628 \u0627\u0644\u0648\u0635\u0648\u0644", "Open":"\u0641\u062a\u062d", 
"Copy link":"\u0646\u0633\u062e \u0627\u0644\u0631\u0627\u0628\u0637", "Google Drive":"\u062c\u0648\u062c\u0644 \u062f\u0631\u0627\u064a\u0641", "Google Docs":"\u0645\u0633\u062a\u0646\u062f\u0627\u062a \u062c\u0648\u062c\u0644", "Google Sheets":"\u0623\u0648\u0631\u0627\u0642 \u062c\u0648\u062c\u0644", "Google Slides":"\u0634\u0631\u0627\u0626\u062d \u062c\u0648\u062c\u0644", "PDF":"PDF", "Word Document":"\u0645\u0633\u062a\u0646\u062f Word", "Excel Spreadsheet":"\u062c\u062f\u0648\u0644 \u0628\u064a\u0627\u0646\u0627\u062a Excel", 
"Modified":"\u062a\u0645 \u062a\u0639\u062f\u064a\u0644\u0647", "Connect":"\u0627\u062a\u0635\u0627\u0644", "Connect to see more":"\u0627\u0631\u0628\u0637 \u0627\u0644\u062d\u0633\u0627\u0628 \u0644\u0627\u0633\u062a\u0639\u0631\u0627\u0636 \u0627\u0644\u0645\u0632\u064a\u062f", "Connect Google account":"\u0631\u0628\u0637 \u062d\u0633\u0627\u0628 \u062c\u0648\u062c\u0644", "Title not available":"\u0627\u0644\u0639\u0646\u0648\u0627\u0646 \u063a\u064a\u0631 \u0645\u062a\u0627\u062d", "Open containing folder":"\u0641\u062a\u062d \u0627\u0644\u0645\u062c\u0644\u062f \u0627\u0644\u0631\u0626\u064a\u0633\u064a", 
"Cell Background":"\u062e\u0644\u0641\u064a\u0629 \u0627\u0644\u062e\u0644\u064a\u0629", "Cell Alignment":"\u0645\u062e\u0627\u0630\u0627\u0629 \u0627\u0644\u062e\u0644\u064a\u0629", "Align content to top":"\u0645\u062d\u0627\u0630\u0627\u0629 \u0627\u0644\u0645\u062d\u062a\u0648\u0649 \u0644\u0644\u0623\u0639\u0644\u0649", "Align content to center":"\u0645\u062d\u0627\u0630\u0627\u0629 \u0627\u0644\u0645\u062d\u062a\u0648\u0649 \u0644\u0644\u0648\u0633\u0637", "Align content to bottom":"\u0645\u062d\u0627\u0630\u0627\u0629 \u0627\u0644\u0645\u062d\u062a\u0648\u0649 \u0644\u0644\u0623\u0633\u0641\u0644", 
"Distribute Columns Evenly":"\u062a\u0648\u0632\u064a\u0639 \u0627\u0644\u0623\u0639\u0645\u062f\u0629 \u0628\u0627\u0644\u062a\u0633\u0627\u0648\u064a", "Match Note Width":"\u0645\u0637\u0627\u0628\u0642\u0629 \u0639\u0631\u0636 \u0627\u0644\u0645\u0644\u0627\u062d\u0638\u0629", "Delete Selected Column(s)":"\u062d\u0630\u0641 \u0627\u0644\u0623\u0639\u0645\u062f\u0629 \u0627\u0644\u0645\u062d\u062f\u062f\u0629", "Delete Selected Row(s)":"\u062d\u0630\u0641 \u0627\u0644\u0635\u0641\u0648\u0641 \u0627\u0644\u0645\u062d\u062f\u062f\u0629", 
"Delete Table":"\u062d\u0630\u0641 \u0627\u0644\u062c\u062f\u0648\u0644", "Merge Cells":"\u062f\u0645\u062c \u0627\u0644\u062e\u0644\u0627\u064a\u0627", "Unmerge Cells":"\u0625\u0644\u063a\u0627\u0621 \u062f\u0645\u062c \u0627\u0644\u062e\u0644\u0627\u064a\u0627"};
goog.provide("uno.i18n.cs");
uno.i18n.cs.textEntries = {"Not available offline":"Offline nen\u00ed dostupn\u00fd", "Not available":"Nen\u00ed k dispozici", "Tap to request access":"Klepnut\u00edm vy\u017e\u00e1dejte p\u0159\u00edstup", "Click to request access":"Kliknut\u00edm vy\u017e\u00e1dejte p\u0159\u00edstup", "Open":"Otev\u0159\u00edt", "Copy link":"Kop\u00edrovat odkaz", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Dokument aplikace Word", 
"Excel Spreadsheet":"Tabulka v aplikaci Excel", "Modified":"Zm\u011bn\u011bno", "Connect":"P\u0159ipojit", "Connect to see more":"Chcete-li zobrazit v\u00edce, p\u0159ipojte se", "Connect Google account":"P\u0159ipojit \u00fa\u010det Google", "Title not available":"N\u00e1zev nen\u00ed k dispozici", "Open containing folder":"Otev\u0159\u00edt slo\u017eku se soubory", "Cell Background":"Pozad\u00ed bu\u0148ky", "Cell Alignment":"Zarovn\u00e1n\u00ed bu\u0148ky", "Align content to top":"Zarovnat nahoru", 
"Align content to center":"Zarovnat na st\u0159ed", "Align content to bottom":"Zarovnat dol\u016f", "Distribute Columns Evenly":"Rozd\u011blit sloupce rovnom\u011brn\u011b", "Match Note Width":"P\u0159izp\u016fsobit \u0161\u00ed\u0159ku pozn\u00e1mky", "Delete Selected Column(s)":"Odstranit vybran\u00e9 sloupce", "Delete Selected Row(s)":"Odstranit vybran\u00e9 \u0159\u00e1dky", "Delete Table":"Odstranit tabulku", "Merge Cells":"Merge Cells", "Unmerge Cells":"Unmerge Cells"};
goog.provide("uno.i18n.da");
uno.i18n.da.textEntries = {"Not available offline":"Ikke tilg\u00e6ngelig offline", "Not available":"Ikke tilg\u00e6ngelig", "Tap to request access":"Tryk for at anmode om adgang", "Click to request access":"Klik for at anmode om adgang", "Open":"\u00c5bn", "Copy link":"Kopi\u00e9r link", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Word-dokument", "Excel Spreadsheet":"Excel-regneark", "Modified":"\u00c6ndret", 
"Connect":"Opret forbindelse", "Connect to see more":"Opret forbindelse for at se mere", "Connect Google account":"Tilslut Google-konto", "Title not available":"Titel ikke tilg\u00e6ngelig", "Open containing folder":"\u00c5bn indeholdende mappe", "Cell Background":"Cellebaggrund", "Cell Alignment":"Cellejustering", "Align content to top":"Juster indhold til toppen", "Align content to center":"Juster indhold til midten", "Align content to bottom":"Juster indhold til bunden", "Distribute Columns Evenly":"Fordel kolonner j\u00e6vnt", 
"Match Note Width":"Match notebredde", "Delete Selected Column(s)":"Slet valgte kolonne(r)", "Delete Selected Row(s)":"Slet valgte r\u00e6kker(r)", "Delete Table":"Slet tabel", "Merge Cells":"Sammenflet celler", "Unmerge Cells":"Fortyd sammenfletning af celler"};
goog.provide("uno.i18n.de");
uno.i18n.de.textEntries = {"Not available offline":"Nicht offline verf\u00fcgbar", "Not available":"Nicht verf\u00fcgbar", "Tap to request access":"Zum Anfordern von Zugriff tippen", "Click to request access":"Zum Anfordern von Zugriff klicken", "Open":"\u00d6ffnen", "Copy link":"Link kopieren", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Tabellen", "Google Slides":"Google Pr\u00e4sentationen", "PDF":"PDF", "Word Document":"Word-Dokument", "Excel Spreadsheet":"Excel-Tabelle", 
"Modified":"Ge\u00e4ndert", "Connect":"Verkn\u00fcpfen", "Connect to see more":"Verkn\u00fcpfen, um mehr zu sehen", "Connect Google account":"Google-Konto verkn\u00fcpfen", "Title not available":"Titel nicht verf\u00fcgbar", "Open containing folder":"\u00dcbergeordneten Ordner \u00f6ffnen", "Cell Background":"Zellenhintergrund", "Cell Alignment":"Zellenausrichtung", "Align content to top":"Inhalt oben ausrichten", "Align content to center":"Inhalt zentriert ausrichten", "Align content to bottom":"Inhalt unten ausrichten", 
"Distribute Columns Evenly":"Spalten gleichm\u00e4\u00dfig verteilen", "Match Note Width":"An Notizbreite anpassen", "Delete Selected Column(s)":"Ausgew\u00e4hlte Spalten l\u00f6schen", "Delete Selected Row(s)":"Ausgew\u00e4hlte Zeilen l\u00f6schen", "Delete Table":"Tabelle l\u00f6schen", "Merge Cells":"Zellen verbinden", "Unmerge Cells":"Zellverbund aufheben"};
goog.provide("uno.i18n.en");
uno.i18n.en.textEntries = {"Not available offline":"Not available offline", "Not available":"Not available", "Tap to request access":"Tap to request access", "Click to request access":"Click to request access", "Open":"Open", "Copy link":"Copy link", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Word Document", "Excel Spreadsheet":"Excel Spreadsheet", "Modified":"Modified", "Connect":"Connect", 
"Connect to see more":"Connect to see more", "Connect Google account":"Connect Google account", "Title not available":"Title not available", "Open containing folder":"Open containing folder", "Cell Background":"Cell Background", "Cell Alignment":"Cell Alignment", "Align content to top":"Align content to top", "Align content to center":"Align content to center", "Align content to bottom":"Align content to bottom", "Distribute Columns Evenly":"Distribute Columns Evenly", "Match Note Width":"Match Note Width", 
"Delete Selected Column(s)":"Delete Selected Column(s)", "Delete Selected Row(s)":"Delete Selected Row(s)", "Delete Table":"Delete Table", "Merge Cells":"Merge Cells", "Unmerge Cells":"Unmerge Cells"};
goog.provide("uno.i18n.es");
uno.i18n.es.textEntries = {"Not available offline":"No disponible sin conexi\u00f3n", "Not available":"No disponible", "Tap to request access":"Pulsa para solicitar acceso", "Click to request access":"Haz clic para solicitar acceso", "Open":"Abrir", "Copy link":"Copiar enlace", "Google Drive":"Google Drive", "Google Docs":"Documentos de Google", "Google Sheets":"Hojas de c\u00e1lculo de Google", "Google Slides":"Presentaciones de Google", "PDF":"PDF", "Word Document":"Documento Word", "Excel Spreadsheet":"Hoja de c\u00e1lculo Excel", 
"Modified":"Modificado", "Connect":"Conectar", "Connect to see more":"Con\u00e9ctate para ver m\u00e1s", "Connect Google account":"Conectar cuenta de Google", "Title not available":"T\u00edtulo no disponible", "Open containing folder":"Abrir carpeta archivadora de contenidos", "Cell Background":"Fondo de la celda", "Cell Alignment":"Alineaci\u00f3n de la celda", "Align content to top":"Alinear contenido a la parte superior", "Align content to center":"Alinear contenido al centro", "Align content to bottom":"Alinear contenido a la parte inferior", 
"Distribute Columns Evenly":"Distribuir columnas uniformemente", "Match Note Width":"Coincidir con el ancho de nota", "Delete Selected Column(s)":"Eliminar columna(s) seleccionada(s)", "Delete Selected Row(s)":"Eliminar fila(s) seleccionada(s)", "Delete Table":"Eliminar Tabla", "Merge Cells":"Combinar celdas", "Unmerge Cells":"Anular la combinaci\u00f3n de celdas"};
goog.provide("uno.i18n.fi");
uno.i18n.fi.textEntries = {"Not available offline":"Ei k\u00e4ytett\u00e4viss\u00e4 offline", "Not available":"Ei k\u00e4ytett\u00e4viss\u00e4", "Tap to request access":"Pyyd\u00e4 k\u00e4ytt\u00f6oikeus napauttamalla", "Click to request access":"Napsauta pyyt\u00e4\u00e4ksesi k\u00e4ytt\u00f6oikeuksia", "Open":"Avaa", "Copy link":"Kopioi linkki", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Word-asiakirja", 
"Excel Spreadsheet":"Excel-laskentataulukko", "Modified":"Muokattu", "Connect":"Yhdist\u00e4", "Connect to see more":"Yhdist\u00e4 n\u00e4hd\u00e4ksesi enemm\u00e4n", "Connect Google account":"Yhdist\u00e4 Google-tili", "Title not available":"Otsikko ei saatavilla", "Open containing folder":"Avaa tallennuskansio", "Cell Background":"Solun tausta", "Cell Alignment":"Solun tasaus", "Align content to top":"Tasaa sis\u00e4lt\u00f6 yl\u00e4osaan", "Align content to center":"Tasaa sis\u00e4lt\u00f6 keskelle", 
"Align content to bottom":"Tasaa sis\u00e4lt\u00f6 alaosaan", "Distribute Columns Evenly":"Muuta sarakkeet tasalevyisiksi", "Match Note Width":"T\u00e4sm\u00e4\u00e4 muistiinpanon leveys", "Delete Selected Column(s)":"Poista valitut sarakkeet", "Delete Selected Row(s)":"Poista valitut rivit", "Delete Table":"Poista taulukko", "Merge Cells":"Yhdist\u00e4 solut", "Unmerge Cells":"Pura solujen yhdist\u00e4minen"};
goog.provide("uno.i18n.fr");
uno.i18n.fr.textEntries = {"Not available offline":"Non disponible hors-ligne", "Not available":"Indisponible", "Tap to request access":"Appuyez pour demander l'acc\u00e8s", "Click to request access":"Cliquez pour demander l'acc\u00e8s", "Open":"Ouvrir", "Copy link":"Copier le lien", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Document Word", "Excel Spreadsheet":"Feuille de calcul Excel", 
"Modified":"Modifi\u00e9", "Connect":"Connecter", "Connect to see more":"Connectez-vous pour en voir davantage", "Connect Google account":"Connecter un compte Google", "Title not available":"Titre non disponible", "Open containing folder":"Ouvrir le dossier conteneur", "Cell Background":"Arri\u00e8re-plan de cellule", "Cell Alignment":"Alignement de cellule", "Align content to top":"Aligner le contenu en haut", "Align content to center":"Aligner le contenu au centre", "Align content to bottom":"Aligner le contenu en bas", 
"Distribute Columns Evenly":"Uniformiser la largeur des colonnes", "Match Note Width":"Respecter la largeur de la note", "Delete Selected Column(s)":"Supprimer la ou les colonne(s) s\u00e9lectionn\u00e9e(s)", "Delete Selected Row(s)":"Supprimer la ou les ligne(s) s\u00e9lectionn\u00e9e(s)", "Delete Table":"Supprimer le tableau", "Merge Cells":"Fusionner les cellules", "Unmerge Cells":"Annuler Fusionner les cellules"};
goog.provide("uno.i18n.id");
uno.i18n.id.textEntries = {"Not available offline":"Tidak tersedia offline", "Not available":"Tidak tersedia", "Tap to request access":"Tekan untuk meminta akses", "Click to request access":"Klik untuk meminta akses", "Open":"Buka", "Copy link":"Salin tautan", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Dokumen Word", "Excel Spreadsheet":"Lembar Lajur Excel", "Modified":"Diubah", "Connect":"Sambungkan", 
"Connect to see more":"Sambungkan untuk melihat lebih banyak", "Connect Google account":"Sambungkan akun Google", "Title not available":"Judul tidak tersedia", "Open containing folder":"Buka map yang menampung", "Cell Background":"Latar Belakang Sel", "Cell Alignment":"Perataan Sel", "Align content to top":"Ratakan konten ke atas", "Align content to center":"Ratakan konten ke tengah", "Align content to bottom":"Ratakan konten ke bawah", "Distribute Columns Evenly":"Distribusikan Kolom Merata", "Match Note Width":"Sesuaikan Lebar Catatan", 
"Delete Selected Column(s)":"Hapus Kolom yang Dipilih", "Delete Selected Row(s)":"Hapus Baris yang Dipilih", "Delete Table":"Hapus Tabel", "Merge Cells":"Gabungkan Sel", "Unmerge Cells":"Batalkan Penggabungan Sel"};
goog.provide("uno.i18n.it");
uno.i18n.it.textEntries = {"Not available offline":"Non disponibile offline", "Not available":"Non disponibile", "Tap to request access":"Tocca per richiedere accesso", "Click to request access":"Clicca per richiedere accesso", "Open":"Apri", "Copy link":"Copia link", "Google Drive":"Google Drive", "Google Docs":"Documenti Google", "Google Sheets":"Fogli Google", "Google Slides":"Presentazioni Google", "PDF":"PDF", "Word Document":"Documento di Word", "Excel Spreadsheet":"Foglio di lavoro di Excel", 
"Modified":"Modificato", "Connect":"Connettiti", "Connect to see more":"Connettitti per vedere di pi\u00f9", "Connect Google account":"Collega account Google", "Title not available":"Titolo non disponibile", "Open containing folder":"Apri cartella contenente", "Cell Background":"Sfondo cella", "Cell Alignment":"Allineamento cella", "Align content to top":"Allineare il contenuto in alto", "Align content to center":"Allineare contenuto al centro", "Align content to bottom":"Allineare il contenuto in basso", 
"Distribute Columns Evenly":"Distribuire colonne uniformemente", "Match Note Width":"Adegua alla larghezza della nota", "Delete Selected Column(s)":"Eliminare colonne selezionate", "Delete Selected Row(s)":"Eliminare righe selezionate", "Delete Table":"Eliminare Tabella", "Merge Cells":"Unire celle", "Unmerge Cells":"Annulla unione celle"};
goog.provide("uno.i18n.ja");
uno.i18n.ja.textEntries = {"Not available offline":"\u30aa\u30d5\u30e9\u30a4\u30f3\u3067\u306f\u5229\u7528\u3067\u304d\u307e\u305b\u3093", "Not available":"\u5229\u7528\u3067\u304d\u307e\u305b\u3093", "Tap to request access":"\u30bf\u30c3\u30d7\u3067\u30a2\u30af\u30bb\u30b9\u6a29\u3092\u30ea\u30af\u30a8\u30b9\u30c8", "Click to request access":"\u30af\u30ea\u30c3\u30af\u3067\u30a2\u30af\u30bb\u30b9\u6a29\u3092\u30ea\u30af\u30a8\u30b9\u30c8", "Open":"\u958b\u304f", "Copy link":"\u30ea\u30f3\u30af\u3092\u30b3\u30d4\u30fc", 
"Google Drive":"Google \u30c9\u30e9\u30a4\u30d6", "Google Docs":"Google \u30c9\u30ad\u30e5\u30e1\u30f3\u30c8", "Google Sheets":"Google \u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8", "Google Slides":"Google \u30b9\u30e9\u30a4\u30c9", "PDF":"PDF", "Word Document":"Word \u6587\u66f8", "Excel Spreadsheet":"Excel \u30b9\u30d7\u30ec\u30c3\u30c9\u30b7\u30fc\u30c8", "Modified":"\u5909\u66f4", "Connect":"\u63a5\u7d9a", "Connect to see more":"\u63a5\u7d9a\u3057\u3066\u8a73\u7d30\u3092\u898b\u308b", "Connect Google account":"Google \u30a2\u30ab\u30a6\u30f3\u30c8\u3092\u63a5\u7d9a", 
"Title not available":"\u30bf\u30a4\u30c8\u30eb\u3092\u8868\u793a\u3067\u304d\u307e\u305b\u3093", "Open containing folder":"\u30d5\u30a9\u30eb\u30c0\u3092\u958b\u304f", "Cell Background":"\u30bb\u30eb\u306e\u80cc\u666f", "Cell Alignment":"\u30bb\u30eb\u306e\u914d\u7f6e", "Align content to top":"\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u4e0a\u5074\u306b\u914d\u7f6e", "Align content to center":"\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u4e2d\u592e\u306b\u914d\u7f6e", "Align content to bottom":"\u30b3\u30f3\u30c6\u30f3\u30c4\u3092\u4e0b\u5074\u306b\u914d\u7f6e", 
"Distribute Columns Evenly":"\u5217\u306e\u5e45\u3092\u5747\u7b49\u5316", "Match Note Width":"\u30ce\u30fc\u30c8\u306e\u5e45\u306b\u5408\u308f\u305b\u308b", "Delete Selected Column(s)":"\u9078\u629e\u3057\u305f\u5217\u3092\u524a\u9664", "Delete Selected Row(s)":"\u9078\u629e\u3057\u305f\u884c\u3092\u524a\u9664", "Delete Table":"\u8868\u3092\u524a\u9664", "Merge Cells":"\u30bb\u30eb\u3092\u7d50\u5408", "Unmerge Cells":"\u30bb\u30eb\u306e\u7d50\u5408\u3092\u89e3\u9664"};
goog.provide("uno.i18n.ko");
uno.i18n.ko.textEntries = {"Not available offline":"\uc624\ud504\ub77c\uc778\uc5d0\uc11c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc74c", "Not available":"\uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4", "Tap to request access":"\ub20c\ub7ec\uc11c \uc561\uc138\uc2a4 \uc694\uccad", "Click to request access":"\ud074\ub9ad\ud558\uc5ec \uc561\uc138\uc2a4 \uc694\uccad", "Open":"\uc5f4\uae30", "Copy link":"\ub9c1\ud06c \ubcf5\uc0ac", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", 
"Google Slides":"Google \ud504\ub808\uc820\ud14c\uc774\uc158", "PDF":"PDF", "Word Document":"Word \ubb38\uc11c", "Excel Spreadsheet":"Excel \uc2a4\ud504\ub808\ub4dc\uc2dc\ud2b8", "Modified":"\uc218\uc815", "Connect":"\uc5f0\uacb0", "Connect to see more":"\ub354 \ubcf4\ub824\uba74 \uc5f0\uacb0\ud558\uc138\uc694", "Connect Google account":"Google \uacc4\uc815 \uc5f0\uacb0", "Title not available":"\uc81c\ubaa9 \uc54c \uc218 \uc5c6\uc74c", "Open containing folder":"\ud3ec\ud568 \ud3f4\ub354 \uc5f4\uae30", 
"Cell Background":"\uc140 \ubc30\uacbd", "Cell Alignment":"\uc140 \uc815\ub82c", "Align content to top":"\uc704\ucabd \ub9de\ucda4", "Align content to center":"\uac00\uc6b4\ub370 \ub9de\ucda4", "Align content to bottom":"\uc544\ub798\ucabd \ub9de\ucda4", "Distribute Columns Evenly":"\uc5f4 \ub108\ube44\ub97c \uac19\uac8c", "Match Note Width":"\ub178\ud2b8 \ud3ed\uc5d0 \ub9de\ucda4", "Delete Selected Column(s)":"\uc120\ud0dd\ud55c \uc5f4 \uc0ad\uc81c", "Delete Selected Row(s)":"\uc120\ud0dd\ud55c \ud589 \uc0ad\uc81c", 
"Delete Table":"\ud45c \uc0ad\uc81c", "Merge Cells":"\uc140 \ud569\uce58\uae30", "Unmerge Cells":"\uc140 \ud569\uce58\uae30 \ucde8\uc18c"};
goog.provide("uno.i18n.ms");
uno.i18n.ms.textEntries = {"Not available offline":"Tidak tersedia di luar talian", "Not available":"Tidak tersedia", "Tap to request access":"Ketik untuk meminta akses", "Click to request access":"Klik untuk meminta akses", "Open":"Buka", "Copy link":"Salin pautan", "Google Drive":"Google Drive", "Google Docs":"Dokumen Google", "Google Sheets":"Helaian Google", "Google Slides":"Slaid Google", "PDF":"PDF", "Word Document":"Dokumen Word", "Excel Spreadsheet":"Hamparan Excel", "Modified":"Diubah suai", 
"Connect":"Sambung", "Connect to see more":"Sambung untuk melihat lebih banyak", "Connect Google account":"Sambung ke akaun Google", "Title not available":"Tajuk tidak tersedia", "Open containing folder":"Buka folder yang mengandungi", "Cell Background":"Latar Belakang Sel", "Cell Alignment":"Penjajaran Sel", "Align content to top":"Jajarkan kandungan ke atas", "Align content to center":"Jajarkan kandungan ke tengah", "Align content to bottom":"Jajarkan kandungan ke bawah", "Distribute Columns Evenly":"Jajarkan Lajur Secara Sama Rata", 
"Match Note Width":"Padankan Lebar Nota", "Delete Selected Column(s)":"Padamkan Lajur Dipilih", "Delete Selected Row(s)":"Padamkan Baris Dipilih", "Delete Table":"Padam Jadual", "Merge Cells":"Gabung Sel", "Unmerge Cells":"Leraikan Sel"};
goog.provide("uno.i18n.nl");
uno.i18n.nl.textEntries = {"Not available offline":"Niet offline beschikbaar", "Not available":"Niet beschikbaar", "Tap to request access":"Tik om toegang aan te vragen", "Click to request access":"Klik om toegang aan te vragen", "Open":"Open", "Copy link":"Kopieer link", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Word-document", "Excel Spreadsheet":"Excel-spreadsheet", "Modified":"Aangepast", 
"Connect":"Koppel", "Connect to see more":"Koppel om meer te zien", "Connect Google account":"Koppel Google account", "Title not available":"Titel niet beschikbaar", "Open containing folder":"Open bijbehorende map", "Cell Background":"Achtergrond cel", "Cell Alignment":"Uitlijning cel", "Align content to top":"Lijn content bovenin uit", "Align content to center":"Lijn content uit in het midden", "Align content to bottom":"Lijn content onderin uit", "Distribute Columns Evenly":"Verdeel kolommen gelijkmatig", 
"Match Note Width":"Pas notitiebreedte aan", "Delete Selected Column(s)":"Verwijder geselecteerde kolom(men)", "Delete Selected Row(s)":"Verwijder geselecteerde rij(en)", "Delete Table":"Verwijder tabel", "Merge Cells":"Voeg cellen samen", "Unmerge Cells":"Voeg cellen niet meer samen"};
goog.provide("uno.i18n.no");
uno.i18n.no.textEntries = {"Not available offline":"Ikke tilgjengelig offline", "Not available":"Ikke tilgjengelig", "Tap to request access":"Trykk for \u00e5 be om tilgang", "Click to request access":"Klikk for \u00e5 be om tilgang", "Open":"\u00c5pne", "Copy link":"Kopier lenke", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Word-dokument", "Excel Spreadsheet":"Excel regneark", "Modified":"Modifisert", 
"Connect":"Koble til", "Connect to see more":"Koble til for \u00e5 se mer", "Connect Google account":"Koble til Google-konto", "Title not available":"Tittel ikke tilgjengelig", "Open containing folder":"\u00c5pne mappe med innhold", "Cell Background":"Cellebakgrunn", "Cell Alignment":"Cellejustering", "Align content to top":"Toppjuster innhold", "Align content to center":"Midtstill innhold", "Align content to bottom":"Bunnjuster innhold", "Distribute Columns Evenly":"Distribuer kolonner jevnt", "Match Note Width":"Tilpass notatbredde", 
"Delete Selected Column(s)":"Slett valgt(e) kolonne(r)", "Delete Selected Row(s)":"Slett valgt(e) rad(er)", "Delete Table":"Slett tabell", "Merge Cells":"Sl\u00e5 sammen celler", "Unmerge Cells":"Del celler"};
goog.provide("uno.i18n.pl");
uno.i18n.pl.textEntries = {"Not available offline":"Niedost\u0119pne w trybie offline", "Not available":"Niedost\u0119pne", "Tap to request access":"Dotknij, aby za\u017c\u0105da\u0107 dost\u0119pu", "Click to request access":"Kliknij, aby poprosi\u0107 o dost\u0119p", "Open":"Otw\u00f3rz", "Copy link":"Kopiuj \u0142\u0105cze", "Google Drive":"Dysk Google", "Google Docs":"Dokumenty Google", "Google Sheets":"Arkusze Google", "Google Slides":"Prezentacje Google", "PDF":"PDF", "Word Document":"Dokument Word", 
"Excel Spreadsheet":"Arkusz Excel", "Modified":"Edytowany", "Connect":"Po\u0142\u0105cz", "Connect to see more":"Po\u0142\u0105cz, aby zobaczy\u0107 wi\u0119cej", "Connect Google account":"Po\u0142\u0105cz z kontem Google", "Title not available":"Nazwa jest niedost\u0119pna", "Open containing folder":"Otw\u00f3rz folder zawieraj\u0105cy", "Cell Background":"T\u0142o kom\u00f3rki", "Cell Alignment":"Wyr\u00f3wnanie kom\u00f3rki", "Align content to top":"Wyr\u00f3wnaj zawarto\u015b\u0107 do g\u00f3ry", 
"Align content to center":"Wyr\u00f3wnaj zawarto\u015b\u0107 do \u015brodka", "Align content to bottom":"Wyr\u00f3wnaj zawarto\u015b\u0107 do do\u0142u", "Distribute Columns Evenly":"Roz\u0142\u00f3\u017c kolumny r\u00f3wnomiernie", "Match Note Width":"Dopasuj szeroko\u015b\u0107 notatki", "Delete Selected Column(s)":"Usu\u0144 zaznaczon\u0105 kolumn\u0119", "Delete Selected Row(s)":"Usu\u0144 zaznaczony wiersz", "Delete Table":"Usu\u0144 tabel\u0119", "Merge Cells":"Po\u0142\u0105cz kom\u00f3rki", 
"Unmerge Cells":"Roz\u0142\u0105cz kom\u00f3rki"};
goog.provide("uno.i18n.pt_BR");
uno.i18n.pt_BR.textEntries = {"Not available offline":"N\u00e3o dispon\u00edvel offline", "Not available":"N\u00e3o est\u00e1 dispon\u00edvel", "Tap to request access":"Toque para solicitar acesso", "Click to request access":"Clique para solicitar acesso", "Open":"Abrir", "Copy link":"Copiar link", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Planilhas do Google", "Google Slides":"Apresenta\u00e7\u00f5es do Google", "PDF":"PDF", "Word Document":"Documento do Word", 
"Excel Spreadsheet":"Planilha do Excel", "Modified":"Modificado em", "Connect":"Conectar", "Connect to see more":"Conecte-se para ver mais", "Connect Google account":"Conectar conta do Google", "Title not available":"T\u00edtulo n\u00e3o dispon\u00edvel", "Open containing folder":"Abrir pasta de destino", "Cell Background":"Fundo da C\u00e9lula", "Cell Alignment":"Alinhamento da C\u00e9lula", "Align content to top":"Alinhar conte\u00fado no topo", "Align content to center":"Alinhar conte\u00fado no centro", 
"Align content to bottom":"Alinhar conte\u00fado embaixo", "Distribute Columns Evenly":"Distribuir Colunas Igualmente", "Match Note Width":"Igualar Largura da Coluna", "Delete Selected Column(s)":"Excluir Coluna(s) Selecionada(s)", "Delete Selected Row(s)":"Excluir Linha(s) Selecionada(s)", "Delete Table":"Excluir Tabela", "Merge Cells":"Mesclar C\u00e9lulas", "Unmerge Cells":"Desfazer Mesclagem de C\u00e9lulas"};
goog.provide("uno.i18n.pt");
uno.i18n.pt.textEntries = {"Not available offline":"Indispon\u00edvel no modo off-line", "Not available":"Indispon\u00edvel", "Tap to request access":"Toque para solicitar acesso", "Click to request access":"Clique para solicitar acesso", "Open":"Abrir", "Copy link":"Copiar liga\u00e7\u00e3o", "Google Drive":"Google Drive", "Google Docs":"Documentos do Google", "Google Sheets":"Folhas de c\u00e1lculo do Google", "Google Slides":"Apresenta\u00e7\u00f5es do Google", "PDF":"PDF", "Word Document":"Documento do Word", 
"Excel Spreadsheet":"Tabela do Excel", "Modified":"Modificado em", "Connect":"Ligar", "Connect to see more":"Ligue para ver mais", "Connect Google account":"Ligar \u00e0 conta Google", "Title not available":"T\u00edtulo indispon\u00edvel", "Open containing folder":"Abrir pasta de destino", "Cell Background":"Fundo da c\u00e9lula", "Cell Alignment":"Alinhamento da c\u00e9lula", "Align content to top":"Alinhar conte\u00fado no topo", "Align content to center":"Alinhar conte\u00fado ao centro", "Align content to bottom":"Alinhar conte\u00fado no fundo", 
"Distribute Columns Evenly":"Distribuir colunas uniformemente", "Match Note Width":"Ajustar largura da nota", "Delete Selected Column(s)":"Eliminar a(s) coluna(s) selecionada(s)", "Delete Selected Row(s)":"Eliminar a(s) linha(s) selecionada(s)", "Delete Table":"Eliminar tabela", "Merge Cells":"Fundir c\u00e9lulas", "Unmerge Cells":"Desfazer c\u00e9lulas fundidas"};
goog.provide("uno.i18n.ru");
uno.i18n.ru.textEntries = {"Not available offline":"\u041d\u0435\u0442 \u043e\u0444\u043b\u0430\u0439\u043d-\u0434\u043e\u0441\u0442\u0443\u043f\u0430", "Not available":"\u041d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d", "Tap to request access":"\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430", "Click to request access":"\u041d\u0430\u0436\u043c\u0438\u0442\u0435 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u043e\u0441\u0442\u0443\u043f\u0430", 
"Open":"\u041e\u0442\u043a\u0440\u044b\u0442\u044c", "Copy link":"\u0421\u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0441\u044b\u043b\u043a\u0443", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442 Word", "Excel Spreadsheet":"\u0422\u0430\u0431\u043b\u0438\u0446\u0430 Excel", "Modified":"\u0418\u0437\u043c\u0435\u043d\u0435\u043d", 
"Connect":"\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c", "Connect to see more":"\u0412\u043e\u0439\u0442\u0438 \u0432 Google Drive", "Connect Google account":"\u041f\u043e\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u044c \u0430\u043a\u043a\u0430\u0443\u043d\u0442 Google", "Title not available":"\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u043e", "Open containing folder":"\u041e\u0442\u043a\u0440\u044b\u0442\u044c \u043f\u0430\u043f\u043a\u0443", 
"Cell Background":"\u0424\u043e\u043d \u044f\u0447\u0435\u0439\u043a\u0438", "Cell Alignment":"\u0412\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435 \u044f\u0447\u0435\u0439\u043a\u0438", "Align content to top":"\u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u0432\u0435\u0440\u0445\u043d\u0435\u043c\u0443 \u043a\u0440\u0430\u044e", "Align content to center":"\u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443", 
"Align content to bottom":"\u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u043f\u043e \u043d\u0438\u0436\u043d\u0435\u043c\u0443 \u043a\u0440\u0430\u044e", "Distribute Columns Evenly":"\u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u0448\u0438\u0440\u0438\u043d\u0443 \u0441\u0442\u043e\u043b\u0431\u0446\u043e\u0432", "Match Note Width":"\u0420\u0430\u0437\u043c\u0435\u0440 \u043f\u043e \u0448\u0438\u0440\u0438\u043d\u0435 \u0437\u0430\u043c\u0435\u0442\u043a\u0438", "Delete Selected Column(s)":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u0439 \u0441\u0442\u043e\u043b\u0431\u0435\u0446", 
"Delete Selected Row(s)":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u0441\u0442\u0440\u043e\u043a\u0443", "Delete Table":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0442\u0430\u0431\u043b\u0438\u0446\u0443", "Merge Cells":"\u041e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0438", "Unmerge Cells":"\u0420\u0430\u0437\u044a\u0435\u0434\u0438\u043d\u0438\u0442\u044c \u044f\u0447\u0435\u0439\u043a\u0438"};
goog.provide("uno.i18n.sv");
uno.i18n.sv.textEntries = {"Not available offline":"Ej tillg\u00e4nglig offline", "Not available":"Ej tillg\u00e4ngligt", "Tap to request access":"Tryck f\u00f6r att beg\u00e4ra \u00e5tkomst", "Click to request access":"Klicka f\u00f6r att beg\u00e4ra \u00e5tkomst", "Open":"\u00d6ppna", "Copy link":"Kopiera l\u00e4nk", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Word-dokument", "Excel Spreadsheet":"Excel-kalkylblad", 
"Modified":"\u00c4ndrad", "Connect":"Anslut", "Connect to see more":"Anslut n\u00e4r du vill se mer", "Connect Google account":"Anslut Google-konto", "Title not available":"Titeln finns inte", "Open containing folder":"\u00d6ppna objektets mapp", "Cell Background":"Cellbakgrund", "Cell Alignment":"Celljustering", "Align content to top":"Justera inneh\u00e5ll upp\u00e5t", "Align content to center":"Justera inneh\u00e5ll \u00e5t mitten", "Align content to bottom":"Justera inneh\u00e5ll ned\u00e5t", 
"Distribute Columns Evenly":"F\u00f6rdela kolumner j\u00e4mnt", "Match Note Width":"Matcha anteckningens bredd", "Delete Selected Column(s)":"Radera markerade kolumner", "Delete Selected Row(s)":"Radera markerade rader", "Delete Table":"Radera tabell", "Merge Cells":"Sammanfoga celler", "Unmerge Cells":"Separera celler"};
goog.provide("uno.i18n.th");
uno.i18n.th.textEntries = {"Not available offline":"\u0e44\u0e21\u0e48\u0e2a\u0e32\u0e21\u0e32\u0e23\u0e16\u0e43\u0e0a\u0e49\u0e07\u0e32\u0e19\u0e15\u0e2d\u0e19\u0e2d\u0e2d\u0e1f\u0e44\u0e25\u0e19\u0e4c\u0e44\u0e14\u0e49", "Not available":"\u0e44\u0e21\u0e48\u0e21\u0e35", "Tap to request access":"\u0e41\u0e15\u0e30\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e02\u0e2d\u0e40\u0e02\u0e49\u0e32\u0e16\u0e36\u0e07", "Click to request access":"\u0e04\u0e25\u0e34\u0e4a\u0e01\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e02\u0e2d\u0e40\u0e02\u0e49\u0e32\u0e16\u0e36\u0e07", 
"Open":"\u0e40\u0e1b\u0e34\u0e14", "Copy link":"\u0e04\u0e31\u0e14\u0e25\u0e2d\u0e01\u0e25\u0e34\u0e07\u0e01\u0e4c", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"\u0e40\u0e2d\u0e01\u0e2a\u0e32\u0e23 Word", "Excel Spreadsheet":"\u0e2a\u0e40\u0e1b\u0e23\u0e14\u0e0a\u0e35\u0e17 Excel", "Modified":"\u0e1b\u0e23\u0e31\u0e1a\u0e40\u0e1b\u0e25\u0e35\u0e48\u0e22\u0e19\u0e41\u0e25\u0e49\u0e27", "Connect":"\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d", 
"Connect to see more":"\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e40\u0e1e\u0e37\u0e48\u0e2d\u0e14\u0e39\u0e40\u0e1e\u0e34\u0e48\u0e21\u0e40\u0e15\u0e34\u0e21", "Connect Google account":"\u0e40\u0e0a\u0e37\u0e48\u0e2d\u0e21\u0e15\u0e48\u0e2d\u0e1a\u0e31\u0e0d\u0e0a\u0e35 Google", "Title not available":"\u0e44\u0e21\u0e48\u0e21\u0e35\u0e0a\u0e37\u0e48\u0e2d", "Open containing folder":"\u0e40\u0e1b\u0e34\u0e14\u0e41\u0e1f\u0e49\u0e21\u0e40\u0e2d\u0e01\u0e2a\u0e32\u0e23\u0e17\u0e35\u0e48\u0e40\u0e01\u0e47\u0e1a", 
"Cell Background":"\u0e1e\u0e37\u0e49\u0e19\u0e2b\u0e25\u0e31\u0e07\u0e02\u0e2d\u0e07\u0e0a\u0e48\u0e2d\u0e07\u0e15\u0e32\u0e23\u0e32\u0e07", "Cell Alignment":"\u0e01\u0e32\u0e23\u0e08\u0e31\u0e14\u0e41\u0e19\u0e27\u0e02\u0e2d\u0e07\u0e0a\u0e48\u0e2d\u0e07\u0e15\u0e32\u0e23\u0e32\u0e07", "Align content to top":"\u0e08\u0e31\u0e14\u0e41\u0e19\u0e27\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e44\u0e27\u0e49\u0e14\u0e49\u0e32\u0e19\u0e1a\u0e19\u0e2a\u0e38\u0e14", "Align content to center":"\u0e08\u0e31\u0e14\u0e41\u0e19\u0e27\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e44\u0e27\u0e49\u0e15\u0e23\u0e07\u0e01\u0e25\u0e32\u0e07", 
"Align content to bottom":"\u0e08\u0e31\u0e14\u0e41\u0e19\u0e27\u0e40\u0e19\u0e37\u0e49\u0e2d\u0e2b\u0e32\u0e44\u0e27\u0e49\u0e14\u0e49\u0e32\u0e19\u0e25\u0e48\u0e32\u0e07\u0e2a\u0e38\u0e14", "Distribute Columns Evenly":"\u0e17\u0e33\u0e43\u0e2b\u0e49\u0e0a\u0e48\u0e2d\u0e07\u0e04\u0e2d\u0e25\u0e31\u0e21\u0e19\u0e4c\u0e21\u0e35\u0e02\u0e19\u0e32\u0e14\u0e40\u0e17\u0e48\u0e32\u0e01\u0e31\u0e19\u0e2b\u0e21\u0e14", "Match Note Width":"\u0e08\u0e31\u0e14\u0e04\u0e27\u0e32\u0e21\u0e01\u0e27\u0e49\u0e32\u0e07\u0e02\u0e2d\u0e07\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01\u0e43\u0e2b\u0e49\u0e1e\u0e2d\u0e14\u0e35", 
"Delete Selected Column(s)":"\u0e25\u0e1a\u0e04\u0e2d\u0e25\u0e31\u0e21\u0e19\u0e4c\u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e44\u0e27\u0e49", "Delete Selected Row(s)":"\u0e25\u0e1a\u0e41\u0e16\u0e27\u0e17\u0e35\u0e48\u0e40\u0e25\u0e37\u0e2d\u0e01\u0e44\u0e27\u0e49", "Delete Table":"\u0e25\u0e1a\u0e15\u0e32\u0e23\u0e32\u0e07", "Merge Cells":"\u0e23\u0e27\u0e21\u0e40\u0e0b\u0e25\u0e25\u0e4c", "Unmerge Cells":"\u0e41\u0e22\u0e01\u0e40\u0e0b\u0e25\u0e25\u0e4c"};
goog.provide("uno.i18n.tr");
uno.i18n.tr.textEntries = {"Not available offline":"\u00c7evrimd\u0131\u015f\u0131 kullan\u0131lamaz", "Not available":"Eri\u015fim sa\u011flanam\u0131yor", "Tap to request access":"Eri\u015fim talebi i\u00e7in t\u0131klay\u0131n", "Click to request access":"Eri\u015fim talebi i\u00e7in t\u0131klay\u0131n", "Open":"A\u00e7", "Copy link":"Ba\u011flant\u0131y\u0131 kopyala", "Google Drive":"Google Drive", "Google Docs":"Google Dok\u00fcmanlar", "Google Sheets":"Google E-Tablolar", "Google Slides":"Google Slaytlar", 
"PDF":"PDF", "Word Document":"Word Belgesi", "Excel Spreadsheet":"Excel Tablosu", "Modified":"De\u011fi\u015ftirildi", "Connect":"Ba\u011flan", "Connect to see more":"Daha fazla g\u00f6rmek i\u00e7in ba\u011flan\u0131n", "Connect Google account":"Google hesab\u0131na ba\u011flan\u0131n", "Title not available":"Ba\u015fl\u0131\u011fa eri\u015filemiyor", "Open containing folder":"Bulundu\u011fu klas\u00f6r\u00fc a\u00e7", "Cell Background":"H\u00fccre Arka Plan\u0131", "Cell Alignment":"H\u00fccre Hizalama", 
"Align content to top":"\u0130\u00e7eri\u011fi \u00fcste yasla", "Align content to center":"\u0130\u00e7eri\u011fi ortaya hizala", "Align content to bottom":"\u0130\u00e7eri\u011fi alta yasla", "Distribute Columns Evenly":"S\u00fctunlar\u0131 E\u015fit Olarak Da\u011f\u0131t", "Match Note Width":"Not Geni\u015fli\u011fini E\u015fle", "Delete Selected Column(s)":"Se\u00e7ili S\u00fctunlar\u0131 Sil", "Delete Selected Row(s)":"Se\u00e7ili Sat\u0131rlar\u0131 Sil", "Delete Table":"Tabloyu Sil", "Merge Cells":"H\u00fccreleri Birle\u015ftir", 
"Unmerge Cells":"H\u00fccreleri \u00c7\u00f6z"};
goog.provide("uno.i18n.uk");
uno.i18n.uk.textEntries = {"Not available offline":"\u041d\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439 \u0432 \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u043c\u0443 \u0440\u0435\u0436\u0438\u043c\u0456", "Not available":"\u041d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0438\u0439", "Tap to request access":"\u0422\u043e\u0440\u043a\u043d\u0456\u0442\u044c\u0441\u044f, \u0449\u043e\u0431 \u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f", 
"Click to request access":"\u041d\u0430\u0442\u0438\u0441\u043d\u0456\u0442\u044c, \u0449\u043e\u0431 \u043e\u0442\u0440\u0438\u043c\u0430\u0442\u0438 \u0434\u043e\u0441\u0442\u0443\u043f", "Open":"\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438", "Copy link":"\u041a\u043e\u043f\u0456\u044e\u0432\u0430\u0442\u0438 \u043f\u043e\u0441\u0438\u043b\u0430\u043d\u043d\u044f", "Google Drive":"\u0414\u0438\u0441\u043a Google", "Google Docs":"\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0438 Google", 
"Google Sheets":"\u0422\u0430\u0431\u043b\u0438\u0446\u044f Google", "Google Slides":"\u041f\u0440\u0435\u0437\u0435\u043d\u0442\u0430\u0446\u0456\u044f Google", "PDF":"PDF", "Word Document":"\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442 Word", "Excel Spreadsheet":"\u0422\u0430\u0431\u043b\u0438\u0446\u044f Excel", "Modified":"\u0417\u043c\u0456\u043d\u0435\u043d\u0438\u0439", "Connect":"\u041f\u0456\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u0438\u0441\u044f", "Connect to see more":"\u041f\u0456\u0434\u043a\u043b\u044e\u0447\u0456\u0442\u044c, \u0449\u043e\u0431 \u0434\u0456\u0437\u043d\u0430\u0442\u0438\u0441\u044f \u0431\u0456\u043b\u044c\u0448\u0435", 
"Connect Google account":"\u041f\u0456\u0434\u043a\u043b\u044e\u0447\u0438\u0442\u0438 \u043e\u0431\u043b\u0456\u043a\u043e\u0432\u0438\u0439 \u0437\u0430\u043f\u0438\u0441 Google", "Title not available":"\u041d\u0430\u0437\u0432\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430", "Open containing folder":"\u0412\u0456\u0434\u043a\u0440\u0438\u0442\u0438 \u043f\u0430\u043f\u043a\u0443", "Cell Background":"\u0424\u043e\u043d \u043a\u043b\u0456\u0442\u0438\u043d\u043a\u0438", "Cell Alignment":"\u0412\u0438\u0440\u0456\u0432\u043d\u044e\u0432\u0430\u043d\u043d\u044f \u0443 \u043a\u043b\u0456\u0442\u0438\u043d\u0446\u0456", 
"Align content to top":"\u0412\u0438\u0440\u0456\u0432\u043d\u044f\u0442\u0438 \u0437\u0430 \u0432\u0435\u0440\u0445\u043d\u0456\u043c \u043a\u0440\u0430\u0454\u043c", "Align content to center":"\u0412\u0438\u0440\u0456\u0432\u043d\u044f\u0442\u0438 \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443", "Align content to bottom":"\u0412\u0438\u0440\u0456\u0432\u043d\u044f\u0442\u0438 \u0437\u0430 \u043d\u0438\u0436\u043d\u0456\u043c \u043a\u0440\u0430\u0454\u043c", "Distribute Columns Evenly":"\u0412\u0438\u0440\u0456\u0432\u043d\u044f\u0442\u0438 \u0448\u0438\u0440\u0438\u043d\u0443 \u0441\u0442\u043e\u0432\u043f\u0446\u0456\u0432", 
"Match Note Width":"\u0412\u0456\u0434\u043f\u043e\u0432\u0456\u0434\u043d\u043e \u0434\u043e \u0448\u0438\u0440\u0438\u043d\u0438 \u043d\u043e\u0442\u0430\u0442\u043a\u0438", "Delete Selected Column(s)":"\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0439 \u0441\u0442\u043e\u0432\u043f\u0435\u0446\u044c", "Delete Selected Row(s)":"\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0432\u0438\u0431\u0440\u0430\u043d\u0438\u0439 \u0440\u044f\u0434\u043e\u043a", 
"Delete Table":"\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044e", "Merge Cells":"\u041e\u0431'\u0454\u0434\u043d\u0430\u0442\u0438 \u043a\u043b\u0456\u0442\u0438\u043d\u043a\u0438", "Unmerge Cells":"\u0421\u043a\u0430\u0441\u0443\u0432\u0430\u0442\u0438 \u043e\u0431\u2019\u0454\u0434\u043d\u0430\u043d\u043d\u044f \u043a\u043b\u0456\u0442\u0438\u043d\u043e\u043a"};
goog.provide("uno.i18n.vi");
uno.i18n.vi.textEntries = {"Not available offline":"Kh\u00f4ng kh\u1ea3 d\u1ee5ng \u1edf ch\u1ebf \u0111\u1ed9 ngo\u1ea1i tuy\u1ebfn", "Not available":"Kh\u00f4ng kh\u1ea3 d\u1ee5ng", "Tap to request access":"Nh\u1ea5p \u0111\u1ec3 y\u00eau c\u1ea7u quy\u1ec1n truy c\u1eadp", "Click to request access":"Nh\u1ea5p \u0111\u1ec3 y\u00eau c\u1ea7u quy\u1ec1n truy c\u1eadp", "Open":"M\u1edf", "Copy link":"Sao ch\u00e9p li\u00ean k\u1ebft", "Google Drive":"Google Drive", "Google Docs":"Google Docs", "Google Sheets":"Google Sheets", 
"Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"T\u00e0i li\u1ec7u Word", "Excel Spreadsheet":"B\u1ea3ng t\u00ednh Excel", "Modified":"\u0110\u00e3 s\u1eeda \u0111\u1ed5i", "Connect":"K\u1ebft n\u1ed1i", "Connect to see more":"K\u1ebft n\u1ed1i \u0111\u1ec3 xem chi ti\u1ebft", "Connect Google account":"K\u1ebft n\u1ed1i v\u1edbi t\u00e0i kho\u1ea3n Google", "Title not available":"Ti\u00eau \u0111\u1ec1 kh\u00f4ng kh\u1ea3 d\u1ee5ng", "Open containing folder":"M\u1edf th\u01b0 m\u1ee5c ch\u1ee9a", 
"Cell Background":"H\u00ecnh n\u1ec1n c\u1ee7a \u00f4", "Cell Alignment":"C\u0103n ch\u1ec9nh \u00f4", "Align content to top":"C\u0103n ch\u1ec9nh n\u1ed9i dung l\u00ean tr\u00ean c\u00f9ng", "Align content to center":"C\u0103n ch\u1ec9nh n\u1ed9i dung v\u00e0o trung t\u00e2m", "Align content to bottom":"C\u0103n ch\u1ec9nh n\u1ed9i dung xu\u1ed1ng d\u01b0\u1edbi c\u00f9ng", "Distribute Columns Evenly":"Ph\u00e2n b\u1ed1 c\u00e1c c\u1ed9t \u0111\u1ec1u nhau", "Match Note Width":"Kh\u1edbp chi\u1ec1u r\u1ed9ng ghi ch\u00fa", 
"Delete Selected Column(s)":"X\u00f3a (nh\u1eefng) c\u1ed9t \u0111\u00e3 ch\u1ecdn", "Delete Selected Row(s)":"X\u00f3a (nh\u1eefng) h\u00e0ng \u0111\u00e3 ch\u1ecdn", "Delete Table":"X\u00f3a b\u1ea3ng", "Merge Cells":"H\u1ee3p nh\u1ea5t \u00f4", "Unmerge Cells":"H\u1ee7y h\u1ee3p nh\u1ea5t \u00f4"};
goog.provide("uno.i18n.zh_CN");
uno.i18n.zh_CN.textEntries = {"Not available offline":"\u672a\u79bb\u7ebf\u7684\u7b14\u8bb0\u672c", "Not available":"\u4e0d\u53ef\u7528", "Tap to request access":"\u70b9\u51fb\u7533\u8bf7\u6743\u9650", "Click to request access":"\u70b9\u51fb\u7533\u8bf7\u6743\u9650", "Open":"\u6253\u5f00", "Copy link":"\u590d\u5236\u94fe\u63a5", "Google Drive":"Google Drive", "Google Docs":"Google\u6587\u6863", "Google Sheets":"Google Sheets", "Google Slides":"Google Slides", "PDF":"PDF", "Word Document":"Word\u6587\u6863", 
"Excel Spreadsheet":"Excel\u6570\u636e\u8868\u683c", "Modified":"\u5df2\u4fee\u6539", "Connect":"\u8fde\u63a5", "Connect to see more":"\u8fde\u63a5\u67e5\u770b\u66f4\u591a", "Connect Google account":"\u8fde\u63a5Google\u5e10\u6237", "Title not available":"\u6807\u9898\u4e0d\u53ef\u7528", "Open containing folder":"\u6253\u5f00\u5305\u542b\u7684\u6587\u4ef6\u5939", "Cell Background":"\u5355\u5143\u683c\u80cc\u666f", "Cell Alignment":"\u5355\u5143\u683c\u5bf9\u9f50", "Align content to top":"\u9876\u7aef\u5bf9\u9f50", 
"Align content to center":"\u5c45\u4e2d\u5bf9\u9f50", "Align content to bottom":"\u5e95\u90e8\u5bf9\u9f50", "Distribute Columns Evenly":"\u5e73\u5747\u5206\u5e03\u5404\u5217", "Match Note Width":"\u5339\u914d\u7b14\u8bb0\u5bbd\u5ea6", "Delete Selected Column(s)":"\u5220\u9664\u9009\u4e2d\u7684\u5217", "Delete Selected Row(s)":"\u5220\u9664\u9009\u4e2d\u7684\u884c", "Delete Table":"\u5220\u9664\u8868\u683c", "Merge Cells":"\u5408\u5e76\u5355\u5143\u683c", "Unmerge Cells":"\u53d6\u6d88\u5408\u5e76\u5355\u5143\u683c"};
goog.provide("uno.i18n.zh_TW");
uno.i18n.zh_TW.textEntries = {"Not available offline":"\u4e0d\u53ef\u96e2\u7dda\u5b58\u53d6", "Not available":"\u4e0d\u9069\u7528", "Tap to request access":"\u9ede\u64ca\u4ee5\u8acb\u6c42\u5b58\u53d6", "Click to request access":"\u9ede\u64ca\u4ee5\u8acb\u6c42\u5b58\u53d6", "Open":"\u958b\u555f", "Copy link":"\u8907\u88fd\u9023\u7d50", "Google Drive":"Google \u96f2\u7aef\u786c\u789f", "Google Docs":"Google \u6587\u4ef6", "Google Sheets":"Google \u8a66\u7b97\u8868", "Google Slides":"Google \u7c21\u5831", 
"PDF":"PDF", "Word Document":"Word \u6587\u4ef6", "Excel Spreadsheet":"Excel \u8a66\u7b97\u8868", "Modified":"\u5df2\u4fee\u6539", "Connect":"\u9023\u7d50", "Connect to see more":"\u9023\u7d50\u4ee5\u770b\u5230\u66f4\u591a", "Connect Google account":"\u9023\u7d50 Google \u5e33\u6236", "Title not available":"\u7121\u6a19\u984c", "Open containing folder":"\u958b\u555f\u6240\u5c6c\u8cc7\u6599\u593e", "Cell Background":"\u8868\u683c\u5132\u5b58\u683c\u80cc\u666f\u984f\u8272", "Cell Alignment":"\u5132\u5b58\u683c\u5167\u6587\u5b57\u5c0d\u9f4a", 
"Align content to top":"\u9f4a\u9802", "Align content to center":"\u7f6e\u4e2d\u5c0d\u9f4a", "Align content to bottom":"\u9f4a\u5e95", "Distribute Columns Evenly":"\u5e73\u5747\u5206\u4f48\u6b04\u4f4d", "Match Note Width":"\u7b26\u5408\u8a18\u4e8b\u5bec", "Delete Selected Column(s)":"\u522a\u9664\u9078\u53d6\u7684\u6b04", "Delete Selected Row(s)":"\u522a\u9664\u9078\u53d6\u7684\u5217", "Delete Table":"\u522a\u9664\u8868\u683c", "Merge Cells":"\u5408\u4f75\u5132\u5b58\u683c", "Unmerge Cells":"\u53d6\u6d88\u5408\u4f75\u5132\u5b58\u683c"};
goog.provide("uno.i18n.en_XA");
uno.i18n.en_XA.textEntries = {"Not available offline":"[Not available offline xxxxxxxxx]", "Not available":"[Not available xxxxxxxx]", "Tap to request access":"[Tap to request access xxxxxxxxx]", "Click to request access":"[Click to request access xxxxxxxxxx]", "Open":"[Open xxx]", "Copy link":"[Copy link xxxxxxxx]", "Google Drive":"[Google Drive xxxxxxx]", "Google Docs":"[Google Docs xxxxxx]", "Google Sheets":"[Google Sheets xxxxxxxx]", "Google Slides":"[Google Slides xxxxxxxx]", "PDF":"[PDF xx]", 
"Word Document":"[Word Document xxxxxxxx]", "Excel Spreadsheet":"[Excel Spreadsheet xxxxxxxxxx]", "Modified":"[Modified xxxxxxx]", "Connect":"[Connect xxxxxx]", "Connect to see more":"[Connect to see more xxxxxxxxxx x]", "Connect Google account":"[Connect Google account xxxxxxxxxx]", "Title not available":"[Title not available xxxxxxxxxx x]", "Open containing folder":"[Open containing folder xxxxxxxxxx]", "Cell Background":"[Cell Background xxxxxxxxx]", "Cell Alignment":"[Cell Alignment xxxxxxxx]", 
"Align content to top":"[Align content to top xxxxxxxxx]", "Align content to center":"[Align content to center xxxxxxxxxx]", "Align content to bottom":"[Align content to bottom xxxxxxxxxx]", "Distribute Columns Evenly":"[Distribute Columns Evenly xxxxxxxxxx ]", "Match Note Width":"[Match Note Width xxxxxxxxxx]", "Delete Selected Column(s)":"[Delete Selected Column(s) xxxxxxxxxx ]", "Delete Selected Row(s)":"[Delete Selected Row(s) xxxxxxxxxx]", "Delete Table":"[Delete Table xxxxxxx]", "Merge Cells":"[Merge Cells xxxxxx]", 
"Unmerge Cells":"[Unmerge Cells xxxxxxxx]"};
goog.provide("uno.i18n.all");
goog.require("uno.i18n.ar");
goog.require("uno.i18n.cs");
goog.require("uno.i18n.da");
goog.require("uno.i18n.de");
goog.require("uno.i18n.en");
goog.require("uno.i18n.es");
goog.require("uno.i18n.fi");
goog.require("uno.i18n.fr");
goog.require("uno.i18n.id");
goog.require("uno.i18n.it");
goog.require("uno.i18n.ja");
goog.require("uno.i18n.ko");
goog.require("uno.i18n.ms");
goog.require("uno.i18n.nl");
goog.require("uno.i18n.no");
goog.require("uno.i18n.pl");
goog.require("uno.i18n.pt_BR");
goog.require("uno.i18n.pt");
goog.require("uno.i18n.ru");
goog.require("uno.i18n.sv");
goog.require("uno.i18n.th");
goog.require("uno.i18n.tr");
goog.require("uno.i18n.uk");
goog.require("uno.i18n.vi");
goog.require("uno.i18n.zh_CN");
goog.require("uno.i18n.zh_TW");
goog.require("uno.i18n.en_XA");
uno.i18n.all.textEntries = {"ar":uno.i18n.ar.textEntries, "cs":uno.i18n.cs.textEntries, "da":uno.i18n.da.textEntries, "de":uno.i18n.de.textEntries, "en":uno.i18n.en.textEntries, "es":uno.i18n.es.textEntries, "fi":uno.i18n.fi.textEntries, "fr":uno.i18n.fr.textEntries, "id":uno.i18n.id.textEntries, "it":uno.i18n.it.textEntries, "ja":uno.i18n.ja.textEntries, "ko":uno.i18n.ko.textEntries, "ms":uno.i18n.ms.textEntries, "nl":uno.i18n.nl.textEntries, "no":uno.i18n.no.textEntries, "pl":uno.i18n.pl.textEntries, 
"pt_BR":uno.i18n.pt_BR.textEntries, "pt":uno.i18n.pt.textEntries, "ru":uno.i18n.ru.textEntries, "sv":uno.i18n.sv.textEntries, "th":uno.i18n.th.textEntries, "tr":uno.i18n.tr.textEntries, "uk":uno.i18n.uk.textEntries, "vi":uno.i18n.vi.textEntries, "zh_CN":uno.i18n.zh_CN.textEntries, "zh_TW":uno.i18n.zh_TW.textEntries, "en_XA":uno.i18n.en_XA.textEntries};
goog.provide("uno.util.loc");
goog.require("uno.i18n.all");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.loc");
  var util = uno.util;
  util.loc.init = function(locale) {
    util.loc.locale = locale;
    if (!util.loc.locale) {
      util.loc.locale = "en";
    }
    util.loc.locale = util.loc.locale.replace(/-/g, "_");
    Object.keys(uno.i18n.all.textEntries).forEach(function(lang) {
      var value = uno.i18n.all.textEntries[lang];
      util.loc.addTranslation(lang, value);
    });
  };
  util.loc.defaultLocale = "en";
  util.loc.translation = null;
  util.loc.translations = {};
  util.loc.missingLocales = {};
  util.loc.missingStrings = {};
  util.loc.addTranslation = function(locale, translation) {
    util.loc.translations[locale] = translation;
    util.loc.missingStrings[locale] = {};
  };
  util.loc.loadTranslation = function(locale) {
    if (locale) {
      util.loc.locale = locale;
    }
    if (util.loc.locale == null) {
      log.warning("Language locale has not been configured. Defaulting to " + util.loc.defaultLocale);
      util.loc.locale = util.loc.defaultLocale;
    }
    util.loc.locale = util.loc.locale.replace(/-/g, "_");
    if (util.loc.missingLocales[util.loc.locale]) {
      return;
    }
    if (util.loc.translation !== null && util.loc.translation === util.loc.translations[util.loc.locale]) {
      return;
    }
    util.loc.translation = util.loc.translations[util.loc.locale];
    if (util.loc.translation == null) {
      log.info("There are no translations available for the " + util.loc.locale + " locale");
      util.loc.missingLocales[util.loc.locale] = true;
      if (util.loc.locale.indexOf("_") !== -1) {
        util.loc.locale = util.loc.locale.substr(0, util.loc.locale.indexOf("_"));
        util.loc.translation = util.loc.translations[util.loc.locale];
        if (util.loc.translation == null) {
          log.warning("There are also no translations for the fallback locale " + util.loc.locale);
          util.loc.missingLocales[util.loc.locale] = true;
        }
      }
    }
    if (util.loc.translation != null) {
      log.fine("Using text for " + util.loc.locale);
      Object.keys(util.loc.translation).forEach(function(key) {
        var text = util.loc.translation[key];
        if (text === "") {
          util.loc.translation[key] = null;
        }
      });
      util.loc.missingStrings[locale] = util.loc.missingStrings[locale] || {};
    }
  };
  util.loc.t = function(text, placeholders) {
    var result;
    if (util.loc.translation == null) {
      util.loc.loadTranslation(util.loc.locale);
    }
    if (util.loc.missingLocales[util.loc.locale]) {
      result = text;
    } else {
      if (util.loc.translation[text] == null) {
        if (util.loc.missingStrings[util.loc.locale] == null) {
          log.warning("No missingStrings object defined for " + util.loc.locale);
        }
        if (util.loc.missingStrings[util.loc.locale][text] == null) {
          log.warning("The " + util.loc.locale + ' locale does not have a translation for "' + text + '"');
          util.loc.missingStrings[util.loc.locale][text] = true;
        }
        result = text;
      } else {
        result = util.loc.translation[text];
      }
    }
    if (placeholders) {
      result = util.loc.replace(result, placeholders);
    }
    return result;
  };
  util.loc.replace = function(text, placeholders) {
    Object.keys(placeholders).forEach(function(token) {
      var value = placeholders[token];
      text = text.replace(new RegExp("{{" + token + "}}", "g"), value);
    });
    return text;
  };
})();
goog.provide("uno.util.menu");
goog.require("goog.style");
goog.require("uno.components.Menu");
goog.require("uno.util.loc");
goog.require("uno.util.dom");
goog.require("uno.util.table");
goog.require("uno.util.table.selection");
goog.require("uno.util.zoomscale");
(function() {
  var util = uno.util;
  var t = util.loc.t;
  var comp = uno.components;
  var instance = null;
  util.menu.presentTableContextMenu = function(target, editor) {
    if (instance) {
      instance.dismiss();
    }
    if (!target) {
      return;
    }
    instance = new comp.Menu;
    var range = editor.getRange();
    var fn = function(command, arg) {
      return function(val) {
        range.select();
        editor.execCommand(command, val || arg, undefined, true);
      };
    };
    var columnIndexes = util.table.selection.getColumnIndexes();
    var cell = util.table.getActiveCell();
    var cells = !util.table.selection.isActive() && cell ? [cell] : util.table.selection.getCells();
    var defaultColor = cell.style.backgroundColor || "#ffffff";
    var valign = cell.style.verticalAlign;
    var isTop = !valign || valign === "top";
    var isMiddle = valign === "middle";
    var isBottom = valign === "bottom";
    var isMergeable = util.table.mergeable(cells);
    var isUnmergeable = util.table.unmergeable(cells);
    instance.addItem(new comp.MenuColorPicker(t("Cell Background"), defaultColor), fn("tablecellcolor"));
    instance.addItem(new comp.MenuSeparator);
    instance.addItem(new comp.MenuItem(t("Match Note Width")), fn("tablefitnote"));
    if (columnIndexes.length > 1) {
      instance.addItem(new comp.MenuItem(t("Distribute Columns Evenly")), fn("tableequalcol"));
    }
    instance.addSubmenuItem(new comp.MenuItem(t("Cell Alignment")), function(menu) {
      menu.addItem(new comp.MenuOption(t("Align content to top"), isTop), fn("tableverticalalign", "top"));
      menu.addItem(new comp.MenuOption(t("Align content to center"), isMiddle), fn("tableverticalalign", "middle"));
      menu.addItem(new comp.MenuOption(t("Align content to bottom"), isBottom), fn("tableverticalalign", "bottom"));
    });
    instance.addItem(new comp.MenuSeparator);
    if (isMergeable || isUnmergeable) {
      if (isMergeable) {
        instance.addItem(new comp.MenuItem(t("Merge Cells")), fn("mergecells", true));
      }
      if (isUnmergeable) {
        instance.addItem(new comp.MenuItem(t("Unmerge Cells")), fn("mergecells", false));
      }
      instance.addItem(new comp.MenuSeparator);
    }
    instance.addItem(new comp.MenuItem(t("Delete Selected Column(s)")), fn("deletetablecol"));
    instance.addItem(new comp.MenuItem(t("Delete Selected Row(s)")), fn("deletetablerow"));
    instance.addItem(new comp.MenuItem(t("Delete Table")), fn("deletetable"));
    var rect = target.getBoundingClientRect();
    instance.present(rect.left + rect.width + 1, rect.top + 6);
  };
})();
goog.provide("uno.util.table.drag");
goog.require("goog.debug.Logger");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("uno.defs");
goog.require("uno.util.table");
goog.require("uno.util.table.selection");
goog.require("uno.util.tools");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.table.drag");
  var util = uno.util;
  var State = util.table.State;
  var Axis = util.table.Axis;
  var model = null;
  util.table.drag.prepare = function(enTable, event) {
    var target = event.target;
    if (model || !target || !target.classList.contains("handle") || event.type !== "mousedown") {
      return;
    }
    var obj = util.table.handleToObject(target);
    var indexes = obj.axis === Axis.VERTICAL ? util.table.selection.getColumnIndexes(State.DRAGGABLE) : util.table.selection.getRowIndexes(State.DRAGGABLE);
    if (indexes.indexOf(obj.index) === -1) {
      return;
    }
    model = {enTable:enTable, baseX:event.clientX, baseY:event.clientY, baseIndex:obj.index, baseAxis:obj.axis};
  };
  util.table.drag.tryStart = function(enTable, event) {
    if (!model || !enTable || !event || model.preview || model.enTable !== enTable || !util.table.selection.isActive(enTable)) {
      return false;
    }
    if (["mousemove", "mouseover"].indexOf(event.type) === -1) {
      return false;
    }
    if (event.ctrlKey || event.shiftKey || event.metaKey || event.altKey) {
      return false;
    }
    if (event.type === "mousemove" && distance(model.baseX, model.baseY, event.clientX, event.clientY) <= 5) {
      return false;
    }
    var indexes = model.baseAxis === Axis.VERTICAL ? util.table.selection.getColumnIndexes(State.DRAGGABLE) : util.table.selection.getRowIndexes(State.DRAGGABLE);
    if (indexes.indexOf(model.baseIndex) === -1) {
      return false;
    }
    util.table.drag.start(enTable, event.clientX, event.clientY, indexes, model.baseAxis);
    return true;
  };
  util.table.drag.start = function(enTable, clientX, clientY, indexes, axis) {
    if (model) {
      util.table.drag.cancel();
    }
    document.documentElement.classList.add("table-dragging");
    var container = util.table.query_(enTable, ".container");
    var containerBounds = container.getBoundingClientRect();
    var bounds = false;
    var animated = !!bounds;
    if (!animated) {
      bounds = containerBounds;
    }
    var preview = createPreview(clientX, clientY, bounds, axis, indexes.length, animated);
    model = {enTable:enTable, preview:preview, axis:axis, indexes:indexes, sequence:isSequence(indexes), baseX:clientX, baseY:clientY, baseLeft:parseInt(preview.style.left, 10), baseTop:parseInt(preview.style.top, 10), zones:{}};
  };
  util.table.drag.move = function(enTable, clientX, clientY) {
    if (!model) {
      return;
    }
    if (model.zones.ownerEnTable !== enTable) {
      if (model.zones.current) {
        util.table.setLine(model.zones.ownerEnTable);
        model.zones.current = null;
      }
      clearAnimationFrame(model.zones.scroll);
      if (enTable) {
        model.zones = createZones(enTable, model.axis, enTable === model.enTable ? model.indexes : [], model.sequence);
      }
    }
    if (enTable) {
      var coordinate = model.axis === Axis.VERTICAL ? clientX : clientY;
      scrollIfNeeded(coordinate);
      updateIfNeeded(coordinate);
    }
    var left = model.baseLeft + (clientX - model.baseX);
    var top = model.baseTop + (clientY - model.baseY) + document.body.scrollTop;
    model.preview.style.left = left + "px";
    model.preview.style.top = top + "px";
  };
  util.table.drag.end = function(multirange) {
    if (!model) {
      return false;
    }
    var changed = false;
    if (model.zones.current) {
      moveCells(model.enTable, model.zones.ownerEnTable, model.axis, model.indexes, model.zones.current.index, multirange);
      changed = true;
    }
    cleanup();
    return changed;
  };
  util.table.drag.cancel = function() {
    if (!model) {
      return;
    }
    cleanup();
  };
  function cleanup() {
    document.documentElement.classList.remove("table-dragging");
    if (model.preview) {
      model.preview.remove();
    }
    if (model.zones) {
      if (model.zones.ownerEnTable) {
        util.table.setLine(model.zones.ownerEnTable);
      }
      clearAnimationFrame(model.zones.scroll);
    }
    model = null;
  }
  function scrollIfNeeded(coordinate) {
    var sdata = model.zones.scroll;
    if (!sdata) {
      return;
    }
    var container = model.zones.container;
    var bounds = container.getBoundingClientRect();
    var offset = 0;
    var detectionWidth = 50;
    if (coordinate < bounds.left + detectionWidth) {
      offset = bounds.left + detectionWidth - coordinate;
    } else {
      if (coordinate > bounds.right - detectionWidth) {
        offset = bounds.right - detectionWidth - coordinate;
      }
    }
    sdata.direction = offset === 0 ? 0 : offset > 0 ? -1 : 1;
    sdata.coordinate = coordinate;
    if (sdata.direction === 0 || isScrolledToEnd(container, sdata.direction)) {
      clearAnimationFrame(sdata);
      return;
    }
    sdata.speed = Math.pow(Math.min(Math.max(Math.abs(offset), 1), detectionWidth) * 2, 1.7);
    if (sdata.rafID === null) {
      sdata.then = Date.now();
      scroll();
    }
  }
  function updateIfNeeded(coordinate) {
    var zone = findZone(model.zones, coordinate, model.axis);
    if (zone !== model.zones.current) {
      model.zones.current = zone;
      if (zone) {
        util.table.setLine(model.zones.ownerEnTable, zone.index, model.axis);
      } else {
        util.table.setLine(model.zones.ownerEnTable);
      }
    }
  }
  function scroll() {
    var sdata = model.zones.scroll;
    var container = model.zones.container;
    if (!sdata || sdata.direction === 0 || isScrolledToEnd(container, sdata.direction)) {
      clearAnimationFrame(sdata);
      return;
    }
    var now = Date.now();
    var delta = (now - sdata.then) / 1000;
    var velocity = sdata.speed * delta * sdata.direction;
    container.scrollLeft = Math.ceil(container.scrollLeft + velocity);
    updateIfNeeded(sdata.coordinate);
    sdata.then = now;
    sdata.rafID = requestAnimationFrame(scroll);
  }
  function moveCells(sourceEnTable, targetEnTable, axis, indexes, dropIndex, multirange) {
    var inPlace = sourceEnTable === targetEnTable;
    if (inPlace) {
      var refDropIndex = dropIndex;
      indexes.forEach(function(v) {
        if (v < refDropIndex) {
          dropIndex -= 1;
        }
      });
    }
    util.table.selection.clear();
    var diffSize = inPlace ? 0 : fitTargetTableSize(sourceEnTable, targetEnTable, axis);
    var transferObj = removeSubmatrix(sourceEnTable, indexes, diffSize, axis);
    if (!inPlace && sourceEnTable.parentNode) {
      util.table.normalizeCellBorders(util.table.query_(sourceEnTable, "table"));
      util.table.layout(sourceEnTable);
    }
    insertSubmatrix(targetEnTable, transferObj, dropIndex, axis);
    util.table.normalizeCellBorders(util.table.query_(targetEnTable, "table"));
    util.table.layout(targetEnTable);
    util.table.setActive(targetEnTable, targetEnTable.querySelector("td.selected"));
    util.table.selection.create(targetEnTable, multirange);
  }
  function removeSubmatrix(sourceEnTable, indexes, diffSize, axis) {
    var table = util.table.query_(sourceEnTable, "table");
    var matrix = util.table.matrix(table);
    var vert = axis === Axis.VERTICAL;
    var submatrix = [];
    var cols = [];
    var vector = vert ? matrix[0] : matrix;
    if (vert) {
      matrix.forEach(function(row, rowIndex) {
        var subitems = [];
        submatrix.push(subitems);
        indexes.forEach(function(colIndex) {
          var info = row[colIndex].info;
          var node = null;
          if (info.startColIndex === colIndex && info.startRowIndex === rowIndex) {
            node = info.node;
            node.classList.add("selected");
            node.remove();
          }
          subitems.push(node);
        });
      });
      for (var i = diffSize; i > 0; i--) {
        var subitems = [];
        submatrix.push(subitems);
        indexes.forEach(function() {
          subitems.push(util.table.createEmptyTd({class:"selected"}));
        });
      }
      var colgroup = util.table.query_(sourceEnTable, "colgroup");
      goog.array.forEachRight(indexes, function(rowIndex) {
        var col = colgroup.children[rowIndex];
        col.remove();
        cols.push(col);
      });
    } else {
      indexes.forEach(function(rowIndex) {
        var subitems = [];
        submatrix.push(subitems);
        matrix[rowIndex].forEach(function(obj, colIndex) {
          var info = obj.info;
          var node = null;
          if (info.startColIndex === colIndex && info.startRowIndex === rowIndex) {
            node = info.node;
            node.classList.add("selected");
            node.remove();
          }
          subitems.push(node);
        });
        for (var i = diffSize; i > 0; i--) {
          subitems.push(util.table.createEmptyTd({class:"selected"}));
        }
      });
      goog.array.forEachRight(indexes, function(rowIndex) {
        table.rows[rowIndex].remove();
      });
    }
    if (vector.length === indexes.length) {
      sourceEnTable.remove();
    }
    return {submatrix:submatrix, cols:cols};
  }
  function insertSubmatrix(targetEnTable, transferObj, dropIndex, axis) {
    var table = util.table.query_(targetEnTable, "table");
    var colgroup = axis === Axis.VERTICAL ? util.table.query_(targetEnTable, "colgroup") : null;
    transferObj.submatrix.forEach(function(row, rowIndex) {
      var tr = null;
      if (axis === Axis.HORIZONTAL) {
        tr = document.createElement("tr");
        table.tBodies[0].insertBefore(tr, table.rows[rowIndex + dropIndex] || null);
      }
      row.forEach(function(td, colIndex) {
        if (td && axis === Axis.HORIZONTAL) {
          tr.appendChild(td);
        } else {
          if (td) {
            util.table.insertTd(td, rowIndex, colIndex + dropIndex, table);
          }
        }
        if (rowIndex === 0 && axis === Axis.VERTICAL) {
          colgroup.insertBefore(transferObj.cols.pop(), colgroup.children[colIndex + dropIndex] || null);
        }
      });
    });
  }
  function fitTargetTableSize(sourceEnTable, targetEnTable, axis) {
    var vert = axis === Axis.VERTICAL;
    var sourceMatrix = util.table.matrix(sourceEnTable);
    var targetMatrix = util.table.matrix(targetEnTable);
    var sourceItemCount = vert ? sourceMatrix.length : sourceMatrix[0].length;
    var targetItemCount = vert ? targetMatrix.length : targetMatrix[0].length;
    if (targetItemCount < sourceItemCount) {
      fn = vert ? util.table.insertRows : util.table.insertColumns;
      fn(targetEnTable, targetItemCount, sourceItemCount - targetItemCount);
    }
    return targetItemCount - sourceItemCount;
  }
  function getVisibleSelectedBounds(enTable, x, y, axis, indexes) {
    var table = util.table.query_(enTable, "table");
    var container = util.table.query_(enTable, ".container");
    var contBounds = container.getBoundingClientRect();
    var groups = [];
    var low = null;
    var high = null;
    var vert = axis === Axis.VERTICAL;
    var lowProp = vert ? "left" : "top";
    var highProp = vert ? "right" : "bottom";
    var items = vert ? table.rows[0].children : table.rows;
    goog.array.forEach(items, function(item, i) {
      if (indexes.indexOf(i) === -1) {
        return;
      }
      var td = vert ? item : item.firstChild;
      var tdBounds = td.getBoundingClientRect();
      if (contBounds[highProp] > tdBounds[lowProp] && tdBounds[lowProp] < contBounds[highProp]) {
        var l = Math.max(tdBounds[lowProp], contBounds[lowProp]);
        var h = Math.min(tdBounds[highProp], contBounds[highProp]);
        var group = goog.array.peek(groups);
        if (!group || group.high !== l) {
          group = {low:l, high:null};
          groups.push(group);
        }
        group.high = h;
      }
    });
    if (groups.length === 0) {
      return null;
    }
    var axisVal = vert ? x : y;
    groups.forEach(function(group) {
      group.distance = Math.min(Math.abs(group.low - axisVal), Math.abs(group.high - axisVal));
    });
    var group = groups.sort(function(a, b) {
      return a.distance - b.distance;
    })[0];
    var bounds = axis === "y" ? {top:contBounds.top - 13, left:group.low, right:group.high, bottom:contBounds.bottom} : {top:group.low, left:contBounds.left - 13, right:contBounds.right, bottom:group.high};
    bounds.width = bounds.right - bounds.left;
    bounds.height = bounds.bottom - bounds.top;
    return bounds;
  }
  function findZone(zones, coordinate, axis) {
    if (!zones) {
      return null;
    }
    var contBounds = zones.container.getBoundingClientRect();
    if (axis === Axis.VERTICAL) {
      coordinate = coordinate - contBounds.left + (zones.scroll ? zones.container.scrollLeft : 0);
    } else {
      coordinate = coordinate - contBounds.top;
    }
    if (zones.current) {
      var b = zones.current.bounds;
      if (b[0] <= coordinate && b[1] > coordinate) {
        return zones.current;
      }
    }
    for (var i = zones.all.length - 1; i >= 0; i--) {
      var chunk = zones.all[i];
      var b = chunk.bounds;
      if (b[0] <= coordinate && b[1] > coordinate) {
        return chunk;
      }
    }
    return null;
  }
  function createZones(enTable, axis, dragIndexes, sequence) {
    var container = util.table.query_(enTable, ".container");
    var matrix = util.table.matrix(enTable);
    var scrollable = axis === Axis.VERTICAL && container.offsetWidth < container.scrollWidth;
    var dropIndexes = createDropIndexes(matrix, axis);
    var all = createZoneBounds(matrix, dragIndexes, dropIndexes, sequence, axis);
    return {all:all, container:container, current:null, ownerEnTable:enTable, scroll:scrollable ? {speed:0, direction:0, coordinate:null, then:null, rafID:null} : null};
  }
  function createZoneBounds(matrix, dragIndexes, dropIndexes, sequence, axis) {
    var vert = axis === Axis.VERTICAL;
    var items = vert ? matrix[0] : matrix;
    var posProp = vert ? "offsetLeft" : "offsetTop";
    var sizeProp = vert ? "offsetWidth" : "offsetHeight";
    var zones = [];
    var dragIndexObj = dragIndexes.reduce(function(obj, val) {
      obj[val] = true;
      return obj;
    }, {});
    var dropIndexObj = dropIndexes.reduce(function(obj, val) {
      obj[val] = true;
      return obj;
    }, {});
    for (var i = 0, length = items.length; i <= length; i++) {
      var selected = dragIndexObj[i];
      var selectedPrev = dragIndexObj[i - 1];
      if (!dropIndexObj[i] || sequence && (selected || selectedPrev) || !sequence && selected && selectedPrev) {
        continue;
      }
      var itemIndex = i === length ? i - 1 : i;
      var td = vert ? items[itemIndex].info.node : items[itemIndex][0].info.node;
      var lastTd;
      var lowBound;
      var highBound;
      if (i === 0) {
        lowBound = -34;
      } else {
        if (i === length && selectedPrev) {
          lowBound = td[posProp] + td[sizeProp] - 16;
        } else {
          if (i === length) {
            lowBound = td[posProp] + Math.ceil(td[sizeProp] / 2);
          } else {
            if (selectedPrev) {
              lowBound = td[posProp] - 16;
            } else {
              lastTd = vert ? items[itemIndex - 1].info.node : items[itemIndex - 1][0].info.node;
              lowBound = td[posProp] - Math.ceil(lastTd[sizeProp] / 2);
            }
          }
        }
      }
      if (i === length) {
        highBound = td[posProp] + td[sizeProp] + 34;
      } else {
        if (selected) {
          highBound = td[posProp] + 16;
        } else {
          highBound = td[posProp] + Math.ceil(td[sizeProp] / 2);
        }
      }
      zones.push({bounds:[lowBound, highBound], index:i});
    }
    return zones;
  }
  function createDropIndexes(matrix, axis) {
    var vert = axis === Axis.VERTICAL;
    var length = vert ? matrix[0].length : matrix.length;
    var blockedIndexes = {};
    var dropIndexes = [];
    matrix.forEach(function(row, rowIndex) {
      row.forEach(function(obj, colIndex) {
        var info = obj.info;
        if (vert && info.endColIndex > colIndex) {
          blockedIndexes[colIndex + 1] = true;
        } else {
          if (!vert && info.endRowIndex > rowIndex) {
            blockedIndexes[rowIndex + 1] = true;
          }
        }
      });
    });
    for (var i = 0; i <= length; i++) {
      if (!blockedIndexes[i]) {
        dropIndexes.push(i);
      }
    }
    return dropIndexes;
  }
  function createPreview(x, y, bounds, axis, count, animated) {
    var preview = util.tools.query(".en-drag-colrow");
    if (!preview) {
      preview = goog.dom.createDom("div", {class:"en-drag-colrow"});
      util.tools.append(preview);
    }
    preview.dataset.count = count;
    var width = 48;
    var height = 40;
    var left = 0;
    var top = 0;
    if (axis === "y") {
      height = Math.min(Math.max(bounds.height, height), 150);
      left = Math.round(x - width / 2);
      top = y - 10;
    } else {
      width = Math.min(Math.max(bounds.width, width), 200);
      left = x - 10;
      top = Math.round(y - height / 2);
    }
    preview.style.width = width + "px";
    preview.style.height = height + "px";
    preview.style.left = left + "px";
    preview.style.top = top + "px";
    if (animated) {
      preview.style.opacity = 0;
      preview.style.transform = ["translate3d(" + (bounds.left - left) + "px, " + (bounds.top - top) + "px, 0)", "scale(" + bounds.width / width + ", " + bounds.height / height + ")"].join(" ");
      setTimeout(function() {
        preview.style.opacity = 1;
        preview.style.transform = "translate3d(0, 0, 0) scale(1, 1)";
      }, 0);
    }
    return preview;
  }
  function clearAnimationFrame(scrollObj) {
    if (scrollObj && scrollObj.rafID) {
      cancelAnimationFrame(scrollObj.rafID);
      scrollObj.rafID = null;
    }
  }
  function isSequence(indexes) {
    if (indexes.length === 0) {
      return false;
    }
    if (indexes.length === 1) {
      return true;
    }
    for (var i = indexes.length - 2; i >= 0; i--) {
      if (indexes[i] + 1 !== indexes[i + 1]) {
        return false;
      }
    }
    return true;
  }
  function isScrolledToEnd(container, direction) {
    var sLeft = container.scrollLeft;
    var sWidth = container.scrollWidth;
    var oWidth = container.offsetWidth;
    return direction < 0 && sLeft === 0 || direction > 0 && sWidth - oWidth - sLeft === 0;
  }
  function distance(x1, y1, x2, y2) {
    var dx = x1 - x2;
    var dy = y1 - y2;
    return Math.sqrt(dx * dx + dy * dy);
  }
})();
goog.provide("uno.util.table.resizer");
goog.require("goog.debug.Logger");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.table.resizer");
  var util = uno.util;
  var model = null;
  util.table.resizer.start = function(enTable, yline, clientX, colIndex) {
    if (model) {
      util.table.resizer.end();
    }
    var table = util.table.query_(enTable, "table");
    var col = util.table.query_(enTable, "colgroup").children[colIndex];
    var minWidth = util.table.getColumnsMinWidth(enTable, colIndex)[colIndex];
    var baseColWidth = parseInt(col.style.width, 10);
    if (colIndex === 0) {
      minWidth += 1;
    }
    yline.classList.add("active");
    document.documentElement.classList.add("col-resizing");
    model = {enTable:enTable, col:col, yline:yline, baseX:clientX, baseYlineLeft:parseInt(yline.style.left, 10), baseColWidth:baseColWidth, baseTableWidth:parseInt(table.style.width, 10), minDelta:Math.min(minWidth - baseColWidth, 0)};
  };
  util.table.resizer.end = function() {
    document.documentElement.classList.remove("col-resizing");
    model.yline.classList.remove("active");
    model = null;
  };
  util.table.resizer.resize = function(clientX) {
    if (!model) {
      return;
    }
    var delta = Math.max(clientX - model.baseX, model.minDelta);
    model.yline.style.left = model.baseYlineLeft + delta + "px";
    model.col.style.width = model.baseColWidth + delta + "px";
    util.table.updateWidth(model.enTable, model.baseTableWidth + delta);
    util.table.updateAdornments(model.enTable);
    util.table.translateX(model.enTable);
    util.table.layoutMenuButton();
  };
  util.table.resizer.getTarget = function() {
    return model ? model.enTable : null;
  };
})();
goog.provide("uno.util.table.scroller");
goog.require("goog.debug.Logger");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.table.scroller");
  var util = uno.util;
  var model = null;
  util.table.scroller.start = function(enTable, thumb, clientX) {
    if (model) {
      util.table.scroller.end();
    }
    var container = util.table.query_(enTable, ".container");
    var scrollLeft = container.scrollLeft;
    var scrollWidth = container.scrollWidth;
    var offsetWidth = container.offsetWidth;
    var scale = offsetWidth / scrollWidth;
    thumb.classList.add("active");
    document.documentElement.classList.add("table-scrolling");
    model = {enTable:enTable, container:container, thumb:thumb, baseX:clientX, baseLeft:scrollLeft, maxDelta:(scrollWidth - offsetWidth - scrollLeft) * scale, minDelta:-scrollLeft * scale, scale:scale};
  };
  util.table.scroller.end = function() {
    document.documentElement.classList.remove("table-scrolling");
    model.thumb.classList.remove("active");
    model = null;
  };
  util.table.scroller.scrollByDrag = function(clientX) {
    if (!model) {
      return;
    }
    var delta = Math.min(Math.max(clientX - model.baseX, model.minDelta), model.maxDelta);
    model.container.scrollLeft = model.baseLeft + delta / model.scale;
    util.table.translateX(model.enTable);
  };
  util.table.scroller.scrollByWheel = function(enTable, deltaX) {
    var container = util.table.query_(enTable, ".container");
    if (container.offsetWidth >= container.scrollWidth) {
      return false;
    }
    container.scrollLeft += deltaX;
    return true;
  };
  util.table.scroller.scrollByClick = function(enTable, scrollbarX) {
    var container = util.table.query_(enTable, ".container");
    var offsetWidth = container.offsetWidth;
    if (offsetWidth >= container.scrollWidth) {
      return false;
    }
    var thumb = util.table.query_(enTable, ".scrollbar-thumb");
    var transform = thumb.style.transform || thumb.style.webkitTransform || "";
    var match = transform.match(/translateX\((\d+)(?:\.\d+)?px\)?/);
    var x = match.length === 2 ? parseInt(match[1], 10) : null;
    if (x === null || isNaN(x)) {
      return false;
    }
    container.scrollLeft += x > scrollbarX ? -offsetWidth : offsetWidth;
    return true;
  };
})();
goog.provide("uno.listeners.TableListener");
goog.require("goog.debug.Logger");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("goog.events.MouseWheelHandler");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.listeners.tablelistener.generic");
goog.require("uno.listeners.tablelistener.win");
goog.require("uno.util.dom");
goog.require("uno.util.menu");
goog.require("uno.util.table");
goog.require("uno.util.table.drag");
goog.require("uno.util.table.resizer");
goog.require("uno.util.table.scroller");
goog.require("uno.util.table.selection");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.TableListener");
  var util = uno.util;
  var Axis = util.table.Axis;
  var KeyCodes = goog.events.KeyCodes;
  var MouseWheelHandler = goog.events.MouseWheelHandler;
  var TableListener = uno.listeners.TableListener = function() {
    uno.BasePlugin.call(this, log.getName());
    this.selectable = true;
    this.scrollable = false;
    this.scrolling = false;
    this.resizing = false;
    this.dragging = false;
    this.leftMouseDown = false;
    this.leftMouseMoving = false;
    this.clicked = false;
    this.clickTimer = null;
    this.mouseWheelHandler = new MouseWheelHandler(document.body);
    goog.events.listen(this.mouseWheelHandler, MouseWheelHandler.EventType.MOUSEWHEEL, this.handleMouseWheel, true, this);
    this.lastRangeState = null;
    this.lastKeyState = null;
    this.lastMouseDownEnTable = null;
    this.lastMouseOverEnTable = null;
    this.lastMouseOverSelectionTd = null;
    this.lastMouseMoveTd = null;
    this.lastMouseMoveInsertion = null;
    this.lastMouseMoveYIndex = -1;
  };
  goog.inherits(TableListener, uno.BasePlugin);
  TableListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  TableListener.prototype.handleKeyDown = function(event) {
    if (this.editor.readOnly) {
      return false;
    }
    var range = this.editor.getRange();
    var keyCode = event.keyCode;
    var enTable = util.table.getActive();
    var cell = util.table.getActiveCell();
    var ignoreKeyCodes = [KeyCodes.BACKSPACE, KeyCodes.DELETE];
    var arrowKeyCodes = [KeyCodes.LEFT, KeyCodes.RIGHT, KeyCodes.UP, KeyCodes.DOWN];
    var targetNode = null;
    this.lastKeyState = null;
    if (!cell || (event.metaKey || event.ctrlKey || event.altKey) || ignoreKeyCodes.indexOf(keyCode) > -1) {
      return false;
    }
    if (util.table.selection.isActive(enTable)) {
      if (keyCode === KeyCodes.ESC && this.dragging) {
        util.table.drag.cancel();
        this.dragging = false;
        return preventStop(event);
      } else {
        if (keyCode === KeyCodes.ESC) {
          util.table.selection.clear();
          goog.dom.Range.createCaret(cell, 0).select();
          return preventStop(event);
        } else {
          if (event.shiftKey && arrowKeyCodes.indexOf(keyCode) > -1) {
            var focusTd = util.table.navigatedFocusSelectionCell(util.table.createKeyState(enTable, cell, event));
            if (focusTd) {
              util.table.selection.selectTo(focusTd);
            }
            return preventStop(event);
          }
        }
      }
      if (!KeyCodes.isTextModifyingKeyEvent(event)) {
        return preventStop(event);
      }
      util.table.selection.clear();
      cell.innerHTML = uno.defs.table.CELL_HTML;
      goog.dom.Range.createCaret(cell, 0).select();
      this.editor.dispatchChange();
    }
    if (keyCode === KeyCodes.TAB && !goog.dom.getAncestor(range.getAnchorNode(), util.dom.isLi, true) && !goog.dom.getAncestor(range.getFocusNode(), util.dom.isLi, true)) {
      targetNode = event.shiftKey ? util.table.prevCell(cell, true) : util.table.nextCell(cell, true);
      if (!targetNode && !event.shiftKey) {
        this.editor.execCommand("inserttablerow", "after");
        targetNode = util.table.nextCell(cell, true);
      }
      if (targetNode) {
        uno.util.range.selectNodeContents(targetNode);
        util.table.scrollCellIntoView(targetNode);
      }
      return preventStop(event);
    } else {
      if (arrowKeyCodes.indexOf(keyCode) > -1) {
        this.lastKeyState = util.table.createKeyState(enTable, cell, event);
      }
    }
    return false;
  };
  TableListener.prototype.handleDoubleClick = function(event) {
    if (this.editor.readOnly) {
      return;
    }
    var target = event.target;
    if (target.classList.contains("yline") && util.table.fitColumnContent(this.lastMouseOverEnTable, this.lastMouseMoveYIndex - 1)) {
      this.editor.dispatchChange();
    }
  };
  TableListener.prototype.handleClick = function(event) {
    var target = event.target;
    if (!target || this.editor.readOnly) {
      return false;
    }
    var enTable = util.table.getActive();
    var cell = util.table.getActiveCell();
    if (enTable && cell && target.classList.contains("en-cell-btn")) {
      util.menu.presentTableContextMenu(target, this.editor);
      return true;
    } else {
      if (target.classList.contains("insertion")) {
        var obj = util.table.insertionToObject(target);
        var fn = obj.axis === Axis.VERTICAL ? util.table.insertColumns : util.table.insertRows;
        var inserted = fn(this.lastMouseOverEnTable, obj.index);
        if (inserted) {
          if (util.table.selection.isActive(this.lastMouseOverEnTable)) {
            util.table.selection.create(this.lastMouseOverEnTable, this.editor.multirange);
          }
          this.editor.dispatchChange();
        }
        return true;
      } else {
        if (target.classList.contains("handle")) {
          var matrix = util.table.matrix(this.lastMouseOverEnTable);
          var obj = util.table.handleToObject(target);
          var focusTd = obj.axis === Axis.VERTICAL ? matrix[0][obj.index].info.node : matrix[obj.index][0].info.node;
          this.lastRangeState = null;
          var isActiveSelection = util.table.selection.isActive(this.lastMouseOverEnTable);
          if (isActiveSelection && (this.client.isToggleKey(event) || event.shiftKey)) {
            if (event.shiftKey) {
              util.table.selection.selectTo(focusTd, obj.axis);
            } else {
              util.table.selection.toggleAt(focusTd, obj.axis);
            }
            this.dispatchEvent(uno.Editor.EventType.STYLE_CHANGED);
          } else {
            util.table.selection.create(this.lastMouseOverEnTable, this.editor.multirange, focusTd, null, obj.axis);
          }
          return true;
        } else {
          if (target.classList.contains("en-table-btn")) {
            var matrix = util.table.matrix(this.lastMouseOverEnTable);
            var lastCol = goog.array.peek(matrix[0]);
            var anchorTd = matrix[0][0].info.node;
            var focusTd = (lastCol.origin || lastCol.info).node;
            this.lastRangeState = null;
            util.table.selection.create(this.lastMouseOverEnTable, this.editor.multirange, anchorTd, focusTd, Axis.VERTICAL);
            return true;
          } else {
            if (enTable && this.client.isToggleKey(event) && !util.table.selection.isActive(enTable)) {
              var focusTd = goog.dom.getAncestor(target, util.dom.isTd, true);
              this.lastRangeState = null;
              util.table.selection.create(enTable, this.editor.multirange, focusTd);
              return true;
            }
          }
        }
      }
    }
    return false;
  };
  TableListener.prototype.handleMouseDown = function(event) {
    var target = event.target;
    this.leftMouseDown = true;
    if (!this.lastMouseOverEnTable) {
      return false;
    }
    if (target.classList.contains("handle")) {
      util.table.drag.prepare(this.lastMouseOverEnTable, event);
      event.preventDefault();
      return true;
    }
    if (target.classList.contains("en-cell-btn") || target.classList.contains("en-table-btn") || target.classList.contains("insertion")) {
      event.preventDefault();
      return true;
    }
    if (target.classList.contains("yline")) {
      util.table.layout(this.lastMouseOverEnTable);
      util.table.resizer.start(this.lastMouseOverEnTable, target, event.clientX, this.lastMouseMoveYIndex - 1);
      this.resizing = true;
      return preventStop(event);
    }
    if (target.classList.contains("scrollbar-thumb")) {
      util.table.scroller.start(this.lastMouseOverEnTable, target, event.clientX);
      this.scrolling = true;
      return preventStop(event);
    }
    if (target.classList.contains("scrollbar")) {
      util.table.scroller.scrollByClick(this.lastMouseOverEnTable, event.clientX - target.getBoundingClientRect().left);
      return preventStop(event);
    }
    var td = goog.dom.getAncestor(target, util.dom.isTd, true);
    if (td) {
      this.clicked = true;
      clearTimeout(this.clickTimer);
      this.clickTimer = setTimeout(function() {
        this.clicked = false;
      }.bind(this), 10);
      this.lastMouseDownEnTable = this.lastMouseOverEnTable;
      this.lastMouseDownEnTable.classList.add("selecting");
      var isSelection = util.table.selection.isActive(this.lastMouseOverEnTable);
      var isSelectionChange = isSelection && (event.shiftKey || this.client.isToggleKey(event));
      var isActive = util.table.getActive() === this.lastMouseOverEnTable && util.table.getActiveCell() !== td;
      if (isSelectionChange || isActive && event.shiftKey) {
        if (isSelectionChange) {
          if (event.shiftKey) {
            util.table.selection.selectTo(td);
          } else {
            util.table.selection.toggleAt(td);
          }
          this.dispatchEvent(uno.Editor.EventType.STYLE_CHANGED);
        } else {
          this.lastRangeState = null;
          util.table.selection.create(this.lastMouseOverEnTable, this.editor.multirange, util.table.getActiveCell(), td);
        }
        return preventStop(event);
      }
    }
    return false;
  };
  TableListener.prototype.handleWindowResize = function() {
    goog.array.forEach(this.editor.field.querySelectorAll("en-table"), util.table.translateX);
  };
  TableListener.prototype.handleWindowMouseUp = function() {
    this.leftMouseDown = false;
    this.leftMouseMoving = false;
    if (this.lastMouseDownEnTable) {
      this.lastMouseDownEnTable.classList.remove("selecting");
      this.lastMouseDownEnTable = null;
    }
    if (this.dragging) {
      this.dragging = false;
      if (util.table.drag.end(this.editor.multirange)) {
        this.editor.dispatchChange();
      }
      return true;
    }
    if (this.resizing) {
      util.table.resizer.end();
      this.resizing = false;
      this.editor.dispatchChange();
      return true;
    }
    if (this.scrolling) {
      util.table.scroller.end();
      this.scrolling = false;
      return true;
    }
    util.table.drag.cancel();
    return false;
  };
  TableListener.prototype.handleWindowMouseMove = function(event) {
    if (this.scrolling) {
      util.table.scroller.scrollByDrag(event.clientX);
      return preventStop(event);
    }
    if (this.resizing) {
      util.table.resizer.resize(event.clientX);
      return preventStop(event);
    }
    if (this.dragging) {
      util.table.drag.move(this.lastMouseOverEnTable, event.clientX, event.clientY);
      return preventStop(event);
    }
    return false;
  };
  TableListener.prototype.handleMouseMove = function(event) {
    if (this.editor.readOnly) {
      return false;
    }
    var target = event.target;
    this.leftMouseMoving = this.leftMouseDown;
    if (this.leftMouseMoving || this.resizing || this.scrolling || this.dragging || target.classList.contains("yline")) {
      if (this.leftMouseMoving && util.table.drag.tryStart(this.lastMouseOverEnTable, event)) {
        this.dragging = true;
        return preventStop(event);
      } else {
        if (this.leftMouseMoving && !this.resizing && !this.scrolling && !this.dragging && util.table.selection.isActive(this.lastMouseOverEnTable)) {
          return preventStop(event);
        }
      }
      return false;
    }
    if (this.lastMouseOverEnTable && util.dom.isTd(target) && !this.lastMouseOverEnTable.classList.contains("selected")) {
      var next = event.offsetX > target.offsetWidth / 2;
      var yIndex = event.offsetX > 6 && event.offsetX < target.offsetWidth - 6 ? -1 : util.table.colIndex(target, next);
      if (yIndex === 0) {
        yIndex = -1;
      }
      if (this.lastMouseMoveTd === target && this.lastMouseMoveYIndex === yIndex) {
        return false;
      }
      this.lastMouseMoveTd = target;
      this.lastMouseMoveYIndex = yIndex;
      if (yIndex > -1) {
        util.table.setLine(this.lastMouseOverEnTable, yIndex, Axis.VERTICAL);
      } else {
        util.table.setLine(this.lastMouseOverEnTable);
      }
    } else {
      if (target.classList.contains("insertion")) {
        if (target === this.lastMouseMoveInsertion) {
          return false;
        }
        this.lastMouseMoveInsertion = target;
        var obj = util.table.insertionToObject(target);
        util.table.setLine(this.lastMouseOverEnTable, obj.index, obj.axis);
      } else {
        if (this.lastMouseMoveTd || this.lastMouseMoveInsertion) {
          this.lastMouseMoveTd = null;
          this.lastMouseMoveInsertion = null;
          this.lastMouseMoveYIndex = -1;
          if (this.lastMouseOverEnTable) {
            util.table.setLine(this.lastMouseOverEnTable);
          }
        }
      }
    }
    return false;
  };
  TableListener.prototype.handleMouseOver = function(event) {
    var target = event.target;
    var oldEnTable = this.lastMouseOverEnTable;
    var overTable = false;
    var enTable = goog.dom.getAncestor(target, function(node) {
      if (util.dom.isTable(node)) {
        overTable = true;
      }
      return util.dom.isEntable(node);
    }, true);
    this.scrollable = !!(overTable && enTable);
    this.lastMouseOverEnTable = enTable;
    if (enTable !== oldEnTable && oldEnTable) {
      util.table.setLine(oldEnTable);
    }
    if (enTable && (!this.leftMouseMoving && enTable.dataset.lazy || this.dragging && enTable.dataset.lazy)) {
      util.table.layout(enTable, true);
      return;
    }
    if (this.resizing || this.scrolling || this.dragging || this.editor.readOnly || !enTable) {
      return;
    }
    if (this.leftMouseMoving && util.table.drag.tryStart(enTable, event)) {
      this.dragging = true;
      return;
    }
    if (this.leftMouseMoving && overTable && util.table.selection.isActive(enTable)) {
      var td = goog.dom.getAncestor(target, util.dom.isTd, true);
      if (td && td !== this.lastMouseOverSelectionTd) {
        this.lastMouseOverSelectionTd = td;
        util.table.selection.selectTo(td);
        this.dispatchEvent(uno.Editor.EventType.STYLE_CHANGED);
      }
    }
  };
  TableListener.prototype.handleMouseWheel = function(event) {
    if (this.resizing || this.scrolling || !this.scrollable || this.lastMouseDownEnTable || !this.lastMouseOverEnTable || Math.abs(event.deltaX) <= Math.abs(event.deltaY)) {
      return;
    }
    if (util.table.scroller.scrollByWheel(this.lastMouseOverEnTable, this.client.getDeltaX(event))) {
      event.preventDefault();
    }
  };
  TableListener.prototype.handleScroll = function(event) {
    var target = event.target;
    if (target && util.dom.isEntable(target.parentNode)) {
      util.table.translateX(target.parentNode);
    }
  };
  TableListener.prototype.handleNativeSelectionChange = function() {
    var range = this.editor.getRange();
    if (!range || this.editor.readOnly) {
      return;
    }
    if (util.table.selection.isPending() || this.leftMouseMoving && util.table.selection.isActive(this.lastMouseOverEnTable)) {
      return;
    }
    if (!util.table.isProcessedRange(range, this.lastRangeState)) {
      var source = this.clicked ? "multiclick" : this.lastKeyState ? "arrowkey" : null;
      var lks = this.lastKeyState;
      var lrs = util.table.processRange(range, this.editor.field.querySelectorAll("en-table"), source);
      this.lastRangeState = lrs;
      if (lks && lrs.cell && lks.cell !== lrs.cell && !lks.shiftKey && util.table.navigateByKeyState(lks)) {
        this.lastKeyState = null;
        return;
      }
      util.table.setActive(lrs.enTable, lrs.cell);
      util.table.selection.clear();
      if (this.selectable && lrs.enTable && lrs.isSelection) {
        var anchorCell = lrs.cell;
        var focusCell = lrs.focusCell;
        if (lks && lks.shiftKey) {
          focusCell = util.table.navigatedFocusSelectionCell(lks);
        }
        util.table.selection.create(lrs.enTable, this.editor.multirange, anchorCell, focusCell);
      }
      this.lastKeyState = null;
    }
  };
  TableListener.prototype.handleContextMenu = function(event) {
    this.selectable = false;
    setTimeout(function() {
      this.handleWindowMouseUp();
      this.selectable = true;
    }.bind(this), 0);
  };
  TableListener.prototype.handleBeforeExecCommand = function(event) {
    if (event.command === "undo" || event.command === "redo") {
      util.table.selection.clear();
      this.lastRangeState = null;
      this.selectable = false;
    }
  };
  TableListener.prototype.handleAfterExecCommand = function(event) {
    if (event.command === "undo" || event.command === "redo") {
      setTimeout(function() {
        goog.array.forEach(document.querySelectorAll("cursor-proxy"), goog.dom.removeNode);
        this.selectable = true;
        var td = this.editor.field.querySelector("en-table td.selected");
        var enTable = goog.dom.getAncestor(td, util.dom.isEntable);
        if (enTable) {
          util.table.setActive(enTable, td);
          util.table.selection.create(enTable, this.editor.multirange);
        }
      }.bind(this), 0);
    }
  };
  function preventStop(event) {
    event.preventDefault();
    event.stopPropagation();
    return true;
  }
})();
goog.provide("uno.listeners.TodoListener");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.util.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.TodoListener");
  var util = uno.util;
  var TodoListener = uno.listeners.TodoListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TodoListener, uno.BasePlugin);
  TodoListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  TodoListener.prototype.handleClick = function(event) {
    if (util.todo.isTodo(event.target)) {
      if (this.editor.readOnly) {
        this.editor.dispatchEvent({type:uno.Editor.EventType.ACTION_DENIED, reason:{readOnly:true}});
        return false;
      }
      event.preventDefault();
      util.todo.toggle(event.target);
      this.editor.dispatchChange();
      return true;
    }
    return false;
  };
})();
goog.provide("uno.listeners.TodoListListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.paragraph");
goog.require("uno.util.range");
goog.require("uno.util.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.TodoListListener");
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  var TAB_KEY = goog.events.KeyCodes.TAB;
  var util = uno.util;
  var TodoListListener = uno.listeners.TodoListListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TodoListListener, uno.BasePlugin);
  TodoListListener.prototype.handleKeyPress = function(event) {
    var currentPar;
    var todo;
    if (event.keyCode === ENTER_KEY) {
      if (event.altKey) {
        this.editor.execCommand("inserttodo");
        event.preventDefault();
        event.stopPropagation();
        return true;
      }
      if ((currentPar = util.paragraph.for(this.editor.getRange().getStartNode())) == null) {
        return;
      }
      if ((todo = util.paragraph.getLeadingTodo(currentPar)) == null) {
        return;
      }
      if (util.range.atBeginningOfDiv(this.editor.getRange())) {
        return;
      }
      if (util.paragraph.hasVisibleContent(currentPar, {excluding:todo})) {
        this.editor.context.pendingTodo = !util.todo.tryToInsertTodo(this.editor);
      } else {
        util.todo.remove(todo);
        if (!util.paragraph.hasBr(currentPar)) {
          util.paragraph.appendBr(currentPar);
        }
        util.paragraph.placeCursorAtStart(currentPar);
      }
      if (!this.editor.context.pendingTodo) {
        event.preventDefault();
        event.stopPropagation();
      }
      return true;
    }
  };
  TodoListListener.prototype.handleKeyUp = function(event) {
    if ((event.keyCode === ENTER_KEY || event.keyCode === 0) && this.editor.context.pendingTodo) {
      this.editor.context.pendingTodo = false;
      this.editor.execCommand("inserttodo");
    }
  };
})();
goog.provide("uno.util.typebehind");
goog.require("goog.debug.Logger");
goog.require("goog.dom.classes");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.typebehind");
  var SPACE_KEY = goog.events.KeyCodes.SPACE;
  var TAB_KEY = goog.events.KeyCodes.TAB;
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  var util = uno.util;
  util.typebehind.tryReplacements = function(event, imps, checkBeginningOfLines, editor) {
    var keyCode = event.keyCode;
    var dom = goog.dom;
    var range = editor.getRange();
    if (!range || !range.isCollapsed()) {
      return false;
    }
    var startNode = range.getStartNode();
    var endNode = range.getEndNode();
    var node = endNode;
    var text = null;
    if (editor.config.typebehind.code) {
      if (goog.dom.classes.has(startNode, "en-code") || goog.dom.classes.has(dom.getParentElement(startNode), ".en-code")) {
        return false;
      }
    }
    var insideAnchor = goog.dom.getAncestor(startNode, function(element) {
      return util.dom.isA(element);
    }, true);
    if (insideAnchor) {
      return false;
    }
    text = node.textContent.substring(0, range.getEndOffset());
    var isBeginningOfLine = checkBeginningOfLines && !util.dom.isPrecededByInlineContent(node);
    if (text != null) {
      for (var i = 0; i < imps.length; i++) {
        var imp = imps[i];
        if (!imp.contextReplaceable(range, keyCode)) {
          continue;
        }
        if (imp.matchBeginningOfLine && !isBeginningOfLine) {
          continue;
        }
        var rxs = imp.getRegexes();
        var response = util.typebehind.isReplacementPossible(text, rxs);
        if (response.possible) {
          var result = util.typebehind.runReplacements(imp, range, response.rx, text, editor);
          if (result.node != null) {
            node = result.node;
            if (keyCode === SPACE_KEY || keyCode === ENTER_KEY || result.trimWhitespace) {
              goog.editor.range.placeCursorNextTo(node, false);
            } else {
              if (keyCode === TAB_KEY && !result.trimWhitespace) {
                var tab = dom.createDom(goog.dom.TagName.SPAN, null, "\u00a0\u00a0 \u00a0");
                goog.dom.insertSiblingBefore(tab, node.nextSibling);
                goog.editor.range.placeCursorNextTo(tab, false);
                event.preventDefault();
              }
            }
          }
          if (result.trimWhitespace) {
            event.preventDefault();
          }
          editor.field.normalize();
          return true;
        }
      }
    }
    return false;
  };
  util.typebehind.isReplacementPossible = function(text, rxs) {
    if (text == null || !goog.isString(text) || rxs == null) {
      return {possible:false, rx:null};
    }
    for (var i = 0; i < rxs.length; i++) {
      if (util.typebehind.matchRegex(text, rxs[i])) {
        return {possible:true, rx:rxs[i]};
      }
    }
    return {possible:false, rx:null};
  };
  util.typebehind.matchRegex = function(text, rx) {
    if (text == null || rx == null) {
      return null;
    }
    var preRx = "(?:\\s+|\u00a0+|^)(";
    var postRx = ")(?:[\u00a0\\t ]*$)";
    var pattern = preRx + rx.source + postRx;
    var rxAtEnd = new RegExp(pattern, "gi");
    var matches = text.match(rxAtEnd);
    if (matches && matches.length > 1) {
      log.warning("Should not be multiple matches here!");
    }
    if (matches == null || matches.length <= 0) {
      return null;
    }
    var matchString = matches[0].trim();
    var index = text.lastIndexOf(matchString);
    return {matchString:matchString, index:index};
  };
  util.typebehind.runReplacements = function(imp, range, rx, text, editor) {
    editor.plugins_.UndoRedo.updateCurrentState_(editor);
    var textNode = range.getEndNode();
    goog.asserts.assert(textNode && textNode.nodeType === Node.TEXT_NODE, "typebehind: node must be text");
    goog.asserts.assert(rx != null, "must be given a regex to work");
    var match = util.typebehind.matchRegex(text, rx);
    var matchText = match.matchString;
    var matchIndex = match.index;
    var newRange = goog.dom.Range.createFromNodes(textNode, matchIndex, textNode, matchIndex + matchText.length);
    return imp.insertReplacement(newRange, rx, matchText, editor);
  };
})();
goog.provide("uno.util.typebehind.code");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.util.table");
goog.require("uno.util.list");
goog.require("uno.util.crypto");
(function() {
  var code = uno.util.typebehind.code;
  var util = uno.util;
  code.matchBeginningOfLine = false;
  code.rxs = [new RegExp(uno.defs.regex.CODEBLOCK, "gi")];
  code.contextReplaceable = function(range) {
    if (util.table.for(range.getContainer()) || util.list.for(range.getContainer()) || util.crypto.for(range.getContainer())) {
      return false;
    }
    return true;
  };
  code.getRegexes = function() {
    code.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return code.rxs;
  };
  code.insertReplacement = function(range, rx, matchedText, editor) {
    for (var i = 0; i < matchedText.length; i++) {
      document.execCommand("delete");
    }
    editor.execCommand("codeblock");
    return {node:null, trimWhitespace:true};
  };
})();
goog.provide("uno.util.typebehind.email");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
(function() {
  var email = uno.util.typebehind.email;
  var log = goog.debug.Logger.getLogger("uno.util.typebehind.email");
  email.name = "email";
  email.matchBeginningOfLine = false;
  email.rxs = [new RegExp(uno.defs.regex.SIMPLE_EMAIL, "gi")];
  email.contextReplaceable = function(range, keyCode) {
    return true;
  };
  email.getRegexes = function() {
    email.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return email.rxs;
  };
  email.insertReplacement = function(range, rx, matchedText) {
    var newNode = goog.dom.createDom("a");
    if (goog.isString(matchedText)) {
      newNode.setAttribute("href", "mailto:" + matchedText);
      newNode.textContent = matchedText;
    }
    range.replaceContentsWithNode(newNode);
    return {node:newNode, trimWhitespace:false};
  };
})();
goog.provide("uno.util.emoticon");
goog.require("goog.debug.Logger");
goog.require("uno.defs");
(function() {
  var util = uno.util;
  var onceList = {"smiling face with open mouth":{"icon":"\ud83d\ude03", "keystrokes":[":)", ":=)", ":-)"], "color":"yellow"}, "pensive":{"icon":"\ud83d\ude14", "keystrokes":[":(", ":=(", ":-("]}, "grinning face":{"icon":"\ud83d\ude00", "keystrokes":[":D", ":=D", ":-D"]}, "smiling face with sunglasses":{"icon":"\ud83d\ude0e", "keystrokes":["8=)", "8-)", "B=)", "B-)"]}, "winking face":{"icon":"\ud83d\ude09", "keystrokes":[";)", ";=)", ";-)"]}, "face with open mouth":{"icon":"\ud83d\ude2e", "keystrokes":[":o", 
  ":=o", ":-o", ":O", ":=O", ":-O"]}, "crying face":{"icon":"\ud83d\ude22", "keystrokes":[";(", ";=(", ";-("]}, "smiling face with open mouth and cold sweat":{"icon":"\ud83d\ude05", "keystrokes":["(:|", ":sweat:"]}, "neutral face":{"icon":"\ud83d\ude10", "keystrokes":[":|", ":=|", ":-|", ":neutral:"]}, "kissing face with closed eyes":{"icon":"\ud83d\ude1a", "keystrokes":[":*", ":=*", ":-*", ":kiss:"]}, "face with stuck-out tongue":{"icon":"\ud83d\ude1b", "keystrokes":[":P", ":=P", ":-P", ":p", ":=p", 
  ":-p"]}, "smiling face with smiling eyes":{"icon":"\ud83d\ude0a", "keystrokes":[":$", ":-$", ":=$", ":simple_smile:"]}, "angry face":{"icon":"\ud83d\ude21", "keystrokes":[":@", ":-@", ":=@", "x(", "x-(", "x=(", "X(", "(X=(", ":angry:"]}, "smiling face with halo":{"icon":"\ud83d\ude07", "keystrokes":["O:)", "O:=)", "O:-)", "o:)", "o:=)", "o:-)", ":innocent:", ":angel:"]}, "heavy black heart":{"icon":"\u2665", "keystrokes":["<3", ":heart:"]}, "sleepy face":{"icon":"\ud83d\ude2a", "keystrokes":["|-)", 
  "I-)", "I=)", ":snooze:"]}, "smiling face with heart-shaped eyes":{"icon":"\ud83d\ude0d", "keystrokes":[":inlove:", ":in_love:"]}, "smiling face with horns":{"icon":"\ud83d\ude08", "keystrokes":[":devil:"]}, "ghost":{"icon":"\ud83d\udc7b", "keystrokes":[":ghost:"]}, "extraterrestrial alien":{"icon":"\ud83d\udc7d", "keystrokes":[":alien:"]}, "skull":{"icon":"\ud83d\udc80", "keystrokes":[":skull:"]}, "face screaming in fear":{"icon":"\ud83d\ude31", "keystrokes":[":scream:"]}, "slice of pizza":{"icon":"\ud83c\udf55", 
  "keystrokes":[":pizza:"]}, "purple heart":{"icon":"\ud83d\udc9c", "keystrokes":[":purple_heart:", ":purpleheart:"]}, "green heart":{"icon":"\ud83d\udc9a", "keystrokes":[":green_heart:", ":greenheart:"]}, "blue heart":{"icon":"\ud83d\udc99", "keystrokes":[":blue_heart:", ":blueheart:"]}, "yellow heart":{"icon":"\ud83d\udc9b", "keystrokes":[":yellow_heart:", ":yellowheart:"]}, "droplet":{"icon":"\ud83d\udca7", "keystrokes":[":droplet:"]}};
  util.emoticon.list = {":(=|-)?\\)":onceList["smiling face with open mouth"], ":(=|-)?\\(":onceList["pensive"], ":(=|-)?D":onceList["grinning face"], "(8|B)(=|-)\\)":onceList["smiling face with sunglasses"], ";(=|-)?\\)":onceList["winking face"], ":(=|-)?(o|O)":onceList["face with open mouth"], ";(=|-)?\\(":onceList["crying face"], "\\(:\\|":onceList["smiling face with open mouth and cold sweat"], ":sweat:":onceList["smiling face with open mouth and cold sweat"], ":(=|-)?\\|":onceList["neutral face"], 
  ":neutral:":onceList["neutral face"], ":(=|-)?\\*":onceList["kissing face with closed eyes"], ":kiss:":onceList["kissing face with closed eyes"], ":(=|-)?(P|p)":onceList["face with stuck-out tongue"], ":(-|=)?\\$":onceList["smiling face with smiling eyes"], ":simple_smile:":onceList["smiling face with smiling eyes"], "\\(?(:|x|X)(=|-)?(@|\\()":onceList["angry face"], ":angry:":onceList["angry face"], "(O|o):(=|-)?\\)":onceList["smiling face with halo"], ":innocent:":onceList["smiling face with halo"], 
  ":angel:":onceList["smiling face with halo"], "<3":onceList["heavy black heart"], ":heart:":onceList["heavy black heart"], "(\\||I)(-|=)\\)":onceList["sleepy face"], ":snooze:":onceList["sleepy face"], ":in_?love:":onceList["smiling face with heart-shaped eyes"], ":devil:":onceList["smiling face with horns"], ":ghost:":onceList["ghost"], ":alien:":onceList["extraterrestrial alien"], ":skull:":onceList["skull"], ":scream:":onceList["face screaming in fear"], ":pizza:":onceList["slice of pizza"], 
  ":purple_?heart:":onceList["purple heart"], ":green_?heart:":onceList["green heart"], ":blue_?heart:":onceList["blue heart"], ":yellow_?heart:":onceList["yellow heart"], ":droplet:":onceList["droplet"]};
  util.emoticon.fromInfo = function(info) {
    if (!info) {
      return null;
    }
    return goog.dom.createTextNode(info.icon);
  };
  util.emoticon.fromPattern = function(pattern) {
    var info = util.emoticon.list[pattern];
    return util.emoticon.fromInfo(info);
  };
})();
goog.provide("uno.util.typebehind.emoticon");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.util.emoticon");
goog.require("uno.util.crypto");
(function() {
  var util = uno.util;
  var emoticon = uno.util.typebehind.emoticon;
  var log = goog.debug.Logger.getLogger("uno.util.typebehind.emoticon");
  emoticon.name = "emoticon";
  emoticon.matchBeginningOfLine = false;
  emoticon.rxs = Object.keys(util.emoticon.list).map(function(key) {
    return new RegExp(key, "g");
  });
  emoticon.contextReplaceable = function(range, keyCode) {
    if (util.crypto.for(range.getContainer())) {
      return false;
    }
    return true;
  };
  emoticon.getRegexes = function() {
    emoticon.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return emoticon.rxs;
  };
  emoticon.insertReplacement = function(range, rx, matchedText) {
    var newNode = util.emoticon.fromPattern(rx.source);
    range.replaceContentsWithNode(newNode);
    return {node:newNode, trimWhitespace:false};
  };
})();
goog.provide("uno.util.typebehind.hr");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.util.table");
(function() {
  var hr = uno.util.typebehind.hr;
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.util.typebehind.hr");
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  hr.name = "hr";
  hr.matchBeginningOfLine = true;
  hr.rxs = [new RegExp(uno.defs.regex.HORIZONTAL_RULE, "gi")];
  hr.contextReplaceable = function(range, keyCode) {
    if (keyCode !== ENTER_KEY || util.crypto.for(range.getContainer()) || util.table.for(range.getContainer())) {
      return false;
    }
    return true;
  };
  hr.getRegexes = function() {
    hr.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return hr.rxs;
  };
  hr.insertReplacement = function(range, rx, matchedText) {
    var newNode = goog.dom.createDom("hr");
    range.replaceContentsWithNode(newNode);
    return {node:newNode, trimWhitespace:false};
  };
})();
goog.provide("uno.util.typebehind.list");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.util.paragraph");
goog.require("uno.util.crypto");
(function() {
  var list = uno.util.typebehind.list;
  var BULLETED_LIST = uno.defs.regex.BULLETED_LIST;
  var NUMBERED_LIST = uno.defs.regex.NUMBERED_LIST;
  var util = uno.util;
  list.name = "list";
  list.matchBeginningOfLine = true;
  list.rxs = [new RegExp(BULLETED_LIST, "gi"), new RegExp(NUMBERED_LIST, "gi")];
  list.contextReplaceable = function(range) {
    if (goog.dom.getAncestorByTagNameAndClass(range.getContainer(), "li") || util.crypto.for(range.getContainer())) {
      return false;
    }
    return true;
  };
  list.getRegexes = function() {
    list.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return list.rxs;
  };
  list.insertReplacement = function(range, rx, matchedText, editor) {
    var p = util.paragraph.for(range.getStartNode());
    if (!util.paragraph.hasBr(p)) {
      util.paragraph.appendBr(p);
    }
    var zwsOffset = 0;
    if (range.getStartNode().textContent.indexOf(uno.defs.unicode.ZERO_WIDTH_SPACE) > -1) {
      zwsOffset = 1;
    }
    range.getStartNode().replaceData(range.getStartOffset() + zwsOffset, matchedText.length - zwsOffset, "");
    if (rx.source === BULLETED_LIST) {
      editor.execCommand("insertunorderedlist");
    } else {
      if (rx.source === NUMBERED_LIST) {
        editor.execCommand("insertorderedlist");
        var startNumber = parseInt(matchedText, 10);
        var node = ed.getRange().getStartNode();
        var ol = goog.dom.getAncestor(node, function(element) {
          return util.dom.isOl(element);
        }, true);
        if (ol) {
          ol.setAttribute("start", startNumber);
        }
      }
    }
    return {node:null, trimWhitespace:true};
  };
})();
goog.provide("uno.util.typebehind.table");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.util.crypto");
(function() {
  var table = uno.util.typebehind.table;
  var util = uno.util;
  table.name = "table";
  table.matchBeginningOfLine = true;
  table.rxs = [new RegExp(uno.defs.regex.TABLE, "gi")];
  table.contextReplaceable = function(range) {
    var container = range.getContainer();
    if (goog.dom.getAncestorByTagNameAndClass(container, "table") || goog.dom.getAncestorByTagNameAndClass(container, "li") || util.crypto.for(range.getContainer())) {
      return false;
    }
    return true;
  };
  table.getRegexes = function() {
    table.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return table.rxs;
  };
  table.insertReplacement = function(range, rx, matchedText, editor) {
    goog.dom.Range.createFromNodes(range.getStartNode(), 0, range.getStartNode(), matchedText.length).select();
    var cols = matchedText.split("][").length;
    var rowMatch = matchedText.match(/[0-9]+$/);
    var rows = 1;
    if (rowMatch) {
      rows = parseInt(rowMatch[0], 10);
    }
    editor.execCommand("inserttable", {columns:cols, rows:rows});
    return {node:null, trimWhitespace:true};
  };
})();
goog.provide("uno.util.typebehind.todo");
goog.require("goog.asserts");
goog.require("goog.dom");
goog.require("goog.dom.classes");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.util.dom");
goog.require("uno.util.todo");
goog.require("uno.util.crypto");
(function() {
  var todo = uno.util.typebehind.todo;
  var util = uno.util;
  todo.name = "todo";
  todo.matchBeginningOfLine = false;
  todo.rxs = [new RegExp(uno.defs.regex.TODO, "gi")];
  todo.contextReplaceable = function(range) {
    if (util.crypto.for(range.getContainer())) {
      return false;
    }
    return true;
  };
  todo.getRegexes = function() {
    todo.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return todo.rxs;
  };
  todo.insertReplacement = function(range, rx, matchedText) {
    var checked = matchedText.toLowerCase().indexOf("x") > 0;
    var newTodo = util.todo.create(checked);
    range.removeContents();
    var rangeParent = range.getStartNode().parentElement;
    if (util.dom.isEmpty(rangeParent)) {
      range.insertNode(document.createElement("br"));
    }
    range.insertNode(newTodo);
    return {node:newTodo, trimWhitespace:true};
  };
})();
goog.provide("uno.util.typebehind.url");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("uno.defs");
(function() {
  var url = uno.util.typebehind.url;
  url.name = "url";
  url.matchBeginningOfLine = false;
  url.rxs = [new RegExp(uno.defs.regex.SIMPLE_URL, "gi")];
  url.contextReplaceable = function() {
    return true;
  };
  url.getRegexes = function() {
    url.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return url.rxs;
  };
  url.insertReplacement = function(range, rx, matchedText) {
    var newNode;
    var href = /^[a-zA-Z]+:\/\//.test(matchedText) ? matchedText : "http://" + matchedText;
    newNode = goog.dom.createDom("a", {href:href});
    newNode.textContent = matchedText;
    range.replaceContentsWithNode(newNode);
    return {node:newNode, trimWhitespace:false};
  };
})();
goog.provide("uno.listeners.TypeBehindListener");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.typebehind");
goog.require("uno.util.typebehind.code");
goog.require("uno.util.typebehind.email");
goog.require("uno.util.typebehind.emoticon");
goog.require("uno.util.typebehind.hr");
goog.require("uno.util.typebehind.list");
goog.require("uno.util.typebehind.table");
goog.require("uno.util.typebehind.todo");
goog.require("uno.util.typebehind.url");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.TypeBehindListener");
  var SPACE_KEY = goog.events.KeyCodes.SPACE;
  var TAB_KEY = goog.events.KeyCodes.TAB;
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  var util = uno.util;
  var TypeBehindListener = uno.listeners.TypeBehindListener = function() {
    uno.BasePlugin.call(this, log.getName());
    this.imps = [];
    this.checkBeginningOfLines = false;
  };
  goog.inherits(TypeBehindListener, uno.BasePlugin);
  TypeBehindListener.IMPLEMENTATIONS = {code:uno.util.typebehind.code, email:uno.util.typebehind.email, emoticon:uno.util.typebehind.emoticon, horizontalrule:uno.util.typebehind.hr, list:uno.util.typebehind.list, table:uno.util.typebehind.table, todo:uno.util.typebehind.todo, url:uno.util.typebehind.url};
  TypeBehindListener.prototype.registerFieldObject = function(fieldObject) {
    var me = this;
    uno.BasePlugin.prototype.registerFieldObject.call(this, fieldObject);
    Object.keys(TypeBehindListener.IMPLEMENTATIONS).forEach(function(name) {
      var imp;
      if (fieldObject.config.typebehind[name]) {
        imp = TypeBehindListener.IMPLEMENTATIONS[name];
        me.imps.push(imp);
        if (imp.matchBeginningOfLine) {
          me.checkBeginningOfLines = true;
        }
      }
    });
  };
  var canTypebehind = true;
  TypeBehindListener.prototype.handleAfterExecCommand = function(event) {
    canTypebehind = !(event.command === "undo");
  };
  TypeBehindListener.prototype.handleKeyDown = function(event) {
    var replaced = false;
    var keyCode = event.keyCode;
    var range = this.editor.getRange();
    if (range && range.isCollapsed() && canTypebehind && (keyCode === SPACE_KEY || keyCode === TAB_KEY || keyCode === ENTER_KEY)) {
      replaced = util.typebehind.tryReplacements(event, this.imps, this.checkBeginningOfLines, this.editor);
    }
    if (replaced) {
      this.editor.dispatchChange();
    }
    canTypebehind = true;
    return replaced;
  };
})();
goog.setTestOnly("goog.testing.stacktrace");
goog.provide("goog.testing.stacktrace");
goog.provide("goog.testing.stacktrace.Frame");
goog.testing.stacktrace.Frame = function(context, name, alias, path) {
  this.context_ = context;
  this.name_ = name;
  this.alias_ = alias;
  this.path_ = path;
};
goog.testing.stacktrace.Frame.prototype.getName = function() {
  return this.name_;
};
goog.testing.stacktrace.Frame.prototype.isAnonymous = function() {
  return !this.name_ || this.context_ == "[object Object]";
};
goog.testing.stacktrace.Frame.prototype.toCanonicalString = function() {
  var htmlEscape = goog.testing.stacktrace.htmlEscape_;
  var deobfuscate = goog.testing.stacktrace.maybeDeobfuscateFunctionName_;
  var canonical = [this.context_ ? htmlEscape(this.context_) + "." : "", this.name_ ? htmlEscape(deobfuscate(this.name_)) : "anonymous", this.alias_ ? " [as " + htmlEscape(deobfuscate(this.alias_)) + "]" : ""];
  if (this.path_) {
    canonical.push(" at ");
    canonical.push(htmlEscape(this.path_));
  }
  return canonical.join("");
};
goog.testing.stacktrace.MAX_DEPTH_ = 20;
goog.testing.stacktrace.MAX_FIREFOX_FRAMESTRING_LENGTH_ = 500000;
goog.testing.stacktrace.IDENTIFIER_PATTERN_ = "[a-zA-Z_$][\\w$]*";
goog.testing.stacktrace.V8_ALIAS_PATTERN_ = "(?: \\[as (" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ")\\])?";
goog.testing.stacktrace.V8_CONTEXT_PATTERN_ = "(?:((?:new )?(?:\\[object Object\\]|" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + "(?:\\." + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ")*))\\.)?";
goog.testing.stacktrace.V8_FUNCTION_NAME_PATTERN_ = "(?:new )?(?:" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + "|<anonymous>)";
goog.testing.stacktrace.V8_FUNCTION_CALL_PATTERN_ = " " + goog.testing.stacktrace.V8_CONTEXT_PATTERN_ + "(" + goog.testing.stacktrace.V8_FUNCTION_NAME_PATTERN_ + ")" + goog.testing.stacktrace.V8_ALIAS_PATTERN_;
goog.testing.stacktrace.URL_PATTERN_ = "((?:http|https|file)://[^\\s)]+|javascript:.*)";
goog.testing.stacktrace.CHROME_URL_PATTERN_ = " (?:" + "\\(unknown source\\)" + "|" + "\\(native\\)" + "|" + "\\((.+)\\)|(.+))";
goog.testing.stacktrace.V8_STACK_FRAME_REGEXP_ = new RegExp("^    at" + "(?:" + goog.testing.stacktrace.V8_FUNCTION_CALL_PATTERN_ + ")?" + goog.testing.stacktrace.CHROME_URL_PATTERN_ + "$");
goog.testing.stacktrace.FIREFOX_FUNCTION_CALL_PATTERN_ = "(" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + "(?:\\." + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ")*" + ")?" + "(\\(.*\\))?@";
goog.testing.stacktrace.FIREFOX_STACK_FRAME_REGEXP_ = new RegExp("^" + goog.testing.stacktrace.FIREFOX_FUNCTION_CALL_PATTERN_ + "(?::0|" + goog.testing.stacktrace.URL_PATTERN_ + ")$");
goog.testing.stacktrace.OPERA_ANONYMOUS_FUNCTION_NAME_PATTERN_ = "<anonymous function(?:\\: " + "(?:(" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + "(?:\\." + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ")*)\\.)?" + "(" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + "))?>";
goog.testing.stacktrace.OPERA_FUNCTION_CALL_PATTERN_ = "(?:(?:(" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ")|" + goog.testing.stacktrace.OPERA_ANONYMOUS_FUNCTION_NAME_PATTERN_ + ")(\\(.*\\)))?@";
goog.testing.stacktrace.OPERA_STACK_FRAME_REGEXP_ = new RegExp("^" + goog.testing.stacktrace.OPERA_FUNCTION_CALL_PATTERN_ + goog.testing.stacktrace.URL_PATTERN_ + "?$");
goog.testing.stacktrace.FUNCTION_SOURCE_REGEXP_ = new RegExp("^function (" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ")");
goog.testing.stacktrace.IE_FUNCTION_CALL_PATTERN_ = "(" + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + "(?:\\." + goog.testing.stacktrace.IDENTIFIER_PATTERN_ + ")*" + "(?:\\s+\\w+)*)";
goog.testing.stacktrace.IE_STACK_FRAME_REGEXP_ = new RegExp("^   at " + goog.testing.stacktrace.IE_FUNCTION_CALL_PATTERN_ + "\\s*\\(" + "(" + "eval code:[^)]*" + "|" + "Unknown script code:[^)]*" + "|" + goog.testing.stacktrace.URL_PATTERN_ + ")\\)?$");
goog.testing.stacktrace.followCallChain_ = function() {
  var frames = [];
  var fn = arguments.callee.caller;
  var depth = 0;
  while (fn && depth < goog.testing.stacktrace.MAX_DEPTH_) {
    var fnString = Function.prototype.toString.call(fn);
    var match = fnString.match(goog.testing.stacktrace.FUNCTION_SOURCE_REGEXP_);
    var functionName = match ? match[1] : "";
    frames.push(new goog.testing.stacktrace.Frame("", functionName, "", ""));
    try {
      fn = fn.caller;
    } catch (e) {
      break;
    }
    depth++;
  }
  return frames;
};
goog.testing.stacktrace.parseStackFrame_ = function(frameStr) {
  var m = frameStr.match(goog.testing.stacktrace.V8_STACK_FRAME_REGEXP_);
  if (m) {
    return new goog.testing.stacktrace.Frame(m[1] || "", m[2] || "", m[3] || "", m[4] || m[5] || m[6] || "");
  }
  if (frameStr.length > goog.testing.stacktrace.MAX_FIREFOX_FRAMESTRING_LENGTH_) {
    return null;
  }
  m = frameStr.match(goog.testing.stacktrace.FIREFOX_STACK_FRAME_REGEXP_);
  if (m) {
    return new goog.testing.stacktrace.Frame("", m[1] || "", "", m[3] || "");
  }
  m = frameStr.match(goog.testing.stacktrace.OPERA_STACK_FRAME_REGEXP_);
  if (m) {
    return new goog.testing.stacktrace.Frame(m[2] || "", m[1] || m[3] || "", "", m[5] || "");
  }
  m = frameStr.match(goog.testing.stacktrace.IE_STACK_FRAME_REGEXP_);
  if (m) {
    return new goog.testing.stacktrace.Frame("", m[1] || "", "", m[2] || "");
  }
  return null;
};
goog.testing.stacktrace.deobfuscateFunctionName_;
goog.testing.stacktrace.setDeobfuscateFunctionName = function(fn) {
  goog.testing.stacktrace.deobfuscateFunctionName_ = fn;
};
goog.testing.stacktrace.maybeDeobfuscateFunctionName_ = function(name) {
  return goog.testing.stacktrace.deobfuscateFunctionName_ ? goog.testing.stacktrace.deobfuscateFunctionName_(name) : name;
};
goog.testing.stacktrace.htmlEscape_ = function(text) {
  return text.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
};
goog.testing.stacktrace.framesToString_ = function(frames) {
  var lastIndex = frames.length - 1;
  while (frames[lastIndex] && frames[lastIndex].isAnonymous()) {
    lastIndex--;
  }
  var privateAssertIndex = -1;
  for (var i = 0; i < frames.length; i++) {
    if (frames[i] && frames[i].getName() == "_assert") {
      privateAssertIndex = i;
      break;
    }
  }
  var canonical = [];
  for (var i = privateAssertIndex + 1; i <= lastIndex; i++) {
    canonical.push("> ");
    if (frames[i]) {
      canonical.push(frames[i].toCanonicalString());
    } else {
      canonical.push("(unknown)");
    }
    canonical.push("\n");
  }
  return canonical.join("");
};
goog.testing.stacktrace.parse_ = function(stack) {
  var lines = stack.replace(/\s*$/, "").split("\n");
  var frames = [];
  for (var i = 0; i < lines.length; i++) {
    frames.push(goog.testing.stacktrace.parseStackFrame_(lines[i]));
  }
  return frames;
};
goog.testing.stacktrace.canonicalize = function(stack) {
  var frames = goog.testing.stacktrace.parse_(stack);
  return goog.testing.stacktrace.framesToString_(frames);
};
goog.testing.stacktrace.getNativeStack_ = function() {
  var tmpError = new Error;
  if (tmpError.stack) {
    return tmpError.stack;
  }
  try {
    null.x();
  } catch (e) {
    return e.stack;
  }
  return "";
};
goog.testing.stacktrace.get = function() {
  var stack = goog.testing.stacktrace.getNativeStack_();
  var frames;
  if (!stack) {
    frames = goog.testing.stacktrace.followCallChain_();
  } else {
    if (goog.isArray(stack)) {
      frames = goog.testing.stacktrace.callSitesToFrames_(stack);
    } else {
      frames = goog.testing.stacktrace.parse_(stack);
    }
  }
  return goog.testing.stacktrace.framesToString_(frames);
};
goog.testing.stacktrace.callSitesToFrames_ = function(stack) {
  var frames = [];
  for (var i = 0; i < stack.length; i++) {
    var callSite = stack[i];
    var functionName = callSite.getFunctionName() || "unknown";
    var fileName = callSite.getFileName();
    var path = fileName ? fileName + ":" + callSite.getLineNumber() + ":" + callSite.getColumnNumber() : "unknown";
    frames.push(new goog.testing.stacktrace.Frame("", functionName, "", path));
  }
  return frames;
};
goog.exportSymbol("setDeobfuscateFunctionName", goog.testing.stacktrace.setDeobfuscateFunctionName);
goog.provide("goog.testing.JsUnitException");
goog.setTestOnly();
goog.require("goog.testing.stacktrace");
goog.testing.JsUnitException = function(comment, opt_message) {
  this.isJsUnitException = true;
  this.message = (comment ? comment : "") + (comment && opt_message ? "\n" : "") + (opt_message ? opt_message : "");
  this.stackTrace = goog.testing.stacktrace.get();
  this.comment = comment || null;
  this.jsUnitMessage = opt_message || "";
  if (Error.captureStackTrace) {
    Error.captureStackTrace(this, goog.testing.JsUnitException);
  } else {
    this.stack = (new Error).stack || "";
  }
};
goog.inherits(goog.testing.JsUnitException, Error);
goog.testing.JsUnitException.prototype.toString = function() {
  return this.message;
};
goog.provide("goog.testing.asserts");
goog.setTestOnly();
goog.require("goog.testing.JsUnitException");
var DOUBLE_EQUALITY_PREDICATE = function(var1, var2) {
  return var1 == var2;
};
var JSUNIT_UNDEFINED_VALUE = void 0;
var TO_STRING_EQUALITY_PREDICATE = function(var1, var2) {
  return var1.toString() === var2.toString();
};
var PredicateFunctionType;
var PRIMITIVE_EQUALITY_PREDICATES = {"String":DOUBLE_EQUALITY_PREDICATE, "Number":DOUBLE_EQUALITY_PREDICATE, "Boolean":DOUBLE_EQUALITY_PREDICATE, "Date":function(date1, date2) {
  return date1.getTime() == date2.getTime();
}, "RegExp":TO_STRING_EQUALITY_PREDICATE, "Function":TO_STRING_EQUALITY_PREDICATE};
goog.testing.asserts.numberRoughEqualityPredicate_ = function(var1, var2, tolerance) {
  return Math.abs(var1 - var2) <= tolerance;
};
goog.testing.asserts.primitiveRoughEqualityPredicates_ = {"Number":goog.testing.asserts.numberRoughEqualityPredicate_};
var _trueTypeOf = function(something) {
  var result = typeof something;
  try {
    switch(result) {
      case "string":
        break;
      case "boolean":
        break;
      case "number":
        break;
      case "object":
        if (something == null) {
          result = "null";
          break;
        }
      case "function":
        switch(something.constructor) {
          case (new String("")).constructor:
            result = "String";
            break;
          case (new Boolean(true)).constructor:
            result = "Boolean";
            break;
          case (new Number(0)).constructor:
            result = "Number";
            break;
          case (new Array).constructor:
            result = "Array";
            break;
          case (new RegExp).constructor:
            result = "RegExp";
            break;
          case (new Date).constructor:
            result = "Date";
            break;
          case Function:
            result = "Function";
            break;
          default:
            var m = something.constructor.toString().match(/function\s*([^( ]+)\(/);
            if (m) {
              result = m[1];
            } else {
              break;
            }
        }break;
    }
  } catch (e) {
  } finally {
    result = result.substr(0, 1).toUpperCase() + result.substr(1);
  }
  return result;
};
var _displayStringForValue = function(aVar) {
  var result;
  try {
    result = "<" + String(aVar) + ">";
  } catch (ex) {
    result = "<toString failed: " + ex.message + ">";
  }
  if (!(aVar === null || aVar === JSUNIT_UNDEFINED_VALUE)) {
    result += " (" + _trueTypeOf(aVar) + ")";
  }
  return result;
};
var fail = function(failureMessage) {
  goog.testing.asserts.raiseException("Call to fail()", failureMessage);
};
var argumentsIncludeComments = function(expectedNumberOfNonCommentArgs, args) {
  return args.length == expectedNumberOfNonCommentArgs + 1;
};
var commentArg = function(expectedNumberOfNonCommentArgs, args) {
  if (argumentsIncludeComments(expectedNumberOfNonCommentArgs, args)) {
    return args[0];
  }
  return null;
};
var nonCommentArg = function(desiredNonCommentArgIndex, expectedNumberOfNonCommentArgs, args) {
  return argumentsIncludeComments(expectedNumberOfNonCommentArgs, args) ? args[desiredNonCommentArgIndex] : args[desiredNonCommentArgIndex - 1];
};
var _validateArguments = function(expectedNumberOfNonCommentArgs, args) {
  var valid = args.length == expectedNumberOfNonCommentArgs || args.length == expectedNumberOfNonCommentArgs + 1 && goog.isString(args[0]);
  _assert(null, valid, "Incorrect arguments passed to assert function");
};
var _getCurrentTestCase = function() {
  var testRunner = goog.global["G_testRunner"];
  return testRunner ? testRunner.testCase : null;
};
var _assert = function(comment, booleanValue, failureMessage) {
  if (!booleanValue) {
    goog.testing.asserts.raiseException(comment, failureMessage);
  }
};
goog.testing.asserts.getDefaultErrorMsg_ = function(expected, actual) {
  var msg = "Expected " + _displayStringForValue(expected) + " but was " + _displayStringForValue(actual);
  if (typeof expected == "string" && typeof actual == "string") {
    var limit = Math.min(expected.length, actual.length);
    var commonPrefix = 0;
    while (commonPrefix < limit && expected.charAt(commonPrefix) == actual.charAt(commonPrefix)) {
      commonPrefix++;
    }
    var commonSuffix = 0;
    while (commonSuffix < limit && expected.charAt(expected.length - commonSuffix - 1) == actual.charAt(actual.length - commonSuffix - 1)) {
      commonSuffix++;
    }
    if (commonPrefix + commonSuffix > limit) {
      commonSuffix = 0;
    }
    if (commonPrefix > 2 || commonSuffix > 2) {
      var printString = function(str) {
        var startIndex = Math.max(0, commonPrefix - 2);
        var endIndex = Math.min(str.length, str.length - (commonSuffix - 2));
        return (startIndex > 0 ? "..." : "") + str.substring(startIndex, endIndex) + (endIndex < str.length ? "..." : "");
      };
      msg += "\nDifference was at position " + commonPrefix + ". Expected [" + printString(expected) + "] vs. actual [" + printString(actual) + "]";
    }
  }
  return msg;
};
var assert = function(a, opt_b) {
  _validateArguments(1, arguments);
  var comment = commentArg(1, arguments);
  var booleanValue = nonCommentArg(1, 1, arguments);
  _assert(comment, goog.isBoolean(booleanValue), "Bad argument to assert(boolean)");
  _assert(comment, booleanValue, "Call to assert(boolean) with false");
};
var assertThrows = function(a, opt_b) {
  _validateArguments(1, arguments);
  var func = nonCommentArg(1, 1, arguments);
  var comment = commentArg(1, arguments);
  _assert(comment, typeof func == "function", "Argument passed to assertThrows is not a function");
  try {
    func();
  } catch (e) {
    if (e && goog.isString(e["stacktrace"]) && goog.isString(e["message"])) {
      var startIndex = e["message"].length - e["stacktrace"].length;
      if (e["message"].indexOf(e["stacktrace"], startIndex) == startIndex) {
        e["message"] = e["message"].substr(0, startIndex - 14);
      }
    }
    var testCase = _getCurrentTestCase();
    if (e && e["isJsUnitException"] && testCase && testCase.failOnUnreportedAsserts) {
      goog.testing.asserts.raiseException(comment, "Function passed to assertThrows caught a JsUnitException (usually " + "from an assert or call to fail()). If this is expected, use " + "assertThrowsJsUnitException instead.");
    }
    return e;
  }
  goog.testing.asserts.raiseException(comment, "No exception thrown from function passed to assertThrows");
};
var assertNotThrows = function(a, opt_b) {
  _validateArguments(1, arguments);
  var comment = commentArg(1, arguments);
  var func = nonCommentArg(1, 1, arguments);
  _assert(comment, typeof func == "function", "Argument passed to assertNotThrows is not a function");
  try {
    return func();
  } catch (e) {
    comment = comment ? comment + "\n" : "";
    comment += "A non expected exception was thrown from function passed to " + "assertNotThrows";
    var stackTrace = e["stack"] || e["stacktrace"] || e.toString();
    goog.testing.asserts.raiseException(comment, stackTrace);
  }
};
var assertThrowsJsUnitException = function(callback, opt_expectedMessage) {
  try {
    goog.testing.asserts.callWithoutLogging(callback);
  } catch (e) {
    var testCase = _getCurrentTestCase();
    if (testCase) {
      testCase.invalidateAssertionException(e);
    } else {
      goog.global.console.error("Failed to remove expected exception: no test case is installed.");
    }
    if (!e.isJsUnitException) {
      fail("Expected a JsUnitException");
    }
    if (typeof opt_expectedMessage != "undefined" && e.message != opt_expectedMessage) {
      fail("Expected message [" + opt_expectedMessage + "] but got [" + e.message + "]");
    }
    return e;
  }
  var msg = "Expected a failure";
  if (typeof opt_expectedMessage != "undefined") {
    msg += ": " + opt_expectedMessage;
  }
  throw new goog.testing.JsUnitException(msg);
};
var assertTrue = function(a, opt_b) {
  _validateArguments(1, arguments);
  var comment = commentArg(1, arguments);
  var booleanValue = nonCommentArg(1, 1, arguments);
  _assert(comment, goog.isBoolean(booleanValue), "Bad argument to assertTrue(boolean)");
  _assert(comment, booleanValue, "Call to assertTrue(boolean) with false");
};
var assertFalse = function(a, opt_b) {
  _validateArguments(1, arguments);
  var comment = commentArg(1, arguments);
  var booleanValue = nonCommentArg(1, 1, arguments);
  _assert(comment, goog.isBoolean(booleanValue), "Bad argument to assertFalse(boolean)");
  _assert(comment, !booleanValue, "Call to assertFalse(boolean) with true");
};
var assertEquals = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var var1 = nonCommentArg(1, 2, arguments);
  var var2 = nonCommentArg(2, 2, arguments);
  _assert(commentArg(2, arguments), var1 === var2, goog.testing.asserts.getDefaultErrorMsg_(var1, var2));
};
var assertNotEquals = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var var1 = nonCommentArg(1, 2, arguments);
  var var2 = nonCommentArg(2, 2, arguments);
  _assert(commentArg(2, arguments), var1 !== var2, "Expected not to be " + _displayStringForValue(var2));
};
var assertNull = function(a, opt_b) {
  _validateArguments(1, arguments);
  var aVar = nonCommentArg(1, 1, arguments);
  _assert(commentArg(1, arguments), aVar === null, goog.testing.asserts.getDefaultErrorMsg_(null, aVar));
};
var assertNotNull = function(a, opt_b) {
  _validateArguments(1, arguments);
  var aVar = nonCommentArg(1, 1, arguments);
  _assert(commentArg(1, arguments), aVar !== null, "Expected not to be " + _displayStringForValue(null));
};
var assertUndefined = function(a, opt_b) {
  _validateArguments(1, arguments);
  var aVar = nonCommentArg(1, 1, arguments);
  _assert(commentArg(1, arguments), aVar === JSUNIT_UNDEFINED_VALUE, goog.testing.asserts.getDefaultErrorMsg_(JSUNIT_UNDEFINED_VALUE, aVar));
};
var assertNotUndefined = function(a, opt_b) {
  _validateArguments(1, arguments);
  var aVar = nonCommentArg(1, 1, arguments);
  _assert(commentArg(1, arguments), aVar !== JSUNIT_UNDEFINED_VALUE, "Expected not to be " + _displayStringForValue(JSUNIT_UNDEFINED_VALUE));
};
var assertNotNullNorUndefined = function(a, opt_b) {
  _validateArguments(1, arguments);
  assertNotNull.apply(null, arguments);
  assertNotUndefined.apply(null, arguments);
};
var assertNonEmptyString = function(a, opt_b) {
  _validateArguments(1, arguments);
  var aVar = nonCommentArg(1, 1, arguments);
  _assert(commentArg(1, arguments), aVar !== JSUNIT_UNDEFINED_VALUE && aVar !== null && typeof aVar == "string" && aVar !== "", "Expected non-empty string but was " + _displayStringForValue(aVar));
};
var assertNaN = function(a, opt_b) {
  _validateArguments(1, arguments);
  var aVar = nonCommentArg(1, 1, arguments);
  _assert(commentArg(1, arguments), isNaN(aVar), "Expected NaN");
};
var assertNotNaN = function(a, opt_b) {
  _validateArguments(1, arguments);
  var aVar = nonCommentArg(1, 1, arguments);
  _assert(commentArg(1, arguments), !isNaN(aVar), "Expected not NaN");
};
goog.testing.asserts.callWithoutLogging = function(fn) {
  var testRunner = goog.global["G_testRunner"];
  var oldLogTestFailure = testRunner["logTestFailure"];
  try {
    testRunner["logTestFailure"] = undefined;
    fn();
  } finally {
    testRunner["logTestFailure"] = oldLogTestFailure;
  }
};
goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS = null;
goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL = "";
goog.testing.asserts.findDifferences = function(expected, actual, opt_equalityPredicate) {
  var failures = [];
  var seen1 = [];
  var seen2 = [];
  function innerAssertWithCycleCheck(var1, var2, path) {
    for (var i = 0; i < seen1.length; ++i) {
      var match1 = seen1[i] === var1;
      var match2 = seen2[i] === var2;
      if (match1 || match2) {
        if (!match1 || !match2) {
          failures.push("Asymmetric cycle detected at " + path);
        }
        return;
      }
    }
    seen1.push(var1);
    seen2.push(var2);
    innerAssertImplementation(var1, var2, path);
    seen1.pop();
    seen2.pop();
  }
  var equalityPredicate = opt_equalityPredicate || function(type, var1, var2) {
    var typedPredicate = PRIMITIVE_EQUALITY_PREDICATES[type];
    if (!typedPredicate) {
      return goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS;
    }
    var equal = typedPredicate(var1, var2);
    return equal ? goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL : goog.testing.asserts.getDefaultErrorMsg_(var1, var2);
  };
  function innerAssertImplementation(var1, var2, path) {
    if (var1 === var2) {
      return;
    }
    var typeOfVar1 = _trueTypeOf(var1);
    var typeOfVar2 = _trueTypeOf(var2);
    if (typeOfVar1 == typeOfVar2) {
      var isArray = typeOfVar1 == "Array";
      var errorMessage = equalityPredicate(typeOfVar1, var1, var2);
      if (errorMessage != goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS) {
        if (errorMessage != goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL) {
          failures.push(path + ": " + errorMessage);
        }
      } else {
        if (isArray && var1.length != var2.length) {
          failures.push(path + ": Expected " + var1.length + "-element array " + "but got a " + var2.length + "-element array");
        } else {
          if (typeOfVar1 == "String") {
            if (var1 != var2) {
              failures.push(path + ': Expected String "' + var1 + '" ' + 'but got "' + var2 + '"');
            }
          } else {
            var childPath = path + (isArray ? "[%s]" : path ? ".%s" : "%s");
            if (typeof Map != "undefined" && var1 instanceof Map || typeof Set != "undefined" && var1 instanceof Set) {
              var1.forEach(function(value, key) {
                if (var2.has(key)) {
                  if (var2.get) {
                    innerAssertWithCycleCheck(value, var2.get(key), childPath.replace("%s", key));
                  }
                } else {
                  failures.push(key + " not present in actual " + (path || typeOfVar2));
                }
              });
              var2.forEach(function(value, key) {
                if (!var1.has(key)) {
                  failures.push(key + " not present in expected " + (path || typeOfVar1));
                }
              });
            } else {
              if (!var1["__iterator__"]) {
                for (var prop in var1) {
                  if (isArray && goog.testing.asserts.isArrayIndexProp_(prop)) {
                    continue;
                  }
                  if (prop in var2) {
                    innerAssertWithCycleCheck(var1[prop], var2[prop], childPath.replace("%s", prop));
                  } else {
                    failures.push("property " + prop + " not present in actual " + (path || typeOfVar2));
                  }
                }
                for (var prop in var2) {
                  if (isArray && goog.testing.asserts.isArrayIndexProp_(prop)) {
                    continue;
                  }
                  if (!(prop in var1)) {
                    failures.push("property " + prop + " not present in expected " + (path || typeOfVar1));
                  }
                }
                if (isArray) {
                  for (prop = 0; prop < var1.length; prop++) {
                    innerAssertWithCycleCheck(var1[prop], var2[prop], childPath.replace("%s", String(prop)));
                  }
                }
              } else {
                if (goog.isFunction(var1.equals)) {
                  if (!var1.equals(var2)) {
                    failures.push("equals() returned false for " + (path || typeOfVar1));
                  }
                } else {
                  if (var1.map_) {
                    innerAssertWithCycleCheck(var1.map_, var2.map_, childPath.replace("%s", "map_"));
                  } else {
                    failures.push("unable to check " + (path || typeOfVar1) + " for equality: it has an iterator we do not " + "know how to handle. please add an equals method");
                  }
                }
              }
            }
          }
        }
      }
    } else {
      failures.push(path + " " + goog.testing.asserts.getDefaultErrorMsg_(var1, var2));
    }
  }
  innerAssertWithCycleCheck(expected, actual, "");
  return failures.length == 0 ? null : goog.testing.asserts.getDefaultErrorMsg_(expected, actual) + "\n   " + failures.join("\n   ");
};
var assertObjectEquals = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var v1 = nonCommentArg(1, 2, arguments);
  var v2 = nonCommentArg(2, 2, arguments);
  var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : "";
  var differences = goog.testing.asserts.findDifferences(v1, v2);
  _assert(failureMessage, !differences, differences);
};
var assertObjectRoughlyEquals = function(a, b, c, opt_d) {
  _validateArguments(3, arguments);
  var v1 = nonCommentArg(1, 3, arguments);
  var v2 = nonCommentArg(2, 3, arguments);
  var tolerance = nonCommentArg(3, 3, arguments);
  var failureMessage = commentArg(3, arguments) ? commentArg(3, arguments) : "";
  var equalityPredicate = function(type, var1, var2) {
    var typedPredicate = goog.testing.asserts.primitiveRoughEqualityPredicates_[type];
    if (!typedPredicate) {
      return goog.testing.asserts.EQUALITY_PREDICATE_CANT_PROCESS;
    }
    var equal = typedPredicate(var1, var2, tolerance);
    return equal ? goog.testing.asserts.EQUALITY_PREDICATE_VARS_ARE_EQUAL : goog.testing.asserts.getDefaultErrorMsg_(var1, var2) + " which was more than " + tolerance + " away";
  };
  var differences = goog.testing.asserts.findDifferences(v1, v2, equalityPredicate);
  _assert(failureMessage, !differences, differences);
};
var assertObjectNotEquals = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var v1 = nonCommentArg(1, 2, arguments);
  var v2 = nonCommentArg(2, 2, arguments);
  var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : "";
  var differences = goog.testing.asserts.findDifferences(v1, v2);
  _assert(failureMessage, differences, "Objects should not be equal");
};
var assertArrayEquals = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var v1 = nonCommentArg(1, 2, arguments);
  var v2 = nonCommentArg(2, 2, arguments);
  var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : "";
  var typeOfVar1 = _trueTypeOf(v1);
  _assert(failureMessage, typeOfVar1 == "Array", "Expected an array for assertArrayEquals but found a " + typeOfVar1);
  var typeOfVar2 = _trueTypeOf(v2);
  _assert(failureMessage, typeOfVar2 == "Array", "Expected an array for assertArrayEquals but found a " + typeOfVar2);
  assertObjectEquals(failureMessage, Array.prototype.concat.call(v1), Array.prototype.concat.call(v2));
};
var assertElementsEquals = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var v1 = nonCommentArg(1, 2, arguments);
  var v2 = nonCommentArg(2, 2, arguments);
  var failureMessage = commentArg(2, arguments) ? commentArg(2, arguments) : "";
  if (!v1) {
    assert(failureMessage, !v2);
  } else {
    assertEquals("length mismatch: " + failureMessage, v1.length, v2.length);
    for (var i = 0; i < v1.length; ++i) {
      assertEquals("mismatch at index " + i + ": " + failureMessage, v1[i], v2[i]);
    }
  }
};
var assertElementsRoughlyEqual = function(a, b, c, opt_d) {
  _validateArguments(3, arguments);
  var v1 = nonCommentArg(1, 3, arguments);
  var v2 = nonCommentArg(2, 3, arguments);
  var tolerance = nonCommentArg(3, 3, arguments);
  var failureMessage = commentArg(3, arguments) ? commentArg(3, arguments) : "";
  if (!v1) {
    assert(failureMessage, !v2);
  } else {
    assertEquals("length mismatch: " + failureMessage, v1.length, v2.length);
    for (var i = 0; i < v1.length; ++i) {
      assertRoughlyEquals(failureMessage, v1[i], v2[i], tolerance);
    }
  }
};
var assertSameElements = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var expected = nonCommentArg(1, 2, arguments);
  var actual = nonCommentArg(2, 2, arguments);
  var message = commentArg(2, arguments);
  assertTrue("Bad arguments to assertSameElements(opt_message, expected: " + "ArrayLike, actual: ArrayLike)", goog.isArrayLike(expected) && goog.isArrayLike(actual));
  expected = goog.testing.asserts.toArray_(expected);
  actual = goog.testing.asserts.toArray_(actual);
  _assert(message, expected.length == actual.length, "Expected " + expected.length + " elements: [" + expected + "], " + "got " + actual.length + " elements: [" + actual + "]");
  var toFind = goog.testing.asserts.toArray_(expected);
  for (var i = 0; i < actual.length; i++) {
    var index = goog.testing.asserts.indexOf_(toFind, actual[i]);
    _assert(message, index != -1, "Expected [" + expected + "], got [" + actual + "]");
    toFind.splice(index, 1);
  }
};
var assertEvaluatesToTrue = function(a, opt_b) {
  _validateArguments(1, arguments);
  var value = nonCommentArg(1, 1, arguments);
  if (!value) {
    _assert(commentArg(1, arguments), false, "Expected to evaluate to true");
  }
};
var assertEvaluatesToFalse = function(a, opt_b) {
  _validateArguments(1, arguments);
  var value = nonCommentArg(1, 1, arguments);
  if (value) {
    _assert(commentArg(1, arguments), false, "Expected to evaluate to false");
  }
};
var assertHTMLEquals = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var var1 = nonCommentArg(1, 2, arguments);
  var var2 = nonCommentArg(2, 2, arguments);
  var var1Standardized = standardizeHTML(var1);
  var var2Standardized = standardizeHTML(var2);
  _assert(commentArg(2, arguments), var1Standardized === var2Standardized, goog.testing.asserts.getDefaultErrorMsg_(var1Standardized, var2Standardized));
};
var assertCSSValueEquals = function(a, b, c, opt_d) {
  _validateArguments(3, arguments);
  var propertyName = nonCommentArg(1, 3, arguments);
  var expectedValue = nonCommentArg(2, 3, arguments);
  var actualValue = nonCommentArg(3, 3, arguments);
  var expectedValueStandardized = standardizeCSSValue(propertyName, expectedValue);
  var actualValueStandardized = standardizeCSSValue(propertyName, actualValue);
  _assert(commentArg(3, arguments), expectedValueStandardized == actualValueStandardized, goog.testing.asserts.getDefaultErrorMsg_(expectedValueStandardized, actualValueStandardized));
};
var assertHashEquals = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var var1 = nonCommentArg(1, 2, arguments);
  var var2 = nonCommentArg(2, 2, arguments);
  var message = commentArg(2, arguments);
  for (var key in var1) {
    _assert(message, key in var2, "Expected hash had key " + key + " that was not found");
    _assert(message, var1[key] == var2[key], "Value for key " + key + " mismatch - expected = " + var1[key] + ", actual = " + var2[key]);
  }
  for (var key in var2) {
    _assert(message, key in var1, "Actual hash had key " + key + " that was not expected");
  }
};
var assertRoughlyEquals = function(a, b, c, opt_d) {
  _validateArguments(3, arguments);
  var expected = nonCommentArg(1, 3, arguments);
  var actual = nonCommentArg(2, 3, arguments);
  var tolerance = nonCommentArg(3, 3, arguments);
  _assert(commentArg(3, arguments), goog.testing.asserts.numberRoughEqualityPredicate_(expected, actual, tolerance), "Expected " + expected + ", but got " + actual + " which was more than " + tolerance + " away");
};
var assertContains = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var contained = nonCommentArg(1, 2, arguments);
  var container = nonCommentArg(2, 2, arguments);
  _assert(commentArg(2, arguments), goog.testing.asserts.contains_(container, contained), "Expected '" + container + "' to contain '" + contained + "'");
};
var assertNotContains = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var contained = nonCommentArg(1, 2, arguments);
  var container = nonCommentArg(2, 2, arguments);
  _assert(commentArg(2, arguments), !goog.testing.asserts.contains_(container, contained), "Expected '" + container + "' not to contain '" + contained + "'");
};
var assertRegExp = function(a, b, opt_c) {
  _validateArguments(2, arguments);
  var regexp = nonCommentArg(1, 2, arguments);
  var string = nonCommentArg(2, 2, arguments);
  if (typeof regexp == "string") {
    regexp = new RegExp(regexp);
  }
  _assert(commentArg(2, arguments), regexp.test(string), "Expected '" + string + "' to match RegExp " + regexp.toString());
};
goog.testing.asserts.toArray_ = function(arrayLike) {
  var ret = [];
  for (var i = 0; i < arrayLike.length; i++) {
    ret[i] = arrayLike[i];
  }
  return ret;
};
goog.testing.asserts.indexOf_ = function(container, contained) {
  if (container.indexOf) {
    return container.indexOf(contained);
  } else {
    for (var i = 0; i < container.length; i++) {
      if (container[i] === contained) {
        return i;
      }
    }
    return -1;
  }
};
goog.testing.asserts.contains_ = function(container, contained) {
  return goog.testing.asserts.indexOf_(container, contained) != -1;
};
var standardizeHTML = function(html) {
  var translator = document.createElement("DIV");
  translator.innerHTML = html;
  return translator.innerHTML.replace(/^\s+|\s+$/g, "");
};
var standardizeCSSValue = function(propertyName, value) {
  var styleDeclaration = document.createElement("DIV").style;
  styleDeclaration[propertyName] = value;
  return styleDeclaration[propertyName];
};
goog.testing.asserts.raiseException = function(comment, opt_message) {
  var e = new goog.testing.JsUnitException(comment, opt_message);
  var testCase = _getCurrentTestCase();
  if (testCase) {
    testCase.raiseAssertionException(e);
  } else {
    goog.global.console.error("Failed to save thrown exception: no test case is installed.");
    throw e;
  }
};
goog.testing.asserts.isArrayIndexProp_ = function(prop) {
  return (prop | 0) == prop;
};
goog.exportSymbol("fail", fail);
goog.exportSymbol("assert", assert);
goog.exportSymbol("assertThrows", assertThrows);
goog.exportSymbol("assertNotThrows", assertNotThrows);
goog.exportSymbol("assertThrowsJsUnitException", assertThrowsJsUnitException);
goog.exportSymbol("assertTrue", assertTrue);
goog.exportSymbol("assertFalse", assertFalse);
goog.exportSymbol("assertEquals", assertEquals);
goog.exportSymbol("assertNotEquals", assertNotEquals);
goog.exportSymbol("assertNull", assertNull);
goog.exportSymbol("assertNotNull", assertNotNull);
goog.exportSymbol("assertUndefined", assertUndefined);
goog.exportSymbol("assertNotUndefined", assertNotUndefined);
goog.exportSymbol("assertNotNullNorUndefined", assertNotNullNorUndefined);
goog.exportSymbol("assertNonEmptyString", assertNonEmptyString);
goog.exportSymbol("assertNaN", assertNaN);
goog.exportSymbol("assertNotNaN", assertNotNaN);
goog.exportSymbol("assertObjectEquals", assertObjectEquals);
goog.exportSymbol("assertObjectRoughlyEquals", assertObjectRoughlyEquals);
goog.exportSymbol("assertObjectNotEquals", assertObjectNotEquals);
goog.exportSymbol("assertArrayEquals", assertArrayEquals);
goog.exportSymbol("assertElementsEquals", assertElementsEquals);
goog.exportSymbol("assertElementsRoughlyEqual", assertElementsRoughlyEqual);
goog.exportSymbol("assertSameElements", assertSameElements);
goog.exportSymbol("assertEvaluatesToTrue", assertEvaluatesToTrue);
goog.exportSymbol("assertEvaluatesToFalse", assertEvaluatesToFalse);
goog.exportSymbol("assertHTMLEquals", assertHTMLEquals);
goog.exportSymbol("assertHashEquals", assertHashEquals);
goog.exportSymbol("assertRoughlyEquals", assertRoughlyEquals);
goog.exportSymbol("assertContains", assertContains);
goog.exportSymbol("assertNotContains", assertNotContains);
goog.exportSymbol("assertRegExp", assertRegExp);
goog.setTestOnly("goog.testing.editor.dom");
goog.provide("goog.testing.editor.dom");
goog.require("goog.dom.NodeType");
goog.require("goog.dom.TagIterator");
goog.require("goog.dom.TagWalkType");
goog.require("goog.iter");
goog.require("goog.string");
goog.require("goog.testing.asserts");
goog.testing.editor.dom.getPreviousNonEmptyTextNode = function(node, opt_stopAt, opt_skipDescendants) {
  return goog.testing.editor.dom.getPreviousNextNonEmptyTextNodeHelper_(node, opt_stopAt, opt_skipDescendants, true);
};
goog.testing.editor.dom.getNextNonEmptyTextNode = function(node, opt_stopAt, opt_skipDescendants) {
  return goog.testing.editor.dom.getPreviousNextNonEmptyTextNodeHelper_(node, opt_stopAt, opt_skipDescendants, false);
};
goog.testing.editor.dom.getPreviousNextNonEmptyTextNodeHelper_ = function(node, opt_stopAt, opt_skipDescendants, opt_isPrevious) {
  opt_stopAt = opt_stopAt || node.ownerDocument.body;
  var iter = new goog.dom.TagIterator(opt_stopAt, opt_isPrevious);
  var walkType;
  var depth = goog.testing.editor.dom.getRelativeDepth_(node, opt_stopAt);
  if (depth == -1) {
    return null;
  }
  if (node.nodeType == goog.dom.NodeType.ELEMENT) {
    if (opt_skipDescendants) {
      walkType = opt_isPrevious ? goog.dom.TagWalkType.START_TAG : goog.dom.TagWalkType.END_TAG;
    } else {
      depth++;
    }
  }
  iter.setPosition(node, walkType, depth);
  try {
    iter.next();
  } catch (e) {
    return null;
  }
  var filter = goog.iter.filter(iter, goog.testing.editor.dom.isNonEmptyTextNode_);
  try {
    return filter.next();
  } catch (e$12) {
    return null;
  }
};
goog.testing.editor.dom.isNonEmptyTextNode_ = function(node) {
  return !!node && node.nodeType == goog.dom.NodeType.TEXT && node.length > 0;
};
goog.testing.editor.dom.getRelativeDepth_ = function(node, parentNode) {
  var depth = 0;
  while (node) {
    if (node == parentNode) {
      return depth;
    }
    node = node.parentNode;
    depth++;
  }
  return -1;
};
goog.testing.editor.dom.assertRangeBetweenText = function(before, after, range, opt_stopAt) {
  var previousText = goog.testing.editor.dom.getTextFollowingRange_(range, true, opt_stopAt);
  if (before == "") {
    assertNull("Expected nothing before range but found <" + previousText + ">", previousText);
  } else {
    assertNotNull("Expected <" + before + "> before range but found nothing", previousText);
    assertTrue("Expected <" + before + "> before range but found <" + previousText + ">", goog.string.endsWith(previousText, before));
  }
  var nextText = goog.testing.editor.dom.getTextFollowingRange_(range, false, opt_stopAt);
  if (after == "") {
    assertNull("Expected nothing after range but found <" + nextText + ">", nextText);
  } else {
    assertNotNull("Expected <" + after + "> after range but found nothing", nextText);
    assertTrue("Expected <" + after + "> after range but found <" + nextText + ">", goog.string.startsWith(nextText, after));
  }
};
goog.testing.editor.dom.getTextFollowingRange_ = function(range, isBefore, opt_stopAt) {
  var followingTextNode;
  var endpointNode = isBefore ? range.getStartNode() : range.getEndNode();
  var endpointOffset = isBefore ? range.getStartOffset() : range.getEndOffset();
  var getFollowingTextNode = isBefore ? goog.testing.editor.dom.getPreviousNonEmptyTextNode : goog.testing.editor.dom.getNextNonEmptyTextNode;
  if (endpointNode.nodeType == goog.dom.NodeType.TEXT) {
    var endText = endpointNode.nodeValue;
    if (isBefore ? endpointOffset > 0 : endpointOffset < endText.length) {
      return isBefore ? endText.substr(0, endpointOffset) : endText.substr(endpointOffset);
    } else {
      followingTextNode = getFollowingTextNode(endpointNode, opt_stopAt);
      return followingTextNode && followingTextNode.nodeValue;
    }
  } else {
    var numChildren = endpointNode.childNodes.length;
    if (isBefore ? endpointOffset > 0 : endpointOffset < numChildren) {
      var followingChild = endpointNode.childNodes[isBefore ? endpointOffset - 1 : endpointOffset];
      if (goog.testing.editor.dom.isNonEmptyTextNode_(followingChild)) {
        return followingChild.nodeValue;
      } else {
        followingTextNode = getFollowingTextNode(followingChild, opt_stopAt);
        return followingTextNode && followingTextNode.nodeValue;
      }
    } else {
      followingTextNode = getFollowingTextNode(endpointNode, opt_stopAt, true);
      return followingTextNode && followingTextNode.nodeValue;
    }
  }
};
goog.provide("uno.listeners.SelectionListener");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("goog.testing.editor.dom");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.SelectionListener");
  var SelectionListener = uno.listeners.SelectionListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(SelectionListener, uno.BasePlugin);
  SelectionListener.prototype.handleKeyDown = function(event) {
    var range = this.editor.getRange();
    if (!range || !range.isCollapsed()) {
      return;
    }
    var startNode = range.getStartNode();
    var startOffset = range.getStartOffset();
    if ((event.keyCode === 37 || event.keyCode === 39) && startNode.nodeType === Node.TEXT_NODE) {
      var char;
      var newIndex;
      if (event.keyCode === 37) {
        if (startOffset === 0) {
          var prevSibling = goog.testing.editor.dom.getPreviousNonEmptyTextNode(startNode);
          if (prevSibling && prevSibling.nodeType === Node.TEXT_NODE) {
            char = prevSibling.textContent[prevSibling.length - 1];
            startNode = prevSibling;
            newIndex = prevSibling.length - 1;
          }
        } else {
          char = startNode.textContent[startOffset - 1];
          newIndex = startOffset - 1;
        }
      } else {
        if (event.keyCode === 39) {
          if (startOffset === startNode.length) {
            var nextSibling = goog.testing.editor.dom.getNextNonEmptyTextNode(startNode);
            if (nextSibling && nextSibling.nodeType === Node.TEXT_NODE) {
              char = nextSibling.textContent[0];
              startNode = nextSibling;
              newIndex = 1;
            }
          } else {
            char = startNode.textContent[startOffset];
            newIndex = startOffset + 1;
          }
        }
      }
      if (char === uno.defs.unicode.ZERO_WIDTH_SPACE) {
        var newRange = goog.dom.Range.createFromNodes(startNode, newIndex, startNode, newIndex);
        newRange.select();
      }
    }
  };
})();
goog.provide("uno.listeners.strict.DeleteListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.codeblock");
goog.require("uno.model.item");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.strict.DeleteListener");
  var model = uno.model;
  var util = uno.util;
  var BACKSPACE = goog.events.KeyCodes.BACKSPACE;
  var DeleteListener = uno.listeners.strict.DeleteListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(DeleteListener, uno.BasePlugin);
  DeleteListener.prototype.handleKeyDown = function(event) {
    if (event.keyCode === BACKSPACE) {
      if (this.editor.execCommand("delete", null, {native:true}, true)) {
        event.preventDefault();
        return true;
      } else {
        setTimeout(this.editor.dispatchChange.bind(this.editor));
      }
    }
  };
  DeleteListener.prototype.handleAfterExecCommand = function(event) {
    if (event.command === "delete") {
      var range = this.editor.getRange();
      util.codeblock.updateTopSpace(this.editor);
      if (range) {
        util.codeblock.updateEmpty(range.getStartNode());
        var item = model.item.for(util.range.boundary(range.getStartNode(), range.getStartOffset()));
        if (item != null) {
          model.item.updateEmpty(model.item.for(range.getStartNode()));
          if (!model.p.for(this.editor.getRange().getStartNode())) {
            model.origin.placeCursorAtStart(item);
          }
        }
      }
    }
  };
})();
goog.provide("uno.listeners.strict.HrListener");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.hr");
goog.require("uno.model.origin");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.strict.HrListener");
  var model = uno.model;
  var util = uno.util;
  var HrListener = uno.listeners.strict.HrListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(HrListener, uno.BasePlugin);
  HrListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  HrListener.prototype.handleNativeSelectionChange = function() {
    var prev;
    var next;
    var container;
    var range = this.editor.getRange();
    if (range) {
      if (range.isCollapsed() && model.origin.is(range.getStartNode())) {
        prev = range.getStartOffset() > 0 && range.getStartNode().childNodes[range.getStartOffset() - 1];
        if (prev && model.hr.is(prev) && model.hr.toggleSelected(prev)) {
          util.range.selectNode(prev);
          range = this.editor.getRange();
        }
        next = range.getStartNode().childNodes[range.getStartOffset()];
        if (model.hr.is(next) && model.hr.toggleSelected(next)) {
          util.range.selectNode(next);
          range = this.editor.getRange();
        }
      }
      if (!range.isCollapsed()) {
        goog.array.forEach(this.editor.field.querySelectorAll("hr.selected"), function(node) {
          if (!range.containsNode(node)) {
            model.hr.unselect(node);
          }
        });
        container = range.getContainer();
        if (container.nodeType === Node.ELEMENT_NODE) {
          goog.array.forEach(container.querySelectorAll("hr:not(.selected)"), function(node) {
            if (range.containsNode(node)) {
              model.hr.select(node);
            }
          });
        }
      } else {
        goog.array.forEach(this.editor.field.querySelectorAll("hr.selected"), model.hr.unselect);
      }
    } else {
      goog.array.forEach(this.editor.field.querySelectorAll("hr.selected"), model.hr.unselect);
    }
  };
})();
goog.provide("uno.listeners.strict.ListListener");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.list");
goog.require("uno.model.p");
goog.require("uno.model.section");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.strict.ListListener");
  var Chunk = uno.model.Chunk;
  var model = uno.model;
  var util = uno.util;
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  var TAB_KEY = goog.events.KeyCodes.TAB;
  var ListListener = uno.listeners.strict.ListListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(ListListener, uno.BasePlugin);
  ListListener.prototype.handleKeyDown = function(event) {
    var chunk;
    var p;
    var refPar;
    var newPar;
    var newItem;
    var list;
    var section;
    var sections = [];
    var handled = false;
    var range = this.editor.getRange();
    var item = model.item.for(range.getStartNode());
    if (item != null) {
      if (event.keyCode === ENTER_KEY) {
        if (event.shiftKey === true) {
          refPar = model.p.lastFromRange(range);
          newPar = model.p.splitAt(range.getEndNode(), range.getEndOffset(), refPar);
          model.p.placeCursorAtStart(newPar);
        } else {
          if (model.item.isEmpty(item)) {
            if (model.item.nextItem(item) != null) {
              model.list.splitBefore(model.item.nextItem(item));
            }
            list = model.list.for(item);
            if (model.list.parentListCount(list) > 0) {
              savedRange = range.saveUsingDom();
              model.item.outdent(item);
              savedRange.restore().select();
            } else {
              model.item.remove(item);
              p = model.p.create();
              model.section.insertSiblingAfter(p, list);
              if (model.list.itemCount(list) === 0) {
                model.section.remove(list);
              }
              model.p.placeCursorAtStart(p);
            }
          } else {
            refPar = model.p.lastFromRange(range);
            newPar = model.p.splitAt(range.getEndNode(), range.getEndOffset(), refPar);
            section = newPar;
            sections = [section];
            while (section.nextSibling != null) {
              sections.push(section.nextSibling);
              section = section.nextSibling;
            }
            newItem = model.item.create(sections);
            model.section.insertSiblingAfter(newItem, item);
            model.origin.placeCursorAtStart(newItem);
          }
        }
        handled = true;
      } else {
        if (event.keyCode === TAB_KEY) {
          if (event.shiftKey === true) {
            this.editor.execCommand("outdent");
          } else {
            this.editor.execCommand("indent");
          }
          handled = true;
        }
      }
    }
    if (handled) {
      event.preventDefault();
    }
    return handled;
  };
})();
goog.provide("uno.listeners.strict.OriginListener");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.list");
goog.require("uno.model.origin");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.model.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.strict.OriginListener");
  var Chunk = uno.model.Chunk;
  var model = uno.model;
  var util = uno.util;
  var OriginListener = uno.listeners.strict.OriginListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(OriginListener, uno.BasePlugin);
  OriginListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  OriginListener.prototype.handleNativeSelectionChange = function() {
    var range = this.editor.getRange();
    var prev;
    var next;
    if (range && range.isCollapsed() && model.origin.is(range.getStartNode())) {
      prev = range.getStartOffset() > 0 && range.getStartNode().childNodes[range.getStartOffset() - 1];
      next = range.getStartNode().childNodes[range.getStartOffset()];
      if (model.list.is(next) || model.p.is(next) || model.table.is(next)) {
        model.section.placeCursorAtStart(model.section.for(next));
      } else {
        if (model.list.is(prev) || model.p.is(prev) || model.table.is(prev)) {
          model.section.placeCursorAtEnd(model.section.for(prev));
        }
      }
    }
  };
  OriginListener.prototype.handleTextInput = function(event) {
    var p;
    var range = this.editor.getRange();
    if (range == null) {
      return;
    }
    if (model.origin.is(range.getStartNode()) || model.origin.is(range.getEndNode())) {
      if (!range.isCollapsed()) {
        this.editor.execCommand("delete");
      }
      range = this.editor.getRange();
      if (model.origin.is(range.getStartNode())) {
        p = model.p.create();
        model.p.append(Chunk.fromText(event.getBrowserEvent().data), p);
        range.getStartNode().insertBefore(p, range.getStartNode().childNodes[range.getStartOffset()]);
        model.p.placeCursorAtEnd(p);
      }
      event.preventDefault();
    }
  };
})();
goog.provide("uno.listeners.strict.PendingStyleListener");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.defs");
goog.require("uno.util.range");
goog.require("uno.util.styles");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.strict.PendingStyleListener");
  var model = uno.model;
  var util = uno.util;
  var PendingStyleListener = uno.listeners.strict.PendingStyleListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(PendingStyleListener, uno.BasePlugin);
  PendingStyleListener.prototype.handleNativeSelectionChange = function() {
    if (this.editor.context.hasTempStyles) {
      util.styles.clearTempStyles(this.editor);
    }
  };
  PendingStyleListener.prototype.handleTextInput = function(event) {
    var range;
    var chunk;
    var tempStyles;
    if (this.editor.context.hasTempStyles) {
      range = this.editor.getRange();
      if (range && range.isCollapsed()) {
        var bounds = model.chunk.bounds(range);
        var textInput = event.getBrowserEvent().data;
        var startOffset = bounds.startOffset;
        var endOffset = startOffset + textInput.length;
        var chunk = model.chunk.insertText(textInput, bounds.start, startOffset);
        tempStyles = this.editor.context.tempStyles;
        Object.keys(tempStyles.state).forEach(function(key) {
          var adjustOffset = model.fmt.formatValue(key, chunk) !== tempStyles.state[key];
          chunk = model.fmt.formatChunk(key, tempStyles.state[key], chunk, startOffset, endOffset);
          if (adjustOffset) {
            startOffset = 0;
            endOffset = textInput.length;
          }
        });
        Object.keys(tempStyles.value).forEach(function(key) {
          var adjustOffset;
          var val = tempStyles.value[key];
          if (val != null && val !== "") {
            adjustOffset = model.fmt.formatValue(key, chunk) !== val;
            chunk = model.fmt.formatChunk(key, val, chunk, startOffset, endOffset);
          } else {
            adjustOffset = model.fmt.formatValue(key, chunk) == null || model.fmt.formatValue(key, chunk) === "";
            chunk = model.fmt.formatChunk(key, false, chunk, startOffset, endOffset);
          }
          if (adjustOffset) {
            startOffset = 0;
            endOffset = textInput.length;
          }
        });
        var firstLeaf = model.chunk.firstLeaf(model.fmt.normalizeRight(chunk));
        if (firstLeaf.data === " ") {
          firstLeaf.data = uno.defs.unicode.NBSP;
        }
        range = goog.dom.Range.createFromNodes(firstLeaf, endOffset, firstLeaf, endOffset);
        range.select();
        util.styles.clearTempStyles(this.editor);
        event.preventDefault();
      }
    }
  };
})();
goog.provide("uno.listeners.strict.TodoListener");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.p");
goog.require("uno.model.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.strict.TodoListener");
  var Chunk = uno.model.Chunk;
  var model = uno.model;
  var BACKSPACE_KEY = goog.events.KeyCodes.BACKSPACE;
  var util = uno.util;
  var TodoListener = uno.listeners.strict.TodoListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TodoListener, uno.BasePlugin);
  TodoListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  TodoListener.prototype.handleClick = function(event) {
    if (model.todo.is(event.target)) {
      if (this.editor.readOnly) {
        this.editor.dispatchEvent({type:uno.Editor.EventType.ACTION_DENIED, reason:{readOnly:true}});
        return false;
      }
      event.preventDefault();
      event.stopPropagation();
      model.todo.toggle(event.target);
      this.editor.dispatchChange();
      return true;
    }
    return false;
  };
})();
goog.provide("uno.listeners.strict.TodoListListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("goog.functions");
goog.require("uno.BasePlugin");
goog.require("uno.model.chunk");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.model.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.strict.TodoListListener");
  var model = uno.model;
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  var util = uno.util;
  var TodoListListener = uno.listeners.strict.TodoListListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TodoListListener, uno.BasePlugin);
  TodoListListener.prototype.activeOnStrictMode = goog.functions.TRUE;
  TodoListListener.prototype.handleKeyPress = function(event) {
    var range;
    var chunk;
    var p;
    var todo;
    if (event.keyCode === ENTER_KEY) {
      if (event.altKey) {
        this.editor.execCommand("inserttodo");
        event.preventDefault();
        event.stopPropagation();
        return true;
      }
      range = this.editor.getRange();
      p = model.p.lastFromRange(range);
      if (p != null) {
        if (model.p.startsWithTodo(p)) {
          if (!model.p.hasVisibleContent(p, {excluding:model.p.getTodo(p)})) {
            model.p.removeTodo(p);
            model.p.placeCursorAtStart(p);
          } else {
            todo = model.todo.create();
            var newp = model.p.create(todo);
            if (range.isCollapsed()) {
              chunk = model.chunk.firstFromRange(range);
              if (model.chunk.canSplit(chunk)) {
                chunk.split();
                newp = model.p.create(chunk.nextChunks());
              }
            }
            if (newp == null) {
              newp = model.p.create();
            }
            var firstChunk = model.p.firstChunk(newp);
            model.fmt.applyFormatting(model.p.getEndingFormat(p), firstChunk);
            model.p.prepend(todo, newp);
            model.section.insertSiblingAfter(newp, p);
            goog.editor.range.placeCursorNextTo(todo);
          }
          event.preventDefault();
          event.stopPropagation();
        }
      }
      return true;
    }
  };
})();
goog.provide("uno.util.strict.typebehind.email");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
(function() {
  var email = uno.util.strict.typebehind.email;
  var log = goog.debug.Logger.getLogger("uno.util.typebehind.email");
  var model = uno.model;
  email.name = "email";
  email.matchBeginningOfLine = false;
  email.rxs = [new RegExp(uno.defs.regex.SIMPLE_EMAIL, "gi")];
  email.contextReplaceable = function(range, keyCode) {
    return true;
  };
  email.getRegexes = function() {
    email.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return email.rxs;
  };
  email.insertReplacement = function(range, rx, matchedText) {
    var chunk = model.chunk.fromText(matchedText);
    model.fmt.hyperlink("mailto:" + matchedText, chunk);
    range.replaceContentsWithNode(model.chunk.root(chunk));
    return {node:model.chunk.root(chunk), trimWhitespace:false};
  };
})();
goog.provide("uno.util.strict.typebehind.emoticon");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.model.chunk");
goog.require("uno.util.emoticon");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.typebehind.emoticon");
  var model = uno.model;
  var util = uno.util;
  var emoticon = uno.util.strict.typebehind.emoticon;
  emoticon.name = "emoticon";
  emoticon.matchBeginningOfLine = false;
  emoticon.rxs = Object.keys(util.emoticon.list).map(function(key) {
    return new RegExp(key, "g");
  });
  emoticon.contextReplaceable = function(range, keyCode) {
    return true;
  };
  emoticon.getRegexes = function() {
    emoticon.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return emoticon.rxs;
  };
  emoticon.insertReplacement = function(range, rx, matchedText) {
    var newNode = util.emoticon.fromPattern(rx.source);
    var chunk = model.chunk.firstFromRange(range);
    var origText = model.chunk.text(chunk);
    var newText = origText.replace(matchedText, newNode.data);
    chunk = model.chunk.replaceText(newText, chunk);
    model.chunk.placeCursorAtEnd(chunk);
    return {node:null, trimWhitespace:false};
  };
})();
goog.provide("uno.util.strict.typebehind.hr");
goog.require("goog.debug.Logger");
goog.require("uno.defs");
goog.require("goog.events.KeyCodes");
goog.require("uno.model.hr");
goog.require("uno.model.item");
goog.require("uno.model.p");
goog.require("uno.model.section");
goog.require("uno.util.dom");
(function() {
  var hr = uno.util.strict.typebehind.hr;
  var model = uno.model;
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  hr.name = "hr";
  hr.matchBeginningOfLine = true;
  hr.rxs = [new RegExp(uno.defs.regex.HORIZONTAL_RULE, "gi")];
  hr.contextReplaceable = function(range, keyCode) {
    return keyCode === ENTER_KEY;
  };
  hr.getRegexes = function() {
    hr.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return hr.rxs;
  };
  hr.insertReplacement = function(range, rx, matchedText) {
    var p = model.p.firstFromRange(range);
    var hrule = model.hr.create();
    if (!model.item.is(p)) {
      model.p.clear(p);
      model.section.insertSiblingBefore(hrule, p);
      model.p.placeCursorAtStart(p);
    }
    return {node:null, trimWhitespace:true};
  };
})();
goog.provide("uno.util.strict.typebehind.list");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.model.list");
goog.require("uno.model.p");
goog.require("uno.model.section");
(function() {
  var list = uno.util.strict.typebehind.list;
  var BULLETED_LIST = uno.defs.regex.BULLETED_LIST;
  var NUMBERED_LIST = uno.defs.regex.NUMBERED_LIST;
  var TODO_LIST = uno.defs.regex.TODO;
  var model = uno.model;
  var util = uno.util;
  list.name = "list";
  list.matchBeginningOfLine = true;
  list.rxs = [new RegExp(BULLETED_LIST, "gi"), new RegExp(NUMBERED_LIST, "gi")];
  list.contextReplaceable = function(range) {
    if (goog.dom.getAncestorByTagNameAndClass(range.getContainer(), "li")) {
      return false;
    }
    return true;
  };
  list.getRegexes = function() {
    list.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return list.rxs;
  };
  list.insertReplacement = function(range, rx, matchedText, editor) {
    var list;
    var startNumber;
    var p = model.p.firstFromRange(range);
    if (rx.source === BULLETED_LIST) {
      list = model.list.create("unordered");
    } else {
      if (rx.source === NUMBERED_LIST) {
        list = model.list.create("ordered");
        startNumber = parseInt(matchedText, 10);
        model.list.startAt(startNumber, list);
      }
    }
    model.section.replace(list, p);
    model.list.placeCursorAtStart(list);
    return {node:null, trimWhitespace:true};
  };
})();
goog.provide("uno.util.strict.typebehind.table");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.defs");
goog.require("uno.model.p");
(function() {
  var model = uno.model;
  var table = uno.util.strict.typebehind.table;
  table.name = "table";
  table.matchBeginningOfLine = true;
  table.rxs = [new RegExp(uno.defs.regex.TABLE, "gi")];
  table.contextReplaceable = function(range) {
    var container = range.getContainer();
    if (goog.dom.getAncestorByTagNameAndClass(container, "table") || goog.dom.getAncestorByTagNameAndClass(container, "li")) {
      return false;
    }
    return true;
  };
  table.getRegexes = function() {
    table.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return table.rxs;
  };
  table.insertReplacement = function(range, rx, matchedText, editor) {
    var p = model.p.firstFromRange(range);
    var cols = matchedText.split("][").length;
    var rowMatch = matchedText.match(/[0-9]+$/);
    var rows = 1;
    if (rowMatch) {
      rows = parseInt(rowMatch[0], 10);
    }
    model.p.clear(p);
    editor.execCommand("inserttable", {columns:cols, rows:rows});
    return {node:null, trimWhitespace:true};
  };
})();
goog.provide("uno.util.strict.typebehind.todo");
goog.require("goog.debug.Logger");
goog.require("uno.defs");
goog.require("uno.model.chunk");
goog.require("uno.model.p");
goog.require("uno.model.todo");
goog.require("uno.util.dom");
(function() {
  var todo = uno.util.strict.typebehind.todo;
  var model = uno.model;
  todo.name = "todo";
  todo.matchBeginningOfLine = false;
  todo.rxs = [new RegExp(uno.defs.regex.TODO, "gi")];
  todo.contextReplaceable = function() {
    return true;
  };
  todo.getRegexes = function() {
    todo.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return todo.rxs;
  };
  todo.insertReplacement = function(range, rx, matchedText) {
    var checked = matchedText.toLowerCase().indexOf("x") > 0;
    var todo = model.todo.create(checked);
    var p = model.p.firstFromRange(range);
    var chunk = model.p.firstChunk(p);
    var text = model.chunk.text(chunk);
    text = text.replace(new RegExp(uno.defs.regex.TODO), "");
    model.chunk.replaceText(text, chunk);
    model.p.prepend(todo, p);
    var lastLeaf = model.chunk.lastLeaf(model.p.lastChunk(p));
    if (lastLeaf.tagName === "BR") {
      model.chunk.removeLeaf(lastLeaf);
    }
    return {node:todo, trimWhitespace:true};
  };
})();
goog.provide("uno.util.strict.typebehind.url");
goog.require("goog.asserts");
goog.require("goog.debug.Logger");
goog.require("uno.defs");
goog.require("uno.model.chunk");
goog.require("uno.model.fmt");
(function() {
  var url = uno.util.strict.typebehind.url;
  var model = uno.model;
  url.name = "url";
  url.matchBeginningOfLine = false;
  url.rxs = [new RegExp(uno.defs.regex.SIMPLE_URL, "gi")];
  url.contextReplaceable = function() {
    return true;
  };
  url.getRegexes = function() {
    url.rxs.forEach(function(rx) {
      rx.lastIndex = 0;
    });
    return url.rxs;
  };
  url.insertReplacement = function(range, rx, matchedText) {
    var href = /^[a-zA-Z]+:\/\//.test(matchedText) ? matchedText : "http://" + matchedText;
    var chunk = model.chunk.fromText(matchedText);
    model.fmt.hyperlink(href, chunk);
    range.replaceContentsWithNode(model.chunk.root(chunk));
    return {node:model.chunk.root(chunk), trimWhitespace:false};
  };
})();
goog.provide("uno.listeners.strict.TypeBehindListener");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.typebehind");
goog.require("uno.util.typebehind.code");
goog.require("uno.util.strict.typebehind.email");
goog.require("uno.util.strict.typebehind.emoticon");
goog.require("uno.util.strict.typebehind.hr");
goog.require("uno.util.strict.typebehind.list");
goog.require("uno.util.strict.typebehind.table");
goog.require("uno.util.strict.typebehind.todo");
goog.require("uno.util.strict.typebehind.url");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.strict.TypeBehindListener");
  var SPACE_KEY = goog.events.KeyCodes.SPACE;
  var TAB_KEY = goog.events.KeyCodes.TAB;
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  var util = uno.util;
  var TypeBehindListener = uno.listeners.strict.TypeBehindListener = function() {
    uno.BasePlugin.call(this, log.getName());
    this.imps = [];
    this.checkBeginningOfLines = false;
  };
  goog.inherits(TypeBehindListener, uno.BasePlugin);
  TypeBehindListener.IMPLEMENTATIONS = {code:uno.util.typebehind.code, email:uno.util.strict.typebehind.email, emoticon:uno.util.strict.typebehind.emoticon, horizontalrule:uno.util.strict.typebehind.hr, list:uno.util.strict.typebehind.list, table:uno.util.strict.typebehind.table, todo:uno.util.strict.typebehind.todo, url:uno.util.strict.typebehind.url};
  TypeBehindListener.prototype.registerFieldObject = function(fieldObject) {
    var me = this;
    uno.BasePlugin.prototype.registerFieldObject.call(this, fieldObject);
    Object.keys(TypeBehindListener.IMPLEMENTATIONS).forEach(function(name) {
      var imp;
      if (fieldObject.config.typebehind[name]) {
        imp = TypeBehindListener.IMPLEMENTATIONS[name];
        me.imps.push(imp);
        if (imp.matchBeginningOfLine) {
          me.checkBeginningOfLines = true;
        }
      }
    });
  };
  var canTypebehind = true;
  TypeBehindListener.prototype.handleAfterExecCommand = function(event) {
    canTypebehind = !(event.command === "undo");
  };
  TypeBehindListener.prototype.handleKeyDown = function(event) {
    var replaced = false;
    var keyCode = event.keyCode;
    var range = this.editor.getRange();
    if (range && range.isCollapsed() && canTypebehind && (keyCode === SPACE_KEY || keyCode === TAB_KEY || keyCode === ENTER_KEY)) {
      replaced = util.typebehind.tryReplacements(event, this.imps, this.checkBeginningOfLines, this.editor);
    }
    if (replaced) {
      this.editor.dispatchChange();
    }
    canTypebehind = true;
    return replaced;
  };
})();
goog.provide("uno.util.http");
goog.require("goog.debug.Logger");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.http");
  var util = uno.util;
  util.http.fetchAsync = function(input, init) {
    log.fine("Fetching : " + (input.url || input));
    return fetch(input, init).then(function(response) {
      log.fine("Fetch response from : " + (input.url || input));
      log.fine(response);
      if (response.status >= 200 && response.status < 300) {
        return response;
      } else {
        var error = new Error(response.statusText);
        error.response = response;
        throw error;
      }
    });
  };
})();
goog.provide("uno.util.richlink.googledrive.android");
goog.require("uno.util.loc");
(function() {
  var android = uno.util.richlink.googledrive.android;
  var util = uno.util;
  android.getAccessRequestString = function() {
    return util.loc.t("Tap to request access");
  };
  android.getTapToConnectString = function() {
    return util.loc.t("Connect");
  };
  android.activateDrag = function(el) {
    return el;
  };
  android.getImagePath = function(editor) {
    return editor.config.images.androidPath;
  };
})();
goog.provide("uno.util.richlink.googledrive.generic");
goog.require("uno.util.loc");
(function() {
  var generic = uno.util.richlink.googledrive.generic;
  var util = uno.util;
  generic.getAccessRequestString = function() {
    return util.loc.t("Click to request access");
  };
  generic.getTapToConnectString = function() {
    return util.loc.t("Connect to see more");
  };
  generic.activateDrag = function(el) {
    return el;
  };
  generic.getImagePath = function(editor) {
    return editor.config.images.path;
  };
})();
goog.provide("uno.util.richlink.googledrive.ios");
goog.require("uno.util.loc");
goog.require("uno.util.richlink.googledrive.generic");
(function() {
  var ios = uno.util.richlink.googledrive.ios;
  var util = uno.util;
  ios.getAccessRequestString = function() {
    return util.loc.t("Tap to request access");
  };
  ios.getTapToConnectString = function() {
    return util.loc.t("Connect");
  };
  ios.activateDrag = function(el) {
    return el;
  };
  ios.getImagePath = function(editor) {
    return util.richlink.googledrive.generic.getImagePath(editor);
  };
})();
goog.provide("uno.util.img.fixtures.win");
(function() {
  var fixtures = uno.util.img.fixtures.win;
  fixtures.map = {"images/att_icon_drawings_40.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAAyNJREFUaN7tmu9LE2EcwL+3uhuDnIMQemHdOURSktQVSlOEzXKSWHtl1AtfNAiCXpT044VRQS8qetE/IBRJUb4RX8RQX4Q4jAUTVDKYTufITVE5LtztNnbXi/EwKOY2n+25ze7z5nlxz33v+3z4Pvd8bwxAQ0ND4/+Fwg0QEG2m5tcsm+yCT7qW4WHqm3IcPnd0KD+pB/CdYYqVeMW7zmMXox7PiedPxl8stbeT1ZZGhxsAiYO38BLu2+3FFofQD1ZfOXXHao0MPet7VD8zQ0bXv2ALRBWn1gLUFoktkFTFZQOJ3Kp5OvLw/ewsqediCyw1aN9Jif3d1kZK5KETiCAlsmwFKoosJ5PZ5yGRkaHHN+/xhX9Hlq3AWCwSCYdzn68f5C7UfrBaVy/fDd/6GgoVKo+yFSiKXq/HAxCNbmyEQgCynEzmUpGmkTNfzv6ori6USOxG2u+32SwWRSGjLTOCEI8nEgA8nxpzxW73epeWqAN7KNsK/BujkWFoGsBkSo2kODQCEaRFHlVroQZDU1NLC0BFhc3W0wPAMBxXU5O+nkisrQUCAIIwNeV2A4ji/LzPl3t8JBKR79YuWYEmk9PZ3w9gNHZ39/ZmnqfX19XV1wNUVaVGQXC7x8cBeH5sbHQ09+cVWySxLYwqLpu4zCIcjr4+AIOhsbG5+SD3F2drExOItiouRmNXl8OBc39KYGVlYUQSE8gwLMtx+HFommXNZvw4hRKo2iGSiUBgYMDpzHxdlmVZlgHW1xcX/f7M82prW1stluLnS6wCE4lgcHUVP44kRaOxGKmss0NMIGpH8ONsb+/ukso6O8QEoj4OtSP5wvObmzs7AKIoCHt7JBXtD/F3IOrjJGllZXk5farSNMeZzamfqWQZIBZLbVVUcaUmTjWBCFFcWJibS4+IYHD/w6HUOHTfwqTRBGKiCcSk5BppUg1wodAqEBNNICb4f+04rbyC8/G42gvJmyPgg9uShBsGvwJdsKV0Tk+r7SNfqGsAylX8vLEF6t5Q15VfLhd1A3zKxORkqVYkyotqgAaAiQnqo+4cdcnlUjsvDQ0NjXLmD6E2U1wbu1pwAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwGxDoJAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMGpNUJgAAABMdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9hdHRfaWNvbl9kcmF3aW5nc180MC5zdmc7qb9bAAAAAElFTkSuQmCC", 
  "images/att_icon_forms_40.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAAkhJREFUaN7tmk1IFGEYx/+jYZPjJQjpMGVIHTqkSATGugjZxT2I2MEVEjpsnpa61aLQFyTbsegUCB2ilD6OHlTIzwQD0Yg2IrqYpCwICzvDuLQznd4VDNmPd+Z9ndnndxvmnWee+fGfZ4ZhAIIgiOpF4S0w8ivS96mtqemviWf277Ex5Q6anSvhMFpwFfG6Oq8ab7vW+ePEx6Wl/kt3f56/19EhVtseNbwFCuJeYcj50NXltThGY1Z/qA6GQhOfn5xNPVpcFKPrf7gFFhInCdkiuQWKSlwxCiJXk9e/n15eFnVefoGHjMbMqe6jc+3tokQGTiBDlEjfCnQc2y5lHRP5puXx5W8X3Z+RvhWYTm9tmWbp608+PRM/9i4UevEg8Xb1xsaGW334VmAqtbKSyQDb25ubpgnYdj7vOMWPO9d5IXf8vq67JfKIbBGVYlmGkc8Da2uzszs7gGFYlmkC2axlGUaJRXp0HQDwsvI+fJvA/WiaqtbXAw0Nqqpp4s4bGIEM0SIDJ5AhSmRgBTK8Fhl4gQyvRPr2KVwpTCQAlPLaUwzhAoeHx8dbW/e2R0ej0fX1g/eXy/56B6Fp7iSxam5hr+D+Ip1IRCILC27cDHJIJicnw2GlYg+UQE6qdga6BSWQE5qBNAPlQjOQE0ogJzQDaQbKhQRywi/wC2bwPJeTfSFl0wNVGdzd5S3jwq8dzh/E5+dl+ygXJQo4vfx9cwusHVJu1t6KxZTXUPF+evrQJpL1lcZtDExN2QM1I8rXWEx2WwRBEH7mH7lv75z7XaiiAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwGxDoJAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMGpNUJgAAABJdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9hdHRfaWNvbl9mb3Jtc180MC5zdmfQaewzAAAAAElFTkSuQmCC", 
  "images/att_icon_gdocs_40.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAAihJREFUaN7tmjFIG1EYx//v8KJRC6F0qR69QYqVji0SGq2IW4cOdlFXg2YS2kJpwaWLRSkdHCRLRuvQRcRJESWoEaGdVHRxESwuouBZk/TuOuhrQYRc/fLe5S7vN7/73seP//vucRygUCgU1QujFnjR+3nw15JpYtL5qL3NZFgbfrqZzk48xzIeRyKiGu9qfTSk/Vhbe/flZSzyrKNDrrZ/aOQKXNwwvrobPT2ixXGan9zd0toTiYk3cyeF9dVVKbZugCzwb+J8wm+R9ARKSlwpuMjx6fn7v1tyOVn70gVWGAZi37AXj8sSGTqBHFkiAyvQcRzHyzoucuzT7CsRMzKwAo+OTk9t2/t688G911p7IjF6Zzpn7R0clKuPwArc3NzfB4DDw+Nj275MpOuWfq4tbdq1LYZRLpE1fou4LZaVz7susLKyuwsAxeLFxdkZUCxa1vm5hwJPATQaBpZpfQQ2gdfR9bq6aBTQ9YaG+np5+4ZGIEe2yNAJ5MgSGVqBHNEiQy+QI0pkYN/Ct4WLBLxcekojXeDMTCpVKIir39+fTnv5tKHr0eilSBpVc4RFIT2BXhMSFFQCiVTtDCwXKoFE1AwkohJIJHAzsNISrBJIRM1AIiqBRJRAInSBWXRjW+TVWBAxbOB7Pk8tU45fOz6wgWzWbx//TR+bZX30vskC3VrNdKaSSaTYe/ZwcbFiE3nVlzuCHWYsLLAme8wZSCb9bkuhUCiCzB8kv8RReqfpewAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMBsQ6CQAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDBqTVCYAAAASXRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvYXR0X2ljb25fZ2RvY3NfNDAuc3Zncn/20gAAAABJRU5ErkJggg==", 
  "images/att_icon_gsheets_40.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAAkJJREFUaN7tmE9IFFEcx79jq6Ss5EW0GFiyEqRLF0UZpYNXqUNRXaUlDfLgxVOdEiX2IGKQUl6CiL108k/oIVjcFuwSHowurjBIbnhZVhl215nXQZ5BKjvtb+Y9Z/d9bsM8fvPjw/f33swACoVCUb1o1AJN4x86HrdGIqGMZuHu/DyuYQT3+vowjsuI19X51fj9p5GZzpFkcvalkRq+1dsrVttfaqgFjsV9xAQO+/v9Fse5fqlxrnXbMIZfJHtmv6+tidF1ErLA48RJQrZIukBBiSsFF/nk91d9rjmVEvVcusBzRvv78FLL2+5uUSIrTiBHlMjACrRtxhyn9DoucvAg8e71jvd7ZGAFmmYut7fnfv3NN01d+jfDeLD5ORf7YZpe9RFYgcvLu7sbG0A6nc1mMoBtO46bRHYtXUnf+KnrXokMyRZRLtlsoWBZQDxumuvrAGBZxSLA2P5+oeCiwCS+ALpO7SOwCTxJfX1tLaBp4bDIl6oKEsgRK7ICBXLEiKxggRx/RQo/RLa2Bgampvyr39a2sDA6etodLvLoyvVhU4LAnsLlw0Uyxhi9mnSBZyXm36S6XeeehgYvRroK9kB/kZ5Atwnye+8sF+kC5Y2wN6gRJiI9gWqEiagRrnKkJzDoI6wSSER4As/+Vg0mKoFElEAidIHP8QsPvfgxJBb2CjEs5vPUOnSBeW0MnYmEbCH/i3YRjwB632SBh0WnHR3RKKZhYnF19dwmkvf1CUO4vbJiPwtdvXAnGpXdlkKhUASZPwFu9jieEVOZAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwGxDoJAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMGpNUJgAAABLdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9hdHRfaWNvbl9nc2hlZXRzXzQwLnN2Z4XZDF0AAAAASUVORK5CYII=", 
  "images/att_icon_gslides_40.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAAmdJREFUaN7tmMFPE0EUh3/bZZfUAuEAmpQm3UQTo0kvGkhj4QJE9OLJREM4mV684En/DnowHghX45VrlxKDUAwHTNCDiSHQQL02FDbYrdvxsE4wCNh2pjPsOt9xM/PmvW/f7uwsoFAoFP8vGmuA40KhAiSTuIonwMICqigDY2O4Q3KAaXYqcf3TtW/TybU1817q+dvS6KhYbSdEmCNQcTfIK2BiotPiKNrwlfs3n2UybvHzm+nk6qoQW2fALpB2nCRki2QXKKjj/gUV+fP6l/GnH9bXRa3LLvCSQb5G528tp9OiRIZOIEWUyAALJMTzmhj1W6Rb3Hrw+Dv/d2RgBTYajlMqNT9eG469Ts1nMj/iHwsPH+3t8cojsAIJqVQWFwHPOzra3vavNNORemnQSt9NJHiJZP+QPl5aAggRIe0i6nXHAQDXPTxsZd7AwMwMoLXtIbAdeBrDiMUAwDR7e0WuGxqBFNEiQyeQIkpkaAVSOi2yS3RBjUZ//9QU4HmWlcv5pcXjLBFdt1wGdH1nZ3YWiEQODmz771FU5Mms1jab8xDegZ5nWXNzALs4imkODf15Qy6GijSMnh4eq0t4hP2C+dPdnUi0kgUfgcIf4dMYxsZGX1/78+v1kZFqVV7+od9EOo0SyIgSyIgSyIgSyIj0XVj2LsqKhA70Tw78qdX298VXI1wgPXLxE+mL0/XdXT+uWELzQ7VdotHJSfVDVSJKICPsAje1F4Dryi6kZYq4DdRqrGHYBerkPbCyIttHG7zjkTe7QEfrArJZFLEF2Pal7Uial42XQD6PPEkB2azstBQKhSLI/AJie9putJDt3wAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMBsQ6CQAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDBqTVCYAAAAS3RFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvYXR0X2ljb25fZ3NsaWRlc180MC5zdmfYvJjpAAAAAElFTkSuQmCC", 
  "images/att_icon_maps_40.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAA6lJREFUaN7tml9IU1Ecx79XuxukmZBFD5YF/iuFysy0JYJWL2FGlPSPXhwFRkGtv1BU0ENFSQ8iPqgUjSL1xRhBCyLSpUzZi9AEoZStOXKFOPfn3u3u9CCXUW5s8247W93Py2H3nPu7v/Phd8899zJARkZG5v+FkRrgq6c+d8fjggJhH15nVHR3MyNkDXpra8kEcw2jCkWiEl/1vC57v9tgWH//zpsH5r17k6stSIbUAKI4PMNDXG1oSLQ4EaUmv2njBZXKfuveoRtbhoaSo2spkgWKFUdrArRFShaYrIqLhCjyx+a72usvhoeTdV3JAlMN1rSBK3BWVydL5D8nUCRZItNWICGBgCBEHieKtN+63XJ5Lv5rZNoK9Hrt9pmZ6McrNZv2FL5Uqb4dvDRz7qPFEq880lagx2M0GgyA222zWSxAICAI0VRkrrb87bYv+fnxEil5Iz05WV+/cychydEWnvl5nvf5gLm5xTZaGhqMRrOZWbaHFbQnLqJU7t6tUgErVzY2HjsGsGxRUUlJsN/nm5ycmADc7oGBvj6A40ZHP38O9ufkKBQsG/wdq8i0FZidfebM2bNAVtaRIydOhB+nUJSXb98ebF2u/n6tFlhY0Gq7u4Pjki2S2hooVlwkceHIyjp69PRpQKmsrKypWdoviszN/VNovKEmULxV/4bjxsZGRgCHo6WluRlwONTq5maA500mozFUnKamUHFEEi2SmkCWLSwsLl563Ons7GxrAwTh58/ZWUAQHI7ZWWB+vqPjyZPQcUpLI18vUSIproGBQCAQjziExBJHFBmvfQO1CvT7LZapqVATbG29cgXIzMzLW7t2sV23DsjJOX9eo4k+TiRWr45PJVKrQK93cPDDB4BlS0rKyoLHFYqKiqoqIC+vq6u3N/o4tKBWgR7Pu3c6HSAINpvVGvv5gmC322yAx6PX63S0ZkFRICE+H88DTmdPT0dH7Oc7nV1d7e0AITzP87RmkQLvwhw3NjY8HGzjPT7RUBcoEqmipFZsokgZgZHWNKlrZqJIGYEi4Z6qtJ+24Ug5gX6/1To9Her48vZ7iYb615i/IcTlWlgAfD6zeXwcIIQQQgBC3G6Xi3Z2S0k5gSK/ft28efEi7Swik3K3cLohC5SI9L92lJJH2EXzXWCZZMKEVo6TGkZ6Barxg9R9+kTbR6wwxwFyWHrekgVmPGVOku9qNXMKJqJ//z5VK1LMi9mKrYBez7zKqGQOqNW085KRkZFJZ34Dzg3IpkPczfMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDAbEOgkAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwak1QmAAAAEh0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2F0dF9pY29uX21hcHNfNDAuc3ZnIHRLhQAAAABJRU5ErkJggg==", 
  "images/att_src_icon_dropbox_28.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAQAAADYBBcfAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgIRBwMKqfdWAAACTklEQVQ4y8XUTWtUZxjG8d+ZqbpogokiTkkYo2aGdCNibdOVjnUhVmjiyoWKiLjV+hH0Ayi2q0JDS+2mpUI1CWoQdFELdl90MiFIEmNUfEvaGjUzTxfzZMa86U6f5X3d/+e6zn3OuXnXJ1lYClld9mjTijF39LmQjL7lntASvgszYf4ph19D2xscQ7dzGsoGDZkwhUYZOTlpphxILi4KhuNOSxVd93RejiY75Kk4kXyzAAzdzofUdX8t8RCfKUgq9s66RjC0uqXh2pIYdCowpSMZh1SsntJQrGHrHZYFax2Sj9WbSjQ6+ZpjyBoup7/3FCsUbEbFVdN2W4bbBjzHSkely9qSsVnHbunBOJLtNlfD+9CqKHfYBZ4pkdZVj7qbUgw04CYeOOcPN/QYQVFfVEvwZR1sZ6I2hBtG/OY+eOJ3Iy6ZidoEbKyDGf6NUrODso7YKkG7w7IOWR3Vf6AFPlj4vtZghZ02mPZxvOxTl+uzrNQdx2mI4BW9XoBhfytjWm/EYtd43XFYPuNxFEf94hPLrdTuipw//VfLk6l21xz7ydXEl7Z4qGirdTYZtCkmIHb11cELynnNUXyh3yMFsMorAzWwSTszemtgMurHVGytniE/uK2oR/G16hfS9CRjtTERWtzS+OaP/HPbmdSR3KtHldy1T7mgc0ms0zYqDlSxuT/yMWekSq55Mg9qtkOOiq+Tb2drc1fHV37WWDGo5H5cHWvl5aSYtD/pWyqPsCacDa8WWVY/hY/mdi62Hlt12WN9XI/D+l2sTvL9nv8BmADVTZAM0RgAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDAbEOgkAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwak1QmAAAAE90RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2F0dF9zcmNfaWNvbl9kcm9wYm94XzI4LnN2Z85N2HQAAAAASUVORK5CYII=", 
  "images/att_src_icon_evernote_28.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAQAAADYBBcfAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgIRBwMKqfdWAAACHElEQVQ4y8WUv2/TQBSAv7NpBZJDmwFhSKhSUYdIIJggDAhSNqhEwoSATkisQP8E+ANAgBiQioSACYmhJRUTajcoW1mqxigC1Q2BSgWSwFBiH0Oci+0mYYO32Hfvfe/X3T341yK2bskR8kyQIgk4fKTIjFj9ix+ZkA9lU0bFlc9lqk9EWeAphkuJD1SpAzFMLCx0qDMpZruC8jq30VZY4Hskj2HGSYPHlLi3BZQFXkhtgXc9ijhGDuFxvh3VB2WSZYz5nhhAlhzUyYgKgObv3sJY6YvBIjbEuBmIKEcou/q0qi3OAU5Q4xUb/EIqdIir6C4p4cA2AAropQB2EQedOJeATd7w1tf8wCajk+dBO9UzYCu/h1gjqVaDZALp2gBnoR1xDKpKeZSBUG07Av9VgP2d5pjwUykbAcMKDbYH1g2ARLCrAfkaiuaGLpcA8DpgBQyl/OR/14E4QyGnhm/drrFM2mTDVy7hsQ+T1+xkL0dCqZstaxVxDiyl9FiiyDSbHGaRdeUQfKtiB5zBTROP1DpKhQEG6TzFYcagyUsFilUea+QioMNBrtDkvdo5jQ6PhKPaBDLBMrH+l/w4p6BGRnwOHIdY4wJujmxPLMtJ8JhsYeGHfI07aDbzfItAccaxwOOGuB86UYWe4xkxjxI2X/zRsZs0FhrUuCyKPROSu+Rd+bvLsHoi94Qtu43HJHkmGPXHY5k5Zlud/L/yB60vvrbSswzaAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwGxDoJAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMGpNUJgAAABQdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9hdHRfc3JjX2ljb25fZXZlcm5vdGVfMjguc3ZnEE07QgAAAABJRU5ErkJggg==", 
  "images/att_src_icon_google_28.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAQAAADYBBcfAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgIRBwMKqfdWAAACHklEQVQ4y8XUu2tUURDH8c/daCFsIBYhK1nEqLsEhRSCJoXk0fnCRBsLgyAiWPn4E/QPUNRKEAS1EkQSYylGg4WvwkJCshIEo0YUH9kIQrJ7LHKzezcvO53mHn4z33Nmztwz/GuLlkpho177bZLFpHeGDETv/7JPaA7XwlxYbKVwJ2xa5cTQ55Z0ybi3phRRLyMnp46i/mhwWTCccVFqzLAfi/Jo0CNP2bnoyhIw9LkbUsOer1DELt2iskMLp8ZgyBqVfrQiBu26KWqNPsKaWL0gPZbAInu0IbjhS6w90yxX77yTkIobcKxkOLH7Ac/NItKdUB8qcTxkK6A+deOJK2mxzXYvwGYtFf2nAnV6q+BeCok0u7DTqBnQk7j6AuyrgluZqji3acIaWU9Bo+0V3xRsqYIZfsWuOrtB0RuvfQWd1sbeGWiuggnboQE8MSsY9ttva7Ul216utuOjfNq3GITPvuiIm1CJRXo+ugJOyGdi8LUuPLZHJpHH4/ibmY+upPqAXOx6adqEdTVY0at4lYOhKjiglLcezBkxorOm7hGzoMFW5tyvVEu47sS4e1a3w3Jci04lwWaj6lf/yTt0Ma01+pRoR/TBEaVu7Sti7Top65/Hah/yaZekCh75vghar0eOsrPR1QWtdnQcdFt92biCz/HoaJKXk2La0WhoxYRCY7gcZpcZVjfDhtrI5cZjVq/9WuLxOOGBwWjSf7c/JSjCkef4SfAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDAbEOgkAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwak1QmAAAAE50RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2F0dF9zcmNfaWNvbl9nb29nbGVfMjguc3ZnYkokAQAAAABJRU5ErkJggg==", 
  "images/checkbox_off.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwEAQAAACtm+1PAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgIRBwMKqfdWAAABKElEQVRo3u3YsYrCQBDG8VljdaCgfcDm6thdZxnfxwXJA1gtxLyAT6CdWpxFGjs7SSPbCdpKMAEbEewOlZvDNDtXfL9OJqvzJ1ZLBAAgSf01HKx938uShHZhSB+NhtPNLmVJkzRVnSgy1trKAYO173vX7Za+222ni7/a5PltFATj3uHw27jGnfOyJBFfnojoq9XyFnHMjdkA2oWh9O4/dL/PjersoZf/vDFudx4OHz7EzSb3XO2N7/rXECANAdIQIA0B0hAgDQHSECANAdIQIA0B0hAgDQHSECCNvxu9lOXj/ejTXaVr+/OZG/FvYJKmgis/UdlqVTlAdaKINnkuvTzNTydaal05wFhrb6MgIJrNSBeF88V1Uaj5dKqW3a75PB6d/z4AwFvujM5H5k1c2IwAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDAbEOgkAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwak1QmAAAAER0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2NoZWNrYm94X29mZi5zdmcAxvXwAAAAAElFTkSuQmCC", 
  "images/checkbox_on.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwEAYAAAAHkiXEAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAA09JREFUeNrtm19IU1Ecx793OVHClaaPEgT1FvrUQ0JdEnXKZFcqIRQFXxSkhxRyQuQGPeiD86GE/oCgSYELt5ljCkpvog+C4ZMgQSj0IDadBMvpTi/7rTTWPHavd7s7n8fdnXvu+X7GOb972AEEAoFAIBAIshHptA3tXb5Be1dp6cFjdknaHhqS7mAfudXVuIISbBUU6D0wzfiCLZTs7eEbdnBxft40bfLFFIdjqsK+MFWxtsZ7O24BFPzhbTzDk5UVvGEjUltRkd656EYRxtEcCp0rlm6yhbIyv1vp9rs3Nk7a3MTbH/3isz544juaMV5YeNiEt2gZHORtzi0gMdUIjjLJiqWtmhreZtwCDD/Hn5bP6MSwxcLbjF+AQFWEAJ0RAo7jwgfcW1pibsnD7vf3a92dEEDIALC8zJ6aH0Tf19YGrinv/E29vYxJM8zqcGjVrRAgA8DyMvtkNkejVVWBgM0WCIRCdDkQUF75OwYGtBKRvQJk4F/BH0cKsJdSR36+2o+RfQJkgCd4G7xMgdMJG3xQ+vrUfpzsESAD6RQ8YXwBMpCOwRPGFSAD6Rw8obmARD0dr681H1G8n8hMNGo2V1ama/CEdgLq4UWD00n1dKQnajf7a2rYa8nNuhYXVe9PBv6s4+fmGhs9nt3dZF/XO3hCfQHx4KfbG8Z8rS4XfUyB/GzZf5j73GpVTYQMZMJUkwzVBUgv4IOSvF5WTYQMZHLwhOoC2GWMorWnp/6616LsJt9LIRGxW7kj+20cU5MMGCF4QrM14KQigut1V4Pr4XBKETJgpOAJ7aug/xUhA0YMnjiz9wASkQgoCSSC1ohMKSdPS86Z9xgPqP6r16KM5uV9XG0I+y78vcuYqoz8fbvMDJ7Q7U34pFNTMjI9eEL3rQheEUYJntBdAJFKhNGCJ85+DUhBYrFe9SoKIpHEBYMFT6SdgAQGDfw4aTMFZStCgM4IATrDL4D+Hy84igsKfKlfHI/DLyB+MEHv8aYbbAczsM7O8rbjFkAnQuhggt4D1xs2hvP4sb0da48xk9TdzdueWwAdxaETIXBJLub0eFCGYXSGw3oHojnxcbJHyENkYiJ2I3ZgyikvD67frZsMbm7q/XgCgUAgEAgEmcEvuKRTfu/rKrQAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDAbEOgkAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwak1QmAAAAEN0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2NoZWNrYm94X29uLnN2Z9Ts0gYAAAAASUVORK5CYII=", 
  "images/en-attach-icon-3d.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAABkJJREFUaN7tWn9MU1cU/m6Ldcwl4lTG1OnEbbDhdBE18wcmzqlRJ46ZuOkoKGRgC7pSXlvQiIBO6C9+DGwZBgYUqovZMkEXXTaXSFQCwjYmajURZ9RhnYqZk6n03f0BF1kNKdpW1L3vn5f2vvOde77ed+855xUQIECAAAECBAwMyEBPoDcoJWStvzrI+NWqVaSYLsQ7mzf3jMWRAziYkVFk19mSP7RaAYAQSgd6zgMuoEyiDtKeCgrCTf6EWF9QgE9JCl6fP79Pg2B0EmttLSbSdfz1xETzPEOgqrW5eaDm/8gF5KScVF8xZMgti8gCqUpFL9Kp5HRqKrZiLmokkn4TVaIFoZ2d+J2ApJlMjhTy5t0laWnFxVptSsqNG0+VgJQSIp+uGp1TKpXS5yGl47VajIcDTQEBHnPyM6pJytWrpBUpdPeWLf6Xh6y5GVFQkI50pIPnnzgB4zdpjhtLJk8WaR1ieqawELGkFCNmz/aWv/twFPF4uaGBDOf9EJ+QYPrROIK72tDgaTciTxEpoEAu9fOTXVMvNobl54vyeDUNPHasv8LRFBxH4oULpBFWMiw62nmc3KFt1D88HKBalJw963JCM/AFzk2bRv8Rcfi8rk52jms3VFZUJNSnztv2w/Dhnorb7RUom5p8wLBg0SIsEJ1AZFkZruMS7P7+Lg2rEYj2jg76Hf2AlGq1vrccZ8lYnS53Ru4MZV1Hh0ymUhkM905Zs1mv5zhCko4mHc1529e341lxID2vVpPF5Bsao9EgHGfh5+vr0u8wjIK/3U7ewhGRKTratEK/W1m3f//Dxu/+CmwWrcCh8vJ+CzcR1fipulqcTo/Q10JCiiYbXki+lJHBhHNlzu5jdoyH8br03z1P+gtm8vLycnfD93FbwFjEYevIkX0LjCt4kefJFOTgvchIU4Jez3E7dwKwYZ/b3lH4icGiimpt7fq0bJl8nSrVYF25kjZBib2VlZiEkfhDdP9C6e8P7gIe2wP7RHcA9Ax0aMzJkU9XjTaWREUBXaezp9zIYzmpvmLpUp7Dxxis0/UpnIfhfQFjEEC2HD7M0hYailX0enm5TMKdNKYeOsROa2czGkHbqP/KlezqPM7sZBLupCGltpZKSACxV1eTbExE4ZgxPX69DPcfYRcwT9MnK9vDwu7LA2NJKZpmzxYd5K/QZ5qauk7JqiqRfdDyOwFJSdunZ1lU7+7axXji4jSa7OyhQ8XZ9LdB+zIzMY5X00C5HLEkBNd9fO7LA81D1vx1o6Dgsuxv1XNwOLwVn/dXILpqVlO9/mJybEWFY6yIdtYHB9MNOIeL+flohh2jeB5a8hnapFL+lbt7JfEtLbIAdb7h5ehodhVnO9J9dths2EhD6LL16xk343FMEr1/d+uECabL+jVcRH6+txNoBq+vQGf0lFrFAKBQyCTqIG282Yx8vkZ8srsWls2fjwgKoKysx3AjSQNwrxb+lhby2xMTi14a2Fr4kQvoDPMdnU0TbLNBAjGlCxf2dGOW03BcqKxk99GvSTXGREYW2XU2ZaPVCiD3cejGPJJHuDfYXib7Uh1kXJebK7vGdRjDOA7oetSL7Dob91FVlbNd7+8JoZTZMR7G+1QKyJoJxpKoKPF5nvhMP3UK9TScjlMoMI4sp5lZWQ9Myuy6eRivt9KkARNQ1qAy5vjV1rL0pacL02svozGhoQ9MzOwYj3Oa1O3X2/F5fw8sRRvdNGsWWiHGlLY2cg0W0qrRmMz6i8pGiwUPuZf9p5HaOmeOPJaT6hVLl/Jp5E+ywmQi2QDFrFneDs/7jzAr5V6FGqFKJUtnAM+25E0lBosqqqZGZEAVbqvVzK+3w3NfwO7uRp/jrJTrRBZ2WK2y7aogw5I9exJ3cFJ9xfjx7rpnPIyX+XFZyrma9yMT8Hv+DVSuXt3vCR1HOOaGhzvSyUxyuqVl7a/cZeOozZtZm8qVObuP2TEexuvSv1M7y93wPXZKsYbq7amDNjgWZmZCCSnscjlqUYpIsdg1Q1ejlNxBNE1VKFht2zPR7oYqlaCcZOXlAUSD2MBAl7RhiEGlw4EcWOBvMg0+dneb+EBaWh7ykETa2x8bAZ3xf2npCy+VngQBe0N4relhCC/WPYgn8a8dAgQIECBAgICBwr8VnItduBCehgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMPGM87MAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDCA0UsPAAAASXRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvZW4tYXR0YWNoLWljb24tM2Quc3ZnojGHtgAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-after_affects.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAA1VJREFUaN7tmF9IU1Ecx3/nrrmQWSmBU0duJcgcIhllkqBgKEhpDzoohw9CSj1EhNRSpCIjBy76Q6U9jGFbgpsvmS8+KZTLIkTBmSm5JETBWiiam+yeXryrVpfde3fvtofzeTmM+zvfc/jy2/eecwEIBAKBQCAQCAQCIdYgqYTduA/PYI0G3gYdeGZhgbXwuKwe6bTaYnQW6ZDXG29D+EJJJ00bAMrKxKtLTKQz8AX+inNKS0WrS1CkMzATfkAnh87iWpegiJ6BnLMvHIFZOP6yd3n2qFZLX0SpwU2TCW6iAcisqoJUKEKv09PBB+O4ZGUFTaBmVD00hCqDc1Sv2VxU3aDKfc9jfyxI0IFCM43fvLEax9xHQ2UlvkZdDr6amgIncoKzqQn0QMMDtRoywY0/yOXMb2zET3F5czNdIjsQNE9OjufYH868qahIPAOFZhrHeUzHUZ9wO/3I5cJWOAXflErO68xiK6hSUuh3qAX7Xa6xww6dZyg7O3EMFJppHOcxf1XexoWzYyQ1j6vQM5NJqIxoBoaybze0gV6j+adgC+7AtNcbGsPZmRfSYYPJOBawCjWizdbW5AH65LZVqYT7WAGFbW2seoVwF4bZ9WJmYMQMW4J9YBoZCY0CdVAHrML+jAy253uvyu202WIp6GpQFXRtbPg6fFb5eYuFdbkv0I3PZGXF38BIGXYOqdH86GhoFKiD+yAN2mUytudrVwIBdMvvd7vtdo8H49TVtPrtC1tbQvUisUs0AyNmGNUP8GfnBR0RdepE251kRN2BXLOPOd+FznnRZmGCIEIHhjKr5r+PGUPcdvB4MBagCwA2W5x9YiV6A5nMOggAgyLu7K8s/G0gOgvf4XYwyJZde+4lJeEbCoXeaTDonYGA1AZG/xKR6i7LootLYAAtLC2xTVuj/AgNtrRM1/X3T9clJYm+rzAE34UF33n5EnZHdquf+z36np7Q1U0kiouNxrw8xNuPKDowwrnvMzyG0zYbszG2kanjug71BPtkyZ2dkIsaYXl9XSwDhSLcQK7nvkjwPBcyX1GoY7gLKWpr422kcAN5n/sE1rGsUzRvvKQ7MTyMy+EQ/MzPRxUwga53dyMTGNCRxUXmZRM7KwkEAoFAIBAIBAIhVvwCu8u0NlezHZwAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDDxjPOzAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAwgNFLDwAAAFR0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLWFmdGVyX2FmZmVjdHMuc3ZnZxRiigAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-animate.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAkJJREFUaN7tljFI3GAUx9+LXcohUengIBKRjm46CNKknQ8X0dymLo4K0smhpYXrUIrF0qWF4t2kp4NwOjlIooLDzR1FBymd9CK43uvS7ywnueT78qWXk/dbwpGX9yWPP797AAzDMAzDMAzDMP8b1N3whgrggGVhQC7ZFxdhdWRiBf2RkX7cBg8uLzs9CFWMdNo6jt667KJ9gMb7RtCo2bauuqyjP4FfcBoLMZIVty7jaHNgXPe1IuvCet11bZtI+kPn4YgO7u7gFp5CrlZrDNMMjq2v95d3Pvs/9/dVv1tzAlUTlX4SqQyvMJ/L0R5M4kvHwQ38Bc+q1fq3uR92sVhU7attgKpO67gLXTyEw7W12w/uVwfyeen31/Yiqk7LiAtpC4BmVldln3uS9GDhPgpokIYsq/U+jsJvuLp3G53DIPxTJ37fmAVwzi0r6V7Y11ep+D4+cPv19eysA1NThmEYZJ+cPHiwBybh+fi47HmaEtgmQctUpW3Pa15V+yRkYGB314PT07D75MFHOOvtle2beIBRDmu8MUxjwvfFVbVPVkmewFgOE8lrk8CMuFAW5QE23dfiNIFwn3CauLY6UdB04d++nR5MXBL+iYQnRgykDq5rD90vvvE2YNG3VOr0gKJQTmBazuo2F6o7MC1ndZkLpQcY5b6kdJsLFR0YnhDcoO/0qVQy3+6YxxOLi2F1wbu54EVtc5NWcAlfLyy0Pye7LpROYNy9L6rPY9kL5R0otfdF8fj2QoZhGIZhGIZhmPT5Aw6pDHQgp7roAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABOdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1hbmltYXRlLnN2Z76BYtsAAAAASUVORK5CYII=", 
  "images/en-attach-icon-audio.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAABN1JREFUaN7tmW1IW2cUx8+5xpfiCyw4hJam7bLCOq0MFHWagt5E6Xzph7H4IVAEV2yyKQPrdCq+sc6KjrTr6MzSTXRFobGlipLO1NxofWvpcJuQDW11jNoWW1u2OkGU3bMPM260s5qbe+O63d/HwPM/5/yfk3OfhwdARkZGRkZGRua5BLcqsNHhIhfFxMA4P8PPZGfDEKpgKD0dkiANv9i5E4xwmWzbt68tsMAbmHv3LlwDFx25fRtVWAmXHA5mgMIwrrf3zI9sNVvtdv9nDTS97CIXJSWRlhIpsbISEBroRHa2aAFehAXoGBnBfZCJlsrKZgMbyAYODkpdl2QG1oKLXKRQ3DtBKlIdP44/Qxu1lpVJXZAH0gOA3mp9ZJmff2gpKurszM3NzV1eFjuO6AYW2e037TcjIlbGQn4IbrDb4QGEgyElxS+u/VOBLfAltgwPK7qWapdqs7I+zczcm7n38WOx9BmxhPR6m81mCwpamd1WEhx54cJWG+eB8uFtytdoVtwhZSFl3d1/bnBwsFj6ohmoPBZpjbSazTBO78F4erq367GewiA8JYXnMY3nDxwQK681pqGQ3k1NXSkJ+T4ovLFRLFmfDTSZOI7j4uJwCi5Tj9EoVKdZqU3QJoyOWq1pmJ4+PCxWgU8RgZ8wbxYWGrOcrc7WhARf5Xw2kM/FM6RpaoJRGILRgADJCn8CwR37GtXRhwwDZgyAjvp6X/MQbGBBARfNRavVqKR9UJuaKnnhT+Bzxy7BJMSz7JHJwV8csXv2+N1AJgyyIMtggGZgQYub/pp7W7hks3E1b0Ui3xiQaDD43UDoghLC+HipC5facPqGunF0/TqkM1CFiVAXEyNW4WLhteEzYKPa/fuFxlMIXWgZSPtJG6JWwwCw/jJHUJ4WltU+a8RYfNMX7Rz4f2XDDjy66Apy9o2M4DH6GhTJyZsV3nDn/YTRyHFOJ5G36zxXwOZltp1tX3+WbtiBzAukx6943tsECgpcdOWKRmN80D/ZPynBzULiuPQ6roBtY+M37MC1HbBAO7T/9fvRTs7EmcrL0Ql6euvpAynDkIthhoagigGY9d0Q5qPfp1CFCFVw51l6XsfdTbtgd3m55QOtWqtuaPA2P8EzkM/nk/ikixeFGrLZDvmbIXdw9upVofmuW8cMHsJDnZ1C1ws28OyCLk+XNzUF56AJP+7v33RAkQzx+a/6K0xDRV+f1cq6Wff0tN8NXBNI4qP4qIoKMAEHAoa14LhCN2I1Tz4ckrGlpsbnPHwV+Mypa9W13rgBSuhH7vRpoTp+++iY4BJ2m81WKxvNRl+/7qucaOfAh8XzxfPFpaWetwmvE5F41oEF5sEyOMjHRLRFtJWXiyUr+jntcJQj1hEbGhr6m2KHYkdXFxyG96lEpxPdkM2yatxyaRAb3JyT09KoidRELiyIJS/6TeTcXMZExsTi4tIi2tGek0NF+C0EnjoF32ENVnl/nvQaT5xX0ADmkyeXAPWM7eBBsY3z4LebgvEl7j53PyWFOiCMzldXYytcg1czMnwW9ny8GmAXOB0OWuCD6J26us97dXm6vLExqev69zysK5liULIsdMAEbFOroZMm4FFU1NoCPcaCcm6OGsgNZ2/dwgG6B5kuV0AbtmN7T89WPazLyMjIyMjIyDyn/AEId12K0jpz2AAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMPGM87MAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDCA0UsPAAAATHRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvZW4tYXR0YWNoLWljb24tYXVkaW8uc3ZnwuUY7QAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-dream_weaver.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAt1JREFUaN7tl19IU1Ecx7/HO6UCJQqhlIzWNiXowaeCCDRKjKReFlExqLWwXDcYRVrhZBNNIwi8zUI3SaQgFUvMeuihvRdmUBEb2h+miEjhPyL68+uhrsb04nbZvRflfF4O99zf+f3O+fK959wDcDgcDofD4XA4HI7esGQHBAKRiMtFlHCBC+wc7LOztIE8mIxE2FHkE+vvZy+FnelrJenss63jd0rGx40WQi2aC6iIhM3InZ7GdnYR651Od5dVCp7v7jZakGRJM6yyiE8YyczEWyrFjs7OwOGo6Gqy240WJFmME1DGDStaGYOHXDgSCjXtj4on67OzjZ5WophSrofbZgsG2dzWIPW+Dzkv5eQII8KgcN/hoGq6Sff8fvgxjI6MjLmBr7AaV7OyhBNUIKwRRTwFAK93qS0jvt5SpDqf5g4UDxWcars+OlpRYZVaY42NrJZ52HGvV3FAJczYVVam9bxShe6fMD03Nf2ItbcrBqzCHryzWNTmlyhKLhQVya3W69FdQHfXFnYXY2OKAfLhohIhjy6jvqZGbrVej/GHSIqQHUdVcGJ4vtXaiStGQCXHae3EZS9gvPPi32vtxGUvYKIO08qJy15AJeepjUsW3QW8/Tiy7syB3FzFgEJ8Q93UlN7zUovuAv5uZw9+fnc4FAOOYRThoSG1+VkD2mAOh+VW6/Wk/CoXzyJXuWKq9vlQhGF0LIynJ7jFbvT1YZu6er8+s2u44vPJz2nNFIVLu9+YlAu44K4ZA/AFINBuKgX+3oEXGRjGID5OTqab6CArlCQA/XiReF3ZcaLb2hDEvPOaN0WqXOZweMXsgQsIIIrTRKjDB+pwOsvL88tbWiYmkk0T77yl+lOFcQL+cxwe4Q3l2e1um60ytLGnJ9k0c85jVva/82Tkfq32RO0FFFgJemdmsA8PqXZggIrhYa/9ftNe+ppmtljUCieTqMO0diKHw+FwOBwOh8Ph6Mcf0DtKajHjm5cAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDDxjPOzAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAwgNFLDwAAAFN0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLWRyZWFtX3dlYXZlci5zdmdrnj5XAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-editing.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAQAAAAm93DmAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgEOITR0BZreAAAAQklEQVRIx2NgGAWjYBQQBozYBPf9h9BOjMTxkQETtV04+A1kxCdJStgNHS/TJwxH0yFJYDQdUg5G0+EoGAWjgD4AAAmEGiSYNnVwAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABOdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1lZGl0aW5nLnN2Z5Hsl2oAAAAASUVORK5CYII=", 
  "images/en-attach-icon-evernote.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAA7lJREFUaN7tmF1IW2cYx/9P0mVaA0O7sUDNlGBlrZ6MVTraQSnGldlYtkJVOkvN0Y6D0E2mrC1DScPoMPVCWFkhlWVL2iEt/ZhQ3FqmiV13sY15oRmxLe3E6karYhxLNhdzzrubxQshyOqJb+zO7+7AeZ+PH8/7ng9AQ0NDQ0NDQ2NNQmoHLHUENzlOV1Whk31D8tmz9Bp+wfDGjWrnCYVsNp+PFuu3YoCJcLlGUEE+uFxp9raITu2ANMBaYPd40iUuFUygIMQTJ5IiVyuv6gKRixfpZH7+ajWwlKRIQQiYRbjd6c6nvsDMwQ/x+PF0i3ySBSZJq0jVHyKCEAiIImNp19JJ5eu2ms2hPeX0afPkZNrzpWDtTuBe7JXbu7uFr4Ps7dP8zty1O4GPydLXn5XCfwLnsA3FsRjrRyN77/Jl2RnfpLdu2GAwxI4aDDk5OEdn6JwoAvgCzZEI3sWf0M/P8y47yTpumQsxx5zRKN1XfqMLdjuL6X7VhYuKwjWVZm/r7OzifS9jCPD7AQBb/X5Irs9c0Om2XNrFJrosFv1mvCKPOp14i53CwqFDq90GvwnswRWKXryoHKR6zGVlUYIMytiDB8svdMEFRQnXlJO39d499qZyhvo8Hl5tcJtA+Xrcre8/dizcVmn2ds7Oou3x4ihu3Tbd+1NT+g9ZUB5Z/T44noFP58utBsNKo2S7E/3629PTvLrgJlD/Eozso5KS/7pO+CCwT4THs9k+EDlsKih4qtfYEInE47z64CaQipUote3cudx9ZWXXyiRp/frkdajD1utDU9PoVxW53ofj4zNfRoKmBkXh1Qc3gcoktbM7+/cvFZREEG7dqqvLzY2fNP60UGi3p4pjbM4u+sOenc2rD24PEdqDCuooLY0X5pT97Xz0SPg44Ha8MzjIRnGHioeHcWDBg7smE5pwg0UaG0uvBn4Uu8NhKJiG9+bNn6ttVb4fjhxRnlVa6HWLBaA3eLy9Z/yXCNXjearfvp0Z2Sn597w8fEcv6PL6+uR9M9bYJ1lZurvP1Rifqa2lCyzIEufPLxfvyfsSSYUVATQwlneUthTYhobwLQ3p7ksSphCFoacnXBOuLbmUSNAga2GHKyt5lZm5Akdgw+dE0zEcHLvicPy1Y753YdzhkKWZV2NdjY3WsV2m8brdu1GMDuyoruZVZsZvYbX5/2zhNYImcIVoAleI+gIjuM3a+f1iT4kFXXg4MaF2WPUFtrHvWUiSMkbkv+Joiq7huiTxLkdDQ0NDQ0NDI0P4BxlTbqdWQMDGAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABPdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1ldmVybm90ZS5zdmdZOLbtAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-excel.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAABHlJREFUaN7tmG1MW1Ucxp9zL7GoTDo0IxOpMidTcCDasBcCEgxGhZEtpMW2jLElRlFpaDeEDLagAxJeWhbJZDAFwkZLblEzthH1A3ElxrFgSMkgDmNQ2CRkOhkwBeXe4wd3/WC98tZeorm/j/c+93/O8+TknPO/gIKCgoKCgoKCgoKCgtwQXxfMmnDYCrUOBwqwkSYbDFI6OoMY2mQ0ct3GJ23TTudyx3l5q3PwUIvRSKPoFQy1t0uOU4NsTDocnMYo1J42mXztl/F1QcEcEM48l5eHVBShcWxMSke24l0S39Cg03FcUZFGs9T6Oh3HWb4MC6N7aCXurq+XFCaiEnuuX6cHAzr41/Pzfe3TbwG6XHp9VdWtW6SCXCSF2dm4C7PYx/Newu+QjKeCgxn3QhPfceaMTsdxOh3LStUtQxnKwDDEtDDFXmhrw1VkoD8kxEv4ETIwKQhMGz7AyZwcl0uvr9tx8+Z/JkCRjlHDppqjvb14Df1Ee/y4pDAZB6BLTCSlCy9p3iwokJJ9/fyWT2d/tVqJE0GYS0mR0tFq+hU4u9152bit9nRPj7/8+T1Akel96sK5j0tKcC/eRrHHI6UjPyGRXKuoyIrsuGo9EBsrPjfscnQVrY+Opn10M8KPHZMMrgkCLR4ausfyW1LQ/JEj/vb117zlGkgMQnAjmmf7+/EC+pAbGOglfIXkIWJ4WGhkT7FjO3eStoUb/A9uN8nFeoTGxHjpX0UN4ubnmV3oxY74eOdtY1DtpsFBuXz5fQWKOM8ZM6p+HhqiboTSD0tLJYWnaANGo6KYDL6ax8CAZHB3oPejlz5UUiJ3cCKyBSgSFTsStO7ZujpqwCwC/2WPOk+t4CMiJN9rSQlS3W6xntw+RGQP8M/TVBBoe4CaT8vJwRZ0QbuMU/IosSJ9akq4zFaxPXv3ivXk9iEi2x4ohT7bYSvUZmaS37GRJnd2LqZf7QXc18i+Ar0m4CGp9A2Vaq3nseL5r9XAS+4o/sZKOxh/sUZ74BI6CimW2cH4G9kDHPZEzs5ctFgW6yiQTuxgR0cl3y+xg/E3sgUoXqRJEiZJZnm5lE7sKIQu9i0WcXEr7WD+NwG+uLn7m/xulYrnMM6nOxySHcidjoJ9ELvJtNEo/pRgbqCGfcxkwifYhta5Oa/vGlGIAZUK79F45hmHIxcttAz/UN9P+P0akxXpDDz0tM2GONqMFKt12QXM+JzU22w0CHbhs4kJUokucq62dqV62kT6aXFrKxdssNse2L9/tf78tgL1F9qfOPh+UhJG6Y+IXsUelQw71Vss+IKeJTMez6IdjJT+Ns5CPzIyd+WXUDbBbPaVT5+vwN1ooQVQq1XbVeUBnYODeBiP4lJ4+KoLf49vsX18XAgXiviwtDSmjNWw82433qF2nFerF9MDOMkE8rzLlW22xQ0P+8qvz4//2Ims+xK1zc24BA0CEhJ8VliNEFwLDiaHyRhzeMMGWo3HSV9lJRGwDo/o9YvpObMpx2Y7ccLXfhUUFBQUFBQUFBQUFOTnD5IT87RPuiVFAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABMdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1leGNlbC5zdmfxydgVAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-flash_builder.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAlBJREFUaN7t1k9oknEYB/Dvz+lJnBBh5GIucFOhQ4tVWBFdGjHWovCYsDmik8QO4YIxsBUxgmC5iKDVdumwYBHuTwwGHarLYIcIfZV5eGUMysFS7GLTp0t6sKR8/TP48XzOz/s8r1+e3+sPYIwxxhhjjLFmE1ofVNVoNBYjatSL2Wwul8MhSu/3r3nl9c2ia/ZA2XCANeIAa6RvVOP9+iY1G29gjaQJsPgvrT5WjsbPZLPJY8rZ2J2NjeSbyA/l28REwpKwJCwWS73nShNgyRVappdGIy3Rcwx2d9MJkRS7Y2OGvtzy3pfNTfW+MqQMeTz1GidfgBVQEEbsmkw4TwPi2vx8vYKU5iJd9Q8fxDq+ZjIGr35d99puP+zrDHWGUqlq+0izgcXAxbT4RB/a2gBcgn90VFyGGUdyufJ6msVJHGpt/RnNHyen3691rjQBFrU/dA47h7e3bTaX6lidnKQw3Lg6Pl7xgRW8oK3+fq3zpAuwXKG9cGrPPDdXsaCHpjBit2vtL/1FWv/IsGZYa2kpePJ36d5fClREoGj/tkq/gTSdv0EPvN6KBSnxDCuJhNb+0gWYvK3MKDNWq6pGbbHeQAAm3ML1YLDiA2YcFJ/DYa3zGnaEm614zSGUTuM7nAMojDS2/qwXFzCL9+m0/qLoo4FQCB/xFkvVz5UmwP+WhII4UeEVMuK7z2d1O252BXZ2tLaT7ghXIn5vHOmxKiIeT4fb9bQrsLBQa1/5NnAKHcKdzYon4gCdjsfRg16hW1wsHtVaN44xxhhjjDHG9t8vz+jmi31f438AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDDxjPOzAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAwgNFLDwAAAFR0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLWZsYXNoX2J1aWxkZXIuc3ZncTh8HwAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-font.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAABBNJREFUaN7tmV9IW1ccx7+/28RSZxGprWVWbMaElHbV0BVj6SqaJvTF1I6ylTLdJBkrtezBqblRcQplSc320IeOUheHun/kpVqFYZLGWR0qtg91xclWJ+omjmxuDkXUJGcP475Yr2FbspPR+3kL93cO33zu+d3LORdQUFBQUFBQUFB4GiHeAf4uDofD0c9On2YXyYfS2lo6hp/ZeZ0O76AMmenpTww4iuPUsL6OcWhZ6r17ROgMV1ksoiiKRuPs7FMj0HnQeTCw0djI3sIlDDY3/9N52EV46brPV5ctBoq6TaZ/m0vgLSYajgOOA/3szJmo4vaiFnqvF3fgRcHamlwZvYcX2bN6fazyJbxASqVU9kl1tWzBDdzES+GwcJK+C2dVVMCMTrw8OChXzupwn+ZHRmKVL2EFujpcHd6j+/axSrxNt4qKZAvn2DRuDw3ZtDat8df5+fAtVSP7zGqVWhWv4wp+X16WVqjwOUyhK1ZrrHKqeIuSY+NR5LL6SEkJpaGBWQXZG80eCzkspatL+t0wXe02pM3MIBsATCYAKeiOX86EW4HXJq9NDv2yezfdYEfYrM0WrT6sFhpVJ7rjqGh7uL+Fm9CEnmPJyWrfrg9SJgsKhD6WwzJcLuzBBD7S6WQHfo+9SHr40N4mWopP5uXxys9NoMPhdAYCjMVrfrtdFIuLKe7/L+Fa+P8G9xaW8Hg8Ho9nx46pyz80p68tLMjuLERmQ9bMjAgRRc9rNERERPFbydFImBU4lTGVkf5mYaGsOIks+hFlXV28xUkkjEDkIQ/us2ejlUXu0wr7ht9bdzMJI5A0pMHNkhLZgkZcp6rFxY39q1phWX6n8V/DXaBjwjExYNbpWA1qUafRyBY+h09ZW29vE5pQRKEQ79wS3AXiEA6FuqO3Lsugj9GROK0rwV+ghdro69JS2esDGMOd1VW1VTCGAn19vONuhpvAq5r3LXd/y85GDoJYz82VLVyAmb71+2vKa8pN4ysrvPLKwU2g4A0PYPjcuWh1zESV2JN4rSsRs9MYaUWpkkMj1Ot2sxdQgFK9HrloxivDw5uP0oUTbElwm82sCmCVW0yYijR6NxJRZwofbiz19AAo5y1rK2K2E3Eedh4OdPr97DWUIdNg2HxdOp9TjQqX0FVeHg5FiHnn5jCDKahVW93IMrj8frtdzCz+0mjkLUqOmLUw82EUz+Tny12nCwD74tSp8B+R82y1vX0bcX8F66cKttjSwltQNGL3DGzHElq3OSo3w4ThnTsRRAtG5D/m0BQe43h9vc1r8xpGfT7egqIRsxaWnoHCV6Fp4Y3WVnqEegQLCzGOMXY1KemJARro4Q4GsYtexU8PHkTyMcDGWlrq99u0hpX+ft5iFBQUFBQUFBQUFLbjT7zJdhtwzFwbAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABLdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1mb250LnN2Z50G1j0AAAAASUVORK5CYII=", 
  "images/en-attach-icon-gdocs.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAAihJREFUaN7tmjFIG1EYx//v8KJRC6F0qR69QYqVji0SGq2IW4cOdlFXg2YS2kJpwaWLRSkdHCRLRuvQRcRJESWoEaGdVHRxESwuouBZk/TuOuhrQYRc/fLe5S7vN7/73seP//vucRygUCgU1QujFnjR+3nw15JpYtL5qL3NZFgbfrqZzk48xzIeRyKiGu9qfTSk/Vhbe/flZSzyrKNDrrZ/aOQKXNwwvrobPT2ixXGan9zd0toTiYk3cyeF9dVVKbZugCzwb+J8wm+R9ARKSlwpuMjx6fn7v1tyOVn70gVWGAZi37AXj8sSGTqBHFkiAyvQcRzHyzoucuzT7CsRMzKwAo+OTk9t2/t688G911p7IjF6Zzpn7R0clKuPwArc3NzfB4DDw+Nj275MpOuWfq4tbdq1LYZRLpE1fou4LZaVz7susLKyuwsAxeLFxdkZUCxa1vm5hwJPATQaBpZpfQQ2gdfR9bq6aBTQ9YaG+np5+4ZGIEe2yNAJ5MgSGVqBHNEiQy+QI0pkYN/Ct4WLBLxcekojXeDMTCpVKIir39+fTnv5tKHr0eilSBpVc4RFIT2BXhMSFFQCiVTtDCwXKoFE1AwkohJIJHAzsNISrBJIRM1AIiqBRJRAInSBWXRjW+TVWBAxbOB7Pk8tU45fOz6wgWzWbx//TR+bZX30vskC3VrNdKaSSaTYe/ZwcbFiE3nVlzuCHWYsLLAme8wZSCb9bkuhUCiCzB8kv8RReqfpewAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMBsQ6CQAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDBqTVCYAAAATHRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvZW4tYXR0YWNoLWljb24tZ2RvY3Muc3ZnB2JdzQAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-generic.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAACidJREFUaN7tmXt8TGcax3/PmcnkOghaFSqT20i0rpmkaC2p6xLNolKCukcwCSIxEsIqRVyLKMalWyp8XNpE6bpU0hRRMknrGpMwM8lHrJYoIhfGzLN/NDl2M59+rIrF7vz+mc+c9znP+z7fc877e897ALvssssuu+yyy66XUvS8B/A46XTXIq9FurgAZYFVAyIi2J/UdGvgQMzjKvzati3CcRn9PDxwG99BcecO3NCeAvR6VlAf1mZk0Dj0ETw3bgw6oEz19DQY/m8A6pT65sZ1YWG4j6V0PiWF96ADxzVv/sQFjscybLFY8CeUUuDKlWWrZHs5LCkphLzIi6qqnnacLxxAna7gmHFSTAyv5VNQrVyJSeiPEEGwCUzHZYq8cQM/0nb2KC4mHUooWy7nvtyfE3x9f/e8naTG6cxMGurm5Xg0NFSl8tB6aCsqXnqAunoFJYaNPXvyIN5BkoMHbQBUUE8knDiB1tbzQh+NRuXeUt5iZHY2ERER86MLkO9c1LtpU14mXLC6xMXRJSzCm1Om8EbEYYxEIuY7AgsN2ro1KLFlK0XeyJEvLcDjNy9tvrRZLnesIqPT7gsX8A+M4HWvvy4G5NEhStuz515kSbRx6tChbtte69Wiib8/CiQPhSZTp9Ji1MfggAB254Yku3WL/i5sQ+sdO1QqP7OiX2rq6Z4FDU3jBgyg5pzInffssbkwPtxUyHrnnaCG/vU8R5048aTjlz5vgE4fC3LHMfPncwSP4Hf/BdxWmgJFUZHLdbO8PHv0aOFm0+MKS/fuVldKI5d9+xDGV3mfTMZhj3IxAGarBggNzcnSXzSlduoU1FU5QBERHZ0zTR9vHK/VAugPREXVnENdhOFcUfP/yQEKT3pCXenUpUubrySrVMjkI5ijVtdu573YxQPU6kqN02KnxRKJ9TbtgNOWLXgbVzlTJhMDc1AA06NHWNQFSLnp5Mk63WX/ot4dOtAwSUthzsaNNv3sZw0/6Nz5j9bxXweYyZmcyVKpUE6XhZZarc3cVP3IBl9T1vNO278fOy3hQtLCheJypUaNcRPpBoPjO/c9Be9GjZBPg6FITxfbg6CEggiwTLNM7dChSvEwvjK8sNBmQMVYBdfXXntpAMojPM55fRITAytGoW379mJD9TpO8obVVbg2ZUruN4XRRu7YkUt5KHo8euRqRKXCTnw8cWJ5X8l8YQ8RzeMOQMeOteOsCZQg7C0tdTJJfnJRvPqqzYCOYCTtKi9/4QHmTb94wFDp6cn3qRsuzJtXu5298T1tTEy0Ot1r+8sHN25YDfwDvafV2kz6cRiOpampKpXfGq8bhw9LnR32WtyTk3knEmBq0kQEHEqR1KugQFh09/DNqP37OY1HWaYOHGgzsKu4ytLTp194gJatkr3CqpQUJPBJnuXmJhaahOHIPXkyyFv5hef49esBeW6jwOnT8RZ/watbtxbjhtEQHLx1y9LUIZLbx8bmbivobFB36YJpnM5eY8eKHVXPiTSbK3B24kRAnivPrV8fndid3p4xo/a4SE9EDbdvf2EB6tpdGm1IeP99fAMNfxAaKjaYqTuNMZuxgKus7SdM0IUWDisuVii4HEexKSnJJlEqR7FCo5FbKg9XHv71V+thTqLeGzY8muuqtQnX0G3r1sDoljkK54wMjgRkkcuW4VWYWdO4sQhuIdKw9+JFwzS/8Z5f7Nr1wgE85VsYXRhdrx4CaBpVfPJJ7Xb2QgXPW75cpfI/5+Nz7hxe4a7WqNWr4YL56OHiIgaqUUzxx44FBiojvfps3lyRL23g4j9zJmLgjTcDAsQ4H2qLtaWlUhfh/MOY+PicNwujjUldu2IcPPDdhx+KcTWuPYsb0x21OjyciMhi+aN1PrN1oFDGMqnf4sUcC0f0b9as5jgtpR4wm0yyFpVjnCsXLNDpCleZDkREMFu7cat+/cQEJ9CcQh48sJYKKTQ+KupUan6WIcrXV0qSEEGTkFB73UKD+CKuxMa6taeVaH737u021pkYvn492uEeZI/uUCpCA9q9aZNqkn9/xaeZmU9dZ12Dy9EXNDT8FByMvtwUbhMm2ATMQLgQrVZX7JQWmc87OuID6zDuu2JF7TC6SOHwXLw4uNB3dYvE/HzpJskY4Zd163gLAkFOTmKgCrOgyMoKzFB6Kb7ctu32j5Ykh/dmz/4NnL+/mG8IFkHx88+yYffrk0ajqat66+xVrmZ9J6/vsUuhz8nho2gHx3btxI7SKQ1Dtm9XLVBqvE4NH54zuyDE2HrTJoTxeux7ZAKUTKtpcmFh2W6HFD7Qpo3rbvNuYMgQ8uK2MH32mdjhSpRDcf8+xSIHaNeO01iKNswwUHucPXMG0+AKk6OjmDeGsmh2RITqpDJSsX3Hjrqqu87uQHmuh1aBuDgbcNXu+fCytCGPmz5ddE8PjsXqMWPEBNVzk7U1jyTfiRNdm1WlyOq5utJZdqVeS5bU7o+cyImrFiwIDFRGKqDXo1LYidnr1tUGh3BaC8WhQ3UNrs4AnuR8NrJCwW+gBBlz5tgEPKF7Bs9tGey5+uhRUgvdzX4rViAMvqx95RURXLV7OpeZ51Z+uGRJTnaB2SQfNw5DOAXBISFivgok4duKCrTCTaF40qS6BldnAB1mCsdpcmIizmMYvJ2dxUIT8BX1+/77x7rnL3Cg5Js3SQs80MbF5a7RB5kq330XDXCFl48YIcbVrO8GUjqboqLKJM69nHu5u9NCGoUvk5Nrj4s24zY8P/roWe1E1xlAtqLzv7lnzfEjVg1fmDv3x05XYq/E+vgQIQSjExJsCl0G8M/Tp5cFyiJlkffucRYFY9D69bXv0Br3DByhzPZOOXZM0tesJXV0NP7Kc+Hn7i4mTKbW1PvsWcSULSxtaGtOLxxALKSe+MH2HdPxnPmcUHzmjOVz6+fCyD59bNxzNHXCloyMGvd063L/Bn07axZrOIbX+vmJ4H7HPbkvvU/f5eWJW/aLqBN9fO+edYF1nWXs2LEqlUqlUpnNzxrgU7uwrpn+jvGAwcBpuI5WXl5iQzofx3thYfQXevhAnZ2NKJTKLm3YwDPwZ8icnKyJwpaHFRMmUC8qcMyrX5+Uli+tJXl5tberHueeOp1+g35D48aAtIe0h9msUvn4+PjcufOswdWZdDH6gaa0pUtzcvR6o5FZ/I3XW4wpJSWi69oU/ts+XU50QR8jm0w253sVxBj54MHnXd/j9NR34GmP/DUl8kaNaJgw6cGis2dt9u1qOqp+A6n5z/H8LRwUCpuE1aYiybDkW1eqVB2Wt+rn7VxU9LxBPTOANcpzK0g2nQwIsHzKDXjb118jAN0Q7+PzHyfYBV8cuHbNOpb/Zi0PC3vL33+sj0ane96AHqc6/6gkfghfXqZ+EBAVxdexlnsPHkwldBpZSiWkfIj2ODjAi7ohSK/nrmgA+VdfWbUUaL6ekvLWZb81fmvu3n3eYOyyyy677LLLLrv+x/VP5iCYHXEHs4UAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDDxjPOzAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAwgNFLDwAAAE50RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLWdlbmVyaWMuc3Znf25HpQAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-gsheets.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAAkJJREFUaN7tmE9IFFEcx79jq6Ss5EW0GFiyEqRLF0UZpYNXqUNRXaUlDfLgxVOdEiX2IGKQUl6CiL108k/oIVjcFuwSHowurjBIbnhZVhl215nXQZ5BKjvtb+Y9Z/d9bsM8fvPjw/f33swACoVCUb1o1AJN4x86HrdGIqGMZuHu/DyuYQT3+vowjsuI19X51fj9p5GZzpFkcvalkRq+1dsrVttfaqgFjsV9xAQO+/v9Fse5fqlxrnXbMIZfJHtmv6+tidF1ErLA48RJQrZIukBBiSsFF/nk91d9rjmVEvVcusBzRvv78FLL2+5uUSIrTiBHlMjACrRtxhyn9DoucvAg8e71jvd7ZGAFmmYut7fnfv3NN01d+jfDeLD5ORf7YZpe9RFYgcvLu7sbG0A6nc1mMoBtO46bRHYtXUnf+KnrXokMyRZRLtlsoWBZQDxumuvrAGBZxSLA2P5+oeCiwCS+ALpO7SOwCTxJfX1tLaBp4bDIl6oKEsgRK7ICBXLEiKxggRx/RQo/RLa2Bgampvyr39a2sDA6etodLvLoyvVhU4LAnsLlw0Uyxhi9mnSBZyXm36S6XeeehgYvRroK9kB/kZ5Atwnye+8sF+kC5Y2wN6gRJiI9gWqEiagRrnKkJzDoI6wSSER4As/+Vg0mKoFElEAidIHP8QsPvfgxJBb2CjEs5vPUOnSBeW0MnYmEbCH/i3YRjwB632SBh0WnHR3RKKZhYnF19dwmkvf1CUO4vbJiPwtdvXAnGpXdlkKhUASZPwFu9jieEVOZAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwGxDoJAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMGpNUJgAAABOdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1nc2hlZXRzLnN2Z1sV6wcAAAAASUVORK5CYII=", 
  "images/en-attach-icon-gslides.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAAmdJREFUaN7tmMFPE0EUh3/bZZfUAuEAmpQm3UQTo0kvGkhj4QJE9OLJREM4mV684En/DnowHghX45VrlxKDUAwHTNCDiSHQQL02FDbYrdvxsE4wCNh2pjPsOt9xM/PmvW/f7uwsoFAoFP8vGmuA40KhAiSTuIonwMICqigDY2O4Q3KAaXYqcf3TtW/TybU1817q+dvS6KhYbSdEmCNQcTfIK2BiotPiKNrwlfs3n2UybvHzm+nk6qoQW2fALpB2nCRki2QXKKjj/gUV+fP6l/GnH9bXRa3LLvCSQb5G528tp9OiRIZOIEWUyAALJMTzmhj1W6Rb3Hrw+Dv/d2RgBTYajlMqNT9eG469Ts1nMj/iHwsPH+3t8cojsAIJqVQWFwHPOzra3vavNNORemnQSt9NJHiJZP+QPl5aAggRIe0i6nXHAQDXPTxsZd7AwMwMoLXtIbAdeBrDiMUAwDR7e0WuGxqBFNEiQyeQIkpkaAVSOi2yS3RBjUZ//9QU4HmWlcv5pcXjLBFdt1wGdH1nZ3YWiEQODmz771FU5Mms1jab8xDegZ5nWXNzALs4imkODf15Qy6GijSMnh4eq0t4hP2C+dPdnUi0kgUfgcIf4dMYxsZGX1/78+v1kZFqVV7+od9EOo0SyIgSyIgSyIgSyIj0XVj2LsqKhA70Tw78qdX298VXI1wgPXLxE+mL0/XdXT+uWELzQ7VdotHJSfVDVSJKICPsAje1F4Dryi6kZYq4DdRqrGHYBerkPbCyIttHG7zjkTe7QEfrArJZFLEF2Pal7Uial42XQD6PPEkB2azstBQKhSLI/AJie9putJDt3wAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMlQxNzowNzowMy0wMzowMBsQ6CQAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDBqTVCYAAAATnRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvZW4tYXR0YWNoLWljb24tZ3NsaWRlcy5zdmc/q3XOAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-illustrator.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAaVJREFUaN7tlzFOw0AQRWcNHRVJQetcgYLScToK2kQU3AIJ4RMYIXEAOpcIt0iUOC5TwBHiNkVCRYmHAq9Bjs0ui3e9RvOaLfI9K3+Nvn8ACIIgCIIgCIIgTMNMX/iKl+CD6+YbFuTectmkcwYYOulotM+uIIEsk52/XgeB5yE2/T4chmGastbe2zHmXEE+de7fp77flq5rjBvI3vIDdjEet6XrGuMG4inb4KF4s2R1XWMsA2Wzr4pqFprC2AaqZprtWbhr6iKeaQgM4Pz3zwEAQBxFIv2//QqrZprtWajdQJ59cAILNnHdLcEDHOFTlpVnleK5co5laDdQlGHsDgfsOUn4qTqnK7QbKOpzuOes8Ho+56fqnK7Q/hH5nmF1ye3E+Wwn/tq8z5rzw5zHzryqRdsGymYf73dlz+tZFmrbwDKzbvGFrWoEhSE1tWMBE4m5ADOZWqMbbRuoK7Nsy0JtBurqb7b1wtYNFGbfX7EsC1s3UNj7zvAYbqKI/6VqOrlO9Z7eGijb+0Rz+tILWzdQlFHV3qeqsy0LCYIgCIIgCIIgzPEBODUacLLlyygAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDDxjPOzAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAwgNFLDwAAAFJ0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLWlsbHVzdHJhdG9yLnN2Z5fOOiMAAAAASUVORK5CYII=", 
  "images/en-attach-icon-image.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAABDRJREFUaN7tmW1IW2cUx//nRq2onVCLhZm4rozFVSuC0qqr26oRtOmGWEznIlUri45CGZ0gsxRxa2GUbogdolaX6YyCGVNWpYZIhy4v3dZSNOpa1M0l2tY2mwPFhWry7EPNPqyIL9ckZru/j7m5557zu+c893IfQEBAQEBAQEBA4P8I8Q3Q8YbRYflSLmd2MnC9DQ3sQ4SwqqgoXxe2KvvQSznT0yyUymBSqQriUySxkdevbzYcb4Eas+nc6Es2G36BnHWLxb72s276UY69NptSnWqKC4uO3myYAN6J/EucUpmaGhdHvG+Mp9BoTKaREcYgw2VMSSRQI5VPPP4C10p0m+CpG8v5ujB/RxDIE68LZHmkoOre3uVLpFj+Xixmv4tOusolEuThM9Rs/mnoKzy2Bq5KPRfsnC8rKxw6NJHw3swMzjz9uUP607RlorTUhaWz5LBafS1mvQgjzBOvdyCVORM4cWNjG37AcJZKJZJy0/Q5kSt/qYmMjY24AiDR11rWj/c7UIuzeD87myKcrdxlm81lX7pBDqsVV7APiVlZa51OH1ET9gwNcRWkoOrs7IWFoCCHIzQ0MJAUVB0RwfTUiueKilCJBsw/fOjpcry/Bm6WGCRANTgY8LGjmaLkcoXiCMVqFxZQiiRo3X9aXARQD21LSwczs5/ZwACLhsRpGBjwVFrbfw0sQRhlm0yOftdiQMmxY25x7QvGGktlQYHmgWly9OXZWY3dLB7Nu3u3Pc7YZIlMScmnFHqFpqY4iasI+enp/xmBq42g+3WGGDLw7enTeIx4hOh0ga1BT/7qOnq0pOLw7piS+fl2mXFu1FhczJw0SKKWFtzALPsmMhI61smqpFLMUgZd0unaag21Y+PJyW+bXr0QNz056al6vDfC6x9BoK+uDkAYKuvq3Ec0T8z9o7eVStaEA/jk6lX0sE5Ucc80AKvBAyTt3End3Air7OvrOGWwW7plsvwvDu8+kHPr1laX5fkOvEcKqjabNzqC7tPV7Dv2KwsORj97gRkuXkQ462RVItGa181BEasKD3f9xlnoeZ3OU+V5TmArwvH1nTuQLnc4z8vl7hFsKzKXjVgLC1cbQdZAXTSj13+lNb42FpyWVkxH6EVyOOgE9yP3ODMTt3EQtffvrzuPU9iBkF27/E/gSecfrtyMDKUyLS0+fm7O3XF0ED30QXMzelCOE8+OIKZwDvdCQ7lOimFvXrv2dASTkt6ZT1buvzA+zvaKYmguMxPp2EO5jx55LH9fC/xH3KfGd0eGjh9nmZTLdanVGx1B1iZ6i6vQ6zWamzeHhxMTC84cmojVjo2xCHrdqZDJ8CfOo95u97XITeP+7rfdvv95K98tfwr7i8itYvu/SG9z+Atc2eXydSEbZmVTiW8Y3gLd24N+I3JFHKcnKxWrVL5OR0BAQEBAQEBAwD/5GyeSAGFyRyxJAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABMdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1pbWFnZS5zdmf04cYdAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-indesign.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAi1JREFUaN7t2D9oE2EYBvDnjfFAShYDR0kQwaYS3ZwUXEXBlCJCCw4VkykBSSbNUNohHawpDlKwEQkngYKVEpS2FqtuLgrtIOIizWCshmiCtEUleH2dTsRwtJA/3we+v/U77h4e3vv47gAhhBBCCCGE6Dbq1I1rtXjcspjd1v3+XC4apbY9v9vPc3jafcP/jRTYIimwRVJgi6TAFnlVB9hN5Wl8pVAxTeMNYB9OJvkzh5GJRGiZDuBbfz+/xBiO9vSoyqdtgbVaImFZQ0NkMuy3+TxXUUTO53NOXjwKwFSdUsNX2CkOdY7DmpvjKooo+3yqc7nRZgKdV/WviZtBBw6+7abNBP7Z49wm7jau43mjQctYoS/pNEe9n3aqwWCnvjD2SpsJ5B2U8XNgAABwv3mdIjSFd+PjB0/OlK7MZrMASqozAxpNIN1CkY709bmt289s2ztbKKjO+S9tCkQNKb7n/jOAXhuVxoJ+e6I2BXKKw1hdX3cNOmoHPQ9GRlTnbMqlOoCDfuARLS0uuq3zEl/D8Uym/iqRsE6k018Hrw7mbwYCqnNrU2DjAoU9D6enycRFHNraaroghSzOGAaHmJGcnCTrV8Bjbmzs9h+w07QpsPdc7uzl3mqVF/gjv4jFUEcCCovZK20KdPjP343FbszP4z2v8unhYezDYzzZ3FSdy412BTqcIo3S/jyHQiG6hO/4MDFBdzCGU2trdAxlymxvq84phBBCCCGEEN33G5C1y4sYjzPRAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABPdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1pbmRlc2lnbi5zdmcZmMqAAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-keynote.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAWJJREFUaN7t2b9Kw1AUBvBzxRfQtX+ERiwIfQAn3UvHZDVTtk7O0kDnPkAn09FMgkNXB8EnUHBIB5PJZ5Bel97BQqAnN80x6ffbD7n34+OUcokAAAAA4BAp7oDrRuMkGQ7VGfXU3XxOX3SiZ62W9EUKC2mqRlmm3tVg/RoEj+7t0/npcrnrODtA7yNyVpdpSiHd6+d2W/r+pXmhK9VP0/jb7/d+ut1dx47YH2pacMYNvenPToc7dlzV+eLY9x1HsRtflOdFUZJove/v8BsIfyBASwjQUmU7MI/trqp6t25DAy2JN1C6QbbQQEviDcQOPHDiDZRukC000JJ4A/N24HYzq/pvy4UGWhJvYNEdmDfn0YNOdBiSpxa0mkz2ff7GNLDq4IzaBygVnFHbAKWDM/hvIv/017As3J1c5E1kqkZZJn3R0m0elbhj7ADN819jgtwEp6/1xXocBNLHAQAAAIB6+AUQ7pEMC5OXngAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMPGM87MAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDCA0UsPAAAATnRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvZW4tYXR0YWNoLWljb24ta2V5bm90ZS5zdmfWvv9nAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-link.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAABedJREFUaN7tmXtMU1ccx3+/3tuLmUMQhfmamiD8M6YLPnAbGgEfpDzcqBSjJqJkVZ6RTbdMwEdETdREtCCxc0CiIFSFQbUiimyAUxamg8Q4BNmwzkysIj620cc9+4dTCYSUttDKdr//NDnn3HN/59Nzzu97zgUQJEiQIEGCBAkalUJnB2CtNleVHqya7eXFdujnsB0pKbhZtJ80RkQQV6KBsd7e5oaLoQNOtrWR9/E9EKvVoo/hNJdx9KhCIpMtevX48f8OYOKLkpM1H0ml8ALy+Jn5+bgPNkOcq+uQO3gC4Sh//hwfkwKI2LBBcWV1YnBWaam9cYmcDcaSkteViK482LQJH0IZv+TMGavBUU2A80Q5bhzJwWry1tmzyUuLc65uiYqyN743FiAFRzLgEzyWmwsKiIEQNK8YkgLNoG1pQQkiWRAdzQaIE8XNU6bQX1oO02Ah+N+9a+64tx/iibGgzs+Xy4vkNWTiRFvjfOOWsCVwEIvZoG5oYOeJa0WHQ0Oz4FMMwmfPBusvPr6wsK5u/HhmBhuo97txAx7ADbjp62tucB/KIXLPnuyKmKKQVzt2WBvvGzMDhwpOr4RkPmzFCkvgqHJz165dtKirCx6Q63AzPX1Ag30wAfwiImyN2+kAkzWaVk2riwvPQyiOvXOH/UlcK/acOtVkMho5zsODTCbhoJ47Fzv10T2Jy5crlTLZsmXd3da+hw3gksTN9fUDKkphDsTPmjXqAFI7Qv54/tuYeRkZohL8G3QKhTHZoDXEtLYyp9kovbdWiw2ohcl5efw1LtVFvW1bskalqhvr6emsuPvL4Xugs+xIUlJxcXV1dDQAIoBKZa4ox1z87NatbK3s++B2f39rx+OwGThSdiShq3h3zQcrVw7WfAuUkRri7g7T8EPwz8zsX49j+BSIVattHdeIAxxpOyJagpd5eUFB6nWVqlLr4UGr5XKV6vJlNzdjo2Exn1pZOSD7xsIzmNnd3RPEV2KGQmHr+EZsCQ81qxqfspGmq5GRk5Y3b/uxWafbBbtgF/B8//7MdqSA3Wr4uqEB4iCL7PbxMf8RdxExJSHBMBPAlFVUxMlBIbpw6RIUkCSICAh4HRiUQDUh5ASuBl+pNOegTBYSW1Zm6ziHfQZaC45dZ1AzPXl5j+J9CkPq3NwG65faETyHR/iL27ebK1SQAwkXLpi2sh1G5tw5S+BwD3xHEuLj7QU37ABtBQcySIRjYWGiAyxv/Co42NJ7+IniHVBaU0PBGU+JI0wuGzeyHsYKJriiwhI4xakYfum048eHa9x2A6RZdagGmDlknMGapFIKjjZDL/iSiPbvp0t1sPd5Lmj6tX59VxcTYNKAe1ycs8CZ47b1QerjGD+DhvFraxuQVfuBowaYbvYGMekS69vboQDc4fc+S7c3WeBsbCBsWhrzhE3gTly7RquNDfpsw+zAQPgWU3Hn3r3990JHgbMbYNI3xVVX3TIzoQm7SGlaGi2nWVXsy2WK1i9cONiRi9oPUSc28ZKysgEz11o5GByVzUuYXmQO6LAN5xBperqls+qx8at3Bv1SXo6JJAT/WrWKGmSrA+m1IzSrOgocFWvrg31ugCv6lvdfcpZETxJyeVFTDamt5e4zL8nbKSlwCx/iO+Hh8IJcJPV9/Fs2tENnSwvuJi1Ycf58j57/GYMVCqVyjTLIW6dzFDi7AcLnUAhVhEAnuMK79geiVK5RBqFOl6w5dVTTeugQVnKTxmjLyw0GYyl3r73dZMIfjIEMI+4QHeYPTJ+OR8Zx/yTevq2USKIk2NPjaHBUtmfhRgiER/fu9S82b/JWip4ciBd3xiWnqornCSGksZFhWFavf/qU+4LR8WmdnaI76Eq2zp+vkEh8JD7OA2c3QPqxZkBF75nTkh2homfVoRpgR+9xlmRz1qPXSuQkCTNMamujh/zXIEeXHXE4QPM4ez/O0NuR0WpHbJXdJxGaRUe7HbFVw34bQ79ycX8yL3lr7EjvtRLNxs4GI0iQIEGCBAkS9B/Xv0R6xmS+OKmNAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABLdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1saW5rLnN2Z42m/5wAAAAASUVORK5CYII=", 
  "images/en-attach-icon-maps.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QICEQcDCqn3VgAAA6lJREFUaN7tml9IU1Ecx79XuxukmZBFD5YF/iuFysy0JYJWL2FGlPSPXhwFRkGtv1BU0ENFSQ8iPqgUjSL1xRhBCyLSpUzZi9AEoZStOXKFOPfn3u3u9CCXUW5s8247W93Py2H3nPu7v/Phd8899zJARkZG5v+FkRrgq6c+d8fjggJhH15nVHR3MyNkDXpra8kEcw2jCkWiEl/1vC57v9tgWH//zpsH5r17k6stSIbUAKI4PMNDXG1oSLQ4EaUmv2njBZXKfuveoRtbhoaSo2spkgWKFUdrArRFShaYrIqLhCjyx+a72usvhoeTdV3JAlMN1rSBK3BWVydL5D8nUCRZItNWICGBgCBEHieKtN+63XJ5Lv5rZNoK9Hrt9pmZ6McrNZv2FL5Uqb4dvDRz7qPFEq880lagx2M0GgyA222zWSxAICAI0VRkrrb87bYv+fnxEil5Iz05WV+/cychydEWnvl5nvf5gLm5xTZaGhqMRrOZWbaHFbQnLqJU7t6tUgErVzY2HjsGsGxRUUlJsN/nm5ycmADc7oGBvj6A40ZHP38O9ufkKBQsG/wdq8i0FZidfebM2bNAVtaRIydOhB+nUJSXb98ebF2u/n6tFlhY0Gq7u4Pjki2S2hooVlwkceHIyjp69PRpQKmsrKypWdoviszN/VNovKEmULxV/4bjxsZGRgCHo6WluRlwONTq5maA500mozFUnKamUHFEEi2SmkCWLSwsLl563Ons7GxrAwTh58/ZWUAQHI7ZWWB+vqPjyZPQcUpLI18vUSIproGBQCAQjziExBJHFBmvfQO1CvT7LZapqVATbG29cgXIzMzLW7t2sV23DsjJOX9eo4k+TiRWr45PJVKrQK93cPDDB4BlS0rKyoLHFYqKiqoqIC+vq6u3N/o4tKBWgR7Pu3c6HSAINpvVGvv5gmC322yAx6PX63S0ZkFRICE+H88DTmdPT0dH7Oc7nV1d7e0AITzP87RmkQLvwhw3NjY8HGzjPT7RUBcoEqmipFZsokgZgZHWNKlrZqJIGYEi4Z6qtJ+24Ug5gX6/1To9Her48vZ7iYb615i/IcTlWlgAfD6zeXwcIIQQQgBC3G6Xi3Z2S0k5gSK/ft28efEi7Swik3K3cLohC5SI9L92lJJH2EXzXWCZZMKEVo6TGkZ6Barxg9R9+kTbR6wwxwFyWHrekgVmPGVOku9qNXMKJqJ//z5VK1LMi9mKrYBez7zKqGQOqNW085KRkZFJZ34Dzg3IpkPczfMAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDAbEOgkAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwak1QmAAAAEt0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLW1hcHMuc3ZnG68OzQAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-numbers.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoAgMAAADxkFD+AAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAACVBMVEUAAACBwVEAAADxS4cRAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgEOITR0BZreAAAAGklEQVQY02NgGAAgGkIZUzSEDCaIQWMmHQEAf2wRpOlkzi4AAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDDxjPOzAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAwgNFLDwAAAE50RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLW51bWJlcnMuc3Znu00KjgAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-pages.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAA/NJREFUaN7tmm1oU2cUx/8nbyZanKwFKzrG2O7AKShDuw3am3RbXdNuig7HtjSusln24kCN2A41zg1rdemElFUqW9G2spZULQPHsDBo8kEZYaxOUSTCuk3bsha2pjNt3s6+NPlQF25r8tywcX9f8iHnnnP+/zzPvee5BNDQ0NDQ0NDIDyS6QPRF/23nl42NOIk9CLtceBQu/GgyCSs4hGY8HY1iG4ppwOMxXZbbOvr27xdVTryB/f47zkA4DCtu41RBgeh6afrxKy6Fw6ZquaZzdPFiUWV0woW48Qk1e73plSGaVJ2P+GXA6xVeT0Mjrwi/B85mumjg0hsTkkR3yWz44NatXOVNjibKuEiSzI+UU9eJUEgtPeLvgbMLvqALGCS7Pdd59e/r/6TDuc+rqEftgryE/0Zn7oXyw1jNv/2PDWS+vGLrVosFb2GYK2Q55wV2wk0/22zMwWBd3cKFaulSzcCEO1FhedNmwzq8R9sECFyDlbhosST2RAbuLRLwA2VANQOT1qQtaRW/xZLP89f0mHpbWTUDqZW+oFbxwugU+lGrnoHCxxhRY4sSao01wlegqLFFCbXGGuEGspnb+fvKSsXAmTMsnSc3xurr46t1T8Vsy5enPuk7In6ioWGuZ2q1xhphWzg1tsSCsYPmV8fHU0/JjI3MGGTcWFbWdejYsUxxsW8CgZrD9fVcyUyhpqaMDQziBqojEeM646dT5woLiZ773eeLRHKtU9gKTI8tCsalMLzCQXR3dCjHxUsNh86cUWwgPdbEdy9YYbWK0inMwPmPLYldiV2xmHKcoYAaE4k591HNRThYVSVKpzAD5zu2xFv16/VLa2sV43qwPh7Yvl1UH/NFmIH8Ayfp7IEDaCM3xsbHFeM3o42ko0dj3QGb075v3+zv0/c+mZvhOXJEsYGZuuk+BCF8DmT2n6hZuWxZbAQb8VNfHwpxh94pKVG6zmSS5c5OSvcXjfr9TiezYsFf4MZnV64YJWzi8i1biOTdXTeGh0XpEz7GpAQYixe8xHsrKmgturn9+vWc11lFLXjo2jWjpOs1fr5hg2jjUqh3lKNnQmdbJib4bZ0PXzkc+IvsKJ77wyAjY1iEhnic7eyiNQ4HUWlR+/FwWC1dqr8PNLlK/+h6d3CQWrmFay5cyDYffYwhnOvtNXnlZzt2XL2qth7VDUyRrKMPdT09PVnncfAQnvT58qUjfwYWxyd1jcFg1nm+1V9ESfZ5HpS8GWgGAIyMZJ2naeLkkpujo/nSkTcDicrpNKam7ns5EKLX+Pj09H0XZIgjqpJaqv4lXiXyZmCamf+wYACPo25yEq8nb9Jaj+eB4zQ0NDQ0NP4r/ANgmKYXDkKkbgAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMPGM87MAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDCA0UsPAAAATHRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvZW4tYXR0YWNoLWljb24tcGFnZXMuc3ZnYpXRawAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-pdf.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAABc1JREFUaN7tmGtMFFcYht9vQERA1LilddGoiJHuoqb1hraRiwJyjZCwsoApRkWjorZYtdXCaihWixVCJPUK0bgoE0sQBMULiLcQNCtUQQW0XqhcqlSqIsjO6Q8LbdxuWEEcTeb5eeY737z77JzZsweQkJCQkJCQkHgvIbEDdFBRHxrrdzMoiN0gezZ/zRo8ZDOgUyjgChnW3rtHcXQev6Wns7r2dOvHyclKnud5vq1N7NyiC6z0DBvntz80VIhi37NmrRYKaHGUjOair1GOuJyc+qMPrj2bEhzsTkUoQnu7WPk5sW7cARvGwtm5mJiuxHXW/4hx2BAQYKeSZ1plRkSInV98gfFQs612dq+Ok4yNpqTgYGPzaAybhQFqtdj5RReIFYihvNu3Xx1my5AlyPv1QwXC4MeYwXUbVMBHLhc7vvgCVSwCjYWFBuOTkUqHoqONLW26iTNY+Py52PFFF0hl5M4laLUGT5ovpeKwi4vRiW2oR1pVldj5RReoiM+wza2tqkImzuLUyZOmzmOtmIcPLl0SO7/oAjugSIoE4uNNDj5dOAPk5oqd+50RiItsKFfy4IGp5UKxmR22TZsmdux3R+BjnBV8Zs82tZxusU+RsH17peccT7/9zs5ixRZdIGMaaMBxuI31OL14scnz9uE7yK2smC1nKYzn+fLysDA/v0GD3nZ+0QVWqK7vKV3v7882wwlODg4GBXdQCnbnDjRsCyJv3Hj1MtsIG1rr5GT2F5sn7MzOvs0i4QZLy7eVX/T/wtdC1CG+mUVF0MAc6a6uBgX38TvdWr7c7D6n1dsUFOiPCbnc6pISaFCE9AEDDOo1iGJeWVnkTru4E6mpGI71rG9bG1dHA4S79fXWf7at7D/y7t1hMTzP8y0t763AX1ko/OHmxlWQWvD9n420BhGQNzZSJI3Eo0mTyAHx1CqTCReYhgUsWAAXxOGI6Uv+P31tcEuvxxLIsLi8HKkYAXlmpsVH3FX2bWrq6JQDKfnVzc3vvMCKr9SXffILC9l8JFKKm5tYOTpFxOIJ++H6df1m1qq/7OU11vFgQcG8e/e6nNfbwV6+3B0cOCWKhRXh4VTIXMlxzhwMgYBlSqXY4gxhGqbheaXy4Jj8ySpVV9Xmb/r2lXPVC30cXV2FlZROi9eswS8sWwjy9oYZAima4zAEghhaKJsFQ5abi+04B/sTJ1gBNaAsOdmgsBpytHp4mNy3p8F0LBKzMXCghaq1sDVp715osJMKgoK63bA/luJZXR0ayR3+Oh2U7DyeXbmCGkqiEp1O6Cv8gdO1teTG4gT7+np9qEVw++G6OjPNixl9mqOiKJGymTwxESH/fGGvK9oLbhhfU6OozViUt8nRsdcElq2a+6FnmbW1+az2mX36l5T0fEm+3tIxxtWL6nM+jgEB1MDGIy0tDY4URZsGDza5gYIykLdhg5K0yING01V5t/eB5sntO/s8jI01Jo6m4BEeNTXRBIzDzWPHjPWhJUyLZQ0NFj/r1yNs6dLu5unAeWrG5/nVOTlcqPlkoXHsWApkE3EhPb3z19dYjo4lrnoRYh2SkGDq/br9BFbYq3f4flNdzQpQhLJRozovNGAEvHQ6pOIUc1i1CglQkTw7G224jFgbm38bvDy+YlvIFQmBgc6lWtu82t47HLi+J3RP4Hm5XDhAy/URHh7YgSGCmUxGG+EO6HRO+zJ25VcXF788eTQ8wH3zAi3V43xjnzxhl6HEJWvrzobROMJijh/HVXxJFgoFK0QNNg0bZtCgnH1CFxMSlOqDq482rVvXW+J6m24vYXaeKmFbXGwwnoJA2urtbVRcESzQlJmpCNWXWs2MjRVbQE/ptkDKYg+5bStW0ARcw8SnT7ucoMFPiDx0qGVK/771bRERRDzP88bfSe8LPd7GVFSFR/s4urhgkzCUZqSksOHYARdnZ3yGqXCtqeECMB1fJCV93JKxKO/s7t1if2AJCQkJCQkJCQkAwN+G5UkRnhwXSQAAACV0RVh0ZGF0ZTpjcmVhdGUAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMPGM87MAAAAldEVYdGRhdGU6bW9kaWZ5ADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDCA0UsPAAAASnRFWHRzdmc6YmFzZS11cmkAZmlsZTovLy9Vc2Vycy9kbWFydGluZXovZ2l0L3Vuby9pbWFnZXMvZW4tYXR0YWNoLWljb24tcGRmLnN2Z1JhdqAAAAAASUVORK5CYII=", 
  "images/en-attach-icon-photoshop.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAA4xJREFUaN7t2F9MU1ccB/DvrzbuAcEs08SQrVdjtwd9EFPUGFFoGRozCZGVBJqACg8+DB8kmTUQIVQwII74BzWYdLqQlEaROAlZtmmvBsIDDWicmsDmw20ibigZKsYHkJ8v3j5UrpcW24vkfB7vPfecc7/3/GsBQRAEQRAEQRCERKNYHywqCgQUhTnqBx9gA3599QrfYR1dGB7GD7QXR7u7zbbJjsn9Z860/bf93urR0VGjg5mtxAeogY/iCtW8fIl6Osdfl5b6L9pJquroMDogPSajO6CiIyjg2uRkyucj2Hb5cuE+mZV6p9PofumZNwGG+eCAhYiGkE43vN6Cgp6kJz8vX250t7SY41Vxe7vDIUn03hJR6P3zi9CPqammm+YyLi8u5hXopVyPB0+4jrsWLw4XlLiJL6WkLPp2Kmey5cABXAGA6mqt9lw35LTQg7w8buVKrjl4EEPYiW3p6ViLIPKSkmLtr56Ej0B/Wc6YpWlkxOezH5ekxkb6FxncpR0M/cMSftu1S+t+4eHAV4rS0MBebuYl167BjGX4KTNztsHNleFTeDp7ykstbW1a97kMO5ButUZeV0ccKfgFcLuN6r/hAeqhEurHDLt9eKoaLG5r4GzRlKkfHSUlABSUz1Agk//H00eP0BdxfRPMsNhsGJi5Xh7jJdi8ZYv/j+yN0khfH+Ik4SNQ3URcLvmQorjdGDIVI7m2VvOB+9iLpV1d0bZD35s20GemuL/fvDlIvycLaZT1/DlAn5tzrNb2/XZKvfDsWbj9gUB+yCPLOIFy3pOVpVmP+svnIvbQeDCI17wOp5qb2zOyayxj0X+YSPNvDXQhgBAzjcMz7SstjQwu7F0QuvWpu7Ea9FnayoPXrxceDzQrtvr6hRPguxFHDzHBZqfT53acXLm5s1OruDqCeD3uIv/YsWiboztIQ2dlpeuFzEqn9jFJT+IDtGEcpyYmcJJ20zeDg5hAL7k8HnWq6gUXyX/IUSENVFVRK9kxkJvLLXSWKmU53I6O6Uk46WpFRayvE7c1MNaT/cdW1CpzaFVGBm6xzLd6eiLvq39i+K2O85ZLKSnR1j9/pnCccMObYVTH70Mafg6MVRSngMcfKkSNOI2/gkEA52Ppx4IfgXrYRWt42Sx2cw2f7AicsybqpcG6Ov+X9r8tv3d3x1rNwg9Q3Y2HkEu3+/vVETfX4ARBEARBEARBEIzzFtJFcqPCIPVgAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABQdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1waG90b3Nob3Auc3ZnqlocOAAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-ppt.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAkdJREFUaN7t1z9oE1EcB/Dvu4QM0csSS22gInJokQ5pzSYVBxGEKlW6SRxOFyehpAkugTSoJEMRMzlUKKmDIQQh7SgORQSh6bWIyGGLWCxYIpheW6g0+XWKFOOpmL6kJ7/PeH/e7/e+vHd/AMYYY4wxxhhrNSFr4PX1dDoYJNq3RqOw4N/cpDJFEDJNVEUJt2ZmlENipfY8kzk8NXpjcXRtrTWx7elL1sD7HaDtBK7Di7uWhQQ9REDX1f7YB2Mgn5ddt05pVSFZ6Cm28EBVqVN8w5NcziqltODs8HCr6js+wB9URDEvBEaERd6JCat0/2hwtqNDdllpW9jOn7a2zxeNGoZo6GvrZOp939lAoFrBu1pXOExp0S1qY2O4ipdY9ngaBrpAV8ifTPrexHoWXsTjsubjmBXoNWM9869WV9UvsWsL+VRKRGmFlN8EcwxdIjQ4KLsvxwTY0PiA2PGIyUm782JbZNGvadL7aHcQ/0oE3ePf/S6X7QUWkqTJ/wpwbIDVws6I8iwctjtPR8gUuaUl2X242x3E32p4idxBN9USCQAfsfyLG16LbTpdLMru68C9hZue0Hkch1GpAMoJ1xlNU0uR0NxcuSyrnmO3cAMLafQRYYiKtbe6Lju4OsdsYTuivuKG6FJtStfVeCy72FsotKq+YwIUt8U9XNzYwCkaxznTpMe4TF+np9GpfHI/ymTUeCRr9MpfcT87cAHa/YkAAAwAwE2k9xz73N5+/59nYJtwgE3iAJvEATaJA2SMMcYYY4wxx9kFEeHOUD7gGgAAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDDxjPOzAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAwgNFLDwAAAEp0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLXBwdC5zdmfQBvLPAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-premier.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAsVJREFUaN7t111IU2EYB/D/W0MvnHZlF7twfdgHqRQ4KDE1IiPB2kUrCFJiXVjhXNLHiECnUigWOLekAvvAELJlyrSFCV2EQheBVJNaiZ1dGJgXihrkx54ucl44D1PHdiY8v5uN95xne/jzvO/ZAMYYY4wxxhiLNrHWQkmy2TweolUXduKIyJyeFg/RQG6vFzW0H4e7u2dL4p/PXbHbt49efLv3zuio0sGsVPQDlGukEpfgnZykHeIEWo1G7c0yd9oLp1PpgELZoHQDAVSFJuxMTEQufcPptjbpVmOB55TBoHRfocRMgItSYMYeIUQv5SCjufnXo8aC76bkZKXbkqOK1AdrtWZzWpoIOiJ81+ydX5s1Giql+3Nni4rEceoSw9XV5IID83FxgfvoCRJwMilp1kGXZwdMJgBu2Csq5L7P57F98gzr9VSJGlwvL0curMKl00GPXvqYkLDWfkOJ+gSm1Jv0u8+PjGi1Ze70+Lo6colC2iofDNxwkqawUO6yJDWMDzbV1pIa7/CnowN3cRDWvLyVBhcuxbewcIgLqmctLbI36NCE8dTUpcuBiQPEU8qzWJTqX/EAQ5JQj8/BT/vFraqwiJ2BK+b0n5t/U1yMUlhxYJnrvzGMnKGhoPUUqHE7MxMAMLNMXRY2++Ozs7Uj5jMZqf39kWo/6hMYeIhIUmPBl78WCxIxhpqqKtmCTXRDOFyuoHUz9mFGrZYri3RwARGbQLkf2gT/z/n/b4+JHwC54FiuXhyCFdaJCVX+XPbGo3Y7+gC8jHQcq6f8Fl7KBxsGifytoo2mjUZN1lXdrpKxMaXbkhMzDxGxMHGkEg/oscGwJassP/11e7vSfYUS/Qm0YQBxU1PinujBK68XOv978aGrK7BVY33ilor6P5Egfdi28BqTZ1woMbOF1ysOMEwcYJg4wDBxgIwxxhhjjDG27vwD838BsbHlHVwAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDFUMTQ6MzM6NTItMDM6MDDxjPOzAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAwgNFLDwAAAE50RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2VuLWF0dGFjaC1pY29uLXByZW1pZXIuc3ZnI/o/aQAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-svg.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAABgtJREFUaN7tmWtMFFcUx/93FnalBTREEYVilEfFNtYiaXlqsSosEoRq1dpqxbWLghq1FbWC8V1EYwkVAeWh0UBFQF6ytFUQBVYjNj5aBXlYWFARghAw4sLO7YeyaiAjZZkVNPv7tLlz7pw9/zn3zLlzAR06dOjQoUOHDl4p7sjzixfMmVMcl2eV4FtXV/y17GaiQKEo8s9dHP+nWMyXH73BDlRrSOgOBjExCEQ99TE3hx3qqQ/AbCS2RB4b+5+RpeVA3TCDHafWCMYwOu3Zs57DNBqLkapU8uVm0DJQbpGniFtvYkKD2A7BA19f6kUC6VQfH5hjLWZNnIgv8BBxFhbkOrJJMqV0HmmESKFAET1Dr5aVIQj5yE1PF7nqjepks7MdHGbNCghobVXfn1TjAOMUEEBN4cfi3Lme4wCAgoHHQV6fYCkpKSkGBmycUWj7rg0bUIF4mAUHwx5t+MrYWOMAJGQ3Hra0IJs9Rqfs2CFsNW3tUkRFOTg4OAQEdHYWF8tkCQmUqu1dXMTi5csJb3FrXcAr1rkVR9dYWHRNIrmCDzIzsQm2ENrba82hIWrIKrlcObnrqDLSx0dYordbX7+xUX2ZbwG1VgOfC7eZ8RQoLl/WunBq2jGORjs5CcV6rP7jkhJtu+O9BqqXatckktvenJkJO3oIH5ubc06gKELMo0doRyqeRkYinp1Mbp49+6Rcv1zQUFFh1NwSMuwiywKG/k8Sra2pDa6zBxYtwgNmGckMDKTxNARmI0b0um8o9sLUxuaNE/B5jTNCBNa/IuO2A9h++jRNVhbQIInEdeTccsmmtjYA5T0Ky4IXP2/dQh1sILt1q4CeoYl0/35hrcG7sDp1CnU0jYbMnq1twXrCWy1Qv1XZTbSG+evePc6XQ7dwzr97evrXLFxICCGEvCjy/aW0tLQ0NlZf/1lE4+f6tunpWIVfcc/bm8uevq/cRRuNjV1Hzi3pfmADgrcaqG5HOIXrXqo0WbmLBkkkAxVOjfptq5pKZnTelUphg0+x/fFjLnuyTvg3+SQp6dKlnJwEywkTho6A6j6Oi+4ax9eT74nQlNkm3GdoiEJkIeUVD6Y7QxkikMNMLi8Oya041mBlNegCkmWkCOF2dlzX6RLGgMpzcvgWTg17UpVOp4aFYSxG47aJSd9/GK5YaWpK4pi9bMSePZr65S8Dj0GEmDFjOA3udLyDqOpqvoV77t8LHmiZObPfE5toICbOmKGpX/4y0I1OI1L+GtR++18PEb7pvfftC3oBGYjSvBbz10hbkT8oc/8+Z4Cr9MyZYM1rTZ+MJIdRlp/f73nHYYDj589r6pa/JTwHnvTB7dtc10kls5J2cLcXA/a/gv2RWbd1KwrwAzwaGvqcsA3TUfHwIbtUNQUeISGa+uUvA7/HarIkK4szwF+Qj+lr1hQ1ZTrH7zMy4ltAl91eNstGV1V1rRYIVO5OTriIaKw8caKXYfd4V5rAUZXm7Ozm5u29vFbz2sx/I+1EDzGh1dVYh8+QMXx4L8M7ZDVMUlOdJR6V/nMXLOCrH+RC219jeMtApzrP91b83NyMBjKF7A8P5zS0o4fQPH9+Sfxv1omZKSlXrHMrTkZq/jlrsOH9a4yyULQIew8ehCMJgEdpKadht5Cqf0iLcnhlZUlynl98VmioPC3PLyHP3r6AFtCoLw0NB1ugvuBdQHfiTvxJRwczrksk8PL1xWGYk+/q6rjsaSGaoBo1ilpSKWnauZM1o1Lcv3ZNWNKRZyBua9PWYdCQFVCNU513xbc36uuZQtU85kNHxz4zkotA1NOjFhZM+cuHQUMHrR8qqYVUMqIaMtbNjRzHBTp9yxZE4AJ8X5xhvKm8tlM59dJ2PiLeJ7EKC2PXqtxEsvHjEQFPKvP3h4wcoUszMlCLJOSXlRExosnG9nayEVfwVKEgtURCAqXS/+tP/lPe5gTL3ls7rnFNGbStl7YpviG7m+BeWYl2VGHJSzsgQ1jhRFWVy0di2+UF1tYD9fP2nguHo4NcFIl6DpNVSMJ8oZAvN2+tgFRIw9irUqm6C9C0FOjQoUOHDh06hir/AiiIlR7+WsuxAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABKdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi1zdmcuc3ZnEPfmHQAAAABJRU5ErkJggg==", 
  "images/en-attach-icon-unknown.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAQAAAB2Z6ylAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgEOITR0BZreAAAEXElEQVRYw+2Xf0jTeRjHn9Vma2myXDfKQLEy7cf98UUikpE/Ku+usLOzo1RGgXkSVtCd6FEEWUwOEQJ/BLY7HNY/RhnMJLmUlNqhdIuC7CY1pZo3nM7v93mm+WP5uT/u/GxTOoTbjIO9YbC9v5/xvL7P9/Pe8xlAWGGFFdb/S0NFKhUJhYX0bVsb1jkciIyRIIqU2dOD7ZWVopiQ8MngaOWhQ1j29i0iYx999Xq9FFtVxZhSuaRwqDxzBv/48CEAxj48TN8/eUIKm23BNUNn51CRSrUkcFLSvn0BAGOPHuFMaipjMtncmvHudevoy+pq7PV659ZRlskUcriR7Kgo/O7NG19nbt1iTC73FGzfjnajkeDxY4o3myVLXh4AAOXn5ATczExqakgBqfrqVd6R04ODw82RkVJNVhaapqbm7z+y1tQAAODZa9e4d7apKWRw0u6UFP9HhoaDB93u6Oi59CIyho7ZWf/3YpMgiE2CwAHTX78OCRxjcjnmWq3+jxYAANPq6vyLi6Jajc67d7knFBaOZEdF8c+l4+MhAUTDuXO+oqI4kbh+PX6xa5f//pL0+/dLljVrsMvp5Gvzc3Ik/caN/kkPOtzY+bg4yifiRUdOnWJMocD658+5V3/zJgAA9ly/zj2FzcaYQoH20lLfzbW2Bh2Q4s1mXkBtsTC2bBkJ5eXcWzk66rFrtVSs0/E96Jid9RRkZJCg0eCoy8W7/POxY8GFs+bm8sfTMj3t+WXHDlFMSKDS8XH/fcZYRAT29fX5vMZGAAASGhv593978YKx5cuDBjfatno1Gt694wXaKyv/Ltrayr3fu7sZk8nIevGi77duZISsa9eSdc+egI5+np4e1O7h0fp63hH9wICzfdUqyZKXx0FMU1Nk3boVkzdvRsP799w/odcztmIFDr18yT1zQ0NQ4STLzp0BE+DogQPzE4qxly4xJpPhiQcPuNf88CFjMhnmXL7MvS6nUxTV6qDBMSaXY+HTp7x7FTduAACg3Wjknqa/nzGlEpuPH+cgtZOTJCQloX3LFqydnAxdMBaT0J8yM9EQE4P24WG+1njhAmMyGRo6O7n34/37QYUbY/HxWD4xsaiEZplMgQmNiKBvTp70nxpBP7CiuaGBF/21q2tBQkddLhI0Gk9BRoZ/R6lYp/PYtVrSut0cUFtWFlQ4AAD/wU8sLU2ybNq0MKFKJWn6++cnFEuuXPHN6mfPGFMogg/YMTMzV0QU1WrJUlLCi/7Q0fFvCaWKw4ex1+ulfCJpd0pK0OEAAOhru9032LOzSdBo8M7t27T33r2J/g0bPNpt2/zPfvMTSoJG43ZHR4cEDgCAYquqOGCdw0HFOt3cNbFJEOj04GDIEroYoSEmJuAA+s8UIf3AQMCJedTlGjsfF7fkgAAAVJGcTMKrVx/9K1nncIRqj8kWu3CoSKWKjC8ulhmPHIE/ExNhr0IBn9lsoGhpmc6urY35CvGTdC+ssMIK67/pL7RiGH8PMWDpAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABOdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi11bmtub3duLnN2Z6GswhUAAAAASUVORK5CYII=", 
  "images/en-attach-icon-video.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAAT1JREFUaN7t2L9qwlAUBvBzQ0fHbip9AJ+h0N1JpJCpm3mACgpdxEUw4J6sQlHxD3QoPoEP4CMUXZzr4ORxMYKD5B5PSAx8v/ne5OTkywlcIgAAAAAAgLQZ6YbFc7s9eqtWaU8DUwlD/uZPei0Ws36QuzHtTXe7daZmzRXPq036K3e2XNpud8T3C/jf2QVB7hsXMVTgTql0PPAvNcNQuv3p3hvaLq/Xfd91jTjpSZnPW63xmDl24Qf16K9cph/Z9eUNjGnQrYKtHyQht16cbb22xJ8wXFMnMO1kPVq9SKCSuoHRTMn6Z5FVvUigEmagEhKohBmohAQqYQYqIYFKmIFKSKBSajPwURKa9AyUN/B8gmt7Lpibn8yQvuhlsyEiX7JN/AlHR9+XRubduXFmxw1+97ysywEAAAAAAIh3ArpqtUPQiWzvAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABMdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi12aWRlby5zdmdWktNKAAAAAElFTkSuQmCC", 
  "images/en-attach-icon-word.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAA1NJREFUaN7tl19IU1Ecx7/nbimrhxgSmtRLOSeF9FBPOSlxzomKTy7HqIdECgrfaloJQzJZ0EtgD0HQH22hYIhTp60ynEFEgQSy6WsP/bNhhGF67+np7sHb8dw7u66H83kZ3Ht+n3t/v23n3i8gEAgEAoFAIBAIBNsNMVrgvngzP9KTSiFJu3GgtHTjeVosHyUJp/P5wyvulr6FBb3eqv5wcnDQ6bTcx4gsJ5OsdTy/2x0ORyKUGp5EJ37gUioVrw72+D+Wlektk4xeh7rofjI2OsoU9lu9Srix0ajX8pquybv5ddn6uZwnj3GN3RfzfowWkBZlkc5Go6zz1A8b6WtoMNzAHdIND78uaz+vrzTyqcTui4XhAdqbDw5ZhmZmUIDj5OrSkmbBGC3EnsrK6jM34g+eFhTwfPX1vb0DA3Y7mhFATUUF9wYM+nnQEBxwpNNr31aSe9tmZ00f4NCQz+fzyTK9ji6sTE1pFhxDG2wWizRobd7h8Hh4vtVVQqTyujqkkUKr1cq9AY4/Hg8G/X5C1E+AUhwOBFg6EiLnkJiYmEYIVWR93fQBZgrLyZwSZ+8Zygd6RHLr2KsmSDv0rDPJr/QrA+SQ8b0vM4dsC/Oq5ct0LhaDHU7c+8s39xntNOr1nkQIL6n2l6Uep28Qw3htraZe9Zrst7XSd/LXycltH+DYWGdnIJBOI4+cRk0isfE8CWERi3a7Ffn0E1wuzYV/2pJfApWV6jrNBc7iBd7PzGTrV4/z/Jk+tnuAmUYi+EUvbPJUfiI5SIX2qSntRIkyzH6a0gi9RfzRaLZ+KJIMG/uvq/q32v+WBygVy0XW8ZER5oISvKXfm5o0x9vJLnRt9jqivAKiUbP9W+3fcBJhoTehKB7LPukEIczEwUgEZvuzZcu/wEwDOhMKN3EwEoHZ/pwPUHdC4SQOViIw25/zAa5jlRQhkVDf7DULftNHeOZysRIHLxGY7c/5ADNv8oW4TRpiMc0CNWkwEgcvEZjtz/kAM0JOQmGhNxGY7Tfc778WUpcStM6Pj+MUhuFdW+MWGEwEZvtzPsB4vKPD51texjSZx10de43BRGC2P+cDVOElCJVsE4HZfr2YNkBugsiQXSIw2y8QCAQCgUAgEAgE/y9/AJdeW0KXQPvpAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABLdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi13b3JkLnN2ZznjsuoAAAAASUVORK5CYII=", 
  "images/en-attach-icon-zip.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACgAAAAoEAYAAADcbmQuAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAACXBIWXMAAABaAAAAWgBwI7h9AAAAB3RJTUUH4QIBDiE0dAWa3gAAATpJREFUaN7t2TFKA0EYxfG3i3gCwSJJbyFYWHmGSEpBiO3aWLiwBLxCElyLFNkTCNZCIK32NoKVVdKIXQ7g2CQWA0LI9wWf7PsdYJh9/JlmAREREZF/KfE+sOwOFoNFu41uchkOqgpvOMZ1o7HpeXleFL1e8nPPshwO+/0Q1j7gAVc4nM9xi056l2X5STEtppOJ1/em3gPiPdkNz+OxdTg3ZxjhtdnEHo6+PqvK+/idrV14Q+bifvOIfZy3WgCAF7/P9S+wZvwLNIqL21qRTlSgEV2B7MXFVKARXYF6A2uGrkD24mIq0IiuQL2BNUNXIHtxMRVoRD/gqsi4TBb0A7KjewPZ37yYCjTSgEYa0EgDGmlAI/8BV/9h2ZziA/ezmfex/gMuf2DTDLkcLlykT7jJsr++joiIiAiJb63Fj8rw/YGYAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABKdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9lbi1hdHRhY2gtaWNvbi16aXAuc3ZnpS9YEgAAAABJRU5ErkJggg==", 
  "images/loading_progress.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYEAQAAAAa7ikwAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgIRBwMKqfdWAAABrElEQVRIx+VUPW+CUBR9NO37AW/gB7g0TUjsZkPiRAedusgg/IB2beJfaJpG090OTrhAQtJJhzIgD1efAeLm3BCWjq2prwPBKsiXiUt7Rl7OPffcew8A/CvgK9vGgWUdTwBTijGlZTgn8Q+eCCHhZNkTESpaRFURUlVJUlUIcwVWC1EEiqKs2qY577BsXnG9y7LMnWkyzHAIQKuVK3B2MRqBpeuCCsdR3jCyRPQuy34/Ggbocxy4dV0AxuNClucdliW64xBCKdEdJxoXDiwLDyaTaCwachxNo1RDjqN3892miswUSYq/ay+yfHDxCJ6I0Pyz3fbE5PJUFcJwscWP4ShgNiOp2Tbt8/zOa4Dx5XW9nlXg+cO2mUGM94Tx/XvI21wRfVivE+xJfqiY8z08o1wYjwdPRGimSNK+JR+S+B3knSnhZDnKSVYYT9KKU94wQIXjwNJ14WuY0HnNtslb+Dctk/jEWLZTvE0khFJCfheYlvhMB6tFsxl1zkwFodrz/bRmqj3fZ6aCEDn5umk0CjiAMFxsspu4g23XaYkvhTSBLJyWUggwLhK+v4UfFhgQTvHqSuIAAAAldEVYdGRhdGU6Y3JlYXRlADIwMTctMDItMDJUMTc6MDc6MDMtMDM6MDAbEOgkAAAAJXRFWHRkYXRlOm1vZGlmeQAyMDE3LTAyLTAyVDE3OjA3OjAzLTAzOjAwak1QmAAAAEh0RVh0c3ZnOmJhc2UtdXJpAGZpbGU6Ly8vVXNlcnMvZG1hcnRpbmV6L2dpdC91bm8vaW1hZ2VzL2xvYWRpbmdfcHJvZ3Jlc3Muc3ZnMH2+vAAAAABJRU5ErkJggg==", 
  "images/overflow_menu.svg":"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAMAAAAMEAQAAABd5xOiAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAAAmJLR0QAAKqNIzIAAAAJcEhZcwAAAFoAAABaAHAjuH0AAAAHdElNRQfhAgEOITR0BZreAAAAaUlEQVQI12PujW9rc8vYuNHNnJubsUf282eGfB4eBtXPn5kYUidNYpj45cv/j5MmMSADxj4LFZX/jn5+jPs3bWLsOXPnDsMBZWWGuNu3mRiq/v+HKWNh+uTp+e+lr+8/vk2bUAxgJs5SACVPNeDSTb9iAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDE3LTAyLTAxVDE0OjMzOjUyLTAzOjAw8YzzswAAACV0RVh0ZGF0ZTptb2RpZnkAMjAxNy0wMi0wMVQxNDozMzo1Mi0wMzowMIDRSw8AAABFdEVYdHN2ZzpiYXNlLXVyaQBmaWxlOi8vL1VzZXJzL2RtYXJ0aW5lei9naXQvdW5vL2ltYWdlcy9vdmVyZmxvd19tZW51LnN2Z/dX7d8AAAAASUVORK5CYII="};
})();
goog.provide("uno.util.richlink.googledrive.win");
goog.require("uno.util.loc");
goog.require("uno.util.img.fixtures.win");
goog.require("uno.util.richlink.googledrive.generic");
(function() {
  var win = uno.util.richlink.googledrive.win;
  var util = uno.util;
  win.getAccessRequestString = function() {
    return util.loc.t("Click to request access");
  };
  win.getTapToConnectString = function() {
    return util.loc.t("Connect to see more");
  };
  win.activateDrag = function(el) {
    el.setAttribute("draggable", "false");
    return el;
  };
  win.getImagePath = function(editor) {
    return util.richlink.googledrive.generic.getImagePath(editor);
  };
  win.fixtures = uno.util.img.fixtures.win;
})();
goog.provide("uno.util.attachment");
goog.require("uno.defs");
goog.require("uno.util.loc");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.attachment");
  var defs = uno.defs;
  var util = uno.util;
  util.attachment.CLASS_PREFIX = "en-attach-icon-";
  util.attachment.getIconInfoFromFile = function(displayType, mime, fileName) {
    var fileType;
    if (typeof mime === "string" || typeof fileName === "string") {
      if (mime) {
        mime = mime ? mime.toLowerCase() : null;
        fileType = mimeToFileType[mime];
        if (!fileType) {
          if (mime.indexOf("image/") > -1) {
            fileType = "image";
          } else {
            if (mime.indexOf("audio/") > -1) {
              fileType = "audio";
            } else {
              if (mime.indexOf("video/") > -1) {
                fileType = "video";
              }
            }
          }
        }
      }
      if (!fileType && fileName) {
        var extension = fileName.match(/^.+\.([0-9a-z]+)$/i);
        if (extension) {
          fileType = extensionToFileType[extension[1]];
        }
      }
    }
    return util.attachment.CLASS_PREFIX + (fileType || "generic");
  };
  var extensionToFileType = {"pdf":"pdf", "djvu":"pdf", "wav":"audio", "aiff":"audio", "flac":"audio", "ogg":"audio", "ac3":"audio", "mp3":"audio", "avi":"video", "mp4":"video", "mpg":"video", "mpeg":"video", "vob":"video", "pptx":"ppt", "ppt":"ppt", "sdd":"ppt", "odp":"ppt", "doc":"word", "dot":"word", "docx":"word", "odt":"word", "xls":"excel", "xlsx":"excel", "ods":"excel", "csv":"excel", "zip":"zip", "zipx":"zip", "gz":"zip", "tgz":"zip", "rar":"zip", "iso":"zip", "tar":"zip", "mar":"zip", "bz2":"zip", 
  "cab":"zip", "arc":"zip", "dmg":"zip", "jar":"zip", "war":"zip", "7z":"zip", "svg":"svg", "svgz":"svg", "ai":"svg", "cdr":"svg", "wmf":"svg", "drw":"svg", "eps":"svg", "emz":"svg", "odg":"svg", "pic":"svg", "sda":"svg", "swf":"svg", "sketch":"svg", "cad":"3d", "skp":"3d", "stl":"3d", "123dx":"3d", "anim":"3d", "3d":"3d", "3dr":"3d", "3ds":"3d", "dwg":"3d", "dxf":"3d", "pfb":"font", "ttf":"font", "otf":"font", "pages":"pages", "rtf":"pages", "txt":"pages", "numbers":"num", "keynote":"keynote", "key":"keynote", 
  "psd":"edit", "ptg":"edit", "skba":"edit", "pxm":"edit", "xcf":"edit"};
  var mimeToFileType = {"application/pdf":"pdf", "application/mspowerpoint":"ppt", "application/powerpoint":"ppt", "application/vnd.ms-powerpoint":"ppt", "application/x-mspowerpoint":"ppt", "application/vnd.oasis.opendocument.presentation":"ppt", "application/vnd.openxmlformats-officedocument.presentationml.slideshow":"ppt", "application/msword":"word", "application/vnd.oasis.opendocument.text":"word", "application/vnd.openxmlformats-officedocument.wordprocessingml.document":"word", "application/excel":"excel", 
  "application/vnd.ms-excel":"excel", "application/x-excel":"excel", "text/csv":"excel", "application/vnd.oasis.opendocument.spreadsheet":"excel", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":"excel", "application/zip":"zip", "application/x-compress":"zip", "application/x-compressed":"zip", "application/x-zip-compressed":"zip", "multipart/x-zip":"zip", "application/x-gzip":"zip", "application/x-rar-compressed":"zip", "application/x-gtar":"zip", "application/vnd.ms-cab-compressed":"zip", 
  "application/x-apple-diskimage":"zip", "application/x-7z-compressed":"zip", "image/svg+xml":"svg", "application/postscript":"svg", "windows/metafile":"svg", "application/drafting":"svg", "image/pict":"svg", "application/x-shockwave-flash":"svg", "application/x-koan":"3d", "application/sla":"3d", "x-world/x-3dmf":"3d", "application/acad":"3d", "application/dxf":"3d", "application/rtf":"pages", "application/x-rtf":"pages", "text/richtext":"pages", "application/vnd.apple.pages":"pages", "application/x-iwork-pages-sffpages":"pages", 
  "application/vnd.apple.numbers":"numbers", "application/x-iwork-numbers-sffnumbers":"numbers", "application/vnd.apple.keynote":"keynote", "application/x-iwork-keynote-sffkey":"keynote", "application/vnd.google-apps.document":"gdocs", "application/vnd.google-apps.spreadsheet":"gsheets", "application/vnd.google-apps.presentation":"gslides", "unknown":"unknown"};
  util.attachment.isThumbnailableMimeType = function(mimeType) {
    if (!mimeType) {
      return false;
    }
    if (mimeType.indexOf("image/") === 0) {
      return true;
    }
    return mimeType.indexOf("video/") === 0;
  };
  util.attachment.getFileTypeDescription = function(mimeType) {
    switch(mimeType) {
      case "application/vnd.google-apps.document":
        return util.loc.t("Google Docs");
      case "application/vnd.google-apps.spreadsheet":
        return util.loc.t("Google Sheets");
      case "application/vnd.google-apps.presentation":
        return util.loc.t("Google Slides");
      case "application/pdf":
        return util.loc.t("PDF");
      default:
        return null;
    }
  };
})();
goog.provide("uno.util.richlink.googledrive");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.editor.range");
goog.require("goog.string");
goog.require("uno.Auth");
goog.require("uno.defs");
goog.require("uno.util.canvas");
goog.require("uno.util.http");
goog.require("uno.util.img");
goog.require("uno.util.richlink");
goog.require("uno.util.richlink.googledrive.android");
goog.require("uno.util.richlink.googledrive.ios");
goog.require("uno.util.richlink.googledrive.generic");
goog.require("uno.util.richlink.googledrive.win");
goog.require("uno.util.attachment");
goog.require("uno.util.loc");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.richlink.googledrive");
  var defs = uno.defs;
  var util = uno.util;
  var googledrive = util.richlink.googledrive;
  var DRIVE_META_URL = "https://www.googleapis.com/drive/v2/files/";
  var DRIVE_LINK_RX = /https:\/\/(docs|drive).google.com\/[^\s\"]+[\/\=]([^\s\/<#=%&@."?]{20,120})([^\"\<\>\s&]*)/gi;
  var GOOGLE_DATE_RX = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})\.(\d{3})Z$/;
  var THUMBNAIL_RX = /s\d+$/g;
  var client = googledrive.generic;
  var imagePath = "images";
  googledrive.name = "google-drive";
  googledrive.lastInfo = {};
  googledrive.lastImageUrl = {};
  googledrive.uniqueIdCounter = 0;
  googledrive.setClient = function(clientName) {
    client = googledrive[clientName] || client;
  };
  googledrive.canDecorate = function(url) {
    DRIVE_LINK_RX.lastIndex = 0;
    return url && DRIVE_LINK_RX.test(url);
  };
  googledrive.decorate = function(el, editor) {
    imagePath = client.getImagePath(editor);
    var richlink = googledrive.convertAnchorToRichlink(el);
    var range = editor.getRange();
    if (range && range.isCollapsed() && editor.context.format === uno.defs.format.CLIPBOARD) {
      goog.editor.range.placeCursorNextTo(richlink);
    }
    googledrive.renderRichlinkAsync(richlink).then(function(richlink) {
      googledrive.updateRichlinkAsync(richlink, false, editor).catch(function(error) {
        if (error.refreshAuth) {
          googledrive.updateRichlinkAsync(richlink, true, editor);
        }
      });
    });
    client.activateDrag(richlink);
  };
  googledrive.updateRichlinkAsync = function(richlink, refreshAuth, editor) {
    var cancelCachePromise = false;
    var cachedData = editor.cache.readMem(richlink.dataset.href);
    if (cachedData) {
      googledrive.injectDataAsync(richlink, cachedData, editor);
    }
    editor.cache.readDiskAsync(richlink.dataset.href).then(function(data) {
      if (!cancelCachePromise && data) {
        googledrive.injectDataAsync(richlink, data, editor);
        editor.cache.writeMem(richlink.dataset.href, data);
      }
    });
    return editor.auth.getTokenAsync("google-drive", refreshAuth).then(function(token) {
      return googledrive.getDataFromProviderAsync(richlink, token, editor);
    }).then(function(data) {
      cancelCachePromise = true;
      return googledrive.injectDataAsync(richlink, data, editor);
    }).then(function() {
      editor.refreshUndoRedoState();
    }).catch(function(error) {
      return googledrive.injectErrorAsync(richlink, error, editor).then(function() {
        return editor.refreshUndoRedoState();
      });
    });
  };
  googledrive.undecorate = function(el) {
    var anchor = document.createElement("a");
    goog.array.forEach(el.attributes, function(attribute) {
      if (!/^(src|width|height)$/i.test(attribute.name)) {
        anchor.setAttribute(attribute.name, attribute.value);
      }
    });
    goog.dom.replaceNode(anchor, el);
    return anchor;
  };
  googledrive.getDataFromProviderAsync = function(el, token, editor) {
    DRIVE_LINK_RX.lastIndex = 0;
    var match = DRIVE_LINK_RX.exec(el.dataset.href);
    var driveId = match[2];
    var url = DRIVE_META_URL + driveId;
    return util.http.fetchAsync(url, {headers:new Headers({"Authorization":"Bearer " + token})}).then(function(response) {
      return response.json();
    }).then(function(data) {
      data.driveId = driveId;
      if (data.parents && data.parents.length > 0) {
        data.parentFolderLink = data.parents[0].parentLink;
      }
      el.dataset.parentFolderLink = data.parentFolderLink;
      if (data.mimeType) {
        el.dataset.type = data.mimeType;
      }
      if (data.title) {
        el.dataset.title = data.title;
      }
      el.dataset.alternateLink = data.alternateLink;
      editor.cache.write(el.dataset.href, data);
      return data;
    }).catch(function(error) {
      if (error.response) {
        error.errorCode = error.errorCode || error.response.status;
      }
      throw error;
    });
  };
  googledrive.convertAnchorToRichlink = function(el) {
    var richlink = el;
    var displayType = util.richlink.getDisplayType(richlink);
    switch(displayType) {
      case util.richlink.DISPLAY_TYPE.MINIMAL:
        richlink = el;
        break;
      case util.richlink.DISPLAY_TYPE.SMALL:
      default:
        richlink = document.createElement("img");
        goog.array.forEach(el.attributes, function(attribute) {
          richlink.setAttribute(attribute.name, attribute.value);
        });
        goog.dom.replaceNode(richlink, el);
        break;
    }
    richlink.dataset.title = el.textContent;
    goog.dom.classlist.add(richlink, "en-richlink");
    return richlink;
  };
  googledrive.renderRichlinkAsync = function(richlink, iconSrc, line1, line2, connectText, thumbnailSrc, imageMeta, videoMeta) {
    richlink.dataset.icon = iconSrc || imagePath + "/loading_progress.svg";
    richlink.dataset.line1 = line1 || richlink.dataset.line1 || richlink.dataset.title || richlink.dataset.href;
    richlink.dataset.line2 = line2 || richlink.dataset.line2 || util.loc.t("Google Drive");
    richlink.dataset.connectText = connectText || "";
    richlink.dataset.connectBox = "";
    richlink.dataset.thumbnail = thumbnailSrc || "";
    switch(richlink.getAttribute("rev")) {
      case util.richlink.DISPLAY_TYPE.MINIMAL:
        return googledrive.renderMinimalRichlinkAsync(richlink, iconSrc, line1);
        break;
      case util.richlink.DISPLAY_TYPE.SMALL:
      default:
        return googledrive.renderSmallRichlinkAsync(richlink, iconSrc, line1, line2, connectText, thumbnailSrc, imageMeta, videoMeta);
        break;
    }
  };
  googledrive.renderMinimalRichlinkAsync = function(richlink, iconSrc, line1) {
    return Promise.try(function() {
      if (line1) {
        richlink.innerText = line1;
      }
      var mimeType = richlink.dataset.type || googledrive.getMimeType(richlink.dataset.href);
      var displayType = util.richlink.getDisplayType(richlink);
      var icon = util.attachment.getIconInfoFromFile(displayType, mimeType, line1 || richlink.dataset.title || richlink.dataset.href);
      goog.dom.classlist.removeAll(richlink, ["en-attach-icon-unknown", "en-attach-icon-generic"]);
      goog.dom.classlist.addAll(richlink, ["google-drive-minimal-title", icon]);
      return richlink;
    });
  };
  googledrive.renderSmallRichlinkAsync = function(richlink, iconSrc, line1, line2, connectText, thumbnailSrc, imageMeta, videoMeta) {
    var width = 380;
    var height = 55;
    var canvas = util.canvas.create(width, height);
    var context = canvas.getContext("2d");
    var asyncRenderers;
    var showIconOverlay;
    richlink.setAttribute("width", width);
    richlink.style.minWidth = width + "px";
    richlink.setAttribute("height", height);
    showIconOverlay = richlink.dataset.icon !== imagePath + "/loading_progress.svg";
    googledrive.renderMiddle(richlink.dataset.line1, richlink.dataset.line2, richlink.dataset.connectText, richlink, context);
    asyncRenderers = [googledrive.renderIconAsync(richlink.dataset.icon, showIconOverlay, richlink, context), googledrive.renderMenuAsync(richlink, context)];
    if (thumbnailSrc) {
      asyncRenderers.push(googledrive.loadThumbnailAsync(richlink.dataset.thumbnail, richlink, imageMeta, videoMeta));
    }
    return Promise.all(asyncRenderers.map(function(p) {
      return p.reflect();
    })).then(function(results) {
      if (thumbnailSrc) {
        var thumbnailPromise = results[2];
        if (thumbnailPromise.isFulfilled()) {
          canvas = googledrive.renderThumbnail(thumbnailPromise.value(), richlink, canvas);
        }
      }
      richlink.src = canvas.toDataURL();
      return richlink;
    });
  };
  googledrive.renderIconAsync = function(iconSrc, showOverlay, richlink, context) {
    var iconX;
    var iconY;
    var iconWidth;
    var iconHeight;
    var overlayPromise;
    var iconPromise = util.img.loadFromClientAsync(iconSrc, client);
    if (showOverlay) {
      overlayPromise = util.img.loadFromClientAsync(imagePath + "/att_src_icon_google_28.svg", client);
    } else {
      overlayPromise = Promise.resolve();
    }
    return iconPromise.then(function(img) {
      iconWidth = img.naturalWidth;
      iconHeight = img.naturalHeight;
      iconX = Math.floor((64 - iconWidth) / 2);
      iconY = Math.floor((richlink.height - iconHeight) / 2);
      context.drawImage(img, iconX, iconY);
      return overlayPromise;
    }).then(function(img) {
      if (img) {
        var x = iconX + iconWidth - 20;
        var y = iconY + iconHeight - 20;
        context.drawImage(img, x, y, 20, 20);
      }
    });
  };
  googledrive.renderMiddle = function(line1, line2, connectText, richlink, context) {
    var line2width;
    context.save();
    context.fillStyle = "#2e2e2e";
    context.font = "500 14px sans-serif";
    util.canvas.fillText(context, line1, 64, 25, 270);
    context.fillStyle = "#727272";
    context.font = "10px sans-serif";
    util.canvas.fillText(context, line2, 64, 43, 270);
    line2width = context.measureText(line2).width;
    context.restore();
    if (connectText) {
      googledrive.renderConnectText(connectText, line2width + 84, richlink, context);
    }
  };
  googledrive.renderConnectText = function(text, x, richlink, context) {
    var textWidth;
    context.save();
    context.fillStyle = "#37adfc";
    context.strokeStyle = "#37adfc";
    context.lineWidth = 1;
    context.font = "12px sans-serif";
    textWidth = context.measureText(text).width;
    util.canvas.fillText(context, text, x, 43, 270);
    context.beginPath();
    context.moveTo(x, 46);
    context.lineTo(x + textWidth, 46);
    context.stroke();
    context.restore();
    richlink.dataset.connectBox = JSON.stringify({left:x - 5, top:29, width:textWidth + 10, height:19});
  };
  googledrive.renderMenuAsync = function(richlink, context) {
    return util.img.loadFromClientAsync(imagePath + "/overflow_menu.svg", client).then(function(img) {
      var x = richlink.width - 20 - 3;
      var y = Math.floor((richlink.height - 12) / 2);
      context.drawImage(img, x, y);
    });
  };
  googledrive.loadThumbnailAsync = function(url, richlink, imageMeta, videoMeta) {
    var width = richlink.width;
    var height = 0;
    var ratio = -1;
    if (imageMeta && imageMeta.width && imageMeta.height) {
      ratio = imageMeta.height / imageMeta.width;
    }
    if (ratio < 0 || ratio > 0.62) {
      ratio = 0.62;
    }
    height = Math.round(ratio * width);
    var sizeString = "w" + width + (height > 0 ? "-h" + height : "") + "-p-k-nu";
    var thumbnailUrl = url.replace(THUMBNAIL_RX, sizeString);
    return util.img.loadFromClientAsync(thumbnailUrl, client);
  };
  googledrive.renderThumbnail = function(thumbnail, richlink, origCanvas) {
    var canvas = util.canvas.create(richlink.width, richlink.height + thumbnail.height);
    var context = canvas.getContext("2d");
    context.drawImage(origCanvas, 0, 0, util.canvas.width(origCanvas), util.canvas.height(origCanvas));
    context.drawImage(thumbnail, 0, richlink.height);
    richlink.src = "";
    richlink.width = util.canvas.width(canvas);
    richlink.height = util.canvas.height(canvas);
    return canvas;
  };
  googledrive.injectErrorAsync = function(el, error, editor) {
    var line2;
    var connectText;
    var displayType = util.richlink.getDisplayType(el);
    var lastErrorCode = editor.auth.getLastErrorCode(googledrive.name);
    if (displayType === util.richlink.DISPLAY_TYPE.MINIMAL) {
    } else {
      switch(error.errorCode) {
        case uno.Auth.ERROR_CODE_NO_AUTH:
        case uno.Auth.ERROR_CODE_INVALID_AUTH:
        case 401:
          if (lastErrorCode === uno.Auth.ERROR_CODE_NO_AUTH || lastErrorCode === uno.Auth.ERROR_CODE_INVALID_AUTH || lastErrorCode === 401) {
            line2 = util.loc.t("Google Drive");
            connectText = client.getTapToConnectString();
          } else {
            var authError = new Error;
            authError.refreshAuth = true;
            throw authError;
          }
          break;
        case uno.Auth.ERROR_CODE_NETWORK_ERROR:
        case 0:
          line2 = util.loc.t("Google Drive") + ": " + util.loc.t("Not available offline");
          break;
        case 403:
        case 404:
          line2 = client.getAccessRequestString();
          break;
        default:
          line2 = util.loc.t("Google Drive") + ": " + util.loc.t("Not available");
      }
    }
    var mimeType = googledrive.getMimeType(el.dataset.href);
    var icon = imagePath + "/" + util.attachment.getIconInfoFromFile(displayType, mimeType, el.dataset.title || el.dataset.href) + ".svg";
    return googledrive.renderRichlinkAsync(el, icon, null, line2, connectText);
  };
  googledrive.getMimeType = function(url, data) {
    var mimeType = data ? data.mimeType : null;
    if (!mimeType) {
      if (url.indexOf("/document/") > -1) {
        mimeType = "application/vnd.google-apps.document";
      } else {
        if (url.indexOf("/spreadsheets/") > -1) {
          mimeType = "application/vnd.google-apps.spreadsheet";
        } else {
          if (url.indexOf("/presentation/") > -1) {
            mimeType = "application/vnd.google-apps.presentation";
          }
        }
      }
    }
    return mimeType;
  };
  googledrive.injectDataAsync = function(el, data) {
    if (!data) {
      return;
    }
    var icon;
    var line1;
    var line2;
    var displayType = util.richlink.getDisplayType(el);
    var url = el.dataset.href;
    var title = data.title;
    var mimeType = googledrive.getMimeType(url, data);
    var thumbnail;
    var imageMeta;
    var videoMeta;
    if (title) {
      line1 = title;
    }
    if (displayType == util.richlink.DISPLAY_TYPE.SMALL) {
      var fileDescription = util.attachment.getFileTypeDescription(mimeType) || util.loc.t("Google Drive");
      var dateVal = googledrive.parseGoogleDate(data.modifiedDate);
      var dateString = dateVal && dateVal.toLocaleDateString();
      line2 = fileDescription;
      if (dateString) {
        line2 += ": " + util.loc.t("Modified") + " " + dateString;
      }
      icon = imagePath + "/" + uno.util.attachment.getIconInfoFromFile(displayType, mimeType, title || url) + ".svg";
      if (data.thumbnailLink && util.attachment.isThumbnailableMimeType(mimeType)) {
        thumbnail = data.thumbnailLink;
        imageMeta = data.imageMediaMetadata;
        videoMeta = data.videoMediaMetadata;
      }
    }
    return googledrive.renderRichlinkAsync(el, icon, line1, line2, null, thumbnail, imageMeta, videoMeta);
  };
  googledrive.parseGoogleDate = function(d) {
    try {
      var m = GOOGLE_DATE_RX.exec(d);
      var year = +m[1];
      var month = +m[2];
      var day = +m[3];
      var hour = +m[4];
      var minute = +m[5];
      var second = +m[6];
      var msec = +m[7];
      var tzOffset = (new Date).getTimezoneOffset();
      return new Date(year, month - 1, day, hour, minute - tzOffset, second, msec);
    } catch (exception) {
      log.info("error parsing date: " + (exception.stack || exception));
      log.fine(err.stack || err);
    }
  };
  googledrive.reloadAsync = function(el, askUserForPermission, editor) {
    return editor.auth.getTokenAsync(googledrive.name, true, !!askUserForPermission).then(function(token) {
      return googledrive.getDataFromProviderAsync(el, token, editor);
    }).then(function(data) {
      googledrive.injectDataAsync(el, data, editor);
    }).catch(function(error) {
      googledrive.injectErrorAsync(el, error, editor);
    });
  };
  googledrive.openDoc = function(url, target, editor) {
    editor.dispatchEvent({type:"linkclick", target:target, data:{module:googledrive.name || "link", href:url}});
  };
  googledrive.buildOptions = function(el, optionsEl, editor) {
    var rect = optionsEl.getBoundingClientRect();
    var options = {href:el.dataset.href, module:googledrive.name, ceOptions:{"elementId":optionsEl.id, "boundingbox":{"left":rect.left, "right":rect.right, "top":rect.top, "bottom":rect.bottom, "height":rect.height, "width":rect.width}, "optionsArray":[{"id":"open", "text":util.loc.t("Open")}]}};
    var lastErrorCode = editor.auth.getLastErrorCode(googledrive.name);
    if (lastErrorCode === uno.Auth.ERROR_CODE_NO_AUTH || lastErrorCode === uno.Auth.ERROR_CODE_INVALID_AUTH || lastErrorCode === 401) {
      options.ceOptions.optionsArray.push({"id":"connect", "text":util.loc.t("Connect Google account")});
    }
    return options;
  };
  googledrive.isOverMenu = function(richlink, event) {
    var box = goog.style.getBounds(richlink);
    var overMenu = event.target === richlink && event.clientX > box.left + box.width - 46 && event.clientY <= box.top + 55;
    return overMenu;
  };
  googledrive.isOverConnectText = function(richlink, event) {
    var box = goog.style.getBounds(richlink);
    var overConnectText = false;
    if (!richlink.dataset.connectBox) {
      return false;
    }
    try {
      var connectBox = JSON.parse(richlink.dataset.connectBox);
      overConnectText = event.clientX > box.left + connectBox.left && event.clientX < box.left + connectBox.left + connectBox.width && event.clientY > box.top + connectBox.top && event.clientY < box.top + connectBox.top + connectBox.height;
    } catch (ex) {
      log.info(ex.stack || ex);
    }
    return overConnectText;
  };
  googledrive.handleClick = function(el, event, editor) {
    if (util.richlink.getDisplayType(el) === util.richlink.DISPLAY_TYPE.MINIMAL) {
      return;
    }
    if (googledrive.isOverMenu(el, event)) {
      var options = googledrive.buildOptions(el, el, editor);
      editor.router.toHostAsync("showOptions", options).then(function(response) {
        if (response.selectedOptionId === "open") {
          googledrive.openDoc(el.dataset.href || el.dataset.alternateLink, el, editor);
        } else {
          if (response.selectedOptionId === "folder" && el.dataset.parentFolderLink) {
            googledrive.openDoc(el.dataset.parentFolderLink, el, editor);
          } else {
            if (response.selectedOptionId === "connect") {
              googledrive.reloadAsync(el, true, editor);
            }
          }
        }
      });
      event.preventDefault();
    } else {
      if (googledrive.isOverConnectText(el, event)) {
        googledrive.reloadAsync(el, true, editor);
        event.preventDefault();
      } else {
        googledrive.openDoc(el.dataset.href || el.dataset.alternateLink, el, editor);
      }
    }
    return true;
  };
  googledrive.handleMouseMove = function(el, event, editor) {
    if (util.richlink.getDisplayType(el) === util.richlink.DISPLAY_TYPE.MINIMAL) {
      return;
    }
    if (googledrive.isOverMenu(el, event)) {
      goog.dom.classlist.add(el, "google-drive-menu-hover");
    } else {
      goog.dom.classlist.remove(el, "google-drive-menu-hover");
    }
  };
  googledrive.handleMouseOut = function(el, event, editor) {
    if (util.richlink.getDisplayType(el) === util.richlink.DISPLAY_TYPE.MINIMAL) {
      return;
    }
    goog.dom.classlist.remove(el, "google-drive-menu-hover");
  };
})();
goog.provide("uno.util.touch");
(function() {
  var util = uno.util;
  util.touch.init = function(editor) {
    var x;
    var y;
    editor.addListener("touchstart", function(e) {
      x = e.clientX;
      y = e.clientY;
    }, false, editor);
    editor.addListener("touchend", function(e) {
      if (!editor.inEditMode() || x == null || y == null) {
        return;
      }
      if (Math.abs(x - e.clientX) < 5 && Math.abs(y - e.clientY) < 5) {
        var event = new MouseEvent("click", {touch:true, view:window, bubbles:true, cancelable:true, clientX:e.clientX, clientY:e.clientY});
        var preventDefault = event.preventDefault.bind(event);
        event.preventDefault = function() {
          e.preventDefault();
          preventDefault();
        };
        var target = e.target;
        target.dispatchEvent(event);
      }
      x = null;
      y = null;
    }, false, editor);
    editor.addListener("touchcancel", function() {
      x = null;
      y = null;
    }, false, editor);
  };
})();
goog.provide("uno.Editor");
goog.require("goog.array");
goog.require("goog.dom.classes");
goog.require("goog.dom.Range");
goog.require("goog.editor.Field.EventType");
goog.require("goog.editor.SeamlessField");
goog.require("goog.editor.Plugin");
goog.require("goog.editor.plugins.BasicTextFormatter");
goog.require("goog.editor.plugins.EnterHandler");
goog.require("goog.editor.plugins.RemoveFormatting");
goog.require("goog.editor.plugins.SpacesTabHandler");
goog.require("goog.editor.plugins.TableEditor");
goog.require("uno.ConsoleLogger");
goog.require("uno.defs");
goog.require("uno.env");
goog.require("uno.EditorMultiRange");
goog.require("uno.commands.Accentuate");
goog.require("uno.commands.Active");
goog.require("uno.commands.BasicTextFormatter");
goog.require("uno.commands.Bounds");
goog.require("uno.commands.Capitalize");
goog.require("uno.commands.Changes");
goog.require("uno.commands.CodeBlock");
goog.require("uno.commands.Content");
goog.require("uno.commands.ControlTodos");
goog.require("uno.commands.Copy");
goog.require("uno.commands.Count");
goog.require("uno.commands.CreateLink");
goog.require("uno.commands.Crypt");
goog.require("uno.commands.Cut");
goog.require("uno.commands.Delete");
goog.require("uno.commands.DeleteTable");
goog.require("uno.commands.DeleteTableCol");
goog.require("uno.commands.DeleteTableRow");
goog.require("uno.commands.Find");
goog.require("uno.commands.Focus");
goog.require("uno.commands.FontSize");
goog.require("uno.commands.ForeColor");
goog.require("uno.commands.ForwardDelete");
goog.require("uno.commands.Highlight");
goog.require("uno.commands.InsertHorizontalRule");
goog.require("uno.commands.InsertHtml");
goog.require("uno.commands.InsertText");
goog.require("uno.commands.InsertParagraph");
goog.require("uno.commands.InsertTable");
goog.require("uno.commands.InsertTableCol");
goog.require("uno.commands.InsertTableRow");
goog.require("uno.commands.Preview");
goog.require("uno.commands.MergeCells");
goog.require("uno.commands.MigrateTable");
goog.require("uno.commands.TableAlign");
goog.require("uno.commands.TableBorderColor");
goog.require("uno.commands.TableBorderWidth");
goog.require("uno.commands.TableCellColor");
goog.require("uno.commands.TableEqualCol");
goog.require("uno.commands.TableFitNote");
goog.require("uno.commands.TableVerticalAlign");
goog.require("uno.commands.InsertTodo");
goog.require("uno.commands.Lowercase");
goog.require("uno.commands.Margin");
goog.require("uno.commands.Paste");
goog.require("uno.commands.PlainText");
goog.require("uno.commands.PrintPreview");
goog.require("uno.commands.Redo");
goog.require("uno.commands.RemoveFormat");
goog.require("uno.commands.Resources");
goog.require("uno.commands.RichlinksConvert");
goog.require("uno.commands.RichlinksRefresh");
goog.require("uno.commands.SelectAll");
goog.require("uno.commands.Selection");
goog.require("uno.commands.SimpleText");
goog.require("uno.commands.Stats");
goog.require("uno.commands.Strikethrough");
goog.require("uno.commands.Tab");
goog.require("uno.commands.Underline");
goog.require("uno.commands.Undo");
goog.require("uno.commands.UndoRedo");
goog.require("uno.commands.Unlink");
goog.require("uno.commands.Uppercase");
goog.require("uno.commands.ZoomScale");
goog.require("uno.commands.strict.BasicTextFormatter");
goog.require("uno.commands.strict.CodeBlock");
goog.require("uno.commands.strict.ControlTodos");
goog.require("uno.commands.strict.Copy");
goog.require("uno.commands.strict.CreateLink");
goog.require("uno.commands.strict.Delete");
goog.require("uno.commands.strict.FontName");
goog.require("uno.commands.strict.FontSize");
goog.require("uno.commands.strict.ForeColor");
goog.require("uno.commands.strict.Indent");
goog.require("uno.commands.strict.InsertHorizontalRule");
goog.require("uno.commands.strict.InsertList");
goog.require("uno.commands.strict.InsertTable");
goog.require("uno.commands.strict.InsertTodo");
goog.require("uno.commands.strict.Justify");
goog.require("uno.commands.strict.Outdent");
goog.require("uno.commands.strict.Paste");
goog.require("uno.commands.strict.RemoveFormat");
goog.require("uno.commands.strict.Resources");
goog.require("uno.commands.strict.Unlink");
goog.require("uno.filters.CodeBlockFilter");
goog.require("uno.filters.CryptFilter");
goog.require("uno.filters.EnmlFilter");
goog.require("uno.filters.FontSizeFilter");
goog.require("uno.filters.NormalizeFilter");
goog.require("uno.filters.PasteFilter");
goog.require("uno.filters.PrePasteFilter");
goog.require("uno.filters.ResourceFilter");
goog.require("uno.filters.RichlinkFilter");
goog.require("uno.filters.SectionBreakFilter");
goog.require("uno.filters.TableFilter");
goog.require("uno.filters.TodoFilter");
goog.require("uno.filters.BasicTextFormatterFilter");
goog.require("uno.filters.ZoomScaleFilter");
goog.require("uno.filters.CopyFilter");
goog.require("uno.filters.strict.CodeBlockFilter");
goog.require("uno.listeners.AccentuateListener");
goog.require("uno.listeners.AttachmentListener");
goog.require("uno.listeners.AutoCorrectListener");
goog.require("uno.listeners.ChangeListener");
goog.require("uno.listeners.CodeBlockListener");
goog.require("uno.listeners.CryptListener");
goog.require("uno.listeners.DeleteListener");
goog.require("uno.listeners.NoteListener");
goog.require("uno.listeners.ForwardDeleteListener");
goog.require("uno.listeners.HighlightListener");
goog.require("uno.listeners.ImgListener");
goog.require("uno.listeners.LinkListener");
goog.require("uno.listeners.ListListener");
goog.require("uno.listeners.PasteListener");
goog.require("uno.listeners.RichlinkListener");
goog.require("uno.listeners.ShortcutListener");
goog.require("uno.listeners.SmartScrollListener");
goog.require("uno.listeners.TableListener");
goog.require("uno.listeners.TodoListener");
goog.require("uno.listeners.TodoListListener");
goog.require("uno.listeners.TypeBehindListener");
goog.require("uno.listeners.SelectionListener");
goog.require("uno.listeners.strict.DeleteListener");
goog.require("uno.listeners.strict.HrListener");
goog.require("uno.listeners.strict.ListListener");
goog.require("uno.listeners.strict.OriginListener");
goog.require("uno.listeners.strict.PendingStyleListener");
goog.require("uno.listeners.strict.TodoListener");
goog.require("uno.listeners.strict.TodoListListener");
goog.require("uno.listeners.strict.TypeBehindListener");
goog.require("uno.model.resource");
goog.require("uno.util.canvas");
goog.require("uno.util.dom");
goog.require("uno.util.font");
goog.require("uno.util.img");
goog.require("uno.util.loc");
goog.require("uno.util.objects");
goog.require("uno.util.preview");
goog.require("uno.util.resource");
goog.require("uno.util.richlink.googledrive");
goog.require("uno.util.touch");
goog.require("uno.util.todo");
goog.require("uno.util.tools");
(function() {
  var Field = goog.editor.Field;
  var log = goog.debug.Logger.getLogger("uno.Editor");
  var SeamlessField = goog.editor.SeamlessField;
  var Plugin = goog.editor.Plugin;
  var model = uno.model;
  var util = uno.util;
  var Editor = uno.Editor = function(id, options) {
    SeamlessField.call(this, id || "editor");
    this.initConfig(options);
    this.cache = options.cache;
    this.auth = options.auth;
    this.router = options.router;
    this.dirty = false;
    this.empty = true;
    this.focused = false;
    this.isSetup = false;
    this.readOnly = options.rte.active === false || options.realtime != null;
    this.strictMode = this.config.allowStrictMode && !this.hasProtectedContent();
    this.multirange = new uno.EditorMultiRange(this);
    goog.dom.classes.add(document.body, this.config.client);
    model.resource.setClient(this.config.client);
    util.font.setClient(this.config.client);
    util.preview.setClient(this.config.client);
    util.resource.setClient(this.config.client);
    util.todo.setClient(this.config.client);
    util.richlink.googledrive.setClient(this.config.client);
    this.listeners = {};
    this.handlers = [{name:"click", handler:"handleClick"}, {name:"dblclick", handler:"handleDoubleClick"}, {name:"mousedown", handler:"handleMouseDown"}, {name:"mouseup", handler:"handleMouseUp"}, {name:"mouseover", handler:"handleMouseOver"}, {name:"mouseout", handler:"handleMouseOut"}, {name:"mousemove", handler:"handleMouseMove"}, {name:"textInput", handler:"handleTextInput"}, {name:"input", handler:"handleInput"}, {name:"paste", handler:"handlePaste"}, {name:"domupdate", target:this, handler:"handleDomUpdate"}, 
    {name:"beforeexeccommand", target:this, handler:"handleBeforeExecCommand"}, {name:"afterexeccommand", target:this, handler:"handleAfterExecCommand"}, {name:"delayedchange", target:this, handler:"handleDelayedChange"}, {name:"selectionchange", target:document, handler:"handleNativeSelectionChange"}, {name:"resize", target:window, handler:"handleWindowResize"}, {name:"scroll", target:window, handler:"handleScroll", capture:true}, {name:"contextmenu", target:window, handler:"handleContextMenu"}, 
    {name:"winmouseup", eventname:"mouseup", target:window, handler:"handleWindowMouseUp"}, {name:"winmousemove", eventname:"mousemove", target:window, handler:"handleWindowMouseMove"}];
    this.handlers.forEach(function(property) {
      this.listeners[property.name] = [];
    }.bind(this));
    this.importDomFilters = [];
    this.allPluginsInOrder = [];
    this.queryCommandEnabledPlugins = [];
    this.richlinkProviders = [uno.util.richlink.googledrive];
    this.setFollowLinkInNewWindow(false);
    util.loc.init(this.config.locale);
    this.initEvents();
    this.initPlugins();
    if (this.config.richlinks.cacheSupported) {
      this.cache.enableDisk();
    } else {
      this.cache.disableDisk();
    }
  };
  goog.inherits(Editor, SeamlessField);
  Editor.EventType = {PRINT_READY:"printReady", IMAGE_CLICK:"imageclick", IMAGE_DOUBLECLICK:"imagedoubleclick", IMAGE_ANNOTATE:"annotate", IMAGE_PREVIEW:"preview", IMAGE_ROTATE:"rotate", CONTENT_LOADED:"contentloaded", LINK_CLICK:"linkclick", OPEN_LINK:"openLink", ENCRYPT:"encrypt", DECRYPT:"decrypt", CRYPT_DOUBLECLICK:"cryptdoubleclick", STYLE_CHANGED:"stylechanged", EDIT_MODE_CHANGED:"editmodechanged", CONTENT_CHANGED:"contentchanged", ACTION_DENIED:"actiondenied", DOM_UPDATE:"domupdate"};
  Object.keys(Field.EventType).forEach(function(key) {
    if (Field.EventType.hasOwnProperty(key)) {
      Editor.EventType[key] = Field.EventType[key];
    }
  });
  Editor.prototype.setup = function() {
    start("Editor.prototype.setup");
    var options = {type:this.config.initialContentFormat, content:this.config.initialContent || this.config.defaults.html};
    this.makeEditable();
    this.field.removeAttribute("role");
    this.execCommand("margin", this.config.margin);
    this.multirange.clear();
    if (goog.isDef(this.config.initialContent)) {
      this.execCommand("content", options);
    } else {
      this.setHtml(false, this.config.defaults.html, true);
    }
    this.updateEmpty();
    this.isSetup = true;
    stop("Editor.prototype.setup");
  };
  Editor.prototype.makeEditable = function() {
    SeamlessField.prototype.makeEditable.call(this);
    if (!this.strictMode) {
      this.disableStrictMode();
    }
  };
  Editor.prototype.initEvents = function() {
    this.listen(Editor.EventType.DELAYEDCHANGE, this.onDelayedChange);
    this.listen(Editor.EventType.LOAD, this.onLoad);
    this.listen(Editor.EventType.UNLOAD, this.onUnload);
    this.listen(Editor.EventType.FOCUS, this.onFocus);
    this.listen(Editor.EventType.BLUR, this.onBlur);
    this.listen(Editor.EventType.BEFORESELECTIONCHANGE, this.onBeforeSelectionChange);
    this.listen(Editor.EventType.COMMAND_VALUE_CHANGE, this.onCommandValueChange);
    this.listen(Editor.EventType.SELECTIONCHANGE, this.onSelectionChange);
    this.eventRegister.listen(document, "selectionchange", this.onSelectionChange);
    this.eventRegister.listen(document, "click", this.onDocumentClick);
    this.eventRegister.listen(document.body, "textInput", this.onTextInput);
  };
  Editor.prototype.registerPlugin = function(plugin) {
    SeamlessField.prototype.registerPlugin.call(this, plugin);
    this.handlers.forEach(function(property) {
      if (plugin[property.handler]) {
        this.listeners[property.name].push(plugin);
      }
    }, this);
    this.allPluginsInOrder.push(plugin);
    if (plugin.prepareContentsDom) {
      this.importDomFilters.push(plugin);
    }
    if (plugin.queryCommandEnabled) {
      this.queryCommandEnabledPlugins.push(plugin);
    }
  };
  Editor.prototype.unregisterPlugin = function(plugin) {
    SeamlessField.prototype.unregisterPlugin.call(this, plugin);
    this.handlers.forEach(function(property) {
      goog.array.remove(this.listeners[property.name], plugin);
    }, this);
    goog.array.remove(this.allPluginsInOrder, plugin);
    if (plugin.prepareContentsDom) {
      goog.array.remove(this.importDomFilters, plugin);
    }
    if (plugin.queryCommandEnabled) {
      goog.array.remove(this.queryCommandEnabledPlugins, plugin);
    }
  };
  Editor.prototype.registerStrictModePlugin = function(plugin) {
    plugin.strictMode = true;
    this.registerPlugin(plugin);
    if (this.strictMode !== true) {
      plugin.disable(this);
    }
  };
  Editor.prototype.initPlugins = function() {
    this.registerPlugin(new uno.listeners.ShortcutListener);
    this.registerPlugin(new goog.editor.plugins.BasicTextFormatter);
    this.registerPlugin(new goog.editor.plugins.RemoveFormatting);
    this.registerPlugin(new goog.editor.plugins.TableEditor);
    this.registerStrictModePlugin(new uno.commands.strict.BasicTextFormatter);
    this.registerStrictModePlugin(new uno.commands.strict.CodeBlock);
    this.registerStrictModePlugin(new uno.commands.strict.ControlTodos);
    this.registerStrictModePlugin(new uno.commands.strict.Copy);
    this.registerStrictModePlugin(new uno.commands.strict.CreateLink);
    this.registerStrictModePlugin(new uno.commands.strict.Delete);
    this.registerStrictModePlugin(new uno.commands.strict.FontName);
    this.registerStrictModePlugin(new uno.commands.strict.FontSize);
    this.registerStrictModePlugin(new uno.commands.strict.ForeColor);
    this.registerStrictModePlugin(new uno.commands.strict.Indent);
    this.registerStrictModePlugin(new uno.commands.strict.InsertHorizontalRule);
    this.registerStrictModePlugin(new uno.commands.strict.InsertList);
    this.registerStrictModePlugin(new uno.commands.strict.InsertTable);
    this.registerStrictModePlugin(new uno.commands.strict.InsertTodo);
    this.registerStrictModePlugin(new uno.commands.strict.Justify);
    this.registerStrictModePlugin(new uno.commands.strict.Outdent);
    this.registerStrictModePlugin(new uno.commands.strict.Paste);
    this.registerStrictModePlugin(new uno.commands.strict.RemoveFormat);
    this.registerStrictModePlugin(new uno.commands.strict.Resources);
    this.registerStrictModePlugin(new uno.commands.strict.Unlink);
    this.registerPlugin(new uno.commands.Accentuate);
    this.registerPlugin(new uno.commands.Active);
    this.registerPlugin(new uno.commands.BasicTextFormatter);
    this.registerPlugin(new uno.commands.Bounds);
    this.registerPlugin(new uno.commands.Capitalize);
    this.registerPlugin(new uno.commands.Changes);
    this.registerPlugin(new uno.commands.CodeBlock);
    this.registerPlugin(new uno.commands.Content);
    this.registerPlugin(new uno.commands.ControlTodos);
    this.registerPlugin(new uno.commands.Copy);
    this.registerPlugin(new uno.commands.Count);
    this.registerPlugin(new uno.commands.CreateLink);
    this.registerPlugin(new uno.commands.Crypt);
    this.registerPlugin(new uno.commands.Cut);
    this.registerPlugin(new uno.commands.Delete);
    this.registerPlugin(new uno.commands.DeleteTable);
    this.registerPlugin(new uno.commands.DeleteTableCol);
    this.registerPlugin(new uno.commands.DeleteTableRow);
    this.registerPlugin(new uno.commands.Find(this.config));
    this.registerPlugin(new uno.commands.Focus);
    this.registerPlugin(new uno.commands.FontSize);
    this.registerPlugin(new uno.commands.ForeColor);
    this.registerPlugin(new uno.commands.ForwardDelete);
    this.registerPlugin(new uno.commands.Highlight);
    this.registerPlugin(new uno.commands.InsertHorizontalRule);
    this.registerPlugin(new uno.commands.InsertHtml);
    this.registerPlugin(new uno.commands.InsertText);
    this.registerPlugin(new uno.commands.InsertParagraph);
    this.registerPlugin(new uno.commands.InsertTable);
    this.registerPlugin(new uno.commands.InsertTableCol);
    this.registerPlugin(new uno.commands.InsertTableRow);
    this.registerPlugin(new uno.commands.MergeCells);
    this.registerPlugin(new uno.commands.MigrateTable);
    this.registerPlugin(new uno.commands.Preview);
    this.registerPlugin(new uno.commands.TableAlign);
    this.registerPlugin(new uno.commands.TableBorderColor);
    this.registerPlugin(new uno.commands.TableBorderWidth);
    this.registerPlugin(new uno.commands.TableCellColor);
    this.registerPlugin(new uno.commands.TableEqualCol);
    this.registerPlugin(new uno.commands.TableFitNote);
    this.registerPlugin(new uno.commands.TableVerticalAlign);
    this.registerPlugin(new uno.commands.InsertTodo);
    this.registerPlugin(new uno.commands.Lowercase);
    this.registerPlugin(new uno.commands.Margin);
    this.registerPlugin(new uno.commands.Paste(this.config));
    this.registerPlugin(new uno.commands.PlainText);
    this.registerPlugin(new uno.commands.PrintPreview);
    this.registerPlugin(new uno.commands.Redo);
    this.registerPlugin(new uno.commands.RemoveFormat);
    this.registerPlugin(new uno.commands.Resources);
    this.registerPlugin(new uno.commands.RichlinksConvert);
    this.registerPlugin(new uno.commands.RichlinksRefresh);
    this.registerPlugin(new uno.commands.SelectAll);
    this.registerPlugin(new uno.commands.Selection);
    this.registerPlugin(new uno.commands.SimpleText);
    this.registerPlugin(new uno.commands.Stats);
    this.registerPlugin(new uno.commands.Strikethrough);
    this.registerPlugin(new uno.commands.Tab);
    this.registerPlugin(new uno.commands.Underline);
    this.registerPlugin(new uno.commands.Undo);
    this.registerPlugin(new uno.commands.UndoRedo);
    this.registerPlugin(new uno.commands.Unlink);
    this.registerPlugin(new uno.commands.Uppercase);
    this.registerPlugin(new uno.commands.ZoomScale);
    this.registerPlugin(new uno.filters.EnmlFilter);
    this.registerPlugin(new uno.filters.PrePasteFilter);
    this.registerPlugin(new uno.filters.NormalizeFilter);
    this.registerPlugin(new uno.filters.PasteFilter);
    this.registerPlugin(new uno.filters.CryptFilter(this.config));
    this.registerPlugin(new uno.filters.ResourceFilter);
    this.registerPlugin(new uno.filters.RichlinkFilter);
    this.registerPlugin(new uno.filters.SectionBreakFilter);
    this.registerPlugin(new uno.filters.TableFilter);
    this.registerPlugin(new uno.filters.TodoFilter);
    this.registerPlugin(new uno.filters.BasicTextFormatterFilter);
    this.registerStrictModePlugin(new uno.filters.strict.CodeBlockFilter);
    this.registerPlugin(new uno.filters.CodeBlockFilter);
    this.registerPlugin(new uno.filters.FontSizeFilter);
    this.registerPlugin(new uno.filters.ZoomScaleFilter);
    this.registerPlugin(new uno.filters.CopyFilter);
    if (this.config.multirange) {
      this.registerPlugin(new uno.listeners.TableListener);
    }
    this.registerPlugin(new goog.editor.plugins.EnterHandler);
    this.registerPlugin(new uno.listeners.AccentuateListener);
    this.registerPlugin(new uno.listeners.AttachmentListener);
    this.registerPlugin(new uno.listeners.AutoCorrectListener);
    this.registerPlugin(new uno.listeners.ChangeListener);
    this.registerPlugin(new uno.listeners.CodeBlockListener);
    this.registerPlugin(new uno.listeners.CryptListener);
    this.registerStrictModePlugin(new uno.listeners.strict.DeleteListener);
    this.registerPlugin(new uno.listeners.DeleteListener);
    this.registerPlugin(new uno.listeners.ForwardDeleteListener);
    this.registerPlugin(new uno.listeners.HighlightListener);
    this.registerPlugin(new uno.listeners.RichlinkListener);
    this.registerStrictModePlugin(new uno.listeners.strict.TodoListener);
    this.registerPlugin(new uno.listeners.TodoListener);
    this.registerPlugin(new uno.listeners.LinkListener);
    this.registerPlugin(new uno.listeners.ImgListener);
    this.registerStrictModePlugin(new uno.listeners.strict.ListListener);
    this.registerPlugin(new uno.listeners.ListListener);
    this.registerPlugin(new uno.listeners.PasteListener);
    this.registerPlugin(new goog.editor.plugins.SpacesTabHandler);
    this.registerStrictModePlugin(new uno.listeners.strict.TodoListListener);
    this.registerPlugin(new uno.listeners.TodoListListener);
    this.registerStrictModePlugin(new uno.listeners.strict.TypeBehindListener);
    this.registerPlugin(new uno.listeners.TypeBehindListener);
    this.registerStrictModePlugin(new uno.listeners.strict.PendingStyleListener);
    this.registerPlugin(new uno.listeners.NoteListener);
    this.registerPlugin(new uno.listeners.SmartScrollListener);
    this.registerPlugin(new uno.listeners.SelectionListener);
    this.registerStrictModePlugin(new uno.listeners.strict.HrListener);
    this.registerStrictModePlugin(new uno.listeners.strict.OriginListener);
  };
  Editor.prototype.initConfig = function(opt) {
    var options = opt || {};
    options.env = options.env || {};
    options.env.margin = options.env.margin || {};
    options.env.margin.scroll = options.env.margin.scroll || {};
    options.env.margin.offset = options.env.margin.offset || {};
    options.rte = options.rte || {};
    options.rte.imageConfig = options.rte.imageConfig || {};
    options.rte.resourceConfig = options.rte.resourceConfig || {};
    options.rte.typebehind = options.rte.typebehind || {};
    options.rte.locale = options.rte.locale || "en_US";
    options.note = options.note || {};
    this.context = {crypt:{uniqueIdCounter:0, incrementUniqueId:function() {
      return ++this.uniqueIdCounter;
    }}, hasTempStyles:false, copyPaste:{}, format:uno.defs.format.CLIENT_HTML, images:{annotateButton:null, annotateHoverButton:null, previewButton:null, previewHoverButton:null, rotateButton:null, rotateHoverButton:null}, pendingTodo:false, resources:options.rte.resources || {}, style:{state:{}, value:{}, enabled:{}}, tempStyles:{state:{}, value:{}, enabled:{}}};
    this.config = {accentuate:options.accentuate || {clearOnClickSelector:"en-note"}, allowStrictMode:options.rte.allowStrictMode || false, crypt:{unveilCryptElementOnClick:false, readOnly:options.rte.cryptReadOnly || false}, debug:!!options.debug, defaults:{html:"<div><br></div>", placeholderText:options.rte.placeholder || "Drag files here or start typing", plainTextFont:options.env.defaultPlainTextFont || "Courier New", richTextFont:options.env.defaultNoteFont || "sans-serif", selectionColor:"rgb(178, 215, 255)", 
    fontSize:"", fontFamily:"", foreColor:"rgb(0, 0, 0)"}, find:options.find || {}, images:{path:options.rte.imageConfig.path || "images", annotate:!!options.rte.imageConfig.annotate, preview:!!options.rte.imageConfig.preview, resize:!!options.rte.imageConfig.resize || !!options.rte.imageResizing, rotate:!!options.rte.imageConfig.rotate, horizontalThreshold:options.rte.smartMarginThreshold || 0, androidPath:"http://android.local/images"}, initialContent:options.rte.enml || options.rte.html, initialContentFormat:options.rte.enml ? 
    uno.defs.format.ENML : uno.defs.format.CLIENT_HTML, locale:options.rte.locale || "en_US", margin:{note:options.env.margin.note, scroll:{top:options.env.margin.scroll.top || 0, left:options.env.margin.scroll.left || 0, bottom:options.env.margin.scroll.bottom || 0, right:options.env.margin.scroll.right || 0}, offset:{height:options.env.margin.offset.height || 0, width:options.env.margin.offset.width || 0}}, multirange:true, noNormalize:options.noNormalize, note:{contentClass:options.note.contentClass, 
    source:options.note.source, sourceURL:options.note.sourceURL, sourceApplication:options.note.sourceApplication, title:options.note.title}, client:options.env.client || uno.env.getClient(), resourceConfig:{openLinkNotifications:!!options.rte.resourceConfig.openLinkNotifications}, smartScrollEnabled:options.rte.smartScroll, stayInEditMode:options.stayInEditMode !== false, richlinks:{enabled:options.rte.richLinks || false, cacheSupported:options.rte.richLinkCaching || false}, style:{table:{borderCollapse:"collapse", 
    tableLayout:"fixed", cell:{width:264, borderWidth:1, borderColor:"#d3d3d3", borderStyle:"solid", padding:"10px", margin:"0px"}}}, typebehind:{code:options.rte.typebehind.code || false, email:options.rte.typebehind.email || false, emoticon:options.rte.typebehind.emoticon || false, horizontalrule:options.rte.typebehind.horizontalrule || false, inline:options.rte.typebehind.inline || false, list:options.rte.typebehind.list || false, table:options.rte.typebehind.table || false, todo:options.rte.typebehind.todo || 
    false, url:options.rte.typebehind.url || false}};
    util.tools.preloadImages();
    util.img.preloadTools(this);
  };
  Editor.prototype.onLoad = function() {
    var el = this.getElement();
    var me = this;
    me.handlers.forEach(function(property) {
      var src = property.target || me.field;
      var type = property.eventname || property.name;
      var capture = property.capture === true;
      var handler = function(event) {
        me.listeners[property.name].some(function(plugin) {
          if (property.name === "selectionchange" && me.multirange.isInvoking()) {
            return false;
          }
          return plugin.isEnabled(me) && plugin[property.handler](event);
        });
      };
      me.eventRegister.listenWithScope(src, type, handler, capture, me);
    });
    uno.util.touch.init(this);
    el.setAttribute("data-en-placeholder", this.config.defaults.placeholderText);
    this.updateEmpty();
    var computedStyle = window.getComputedStyle(el);
    this.config.defaults.fontSize = computedStyle.fontSize;
    this.config.defaults.fontFamily = computedStyle.fontFamily.replace(/"/g, "");
    setTimeout(function() {
      me.leaveEditMode();
    });
  };
  Editor.prototype.onUnload = function() {
    this.isSetup = false;
  };
  Editor.prototype.onDocumentClick = function(e) {
    if (!this.readOnly && (e.target === document || e.target === document.body || e.target === document.documentElement)) {
      if (this.getRange() && !this.getRange().isCollapsed()) {
        return;
      }
      this.enterEditMode(true);
      this.placeCursorAtEnd();
      util.range.scrollSelectionIntoView(this);
    }
  };
  Editor.prototype.isFocused = function() {
    return this.focused;
  };
  Editor.prototype.inEditMode = function() {
    return this.field && this.field.getAttribute("contenteditable") === "true";
  };
  Editor.prototype.enablePlugins = function() {
    var editor = this;
    var strictMode = editor.strictMode;
    editor.allPluginsInOrder.forEach(function(plugin) {
      if (plugin.strictMode) {
        if (strictMode) {
          plugin.enable(editor);
        }
      } else {
        plugin.enable(editor);
      }
    });
  };
  Editor.prototype.disablePlugins = function() {
    var editor = this;
    editor.allPluginsInOrder.forEach(function(plugin) {
      if (!plugin.activeOnUneditableFields()) {
        plugin.disable(editor);
      }
    });
  };
  Editor.prototype.enableStrictMode = function() {
    var editor = this;
    editor.strictMode = true;
    editor.allPluginsInOrder.forEach(function(plugin) {
      if (plugin.strictMode) {
        plugin.enable(editor);
      }
    });
  };
  Editor.prototype.disableStrictMode = function() {
    var editor = this;
    editor.strictMode = false;
    editor.allPluginsInOrder.forEach(function(plugin) {
      if (plugin.strictMode) {
        plugin.disable(editor);
      }
    });
  };
  Editor.prototype.cleanUX = function() {
    var editor = this;
    editor.allPluginsInOrder.forEach(function(plugin) {
      if (plugin.cleanUX) {
        plugin.cleanUX(editor.field);
      }
    });
  };
  Editor.prototype.restoreUX = function() {
    var editor = this;
    editor.allPluginsInOrder.forEach(function(plugin) {
      if (plugin.restoreUX) {
        plugin.restoreUX(editor.field);
      }
    });
  };
  Editor.prototype.hasProtectedContent = function(frag) {
    var node = frag || this.field;
    var source = this.config.note.source;
    var hasContentClass = !!this.config.note.contentClass;
    var hasWebclipSource = ["Clearly", "External", "web.clip", "web.clip7"].indexOf(source) > -1;
    var hasEmailSource = /^e?mail/i.test(source);
    var hasMarxicoSource = /maxiang/i.test(source);
    var hasPostboxSourceUrl = /postbox/i.test(this.config.note.sourceURL);
    var hasBlockSpans = !!node && !!node.querySelector('span[style*="display: block"],span[style*="display:block"]');
    return hasContentClass || hasWebclipSource || hasEmailSource || hasMarxicoSource || hasPostboxSourceUrl || hasBlockSpans;
  };
  Editor.prototype.hasForeignSource = function() {
    var source = this.config.note.source;
    var hasContentClass = !!this.config.note.contentClass;
    var hasWebclipSource = ["Clearly", "External", "web.clip", "web.clip7"].indexOf(source) > -1;
    var hasEmailSource = /^e?mail/i.test(source);
    var hasMarxicoSource = /maxiang/i.test(source);
    var hasPostboxSourceUrl = /postbox/i.test(this.config.note.sourceURL);
    return hasContentClass || hasWebclipSource || hasEmailSource || hasMarxicoSource || hasPostboxSourceUrl;
  };
  Editor.prototype.enterEditMode = function(rangeOrFocus) {
    if (this.readOnly) {
      return;
    }
    var changed = false;
    var range = rangeOrFocus;
    var focus = true;
    if (goog.isBoolean(rangeOrFocus) && rangeOrFocus === false) {
      focus = false;
    }
    if (!this.inEditMode()) {
      this.field.setAttribute("contenteditable", "true");
      goog.dom.classlist.add(this.field, "editmode");
      goog.dom.classlist.remove(this.field, "viewmode");
      this.enablePlugins();
      if (range) {
        this.restoreRange(range);
      }
      changed = true;
    }
    if (focus) {
      this.focus();
      this.updateUndoCursorPosition();
    }
    if (changed) {
      this.dispatchEvent(Editor.EventType.EDIT_MODE_CHANGED);
    }
  };
  Editor.prototype.setHtml = function() {
    start("Editor.prototype.setHtml");
    SeamlessField.prototype.setHtml.apply(this, arguments);
    var note = this.field;
    var startNode = note.firstChild || note;
    var startOffset = 0;
    var endNode = note.lastChild || note;
    var endOffset = note.lastChild ? note.lastChild.childNodes.length : 0;
    var range = goog.dom.Range.createFromNodes(startNode, startOffset, endNode, endOffset);
    this.dispatchEvent({type:Editor.EventType.DOM_UPDATE, range:range, paste:false});
    stop("Editor.prototype.setHtml");
  };
  Editor.prototype.leaveEditMode = function(force) {
    if (!this.readOnly && force !== true) {
      if (!this.inEditMode() || this.config.stayInEditMode) {
        return;
      }
    }
    if (this.field) {
      this.field.removeAttribute("contenteditable");
      goog.dom.classlist.add(this.field, "viewmode");
      goog.dom.classlist.remove(this.field, "editmode");
      this.disablePlugins();
      this.field.blur();
    }
    this.dispatchEvent(Editor.EventType.EDIT_MODE_CHANGED);
  };
  Editor.prototype.onFocus = function() {
    this.enterEditMode();
    this.focused = true;
    var range = this.getRange();
    if (range && range.getStartNode() === this.field && range.getStartOffset() === 0) {
      if (!this.field.firstChild) {
        this.field.innerHTML = this.config.defaults.html;
      }
      goog.dom.Range.createCaret(this.field.firstChild, 0).select();
    }
  };
  Editor.prototype.onBlur = function() {
    this.leaveEditMode();
    this.focused = false;
  };
  Editor.prototype.blur = function() {
    var range = this.saveRange();
    if (this.field) {
      this.field.blur();
    }
    if (range) {
      range.select();
    }
  };
  Editor.prototype.saveRange = function() {
    var range = this.getRange();
    if (range) {
      this.savedRange = range.saveUsingDom();
    }
    return range;
  };
  Editor.prototype.restoreRange = function(range) {
    if (goog.isObject(range)) {
      range.select();
    } else {
      var didSetSelection = false;
      if (this.savedRange != null && this.savedRange.isDisposed && !this.savedRange.isDisposed()) {
        try {
          this.savedRange.restore().select();
          var newRange = this.getRange();
          newRange.collapse();
          newRange.select();
          didSetSelection = true;
        } catch (err$13) {
          log.fine(err$13.stack || err$13);
        }
      }
      if (!didSetSelection) {
        this.placeCursorAtEnd();
      }
      this.savedRange = null;
    }
  };
  Editor.prototype.cleanup = function() {
    if (this.isSetup) {
      var field = this.field;
      this.makeUneditable(true);
      while (field.firstChild) {
        field.removeChild(field.firstChild);
      }
      this.dispose();
      window.ed = null;
    }
  };
  Editor.prototype.onCommandValueChange = function() {
    this.dispatchEvent(uno.Editor.EventType.STYLE_CHANGED);
  };
  Editor.prototype.onBeforeSelectionChange = function() {
    this.updateUndoCursorPosition();
  };
  Editor.prototype.onDelayedChange = function() {
    this.dirty = true;
  };
  Editor.prototype.onSelectionChange = function() {
    this.updateEmpty();
    if (!this.readOnly) {
      this.dispatchEvent(uno.Editor.EventType.STYLE_CHANGED);
    }
    this.saveRange();
  };
  Editor.prototype.onTextInput = function() {
    this.dispatchChange();
  };
  Editor.prototype.updateEmpty = function() {
    if (this.field == null) {
      return;
    }
    var empty = util.dom.isEmpty(this.field);
    if (empty && this.field.innerHTML !== this.config.defaults.html) {
      this.context.format = uno.defs.format.CLIENT_HTML;
      this.setHtml(false, this.config.defaults.html, true);
      document.body.scrollLeft = 0;
      document.body.scrollTop = 0;
    }
    if (this.inEditMode() && this.field.innerHTML === this.config.defaults.html) {
      var range = this.getRange();
      var div = this.field.querySelector("div");
      if (!(range && range.getStartNode() === div)) {
        goog.dom.Range.createCaret(div, 0).select();
      }
    }
    if (empty) {
      goog.dom.classes.add(this.field, "en-note-is-empty");
    } else {
      goog.dom.classes.remove(this.field, "en-note-is-empty");
    }
    this.empty = empty;
  };
  Editor.prototype.queryCommandValueInternal_ = function(command, isLoaded, opt, isTopLevelCall) {
    var logic = function() {
      var plugins = this.indexedPlugins_[Plugin.Op.QUERY_COMMAND];
      for (var i = 0; i < plugins.length; ++i) {
        var plugin = plugins[i];
        if (plugin.isEnabled(this) && plugin.isSupportedCommand(command) && (isLoaded || plugin.activeOnUneditableFields())) {
          return plugin.queryCommandValue(command, opt);
        }
      }
      return isLoaded ? null : false;
    }.bind(this);
    return logic();
  };
  Editor.prototype.queryCommandValue = function(commands, opt, isTopLevelCall) {
    var isLoaded = this.isLoaded();
    var result;
    if (goog.isString(commands)) {
      result = this.queryCommandValueInternal_(commands, isLoaded, opt, isTopLevelCall);
    } else {
      result = {};
      if (!Array.isArray(commands)) {
        throw Error("commands is null!");
      }
      commands.forEach(function(command) {
        if (goog.isString(command)) {
          result[command] = this.queryCommandValueInternal_(command, isLoaded, isTopLevelCall);
        } else {
          result[command] = this.queryCommandValueInternal_(command.name, isLoaded, command.opt, isTopLevelCall);
        }
      });
    }
    return result;
  };
  Editor.prototype.queryCommandEnabledInternal_ = function(command, isLoaded, opt, isTopLevelCall) {
    var mode = isTopLevelCall ? uno.EditorMultiRange.Mode.FIRST : uno.EditorMultiRange.Mode.NONE;
    return this.multirange.invoke(mode, function() {
      var plugins = this.queryCommandEnabledPlugins;
      for (var i = 0; i < plugins.length; ++i) {
        var plugin = plugins[i];
        if (plugin.isEnabled(this) && plugin.isSupportedCommand(command) && (isLoaded || plugin.activeOnUneditableFields())) {
          return plugin.queryCommandEnabled(command, opt);
        }
      }
      return true;
    });
  };
  Editor.prototype.queryCommandEnabled = function(commands, opt, isTopLevelCall) {
    var isLoaded = this.isLoaded();
    var result;
    if (goog.isString(commands)) {
      result = !!this.queryCommandEnabledInternal_(commands, isLoaded, opt, isTopLevelCall);
    } else {
      result = {};
      commands.forEach(function(command) {
        if (goog.isString(command)) {
          result[command] = !!this.queryCommandEnabledInternal_(command, isLoaded, null, isTopLevelCall);
        } else {
          result[command] = !!this.queryCommandEnabledInternal_(command.name, isLoaded, command.opt, isTopLevelCall);
        }
      });
    }
    return result;
  };
  Editor.prototype.execCommand = function(command, value, options, isTopLevelCall) {
    if (isTopLevelCall == null) {
      isTopLevelCall = false;
    }
    var plugins = this.indexedPlugins_[Plugin.Op.EXEC_COMMAND];
    var targetPlugin = null;
    for (var i = 0; i < plugins.length && targetPlugin == null; ++i) {
      if (plugins[i].isEnabled(this) && plugins[i].isSupportedCommand(command) && (this.isLoaded() || plugins[i].activeOnUneditableFields())) {
        targetPlugin = plugins[i];
      }
    }
    if (!targetPlugin || !goog.isFunction(targetPlugin.execCommand)) {
      return false;
    }
    if (goog.isFunction(targetPlugin.queryCommandEnabled) && targetPlugin.queryCommandEnabled(command, value) === false) {
      return false;
    }
    var mode = uno.EditorMultiRange.Mode.NONE;
    if (isTopLevelCall && targetPlugin.multiRangeMode === uno.EditorMultiRange.Mode.ALL) {
      mode = uno.EditorMultiRange.Mode.ALL;
    }
    return this.multirange.invoke(mode, function() {
      var result = null;
      this.dispatchEvent({type:"beforeexeccommand", command:command});
      result = targetPlugin.execCommand.call(targetPlugin, command, value, options);
      this.updateUndoCursorPosition();
      this.dispatchEvent({type:"afterexeccommand", command:command});
      return result;
    });
  };
  Editor.prototype.isSupportedCommand = function(command) {
    if (!this.isLoaded()) {
      return false;
    }
    var plugins = this.allPluginsInOrder;
    for (var i = 0; i < plugins.length; i++) {
      if (plugins[i].isSupportedCommand(command)) {
        return true;
      }
    }
    return false;
  };
  Editor.prototype.invokeOp_ = function(op) {
    if (op === Plugin.Op.CLEAN_CONTENTS_DOM) {
      return this.invokeOpRight_.apply(this, arguments);
    }
    return SeamlessField.prototype.apply.invokeOp_.apply(this, arguments);
  };
  Editor.prototype.invokeOpRight_ = function(op) {
    var plugins = this.indexedPlugins_[op];
    var argList = goog.array.slice(arguments, 1);
    for (var i = plugins.length - 1; i >= 0; i--) {
      var plugin = plugins[i];
      plugin[Plugin.OPCODE[op]].apply(plugin, argList);
    }
  };
  Editor.prototype.reduceOp_ = function(op, arg, varArgs) {
    var result;
    if (op === Plugin.Op.CLEAN_CONTENTS_DOM || op === Plugin.Op.CLEAN_CONTENTS_HTML) {
      result = this.reduceOpRight_(op, arg, varArgs);
    } else {
      result = SeamlessField.prototype.reduceOp_.apply(this, arguments);
    }
    if (op === Plugin.Op.PREPARE_CONTENTS_HTML) {
      result = this.prepareContentsDom(result);
    }
    return result;
  };
  Editor.prototype.reduceOpRight_ = function(op) {
    var plugins = this.indexedPlugins_[op];
    var argList = goog.array.slice(arguments, 1);
    for (var i = plugins.length - 1; i >= 0; i--) {
      var plugin = plugins[i];
      argList[0] = plugin[Plugin.OPCODE[op]].apply(plugin, argList);
    }
    return argList[0];
  };
  Editor.prototype.prepareContentsHtml = function(html) {
    var styles = {};
    return this.reduceOp_(goog.editor.Plugin.Op.PREPARE_CONTENTS_HTML, html || "", styles);
  };
  Editor.prototype.prepareContentsDom = function(html) {
    if (!html) {
      return "";
    }
    var frag = util.dom.fragFromString(html);
    var strictMode = this.strictMode;
    var filters = this.importDomFilters.filter(function(filter) {
      return !filter.strictMode || filter.strictMode && strictMode;
    });
    filters.forEach(function(filter) {
      start("Editor.prototype.prepareContentsDom : " + filter.getTrogClassId());
      filter.prepareContentsDom(frag);
      stop("Editor.prototype.prepareContentsDom : " + filter.getTrogClassId());
    });
    return util.dom.stringFromFrag(frag);
  };
  Editor.prototype.getAllPluginsInOrder = function() {
    return this.allPluginsInOrder;
  };
  Editor.prototype.getClipboardContent = function(frag) {
    this.context.format = uno.defs.format.CLIPBOARD;
    this.invokeOp_(goog.editor.Plugin.Op.CLEAN_CONTENTS_DOM, frag);
    return this.reduceOp_(goog.editor.Plugin.Op.CLEAN_CONTENTS_HTML, frag.innerHTML);
  };
  Editor.prototype.updateUndoCursorPosition = function() {
    var undoPlugin = this.plugins_.UndoRedo;
    var current = undoPlugin.currentStates_[this.getHashCode()];
    var previous = undoPlugin.undoManager_.undoPeek();
    if (current && this.field && current.undoContent_ === this.field.innerHTML) {
      current.undoCursorPosition_ = undoPlugin.getCursorPosition_(this);
      if (previous) {
        previous.redoCursorPosition_ = current.undoCursorPosition_;
      }
    }
  };
  Editor.prototype.refreshUndoRedoState = function() {
    var undoPlugin = this.plugins_.UndoRedo;
    undoPlugin.refreshCurrentState(this);
    var current = undoPlugin.currentStates_[this.getHashCode()];
    var previous = undoPlugin.undoManager_.undoPeek();
    if (previous) {
      previous.redoContent_ = current.undoContent_;
      previous.redoCursorPosition_ = current.undoCursorPosition_;
    }
  };
})();
goog.provide("uno.util.string");
goog.require("goog.string");
(function() {
  var util = uno.util;
  util.string.removeInvalidHtmlCharacters = function(line) {
    var invalidCharacters = /[\u0000\u0001-\u0008\u000E-\u001F\u007F-\u009F\uFDD0-\uFDEF\u000B\uFFFE\uFFFF]|[\x01-\x10][\uFFFE-\uFFFF]/g;
    return line.replace(invalidCharacters, "");
  };
  util.string.isEmpty = function(s) {
    var rxEmptyString = /^[\x00-\x20\s]*$/g;
    if (goog.string.isEmptySafe(s)) {
      rxEmptyString.lastIndex = 0;
      return s.length === 0 || rxEmptyString.test(s);
    }
    return false;
  };
})();
goog.provide("uno.PluginManager");
goog.require("goog.debug.Logger");
goog.require("goog.array");
(function() {
  var log = goog.debug.Logger.getLogger("uno.PluginManager");
  var PluginManager = uno.PluginManager = function() {
    this.elements = [];
  };
  PluginManager.prototype.add = function(obj) {
    this.elements.push(obj);
  };
  PluginManager.prototype.filterRemove = function(filterFunc) {
    this.elements = goog.array.filter(this.elements, filterFunc);
  };
  PluginManager.prototype.clear = function() {
    this.elements = [];
  };
  PluginManager.prototype.forEach = function(callback) {
    if (callback == null) {
      return;
    }
    for (var i = 0; i < this.elements.length; i++) {
      callback(this.elements[i], i, this.elements);
    }
  };
  PluginManager.prototype.firstToReturnTrue = function(funcName, funcArgs) {
    for (var i = 0; i < this.elements.length; i++) {
      if (this.tryToRun(this.elements[i], funcName, funcArgs) === true) {
        return this.elements[i];
      }
    }
    return null;
  };
  PluginManager.prototype.firstSupportedCommand = function(command) {
    return this.firstToReturnTrue("isSupportedCommand", [command]);
  };
  PluginManager.prototype.isSupportedCommand = function(command) {
    return !!this.firstToReturnTrue("isSupportedCommand", [command]);
  };
  PluginManager.prototype.execCommand = function() {
    var args = Array.prototype.slice.call(arguments);
    var command = args.length > 0 ? args[0] : null;
    var plugin = this.firstSupportedCommand(command);
    if (plugin == null) {
      return false;
    }
    var result = null;
    if (goog.isFunction(plugin.execCommandInternal)) {
      result = this.tryToRun(plugin, "execCommandInternal", args);
    }
    if (result == null) {
      result = this.tryToRun(plugin, "execCommand", args);
    }
    return !!result;
  };
  PluginManager.prototype.queryCommandEnabled = function() {
    var args = Array.prototype.slice.call(arguments);
    var command = args.length > 0 ? args[0] : null;
    var plugin = this.firstSupportedCommand(command);
    return !!this.tryToRun(plugin, "queryCommandEnabled", args);
  };
  PluginManager.prototype.queryCommandValue = function() {
    var args = Array.prototype.slice.call(arguments);
    var command = args.length > 0 ? args[0] : null;
    var plugin = this.firstSupportedCommand(command);
    var result = this.tryToRun(plugin, "queryCommandValue", args);
    if (result == null) {
      result = "";
    }
    if (!goog.isString(result)) {
      result = JSON.stringify(result);
    }
    return result;
  };
  PluginManager.prototype.tryToRun = function(element, funcName, funcArgs) {
    if (element == null) {
      log.warning("No plugin element supplied to tryToRun: \n" + JSON.stringify(funcName) + "\n---\n" + JSON.stringify(funcArgs));
      return null;
    }
    if (goog.isFunction(element[funcName])) {
      try {
        return element[funcName].apply(element, funcArgs);
      } catch (ex) {
        log.severe("Error running " + funcName + " with " + JSON.stringify(funcArgs) + ". \nDetails: " + ex + "\n" + ex.stack);
      }
    }
    return null;
  };
})();
goog.provide("uno.template.util");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.array");
goog.require("uno.util.string");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.template.util");
  var util = uno.util;
  var tmpl = uno.template.util;
  tmpl.TEMPLATE_STYLE_ATTR_CONTEXT_NAME = "-evernote-context-name";
  tmpl.FIELD_TYPES = ["title", "field", "textarea", "phone", "email", "twitter", "linkedin", "facebook", "weibo", "address", "profile-image"];
  tmpl.valueDidChangeForFieldInfo = function(fieldInfo) {
    fieldInfo.opt.fieldLastChanged = fieldInfo.name;
    fieldInfo.template.execCommand("changes", true);
  };
  tmpl.normalizeEditableTextElement = function(fieldInfo) {
    var element = fieldInfo.node;
    var text = tmpl.plainTextHTMLFromElement(element, fieldInfo.isMultiline);
    element.innerHTML = text;
    if (util.string.isEmpty(text) || text === "<div><br></div>") {
      goog.dom.classes.add(element, "en-editable-placeholder");
    } else {
      goog.dom.classes.remove(element, "en-editable-placeholder");
    }
    fieldInfo.html = element.innerHTML;
    return element;
  };
  tmpl.plainTextHTMLFromElement = function(element, wrapLines) {
    element.innerHTML = element.innerHTML.replace(/(<\/div>)/gi, "\n$1");
    var text = element.innerText.trim();
    var html;
    if (!wrapLines && util.string.isEmpty(text)) {
      html = "";
    } else {
      if (wrapLines) {
        var lines = text.split("\n");
        lines = lines.map(function(v) {
          if (util.string.isEmpty(v)) {
            return "<div><br></div>";
          }
          return "<div>" + goog.string.htmlEscape(v) + "</div>";
        });
        html = lines.join("");
      } else {
        html = goog.string.htmlEscape(text.replace(/\n/g, " "));
      }
    }
    return html;
  };
  tmpl.iterateFields = function(root) {
    var selector = "*[style*='-evernote-editable:']";
    var elements = goog.array.toArray(root.querySelectorAll(selector));
    return elements.map(function(el) {
      var fieldType = util.dom.getStyleValue(el, "-evernote-editable");
      if (!goog.array.contains(tmpl.FIELD_TYPES, fieldType)) {
        log.severe("Invalid -evernote-editable field mode! " + fieldType);
        return null;
      }
      var fieldName = util.dom.getStyleValue(el, "x-evernote");
      return {node:el, name:fieldName, type:fieldType};
    }, this).filter(function(el) {
      return el && el.node;
    });
  };
  tmpl.findSubElementByName = function(given, name) {
    var elements = given.querySelectorAll("*[style*='x-evernote:']");
    var found = null;
    goog.array.forEach(elements, function(node) {
      if (util.dom.getStyleValue(node, "x-evernote") === name) {
        found = node;
      }
    });
    return found;
  };
  tmpl.setupPlainTextFieldFormFieldInfo = function(fieldInfo) {
    var editorNode = fieldInfo.node;
    if (editorNode == null) {
      log.error("node missing in fieldinfo: " + JSON.stringify(fieldInfo));
    }
    var title = (fieldInfo.opt.localization[fieldInfo.name + "-placeholder-title"] || "...") + "\u00a0\u00a0\u00a0";
    editorNode.setAttribute("title", title);
    goog.dom.classes.add(editorNode, "en-editable");
    goog.dom.classes.add(editorNode, "en-editable-" + fieldInfo.type);
    editorNode.setAttribute("contenteditable", true);
    tmpl.normalizeEditableTextElement(fieldInfo);
    if (fieldInfo.opt.stripStyle) {
      editorNode.removeAttribute("style");
    }
    var oldValue = null;
    var context = tmpl.findSubElementByName(fieldInfo.container, "context");
    var contextName = util.dom.getStyleValue(context, tmpl.TEMPLATE_STYLE_ATTR_CONTEXT_NAME);
    var localized = fieldInfo.opt.localization[contextName + "-label"];
    if (context && localized) {
      goog.dom.removeChildren(context);
      context.textContent = localized;
    }
    editorNode.addEventListener("focus", function() {
      oldValue = fieldInfo.object.getHTML();
      setTimeout(function() {
        var sel = window.getSelection();
        sel.selectAllChildren(editorNode);
      }, 0);
    });
    editorNode.addEventListener("input", function() {
      fieldInfo.template.execCommand("changes", true);
    });
    editorNode.addEventListener("blur", function() {
      window.getSelection().removeAllRanges();
      tmpl.normalizeEditableTextElement(fieldInfo);
      var newValue = fieldInfo.object.getHTML();
      if (oldValue !== newValue) {
        tmpl.valueDidChangeForFieldInfo(fieldInfo);
      }
    });
    editorNode.addEventListener("keydown", function(event) {
      var handled = false;
      if (event.keyCode === 13) {
        if (!fieldInfo.isMultiline) {
          editorNode.blur();
          handled = true;
        }
      } else {
        if (event.keyCode === 8) {
          document.execCommand("delete");
          handled = true;
        }
      }
      if (handled) {
        event.preventDefault();
        event.stopPropagation();
        return false;
      }
      return false;
    });
  };
  tmpl.setupContextFieldFromFieldInfo = function(fieldInfo, options) {
    fieldInfo.contextNode = tmpl.findSubElementByName(fieldInfo.container, "context");
    var node = fieldInfo.contextNode;
    var contextName = util.dom.getStyleValue(node, tmpl.TEMPLATE_STYLE_ATTR_CONTEXT_NAME);
    goog.dom.classes.add(node, "en-editable-context");
    goog.dom.removeChildren(node);
    var titleNode = goog.dom.createElement("span");
    node.appendChild(titleNode);
    if (contextName === "fax") {
      contextName = "work-fax";
    }
    var localizedTitle = fieldInfo.opt.localization[contextName + "-label"];
    if (!localizedTitle) {
      log.warning("No l18n option for template " + contextName + "-label");
      localizedTitle = contextName;
    }
    titleNode.textContent = localizedTitle;
    var optionElements = [];
    for (var i = 0; i < options.length; i++) {
      var optionName = options[i];
      var title = fieldInfo.opt.localization[optionName + "-label"];
      if (!title) {
        log.warning("No l18n option for template " + optionName + "-label");
        title = optionName;
      }
      var elem = goog.dom.createDom("option", {value:optionName}, document.createTextNode(title));
      if (optionName === contextName) {
        elem.setAttribute("selected", "selected");
      }
      optionElements.push(elem);
    }
    var selectField = goog.dom.createDom.bind(this, "select", {class:"en-editable-select-context", tabindex:"-1"}).apply(this, optionElements);
    node.insertBefore(selectField, null);
    selectField.addEventListener("change", function() {
      var newName = selectField.value;
      util.dom.setStyleValue(node, tmpl.TEMPLATE_STYLE_ATTR_CONTEXT_NAME, newName);
      titleNode.textContent = fieldInfo.opt.localization[newName + "-label"] || newName;
      tmpl.valueDidChangeForFieldInfo(fieldInfo);
    });
    node.parentElement.style.textDecoration = "none";
  };
})();
goog.provide("uno.template.Field");
goog.require("goog.debug.Logger");
goog.require("uno.template.util");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.template.Field");
  var tmpl = uno.template.util;
  var util = uno.util;
  var Field = uno.template.Field = function(fieldInfo) {
    this.fieldInfo = fieldInfo;
    this.setup();
  };
  Field.prototype.setup = function() {
  };
  Field.prototype.copyCurrentValueToDom = function(frag) {
    var allFields = tmpl.iterateFields(frag);
    var matchingContainer = null;
    if (allFields && allFields.length > this.fieldInfo.index) {
      var indexMatch = allFields[this.fieldInfo.index].node;
      var type = util.dom.getStyleValue(indexMatch, "-evernote-editable");
      if (indexMatch == null || type !== this.fieldInfo.type) {
        log.severe("Wrong field type at correct field index! " + this.fieldInfo.type + " @ index " + this.fieldInfo.index);
      }
      matchingContainer = indexMatch;
    }
    if (matchingContainer == null) {
      log.severe("No matching container found for " + this.fieldInfo.name + " @ index " + this.fieldInfo.index);
      return;
    }
    if (this.fieldInfo.contextNode && matchingContainer) {
      var contextName = util.dom.getStyleValue(this.fieldInfo.contextNode, tmpl.TEMPLATE_STYLE_ATTR_CONTEXT_NAME);
      if (contextName) {
        var contextSelector = "*[style*='x-evernote:context']";
        var matchingNode = matchingContainer.querySelector(contextSelector);
        if (matchingNode) {
          var label = contextName + "-label";
          var localization = this.fieldInfo.opt.localization[label];
          util.dom.setStyleValue(matchingNode, tmpl.TEMPLATE_STYLE_ATTR_CONTEXT_NAME, contextName);
          matchingNode.textContent = localization || contextName;
        } else {
          log.severe("No matching context node for " + contextName);
        }
      }
    }
    var neverUpdatedFields = ["card-image", "profile-image"];
    var updateable = neverUpdatedFields.indexOf(this.fieldInfo.name) < 0;
    if (matchingContainer && updateable) {
      var valueNodeSelector = "*[style*='x-evernote:value']";
      var matchingValueNode = matchingContainer.querySelector(valueNodeSelector);
      if (matchingValueNode == null) {
        matchingValueNode = matchingContainer;
      }
      matchingValueNode.innerHTML = this.getHTML() || "&nbsp;";
    }
  };
  Field.prototype.getHTML = function() {
    return this.fieldInfo.node.innerHTML;
  };
})();
goog.provide("uno.template.NoopField");
goog.require("uno.template.Field");
(function() {
  var NoopField = uno.template.NoopField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(NoopField, uno.template.Field);
})();
goog.provide("uno.template.TitleField");
goog.require("uno.template.util");
goog.require("uno.template.Field");
(function() {
  var tmpl = uno.template.util;
  var TitleField = uno.template.TitleField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(TitleField, uno.template.Field);
  TitleField.prototype.getHTML = function() {
    return tmpl.plainTextHTMLFromElement(this.fieldInfo.node);
  };
})();
goog.provide("uno.template.LinkField");
goog.require("uno.template.Field");
goog.require("uno.template.util");
goog.require("uno.util.string");
goog.require("goog.debug.Logger");
(function() {
  var log = goog.debug.Logger.getLogger("uno.template.LinkField");
  var tmpl = uno.template.util;
  var util = uno.util;
  var LinkField = uno.template.LinkField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(LinkField, uno.template.Field);
  LinkField.prototype.createRepresentationElement = function(value, attrs) {
    attrs.href = value;
    var link = goog.dom.createDom("a", attrs, document.createTextNode(value));
    return link;
  };
  LinkField.prototype.getValue = function() {
    var node = this.fieldInfo.node;
    if (node == null) {
      log.severe("couldnt get node of linkfield");
      return "";
    }
    var value = node.textContent;
    if (!value || util.string.isEmpty(value)) {
      return "";
    }
    return value.trim();
  };
  LinkField.prototype.setup = function() {
    var self = this;
    this.fieldInfo.node = tmpl.findSubElementByName(this.fieldInfo.container, "value");
    var node = this.fieldInfo.node;
    var value = this.getValue();
    util.dom.setStyleValue(node, "text-decoration", "");
    goog.dom.removeChildren(node);
    var editable = goog.dom.createDom("div");
    node.appendChild(editable);
    editable.textContent = value;
    this.fieldInfo.node = editable;
    tmpl.setupPlainTextFieldFormFieldInfo(this.fieldInfo);
    var content = goog.dom.createDom("span");
    var preview = goog.dom.createDom("div", {class:"en-editable-preview"}, content);
    node.appendChild(preview);
    var updateEditableFieldVisibilityForStandby = function() {
      goog.dom.classes.remove(preview, "en-editable-hidden");
      goog.dom.classes.add(editable, "en-editable-hidden");
      goog.dom.removeChildren(content);
      var text = self.getValue();
      if (!util.string.isEmpty(text)) {
        content.appendChild(self.createRepresentationElement(text, {tabindex:"-1"}));
      } else {
        goog.dom.classes.remove(editable, "en-editable-hidden");
        goog.dom.classes.add(preview, "en-editable-hidden");
      }
      editable.textContent = text;
    };
    updateEditableFieldVisibilityForStandby();
    preview.addEventListener("click", function(e) {
      if (e.target && e.target.tagName.toLowerCase() === "a") {
        var href = e.target.getAttribute("href");
        EN.notification("openLink", {href:href, module:"template"});
      } else {
        editable.focus();
      }
    });
    editable.addEventListener("focus", function() {
      goog.dom.classes.remove(editable, "en-editable-hidden");
      goog.dom.classes.add(preview, "en-editable-hidden");
    });
    editable.addEventListener("blur", function() {
      updateEditableFieldVisibilityForStandby();
    });
    goog.dom.classes.add(this.fieldInfo.container, "en-editable-container");
  };
  LinkField.prototype.getHTML = function() {
    var text = this.fieldInfo.node.textContent;
    return util.string.isEmpty(text) ? uno.defs.nbsp.CHARACTER_SEQUENCE : util.dom.toHTML(this.createRepresentationElement(text, {}));
  };
})();
goog.provide("uno.template.AddressField");
goog.require("uno.template.LinkField");
goog.require("uno.util.string");
(function() {
  var AddressField = uno.template.AddressField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(AddressField, uno.template.LinkField);
  AddressField.prototype.createRepresentationElement = function(value, attrs) {
    value = value.trim();
    attrs.href = "http://maps.google.com/?q=" + encodeURIComponent(value);
    return goog.dom.createDom("a", attrs, document.createTextNode(value));
  };
})();
goog.provide("uno.template.PlainTextField");
goog.require("uno.template.util");
goog.require("uno.template.Field");
(function() {
  var tmpl = uno.template.util;
  var PlainTextField = uno.template.PlainTextField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(PlainTextField, uno.template.Field);
  PlainTextField.prototype.setup = function() {
    tmpl.setupPlainTextFieldFormFieldInfo(this.fieldInfo);
  };
  PlainTextField.prototype.getHTML = function() {
    return tmpl.plainTextHTMLFromElement(this.fieldInfo.node);
  };
})();
goog.provide("uno.template.PlainTextArea");
goog.require("goog.debug.Logger");
goog.require("uno.template.PlainTextField");
goog.require("uno.template.util");
(function() {
  var log = goog.debug.Logger.getLogger("uno.template.PlainTextArea");
  var tmpl = uno.template.util;
  var PlainTextArea = uno.template.PlainTextArea = function(fieldInfo) {
    fieldInfo.isMultiline = true;
    goog.base(this, fieldInfo);
  };
  goog.inherits(PlainTextArea, uno.template.PlainTextField);
  PlainTextArea.prototype.setup = function() {
    tmpl.setupPlainTextFieldFormFieldInfo(this.fieldInfo);
  };
  PlainTextArea.prototype.getHTML = function() {
    try {
      return tmpl.plainTextHTMLFromElement(this.fieldInfo.node, true);
    } catch (ex) {
      log.fine("getHTML 'PlainTextArea.prototype.getHTML' failed " + ex.stack);
    }
    return null;
  };
})();
goog.provide("uno.template.PhoneField");
goog.require("uno.template.util");
goog.require("uno.template.LinkField");
(function() {
  var tmpl = uno.template.util;
  var PhoneField = uno.template.PhoneField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(PhoneField, uno.template.LinkField);
  PhoneField.prototype.setup = function() {
    goog.base(this, "setup");
    tmpl.setupContextFieldFromFieldInfo(this.fieldInfo, ["phone", "home", "work", "mobile", "main", "home-fax", "work-fax", "other"]);
  };
  PhoneField.prototype.createRepresentationElement = function(value, attrs) {
    value = value.trim().replace(/^tel:/, "");
    attrs.href = "tel:" + encodeURIComponent(value);
    return goog.dom.createDom("a", attrs, document.createTextNode(value));
  };
  PhoneField.prototype.getHTML = function() {
    return tmpl.plainTextHTMLFromElement(this.fieldInfo.node);
  };
})();
goog.provide("uno.template.EmailField");
goog.require("uno.template.LinkField");
goog.require("uno.template.util");
(function() {
  var tmpl = uno.template.util;
  var EmailField = uno.template.EmailField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(EmailField, uno.template.LinkField);
  EmailField.prototype.setup = function() {
    goog.base(this, "setup");
    tmpl.setupContextFieldFromFieldInfo(this.fieldInfo, ["email", "home", "work", "other"]);
  };
  EmailField.prototype.createRepresentationElement = function(value, attrs) {
    value = value.trim().replace(/^mailto:/, "");
    attrs.href = "mailto:" + value;
    return goog.dom.createDom("a", attrs, document.createTextNode(value));
  };
})();
goog.provide("uno.template.TwitterField");
goog.require("uno.template.LinkField");
goog.require("uno.util.string");
(function() {
  var util = uno.util;
  var TwitterField = uno.template.TwitterField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(TwitterField, uno.template.LinkField);
  TwitterField.prototype.getValue = function() {
    var node = this.fieldInfo.node;
    var value = node.textContent;
    if (!value) {
      return "";
    }
    value = value.trim().replace(/^\@/, "");
    if (util.string.isEmpty(value)) {
      return "";
    }
    return value;
  };
  TwitterField.prototype.createRepresentationElement = function(value, attrs) {
    attrs.href = "http://twitter.com/" + encodeURIComponent(value);
    return goog.dom.createDom("a", attrs, document.createTextNode("@" + value));
  };
})();
goog.provide("uno.template.FacebookField");
goog.require("uno.template.LinkField");
(function() {
  var FacebookField = uno.template.FacebookField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(FacebookField, uno.template.LinkField);
})();
goog.provide("uno.template.LinkedInField");
goog.require("uno.template.LinkField");
(function() {
  var LinkedInField = uno.template.LinkedInField = function(fieldInfo) {
    var hrefElement = fieldInfo.node.querySelector("a[href]");
    this.originalHref = null;
    this.originalText = null;
    if (hrefElement != null) {
      this.originalHref = hrefElement.getAttribute("href");
      this.originalText = hrefElement.textContent;
    }
    goog.base(this, fieldInfo);
  };
  goog.inherits(LinkedInField, uno.template.LinkField);
  LinkedInField.prototype.createRepresentationElement = function(value, attrs) {
    attrs.href = null;
    if (this.getValue() === this.originalText) {
      attrs.href = this.originalHref;
    }
    if (attrs.href == null) {
      attrs.href = "http://www.linkedin.com/in/" + encodeURIComponent(value);
    }
    return goog.dom.createDom("a", attrs, document.createTextNode(value));
  };
})();
goog.provide("uno.template.WeiboField");
goog.require("uno.template.LinkField");
goog.require("uno.util.string");
(function() {
  var util = uno.util;
  var WeiboField = uno.template.WeiboField = function(fieldInfo) {
    goog.base(this, fieldInfo);
  };
  goog.inherits(WeiboField, uno.template.LinkField);
  WeiboField.prototype.getValue = function() {
    var node = this.fieldInfo.node;
    var value = node.textContent;
    if (!value) {
      return "";
    }
    value = value.trim().replace(/^\@/, "");
    if (util.string.isEmpty(value)) {
      return "";
    }
    return value;
  };
  WeiboField.prototype.createRepresentationElement = function(value) {
    return document.createTextNode("@" + value);
  };
})();
goog.provide("uno.template.Plugin");
goog.require("goog.editor.Plugin");
(function() {
  var TemplatePlugin = uno.template.Plugin = function(template) {
    goog.editor.Plugin.call(this);
    this.template = template;
  };
  goog.inherits(TemplatePlugin, goog.editor.Plugin);
  TemplatePlugin.prototype.getElement = function() {
    return this.template.templateElement;
  };
})();
goog.provide("uno.template.commands.Changes");
goog.require("goog.debug.Logger");
goog.require("uno.template.Plugin");
goog.require("uno.util.dom");
goog.require("uno.template.util");
(function() {
  var dirty = false;
  var debounceTimer = 0;
  var Changes = uno.template.commands.Changes = function(template) {
    uno.template.Plugin.call(this, template);
  };
  goog.inherits(Changes, uno.template.Plugin);
  Changes.prototype.isSupportedCommand = function(command) {
    return command === "changes" || command === "rte.changes";
  };
  var sendContentChangedNotificationDebounce = function() {
    clearTimeout(debounceTimer);
    debounceTimer = setTimeout(function() {
      window.EN.notification("contentChanged", {module:"content"});
    }, 1000);
  };
  Changes.prototype.execCommandInternal = function(command, value) {
    dirty = !!value;
    if (dirty) {
      sendContentChangedNotificationDebounce();
    }
    return true;
  };
  Changes.prototype.queryCommandValue = function() {
    return dirty;
  };
  Changes.prototype.queryCommandEnabled = function() {
    return true;
  };
})();
goog.provide("uno.template.commands.Content");
goog.require("goog.debug.Logger");
goog.require("goog.array");
goog.require("goog.object");
goog.require("uno.template.Plugin");
goog.require("uno.template.util");
goog.require("uno.util.dom");
goog.require("uno.util.string");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.template.commands.Content");
  var util = uno.util;
  var Content = uno.template.commands.Content = function(template) {
    uno.template.Plugin.call(this, template);
  };
  goog.inherits(Content, uno.template.Plugin);
  Content.prototype.isSupportedCommand = function(command) {
    return command === "content";
  };
  Content.prototype.loadContent = function(opt) {
    if (opt.type === "enml" && opt.content) {
      window.ed.context.format = uno.defs.format.ENML;
    } else {
      if (opt.type === "html" && opt.content) {
        window.ed.context.format = uno.defs.format.CLIENT_HTML;
      } else {
        return false;
      }
    }
    var content = opt.content;
    goog.object.forEach(ed.getAllPluginsInOrder(), function(plugin) {
      if (plugin.prepareContentsHtml && plugin.trogClassId !== "uno.filters.NormalizeFilter") {
        content = plugin.prepareContentsHtml(content);
      }
    });
    var frag = util.dom.fragFromString(content);
    goog.object.forEach(ed.getAllPluginsInOrder(), function(plugin) {
      if (plugin.prepareContentsDom && plugin.trogClassId !== "uno.filters.NormalizeFilter") {
        plugin.prepareContentsDom(frag);
      }
    });
    this.template.templateElement.innerHTML = "";
    while (frag.childNodes && frag.childNodes[0]) {
      this.template.templateElement.appendChild(frag.childNodes[0]);
    }
    return true;
  };
  Content.prototype.getContent = function(opt) {
    if (!opt) {
      opt = {};
    }
    opt = {html:opt.html || false, cleanup:opt.cleanup || false, stripNS:opt.stripNS || false, trim:opt.trim || true, withInsertionPoint:opt.withInsertionPoint || false, hiddenCryptoData:opt.hiddenCryptoData || null, resetChangesState:opt.resetChangesState || false, wrap:opt.wrap || false, type:opt.type || uno.defs.format.ENML};
    if (opt.type !== uno.defs.format.CLIENT_HTML && opt.type !== uno.defs.format.ENML) {
      opt.type = uno.defs.format.ENML;
    }
    var failure = {success:false, value:"", type:opt.type};
    if (opt.resetChangesState) {
      this.template.execCommand("changes", false);
    }
    var enmlFilterPlugin = null;
    goog.object.forEach(ed.getAllPluginsInOrder(), function(plugin) {
      if (plugin instanceof uno.filters.EnmlFilter) {
        enmlFilterPlugin = plugin;
      }
    });
    if (!enmlFilterPlugin) {
      log.severe("Template couldnt necessary plugins from Editor!");
      return failure;
    }
    var startingDocument = this.template.originalDocument || "";
    startingDocument = enmlFilterPlugin.prepareContentsHtml(startingDocument);
    var frag = util.dom.fragFromString(startingDocument);
    goog.array.forEach(this.template.fields, function(fieldInfo) {
      var instance = fieldInfo.object;
      if (instance == null) {
        log.severe("No template fieldInfo.object in " + fieldInfo);
      }
      instance.copyCurrentValueToDom(frag);
    });
    goog.array.forEach(frag.querySelectorAll("en-media"), function(enmedia) {
      enmedia.innerHTML = "";
    });
    var content = (new XMLSerializer).serializeToString(frag).trim();
    content = enmlFilterPlugin.cleanContentsHtml(content);
    var template = this.template;
    return {success:!util.string.isEmpty(content.trim()), value:content.trim(), type:opt.type};
  };
  Content.prototype.execCommandInternal = function(command, value) {
    if (value.scrollToTop === true) {
      window.scrollTo(0, 0);
    }
    if (!goog.object.isEmpty(value.resources)) {
      ed.context.resources = value.resources;
    }
    this.template.originalDocument = value.content;
    var contentResult = this.loadContent(value);
    if (contentResult) {
      this.template.setupFields();
      EN.notification("contentLoaded");
    } else {
      log.severe("Template failed to load content", value);
    }
    return contentResult;
  };
  Content.prototype.queryCommandValue = function(command, value) {
    return this.getContent(value);
  };
  Content.prototype.queryCommandEnabled = function() {
    return true;
  };
})();
goog.provide("uno.template.commands.Copy");
goog.require("goog.debug.Logger");
goog.require("uno.template.Plugin");
goog.require("uno.util.dom");
goog.require("uno.template.util");
(function() {
  var util = uno.util;
  var Copy = uno.template.commands.Copy = function(template) {
    uno.template.Plugin.call(this, template);
  };
  goog.inherits(Copy, uno.template.Plugin);
  Copy.prototype.isSupportedCommand = function(command) {
    return command === "copy";
  };
  Copy.prototype.execCommandInternal = function() {
    return false;
  };
  Copy.prototype.queryCommandValue = function() {
    var range = window.getSelection().getRangeAt(0);
    if (!range || range.collapsed) {
      return "";
    }
    var result = {};
    var frag = range.cloneContents();
    var child = document.createElement("div");
    child.appendChild(frag);
    util.dom.workOnTemporaryDOMNode(child, function(node) {
      result.plain = node.innerText;
    });
    return JSON.stringify(result);
  };
  Copy.prototype.queryCommandEnabled = function() {
    return true;
  };
})();
goog.provide("uno.template.commands.Focus");
goog.require("goog.debug.Logger");
goog.require("uno.template.Plugin");
goog.require("uno.util.dom");
(function() {
  var util = uno.util;
  var Focus = uno.template.commands.Focus = function(template) {
    uno.template.Plugin.call(this, template);
  };
  goog.inherits(Focus, uno.template.Plugin);
  Focus.prototype.isSupportedCommand = function(command) {
    return command === "focus";
  };
  Focus.prototype.execCommandInternal = function() {
    if (this.template.fields && this.template.fields.length > 0) {
      this.template.fields[0].focus();
    }
  };
  Focus.prototype.queryCommandValue = function() {
    var selection = window.getSelection();
    if (!selection) {
      return false;
    }
    if (selection.rangeCount > 0) {
      var range = window.getSelection().getRangeAt(0);
      var ancestors = util.dom.ancestors(range.startContainer);
      for (var i = 0; i < ancestors.length; i++) {
        if (ancestors[i].contentEditable === "true") {
          return true;
        }
      }
    }
    return false;
  };
  Focus.prototype.queryCommandEnabled = function() {
    return true;
  };
})();
goog.provide("uno.template.commands.Margin");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.template.Plugin");
(function() {
  var Margin = uno.template.commands.Margin = function(template) {
    uno.template.Plugin.call(this, template);
  };
  goog.inherits(Margin, uno.template.Plugin);
  Margin.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Margin.prototype.isSupportedCommand = function(command) {
    return command === "margin";
  };
  Margin.prototype.execCommand = function(command, value) {
    if (value == null) {
      return false;
    }
    if (this.template.templateElement == null) {
      return false;
    }
    var container = this.template.templateElement;
    if (value.note) {
      container.style.paddingTop = toCssValue(value.note.top, "px");
      container.style.paddingBottom = toCssValue(value.note.bottom, "px");
      container.style.paddingLeft = toCssValue(value.note.left, "px");
      container.style.paddingRight = toCssValue(value.note.right, "px");
    }
    if (value.scroll) {
      window.ed.config.margin.scroll = {top:value.scroll.top || 0, left:value.scroll.left || 0, bottom:value.scroll.bottom || 0, right:value.scroll.right || 0};
    }
    if (value.offset) {
      window.ed.config.margin.offset = {height:value.offset.height || 0, width:value.offset.width || 0};
    }
    return true;
  };
  var toCssValue = function(value, unit) {
    var result;
    switch(typeof value) {
      case "number":
        result = value + unit;
        break;
      case "string":
        if (value.indexOf(unit) > -1) {
          result = value;
        } else {
          result = value + unit;
        }
        break;
      case "undefined":
        result = null;
        break;
      default:
        result = value;
    }
    return result;
  };
})();
goog.provide("uno.template.commands.PassThrough");
goog.require("goog.debug.Logger");
goog.require("uno.template.Plugin");
goog.require("uno.util.dom");
(function() {
  var commands = ["delete", "forwarddelete"];
  var PassThrough = uno.template.commands.PassThrough = function(template) {
    uno.template.Plugin.call(this, template);
  };
  goog.inherits(PassThrough, uno.template.Plugin);
  PassThrough.prototype.isSupportedCommand = function(command) {
    return commands.indexOf(command) >= 0;
  };
  PassThrough.prototype.execCommandInternal = function(command, value) {
    return document.execCommand(command, value);
  };
  PassThrough.prototype.queryCommandValue = function(command, value) {
    return document.queryCommandValue(command, value);
  };
  PassThrough.prototype.queryCommandEnabled = function(command, value) {
    return document.queryCommandEnabled(command, value);
  };
})();
goog.provide("uno.template.commands.Paste");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("uno.template.Plugin");
goog.require("uno.util.dom");
goog.require("uno.template.util");
(function() {
  var log = goog.debug.Logger.getLogger("uno.template.commands.Paste");
  var util = uno.util;
  var Paste = uno.template.commands.Paste = function(template) {
    uno.template.Plugin.call(this, template);
  };
  goog.inherits(Paste, uno.template.Plugin);
  Paste.prototype.isSupportedCommand = function(command) {
    return command === "paste" || command === "pasteplain";
  };
  Paste.prototype.execCommandInternal = function(command, value) {
    var type = "plain";
    if (command === "pasteplain") {
      type = "plain";
    } else {
      if (value.type === "html") {
        type = "html";
      }
    }
    return pasteAction({type:type, value:value.value || ""});
  };
  Paste.prototype.queryCommandValue = function() {
    return "";
  };
  Paste.prototype.queryCommandEnabled = function() {
    return true;
  };
  var pasteAction = function(opt) {
    var content = opt.value;
    if (opt.type === "html") {
      var frag = util.dom.fragFromString(content);
      content = frag.textContent;
    }
    try {
      return document.execCommand("inserttext", false, content.replace(/\s+/gi, " "));
    } catch (ex) {
      log.severe("Error with document inserttext" + ex.stack);
    }
    return true;
  };
})();
goog.provide("uno.template.commands.Resources");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("uno.template.Plugin");
goog.require("uno.util.resource");
(function() {
  var log = goog.debug.Logger.getLogger("uno.template.commands.Resources");
  var util = uno.util;
  var Resources = uno.template.commands.Resources = function(template) {
    uno.template.Plugin.call(this, template);
  };
  goog.inherits(Resources, uno.template.Plugin);
  Resources.prototype.activeOnUneditableFields = goog.functions.TRUE;
  Resources.prototype.queryCommandEnabled = goog.functions.TRUE;
  Resources.prototype.isSupportedCommand = function(command) {
    return command === "resources";
  };
  Resources.prototype.execCommand = function() {
    return false;
  };
  Resources.prototype.queryCommandValue = function(command, opt) {
    var templateRoot = this.template.getElement();
    var list = goog.array.map(util.resource.all(templateRoot), function(el) {
      var dict = util.resource.toDict(el);
      if (opt === "neighbors") {
        log.warning("opt.neighbors not supported for template resources");
      }
      return dict;
    });
    return list;
  };
})();
goog.provide("uno.template.Template");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.classes");
goog.require("goog.string");
goog.require("goog.functions");
goog.require("uno.defs");
goog.require("uno.filters.EnmlFilter");
goog.require("uno.filters.ResourceFilter");
goog.require("uno.util.string");
goog.require("uno.util.dom");
goog.require("uno.util.objects");
goog.require("uno.PluginManager");
goog.require("uno.template.util");
goog.require("uno.template.Field");
goog.require("uno.template.NoopField");
goog.require("uno.template.TitleField");
goog.require("uno.template.AddressField");
goog.require("uno.template.PlainTextField");
goog.require("uno.template.PlainTextArea");
goog.require("uno.template.PhoneField");
goog.require("uno.template.LinkField");
goog.require("uno.template.EmailField");
goog.require("uno.template.TwitterField");
goog.require("uno.template.FacebookField");
goog.require("uno.template.LinkedInField");
goog.require("uno.template.WeiboField");
goog.require("uno.template.commands.Changes");
goog.require("uno.template.commands.Content");
goog.require("uno.template.commands.Copy");
goog.require("uno.template.commands.Focus");
goog.require("uno.template.commands.Margin");
goog.require("uno.template.commands.PassThrough");
goog.require("uno.template.commands.Paste");
goog.require("uno.template.commands.Resources");
(function() {
  var log = goog.debug.Logger.getLogger("uno.api.ce");
  var util = uno.util;
  var tmpl = uno.template.util;
  var TEMPLATE_ROOT_TAG = "en-template";
  var fieldTypeMap = {title:uno.template.TitleField, field:uno.template.PlainTextField, textarea:uno.template.PlainTextArea, phone:uno.template.PhoneField, email:uno.template.EmailField, twitter:uno.template.TwitterField, linkedin:uno.template.LinkedInField, facebook:uno.template.FacebookField, weibo:uno.template.WeiboField, address:uno.template.AddressField, "profile-image":uno.template.NoopField};
  var Template = uno.template.Template = function(rteID, options) {
    this.templateElement = document.querySelector(TEMPLATE_ROOT_TAG);
    this.initConfig(options);
    if (this.templateElement == null) {
      var rteElement = document.querySelector("#" + rteID);
      if (rteElement == null) {
        log.severe("Fatal: Couldn't find rte element " + rteID);
        return;
      }
      this.templateElement = goog.dom.createDom(TEMPLATE_ROOT_TAG);
      goog.dom.insertSiblingAfter(this.templateElement, rteElement);
    }
    this.PM = new uno.PluginManager;
    this.PM.add(new uno.template.commands.Changes(this));
    this.PM.add(new uno.template.commands.Content(this));
    this.PM.add(new uno.template.commands.Copy(this));
    this.PM.add(new uno.template.commands.Focus(this));
    this.PM.add(new uno.template.commands.Margin(this));
    this.PM.add(new uno.template.commands.PassThrough(this));
    this.PM.add(new uno.template.commands.Paste(this));
    this.PM.add(new uno.template.commands.Resources(this));
    this.execCommand = this.PM.execCommand.bind(this.PM);
    this.queryCommandEnabled = this.PM.queryCommandEnabled.bind(this.PM);
    this.queryCommandValue = this.PM.queryCommandValue.bind(this.PM);
  };
  Template.prototype.opt = {};
  Template.prototype.originalDocument = "";
  Template.prototype.fields = [];
  Template.prototype.PM = null;
  Template.prototype.templateElement = null;
  Template.prototype.contentCssClass = null;
  Template.prototype.isSetup = false;
  Template.prototype.setup = function(opt) {
    var contentClass = opt.template.contentClass;
    this.opt = opt;
    this.opt.localization = opt.template.localization || opt.localization || {"display-as-placeholder-title":"Add Name...", "contact-title-placeholder-title":"Add Title...", "contact-org-placeholder-title":"Add Company...", "note-body-placeholder-title":"Add Notes...", "linkedin-placeholder-title":"Add LinkedIn URL...", "facebook-placeholder-title":"Add Facebook URL...", "twitter-placeholder-title":"Add Twitter Name...", "weibo-placeholder-title":"Add Weibo Name...", "phone-placeholder-title":"Add Phone...", 
    "email-placeholder-title":"Add Email...", "address-placeholder-title":"Add Address...", "email-label":"Email", "home-label":"Home", "work-label":"Work", "other-label":"Other", "phone-label":"Phone", "mobile-label":"Mobile", "main-label":"Main", "home-fax-label":"Home Fax", "work-fax-label":"Work Fax", "twitter-label":"Twitter", "facebook-label":"Facebook", "weibo-label":"Weibo", "linkedin-label":"LinkedIn", "address-label":"Address"};
    this.isSetup = true;
    if (contentClass) {
      this.contentCssClass = contentClass.replace(/[^\w]+/gi, "-");
      this.templateElement.setAttribute("class", "");
      goog.dom.classes.add(this.templateElement, this.contentCssClass);
    } else {
      log.warning("Unnecessary setup of Template w/o contentClass");
      return;
    }
    if (!util.string.isEmpty(opt.template.html)) {
      this.originalDocument = opt.template.html;
      this.execCommand("content", {type:"html", content:opt.template.html});
      return;
    }
    if (!util.string.isEmpty(opt.template.enml)) {
      this.originalDocument = opt.template.enml;
      this.execCommand("content", {type:"enml", content:opt.template.enml});
      return;
    }
  };
  Template.prototype.isSupportedCommand = function(command) {
    return this.isSetup && !!this.PM.firstSupportedCommand(command);
  };
  this.execCommand = goog.functions.NULL;
  this.queryCommandEnabled = goog.functions.NULL;
  this.queryCommandValue = goog.functions.NULL;
  Template.prototype.setupFields = function() {
    var foundFields = tmpl.iterateFields(this.templateElement);
    this.fields = [];
    for (var i = 0; i < foundFields.length; i++) {
      var fieldInfo = foundFields[i];
      fieldInfo.index = i;
      fieldInfo.opt = this.opt;
      fieldInfo.template = this;
      fieldInfo.container = fieldInfo.node;
      if (Object.keys(fieldTypeMap).indexOf(fieldInfo.type) >= 0) {
        fieldInfo.object = new fieldTypeMap[fieldInfo.type](fieldInfo);
      } else {
        log.severe("Tmpl found invalid field type: " + fieldInfo.type);
      }
      this.fields.push(fieldInfo);
    }
  };
  Template.prototype.getElement = function() {
    return this.templateElement;
  };
  Template.prototype.initConfig = function(opt) {
    var options = opt || {};
    this.config = {crypt:{unveilCryptElementOnClick:false, readOnly:options.rte.cryptReadOnly || false}};
  };
  Template.prototype.cleanup = function() {
    if (this.isSetup) {
      this.getElement().remove();
    }
  };
})();
goog.provide("uno.Router");
goog.require("goog.debug.Logger");
(function() {
  var log = goog.debug.Logger.getLogger("uno.Router");
  var Router = uno.Router = function(options) {
    this.messages = {};
    this.routesToHost = options.routesToHost;
    this.routesFromHost = options.routesFromHost;
    this.sendMessage = options.sendMessage;
  };
  Router.correlationId = 0;
  Router.getCorrelationId = function() {
    return ++Router.correlationId;
  };
  Router.prototype.toHostAsync = function(name, data) {
    var deferred;
    var me = this;
    var route = this.routesToHost[name];
    var correlationId = data[route.identifier];
    if (!correlationId && !route.oneway) {
      correlationId = Router.getCorrelationId();
      data[route.identifier] = correlationId;
    }
    deferred = new Deferred(function() {
      me.sendMessage(name, data);
    });
    if (route.oneway) {
      deferred.resolve();
    } else {
      this.messages[correlationId] = deferred;
    }
    return deferred.promise;
  };
  Router.prototype.fromHost = function(name, data) {
    var correlationId;
    var deferred;
    if (this.routesFromHost[name]) {
      correlationId = goog.getObjectByName(this.routesFromHost[name].identifier, data);
      deferred = this.messages[correlationId];
      delete this.messages[correlationId];
      deferred.resolve(data);
      return true;
    }
    return false;
  };
  var Deferred = function(fn) {
    var me = this;
    this.promise = new Promise(function(resolve, reject) {
      me.resolve = resolve;
      me.reject = reject;
      fn();
    });
  };
})();
goog.provide("uno.context.Context");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.functions");
goog.require("goog.object");
goog.require("goog.string");
goog.require("goog.style");
goog.require("uno.util.dom");
goog.require("uno.util.zoomscale");
(function() {
  var log = goog.debug.Logger.getLogger("uno.context.Context");
  var util = uno.util;
  var moduleName = "context";
  var CLICK_EVENT_FLE_KIND = "firstLaunch";
  var CLICK_EVENT_FLE_BUTTON_HREF = "dismiss";
  var CLICK_EVENT_FLE_LEARN_MORE_HREF = "learnMore";
  var TITLE_CLASSNAME = "en-context-item-title";
  var WIDE_CLASSNAME = "en-context-wide";
  var BODY_ITALICS_CLASSNAME = "en-context-body-italics";
  var ITEM_BODY_CLASSNAME = "en-context-item-body";
  var ITEM_BODY_ONE_LINE_CLASSNAME = "en-context-item-body-one";
  var ITEM_BODY_TWO_LINE_CLASSNAME = "en-context-item-body-two";
  var ITEM_CLASSNAME = "en-context-item";
  var CONTEXT_LABEL_CLASSNAME = "en-context-label";
  var HIDE_CLASSNAME = "en-context-hide-label";
  var SHOW_CLASSNAME = "en-context-show-label";
  var MAIN_CONTAINER_CLASSNAME = "en-context";
  var CARD_HOLDER_CLASSNAME = "en-context-card-holder";
  var IMAGE_CLIPPER_CLASSNAME = "en-context-graphic-clipper";
  var IMAGE_CLASSNAME = "en-context-graphic";
  var IMAGE_BLUR_CLASSNAME = "en-context-graphic-blur";
  var IMAGE_HOVER_CLASSNAME = "en-context-graphic-hover";
  var IMAGE_HOVER_SOLID_CLASSNAME = "en-context-graphic-hover-solid";
  var IMAGE_HOVER_MESSAGE_ICON_CLASSNAME = "en-context-workchat";
  var IMAGE_HOVER_TEXT_CLASSNAME = "en-context-share-text";
  var NEWS_SOURCE_CONTAINER_CLASSNAME = "en-context-source";
  var NEWS_SOURCE_IMAGE_CLASSNAME = "en-context-source-img";
  var NEWS_SOURCE_TEXT_CLASSNAME = "en-context-source-text";
  var NEWS_SOURCE_TEXT_BLUE_CLASSNAME = "en-context-source-text-blue";
  var AUTHOR_CLASSNAME = "en-context-author";
  var SEPARATOR_CLASSNAME = "en-context-separator";
  var NOTE_DATE_CLASSNAME = "en-context-note-date";
  var NEWS_DATE_CLASSNAME = "en-context-news-date";
  var POPUP_CLASSNAME = "en-context-popup";
  var POPUP_WRAPPER_CLASSNAME = "en-context-popup-wrapper";
  var POPUP_HEADER_CLASSNAME = "en-context-popup-header";
  var POPUP_BODY_CLASSNAME = "en-context-popup-body";
  var POPUP_FOOTER_CLASSNAME = "en-context-popup-footer";
  var POPUP_ARROW_CLASSNAME = "en-context-popup-down-arrow";
  var POPUP_VISIBLE_CLASSNAME = "en-context-popup-visible";
  var FLE_CONTAINER_CLASSNAME = "en-context-fle-container";
  var FLE_HEADER_CLASSNAME = "en-context-fle-header";
  var FLE_BODY_CLASSNAME = "en-context-fle-body";
  var FLE_DISMISS_BUTTON_CLASSNAME = "en-context-fle-dismiss-button";
  var FLE_SUBHEADER_CLASSNAME = "en-context-fle-subheader";
  var FLE_LEARN_MORE_CLASSNAME = "en-context-fle-learn-more";
  var POPUP_DURATION = 5500;
  var POPUP_FADE_DURATION = 250;
  var POPUP_INITIAL_DELAY = 1500;
  var SCROLL_SPEED = 240;
  var EXPECTED_CARD_HEIGHT = 139;
  var EXPECTED_HEADER_HEIGHT = 32;
  var CONTEXT_KIND_NOTE = "note";
  var CONTEXT_KIND_NEWS = "news";
  var CONTEXT_KIND_PEOPLE = "people";
  var CONTEXT_KIND_COMPANY = "company";
  var SOURCEID_WSJ = "dowjones.wsj";
  var SOURCEID_LINKEDIN = "profile.linkedin";
  var SOURCEID_FACTIVA = "profile.factiva";
  var SOURCEID_EB_PEOPLE = "profile.evernote.business";
  var SOURCEID_EB_NOTE = "evernote.business";
  var SOURCEID_NIKKEI_BUSINESS_ONLINE = "nikkei.bp.business";
  var SOURCEID_NIKKEI_ITPRO = "nikkei.bp.itpro";
  var SOURCEID_NIKKEI_KEN_PLATZ = "nikkei.bp.kenplatz";
  var SOURCEID_NIKKEI_TECHON = "nikkei.bp.tech";
  var BUILT_IN_SOURCE_ICONS = ["factiva", "fastcompany", "inc", "lifehacker", "linkedin", "pandodaily", "techcrunch", "theverge", "evernote-business", "wsj", "forbes", "nikkei", "nikkeibp", "techon", "itpro", "kenplatz"];
  var TITLE_FALLBACK_STRING = "Untitled";
  var CONTEXT_LABEL_FALLBACK_STRING = "Context";
  var settings;
  var container = null;
  var popup = null;
  var popupTimerID;
  var contextSeen = false;
  var contextViewDeJitterTimeoutRef;
  var Context = uno.context.Context = function(opt) {
    if (!document.querySelector("." + MAIN_CONTAINER_CLASSNAME)) {
      container = goog.dom.createDom("div", {class:MAIN_CONTAINER_CLASSNAME, id:MAIN_CONTAINER_CLASSNAME, style:"display:none;"});
      document.body.insertBefore(container, null);
      window.addEventListener("scroll", contextOnScreenHandler);
      window.addEventListener("resize", contextOnScreenHandler);
      window.addEventListener("resize", centerCards);
    }
    contextOnScreenHandler(true);
    goog.object.extend(opt, {showPopup:true, maxRows:9999});
    settings = opt;
  };
  Context.prototype.isSupportedCommand = function(command) {
    return command === "context";
  };
  Context.prototype.execCommandInternal = function(command, value) {
    if (value == null || goog.isString(value) && value === "" || goog.isObject(value) && Object.keys(value).length === 0) {
      log.warning("Context called without data");
      return;
    }
    var opt = value;
    var visible = opt.visible;
    var expanded = opt.expanded;
    var hideLabelText = opt.hideIndicatorLabelWhenExpanded;
    var showLabelText = opt.hideIndicatorLabelWhenCollapsed;
    var chatLabelText = opt.chatButtonLabel || "Chat";
    var shareLabelText = opt.shareButtonLabel || "Share";
    var items = opt.items;
    var contextSectionLabel = opt.contextSectionLabel;
    var firstLaunchInfo = opt.firstLaunchInfo;
    contextSeen = false;
    if (visible != null) {
      goog.style.setElementShown(container, !!visible);
    }
    if (!items || items.length <= 0) {
      return;
    }
    goog.dom.removeChildren(container);
    var contextLabelNode = goog.dom.createDom("div", {class:CONTEXT_LABEL_CLASSNAME});
    contextLabelNode.textContent = contextSectionLabel || CONTEXT_LABEL_FALLBACK_STRING;
    container.appendChild(contextLabelNode);
    var showHideNode = goog.dom.createDom("div", {class:expanded ? HIDE_CLASSNAME : SHOW_CLASSNAME});
    container.appendChild(showHideNode);
    fleAction(firstLaunchInfo);
    var cardHolder = goog.dom.createDom("div", {class:CARD_HOLDER_CLASSNAME});
    container.appendChild(cardHolder);
    for (var i = 0; i < items.length; i++) {
      cardHolder.appendChild(makeCard(items[i], shareLabelText, chatLabelText));
    }
    util.dom.setStyleValue(container, "max-height", EXPECTED_CARD_HEIGHT * settings.maxRows + EXPECTED_HEADER_HEIGHT + "px");
    if (expanded) {
      show(showHideNode, hideLabelText);
    } else {
      hide(showHideNode, showLabelText);
    }
    addShowHideClickHandler(showHideNode, hideLabelText, showLabelText);
    centerCards();
    setTimeout(centerCards, 500);
    contextOnScreenHandler(true);
    if (visible === true && expanded === true && items.length > 0) {
      setTimeout(function() {
        contextPopup(opt);
      }, POPUP_INITIAL_DELAY);
    }
  };
  Context.prototype.queryCommandValue = goog.functions.TRUE;
  var makeCard = function(data, shareLabelText, chatLabelText) {
    var link = data.link || "#";
    var kind = data.kind || "undefined";
    var text = document.createTextNode(goog.string.unescapeEntities(data.text || ""));
    var imgSrc = data.thumbnail || "";
    var hasImage = imgSrc !== "";
    var titleStr = goog.string.unescapeEntities(data.title || TITLE_FALLBACK_STRING);
    var sourceName = data.sourceName || "";
    var sourceId = data.sourceId || "";
    var date = data.date || "";
    var author = data.author || "";
    var canShare = data.canShare;
    var title = goog.dom.createDom("div", {class:hasImage ? TITLE_CLASSNAME : TITLE_CLASSNAME + " " + WIDE_CLASSNAME});
    title.setAttribute("href", link);
    title.setAttribute("name", kind);
    title.textContent = titleStr;
    var authorNode = goog.dom.createDom("span", {class:AUTHOR_CLASSNAME});
    if (author !== "") {
      authorNode.textContent = author;
    }
    var separator = goog.dom.createDom("span", {class:SEPARATOR_CLASSNAME});
    separator.textContent = "|";
    var dateNode = goog.dom.createDom("span", {class:kind === CONTEXT_KIND_NOTE ? NOTE_DATE_CLASSNAME : NEWS_DATE_CLASSNAME});
    if (date !== "") {
      dateNode.textContent = date;
    }
    var bodyContents = [];
    if (kind === CONTEXT_KIND_NEWS) {
      if (date !== "") {
        bodyContents.push(dateNode);
        if (author !== "") {
          bodyContents.push(separator);
          bodyContents.push(authorNode);
        }
      } else {
        if (author !== "") {
          bodyContents.push(authorNode);
        }
      }
    } else {
      if (date !== "") {
        bodyContents.push(dateNode);
      }
      bodyContents.push(text);
    }
    var bodyClasses = ITEM_BODY_CLASSNAME;
    if (!hasImage) {
      bodyClasses += " " + WIDE_CLASSNAME;
    }
    if (kind === CONTEXT_KIND_NEWS) {
      bodyClasses += " " + ITEM_BODY_ONE_LINE_CLASSNAME;
    } else {
      if (kind === CONTEXT_KIND_NOTE && sourceId === SOURCEID_EB_NOTE) {
        bodyClasses += " " + ITEM_BODY_TWO_LINE_CLASSNAME;
      } else {
        if (kind === CONTEXT_KIND_PEOPLE) {
          bodyClasses += " " + BODY_ITALICS_CLASSNAME;
        }
      }
    }
    var body = goog.dom.createDom("div", {class:bodyClasses}, bodyContents);
    var graphicClipper = goog.dom.createDom("div", {class:IMAGE_CLIPPER_CLASSNAME});
    var graphicClasses = IMAGE_CLASSNAME;
    if (canShare) {
      graphicClasses += " " + IMAGE_BLUR_CLASSNAME;
    }
    var graphic = goog.dom.createDom("img", {class:graphicClasses, alt:"graphic", src:imgSrc});
    var graphicOverlayClasses = IMAGE_HOVER_CLASSNAME;
    if (!hasImage) {
      graphicOverlayClasses += " " + IMAGE_HOVER_SOLID_CLASSNAME;
    }
    var graphicOverlay = goog.dom.createDom("div", {class:graphicOverlayClasses}, [goog.dom.createDom("div", {class:IMAGE_HOVER_MESSAGE_ICON_CLASSNAME}), goog.dom.createDom("div", {class:IMAGE_HOVER_TEXT_CLASSNAME}, [kind === CONTEXT_KIND_PEOPLE ? chatLabelText : shareLabelText])]);
    if (hasImage) {
      graphicClipper.appendChild(graphic);
    }
    if (canShare) {
      graphicClipper.appendChild(graphicOverlay);
      graphicClipper.addEventListener("click", function(e) {
        EN.notification("openLink", {href:title.getAttribute("href"), module:moduleName, kind:title.getAttribute("name"), sharing:true});
        e.stopPropagation();
      });
    }
    var sourceIconName = sourceId;
    if (sourceIconName === SOURCEID_WSJ) {
      sourceIconName = "wsj";
    }
    if (sourceIconName === SOURCEID_LINKEDIN) {
      sourceIconName = "linkedin";
    }
    if (sourceIconName === SOURCEID_EB_PEOPLE || sourceIconName === SOURCEID_EB_NOTE) {
      sourceIconName = "evernote-business";
    }
    if (sourceIconName === SOURCEID_FACTIVA) {
      sourceIconName = "factiva";
    }
    if (sourceIconName === SOURCEID_NIKKEI_BUSINESS_ONLINE) {
      sourceIconName = "nikkeibp";
    }
    if (sourceIconName === SOURCEID_NIKKEI_ITPRO) {
      sourceIconName = "itpro";
    }
    if (sourceIconName === SOURCEID_NIKKEI_KEN_PLATZ) {
      sourceIconName = "kenplatz";
    }
    if (sourceIconName === SOURCEID_NIKKEI_TECHON) {
      sourceIconName = "techon";
    }
    var sourceTextClasses = "";
    if (sourceId === SOURCEID_EB_PEOPLE || sourceId === SOURCEID_EB_NOTE) {
      sourceTextClasses = NEWS_SOURCE_TEXT_BLUE_CLASSNAME;
    }
    var sourceNameIcon = goog.dom.createDom("div", {class:NEWS_SOURCE_IMAGE_CLASSNAME + " " + sourceIconName});
    var sourceNameNode = goog.dom.createDom("div", {class:NEWS_SOURCE_TEXT_CLASSNAME + " " + sourceTextClasses});
    if (sourceId === SOURCEID_WSJ) {
      sourceNameNode.textContent = "";
    } else {
      if (sourceId === SOURCEID_EB_NOTE) {
        sourceNameNode.textContent = author;
      } else {
        sourceNameNode.textContent = sourceName;
      }
    }
    var sourceInfo = goog.dom.createDom("div", {class:NEWS_SOURCE_CONTAINER_CLASSNAME});
    if (BUILT_IN_SOURCE_ICONS.indexOf(sourceIconName) !== -1) {
      sourceInfo.appendChild(sourceNameIcon);
    }
    sourceInfo.appendChild(sourceNameNode);
    var cardContent = [title, body];
    cardContent.push(graphicClipper);
    if (kind === CONTEXT_KIND_NEWS || kind === CONTEXT_KIND_PEOPLE || kind === CONTEXT_KIND_COMPANY || kind === CONTEXT_KIND_NOTE && sourceId === SOURCEID_EB_NOTE) {
      cardContent.push(sourceInfo);
    }
    var card = goog.dom.createDom("div", {class:ITEM_CLASSNAME}, cardContent);
    card.addEventListener("click", function(e) {
      EN.notification("openLink", {href:title.getAttribute("href"), module:moduleName, kind:title.getAttribute("name"), sharing:false});
      e.preventDefault();
    });
    return card;
  };
  var contextOnScreenHandler = function(immediate) {
    if (immediate == null) {
      immediate = false;
    }
    var logic = function() {
      var firstCard = container.querySelector("." + ITEM_CLASSNAME);
      if (firstCard == null) {
        return;
      }
      if (util.dom.isOnScreen(firstCard, 100)) {
        if (contextSeen === false) {
          contextSeen = true;
          EN.notification("contextVisible", {module:moduleName});
        }
      }
    };
    if (immediate) {
      logic();
    } else {
      contextViewDeJitterTimeoutRef = setTimeout(logic, 100, contextViewDeJitterTimeoutRef);
    }
  };
  var hide = function(labelNode, showText) {
    var cardHolder = container.querySelector("." + CARD_HOLDER_CLASSNAME);
    var fle = container.querySelector("." + FLE_CONTAINER_CLASSNAME);
    if (cardHolder == null) {
      log.severe("Couldnt find card holder?!");
      return;
    }
    labelNode.textContent = showText;
    goog.dom.classes.remove(labelNode, HIDE_CLASSNAME);
    goog.dom.classes.add(labelNode, SHOW_CLASSNAME);
    goog.style.setElementShown(cardHolder, false);
    if (fle != null && fle.length === 1) {
      goog.style.setElementShown(fle[0], false);
    }
  };
  var show = function(labelNode, hideText) {
    var cardHolder = container.querySelector("." + CARD_HOLDER_CLASSNAME);
    var fle = container.querySelector("." + FLE_CONTAINER_CLASSNAME);
    if (cardHolder == null) {
      log.severe("Couldnt find card holder?!");
      return;
    }
    labelNode.textContent = hideText;
    goog.dom.classes.remove(labelNode, SHOW_CLASSNAME);
    goog.dom.classes.add(labelNode, HIDE_CLASSNAME);
    goog.style.setElementShown(cardHolder, true);
    centerCards();
    if (fle != null && fle.length === 1) {
      goog.style.setElementShown(fle[0], true);
    }
  };
  var addShowHideClickHandler = function(node, hideText, showText) {
    node.addEventListener("click", function() {
      if (node.textContent === hideText) {
        hide(node, showText);
        EN.notification("contextExpanded", {module:moduleName, expanded:false});
      } else {
        if (node.textContent === showText) {
          show(node, hideText);
          EN.notification("contextExpanded", {module:moduleName, expanded:true});
        }
      }
      contextOnScreenHandler(true);
    });
  };
  var contextPopup = function(opt) {
    if (contextSeen === true || settings.showPopup === false || popup != null || container == null || opt == null || opt.items == null || opt.items.length === 0) {
      return;
    }
    var items = opt.items;
    var headerLabel = opt.toastNotificationHeaderLabel || "FIX HEADER";
    var footerLabel = opt.toastNotificationFooterLabel || "FIX FOOTER";
    var titleStr = goog.string.unescapeEntities(items[0].title || TITLE_FALLBACK_STRING);
    var popupHeader = goog.dom.createDom("div", {class:POPUP_HEADER_CLASSNAME});
    popupHeader.textContent = headerLabel;
    var bodyClasses = POPUP_BODY_CLASSNAME;
    if (items[0].kind != null) {
      bodyClasses += " " + items[0].kind;
    }
    var popupBody = goog.dom.createDom("div", {class:bodyClasses});
    popupBody.textContent = titleStr;
    var popupFooter = goog.dom.createDom("div", {class:POPUP_FOOTER_CLASSNAME});
    popupFooter.textContent = footerLabel;
    popupFooter.appendChild(goog.dom.createDom("div", {class:POPUP_ARROW_CLASSNAME}));
    popup = goog.dom.createDom("div", {class:POPUP_CLASSNAME}, [goog.dom.createDom("div", {class:POPUP_WRAPPER_CLASSNAME}, [popupHeader, popupBody, popupFooter])]);
    goog.dom.insertSiblingAfter(popup, container);
    setTimeout(function() {
      goog.dom.classes.add(popup, POPUP_VISIBLE_CLASSNAME);
    }, 1);
    popup.addEventListener("mousedown", function() {
      clearTimeout(popupTimerID);
    });
    popup.addEventListener("mouseup", function() {
      var bounds = getBounds(container);
      util.dom.scrollTo(bounds.top - 15, SCROLL_SPEED);
      goog.dom.classes.remove(popup, POPUP_VISIBLE_CLASSNAME);
      util.dom.setStyleValue(popup, "pointer-events", "none");
    });
    popupTimerID = setTimeout(function() {
      goog.dom.classes.remove(popup, POPUP_VISIBLE_CLASSNAME);
      util.dom.setStyleValue(popup, "pointer-events", "none");
      setTimeout(function() {
        goog.style.setElementShown(popup, false);
      }, POPUP_FADE_DURATION);
    }, POPUP_DURATION, popupTimerID);
  };
  var getBounds = function(node) {
    return util.zoomscale.normalizeRect(goog.style.getBounds(node));
  };
  var getCardLayoutInfo = function() {
    var cardHolder = document.querySelector("." + CARD_HOLDER_CLASSNAME);
    var allCards = document.querySelectorAll("." + ITEM_CLASSNAME);
    var numCards = allCards.length || 0;
    var sampleCard = document.querySelector("." + ITEM_CLASSNAME);
    if (cardHolder == null || sampleCard == null) {
      return null;
    }
    var availableSpace = Math.round(getBounds(cardHolder).width);
    var compStyle = window.getComputedStyle(sampleCard);
    var cardMarginX = parseInt(compStyle["margin-left"], 10) + parseInt(compStyle["margin-right"], 10);
    var cardMarginY = parseInt(compStyle["margin-top"], 10) + parseInt(compStyle["margin-bottom"], 10);
    var cardWidth = Math.round(sampleCard.offsetWidth + cardMarginX);
    var cardHeight = Math.round(sampleCard.offsetHeight + cardMarginY);
    return {availableSpace:availableSpace, numCards:numCards, cardWidth:cardWidth, cardHeight:cardHeight, cardsPerRow:Math.floor(availableSpace / cardWidth)};
  };
  var centerCards = function() {
    var layoutInfo = getCardLayoutInfo();
    var cardHolder = document.querySelector("." + CARD_HOLDER_CLASSNAME);
    if (layoutInfo == null || cardHolder == null) {
      return;
    }
    var realNumCardsPerRow = Math.min(layoutInfo.numCards, layoutInfo.cardsPerRow);
    if (realNumCardsPerRow <= 0) {
      util.dom.setStyleValue(cardHolder, "left", "0px");
      return;
    }
    var remainder = layoutInfo.availableSpace - layoutInfo.cardWidth * realNumCardsPerRow;
    util.dom.setStyleValue(cardHolder, "left", remainder / 2 + "px");
  };
  var fleAction = function(firstLaunchInfo) {
    if (firstLaunchInfo == null || firstLaunchInfo.headline == null || firstLaunchInfo.subHeadline == null || firstLaunchInfo.learnMoreLinkLabel == null || firstLaunchInfo.dismissButtonLabel == null) {
      return;
    }
    log.warning("The FLE functionality has been merged into " + "the context-info command. Please switch " + "to that API.");
    var headline = firstLaunchInfo.headline;
    var subHeadline = firstLaunchInfo.subHeadline;
    var learnMoreLinkLabel = firstLaunchInfo.learnMoreLinkLabel;
    var dismissButtonLabel = firstLaunchInfo.dismissButtonLabel;
    var FLEContainer = goog.dom.createDom("div", {class:FLE_CONTAINER_CLASSNAME});
    container.appendChild(FLEContainer);
    var FLEHeader = goog.dom.createDom("div", {class:FLE_HEADER_CLASSNAME});
    FLEHeader.textContent = headline;
    FLEContainer.appendChild(FLEHeader);
    var FLEBody = goog.dom.createDom("div", {class:FLE_BODY_CLASSNAME});
    FLEContainer.appendChild(FLEBody);
    var FLESubHeader = goog.dom.createDom("span", {class:FLE_SUBHEADER_CLASSNAME});
    FLESubHeader.textContent = subHeadline + " ";
    FLEBody.appendChild(FLESubHeader);
    var FLELearnMore = goog.dom.createDom("span", {class:FLE_LEARN_MORE_CLASSNAME});
    FLELearnMore.textContent = learnMoreLinkLabel;
    FLEBody.appendChild(FLELearnMore);
    FLELearnMore.addEventListener("click", function(e) {
      EN.notification("openLink", {href:CLICK_EVENT_FLE_LEARN_MORE_HREF, module:moduleName, kind:CLICK_EVENT_FLE_KIND, sharing:false});
      e.preventDefault();
      e.stopPropagation();
      return false;
    });
    var FLEDismissButton = goog.dom.createDom("div", {class:FLE_DISMISS_BUTTON_CLASSNAME});
    FLEDismissButton.textContent = dismissButtonLabel;
    FLEContainer.appendChild(FLEDismissButton);
    FLEDismissButton.addEventListener("click", function(e) {
      EN.notification("openLink", {href:CLICK_EVENT_FLE_BUTTON_HREF, module:moduleName, kind:CLICK_EVENT_FLE_KIND, sharing:false});
      goog.dom.removeNode(FLEContainer);
      e.stopPropagation();
    });
  };
})();
goog.provide("uno.context.Info");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.functions");
goog.require("goog.style");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.context.Info");
  var util = uno.util;
  var moduleName = "context-info";
  var MAIN_CONTAINER_CLASSNAME = "en-context-info";
  var BODY_CONTAINER_CLASSNAME = "en-context-info-body";
  var CONTEXT_LOGO_CLASSNAME = "en-context-info-logo";
  var HEADLINE_CLASSNAME = "en-context-info-headline";
  var BUTTON_CLASSNAME = "en-context-info-button";
  var SECTION_CLASSNAME = "en-context-info-section";
  var SECTION_IMAGE_CLASSNAME = "en-context-info-section-image";
  var SECTION_TITLE_CLASSNAME = "en-context-info-section-title";
  var SECTION_TEXT_CLASSNAME = "en-context-info-section-text";
  var STRETCHER_CLASSNAME = "en-context-info-stretcher";
  var NUM_INFO_SECTIONS = 3;
  var ALLOWED_SECTION_TYPES = ["note", "article", "person"];
  var container = null;
  var bodyContainer = null;
  var contextSeen = false;
  var contextViewDeJitterTimeoutRef;
  var ContextInfo = uno.context.Info = function() {
    if (!document.querySelector("." + MAIN_CONTAINER_CLASSNAME)) {
      container = goog.dom.createDom("div", {class:MAIN_CONTAINER_CLASSNAME, style:"display:none;"});
      document.body.insertBefore(container, null);
      window.addEventListener("scroll", onScreenHandler);
      window.addEventListener("resize", onScreenHandler);
    }
    onScreenHandler(true);
  };
  ContextInfo.prototype.isSupportedCommand = function(command) {
    return command === "context-info";
  };
  ContextInfo.prototype.queryCommandEnabled = goog.functions.TRUE;
  ContextInfo.prototype.execCommandInternal = function(command, value) {
    if (value == null || goog.isString(value) && value === "" || goog.isObject(value) && Object.keys(value).length === 0) {
      return false;
    }
    var opt = value;
    var showLogo = opt.showLogo || false;
    var headline = opt.headline || "HEADLINE";
    var infoSections = opt.infoSections || [];
    var buttonLabel = opt.buttonLabel || "BUTTONLABEL";
    var hideOnButtonClick = opt.hideOnButtonClick || false;
    goog.dom.removeChildren(container);
    goog.style.setElementShown(container, true);
    contextSeen = false;
    var logo = goog.dom.createDom("div", {class:CONTEXT_LOGO_CLASSNAME});
    if (showLogo) {
      container.appendChild(logo);
    }
    var headlineNode = goog.dom.createDom("div", {class:HEADLINE_CLASSNAME});
    headlineNode.textContent = headline;
    container.appendChild(headlineNode);
    bodyContainer = goog.dom.createDom("div", {id:BODY_CONTAINER_CLASSNAME});
    container.appendChild(bodyContainer);
    if (infoSections.length === NUM_INFO_SECTIONS) {
      for (var i = 0; i < infoSections.length; i++) {
        bodyContainer.appendChild(createSection(infoSections[i]));
        bodyContainer.appendChild(document.createTextNode(" "));
      }
      var stretcher = goog.dom.createDom("div", {class:STRETCHER_CLASSNAME});
      bodyContainer.appendChild(stretcher);
    }
    var buttonNode = goog.dom.createDom("div", {class:BUTTON_CLASSNAME});
    buttonNode.textContent = buttonLabel;
    container.appendChild(buttonNode);
    buttonNode.addEventListener("click", function(e) {
      EN.notification("openLink", {href:"http://evernote.com", module:moduleName, kind:"info", sharing:true});
      if (hideOnButtonClick) {
        goog.style.setElementShown(container, false);
      }
      e.preventDefault();
      e.stopPropagation();
      return false;
    });
    onScreenHandler(true);
    return true;
  };
  var onScreenHandler = function(immediate) {
    immediate = immediate === true;
    var logic = function() {
      var isOnScreen = container.style.display === "none" ? false : util.dom.isOnScreen(container, 75);
      if (isOnScreen) {
        if (contextSeen === false) {
          contextSeen = true;
          EN.notification("contextVisible", {module:moduleName});
        }
      }
    };
    if (immediate) {
      logic();
    } else {
      clearTimeout(contextViewDeJitterTimeoutRef);
      contextViewDeJitterTimeoutRef = setTimeout(logic, 250);
    }
  };
  var createSection = function(info) {
    if (info == null || !goog.isString(info.type) || !goog.isString(info.title) || !goog.isString(info.text)) {
      log.severe("Incomplete section info for context-info!");
    }
    var found = false;
    for (var i = 0; i < ALLOWED_SECTION_TYPES.length; i++) {
      if (info.type === ALLOWED_SECTION_TYPES[i]) {
        found = true;
      }
    }
    if (found === false) {
      log.severe("Invalid type given for context-info: " + info.type);
    }
    var section = goog.dom.createDom("div", {class:SECTION_CLASSNAME});
    var image = goog.dom.createDom("div", {class:SECTION_IMAGE_CLASSNAME + " " + info.type});
    section.appendChild(image);
    var title = goog.dom.createDom("div", {class:SECTION_TITLE_CLASSNAME});
    title.textContent = info.title;
    section.appendChild(title);
    var text = goog.dom.createDom("div", {class:SECTION_TEXT_CLASSNAME});
    text.textContent = info.text;
    section.appendChild(text);
    return section;
  };
})();
goog.provide("uno.context.Upsell");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.functions");
goog.require("goog.style");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.context.Upsell");
  var util = uno.util;
  var moduleName = "context-upsell";
  var MAIN_CONTAINER_CLASSNAME = "en-context-upsell";
  var BODY_CONTAINER_CLASSNAME = "en-context-upsell-body";
  var HIDE_CLASSNAME = "en-context-upsell-hide-label";
  var SHOW_CLASSNAME = "en-context-upsell-show-label";
  var HEADLINE_CLASSNAME = "en-context-upsell-headline";
  var SUBHEADLINE_CLASSNAME = "en-context-upsell-subheadline";
  var GO_PREMIUM_CLASSNAME = "en-context-upsell-go-premium";
  var HEADLINE_FALLBACK = "Get more Context with Premium";
  var SUBHEADLINE_FALLBACK = "Go Premium to view notes," + " articles, and people related to what you're working on.";
  var PREMIUM_FALLBACK = "Go Premium";
  var HIDE_FALLBACK = "Hide";
  var SHOW_FALLBACK = "Show";
  var container = null;
  var bodyContainer = null;
  var contextSeen = false;
  var contextViewDeJitterTimeoutRef;
  var ContextUpsell = uno.context.Upsell = function() {
    if (!document.querySelector("." + MAIN_CONTAINER_CLASSNAME)) {
      container = goog.dom.createDom("div", {class:MAIN_CONTAINER_CLASSNAME, id:MAIN_CONTAINER_CLASSNAME, style:"display:none;"});
      document.body.insertBefore(container, null);
      window.addEventListener("scroll", onScreenHandler);
      window.addEventListener("resize", onScreenHandler);
    }
    onScreenHandler(true);
  };
  ContextUpsell.prototype.isSupportedCommand = function(command) {
    return command === "context-upsell";
  };
  ContextUpsell.prototype.queryCommandEnabled = goog.functions.TRUE;
  ContextUpsell.prototype.execCommandInternal = function(command, value) {
    if (value == null || goog.isString(value) && value === "" || goog.isObject(value) && Object.keys(value).length === 0) {
      return false;
    }
    log.warning("The FLE functionality has been merged into " + "the context-info command. Please switch " + "to that API.");
    var opt = value;
    var expanded = opt.expanded;
    if (expanded == null) {
      expanded = false;
    }
    var headline = opt.headline || HEADLINE_FALLBACK;
    var subHeadline = opt.subHeadline || SUBHEADLINE_FALLBACK;
    var goPremium = opt.goPremiumLabel || PREMIUM_FALLBACK;
    var hideLabel = opt.hideIndicatorLabelWhenExpanded || HIDE_FALLBACK;
    var showLabel = opt.hideIndicatorLabelWhenCollapsed || SHOW_FALLBACK;
    goog.dom.removeChildren(container);
    goog.style.setElementShown(container, true);
    contextSeen = false;
    bodyContainer = goog.dom.createDom("div", {class:BODY_CONTAINER_CLASSNAME});
    container.appendChild(bodyContainer);
    var showHideNode = goog.dom.createDom("div", {class:expanded ? HIDE_CLASSNAME : SHOW_CLASSNAME});
    container.appendChild(showHideNode);
    if (expanded) {
      show(showHideNode, hideLabel);
    } else {
      hide(showHideNode, showLabel);
    }
    addShowHideClickHandler(showHideNode, hideLabel, showLabel);
    var headlineNode = goog.dom.createDom("div", {class:HEADLINE_CLASSNAME});
    headlineNode.textContent = headline;
    bodyContainer.appendChild(headlineNode);
    var subheadlineNode = goog.dom.createDom("div", {class:SUBHEADLINE_CLASSNAME});
    subheadlineNode.textContent = subHeadline;
    bodyContainer.appendChild(subheadlineNode);
    var goPremiumNode = goog.dom.createDom("div", {class:GO_PREMIUM_CLASSNAME});
    goPremiumNode.textContent = goPremium;
    bodyContainer.appendChild(goPremiumNode);
    goPremiumNode.addEventListener("click", function(e) {
      EN.notification("openLink", {href:"http://evernote.com", module:moduleName, kind:"upsell", sharing:true});
      e.preventDefault();
      e.stopPropagation();
      return false;
    });
    onScreenHandler(true);
    return true;
  };
  var onScreenHandler = function(immediate) {
    immediate = immediate === true;
    var logic = function() {
      var isOnScreen = container.style.display === "none" ? false : util.dom.isOnScreen(container, 75);
      if (isOnScreen) {
        if (contextSeen === false) {
          contextSeen = true;
          EN.notification("contextVisible", {module:moduleName});
        }
      }
    };
    if (immediate) {
      logic();
    } else {
      clearTimeout(contextViewDeJitterTimeoutRef);
      contextViewDeJitterTimeoutRef = setTimeout(logic, 250);
    }
  };
  var hide = function(labelNode, showText) {
    if (bodyContainer == null) {
      return;
    }
    labelNode.textContent = showText;
    goog.dom.classes.remove(labelNode, HIDE_CLASSNAME);
    goog.dom.classes.add(labelNode, SHOW_CLASSNAME);
    goog.style.setElementShown(bodyContainer, false);
  };
  var show = function(labelNode, hideText) {
    if (bodyContainer == null) {
      return;
    }
    labelNode.textContent = hideText;
    goog.dom.classes.remove(labelNode, SHOW_CLASSNAME);
    goog.dom.classes.add(labelNode, HIDE_CLASSNAME);
    goog.style.setElementShown(bodyContainer, true);
  };
  var addShowHideClickHandler = function(node, hideText, showText) {
    node.addEventListener("click", function() {
      if (node.textContent === hideText) {
        hide(node, showText);
        EN.notification("contextExpanded", {module:moduleName, expanded:false});
      } else {
        if (node.textContent === showText) {
          show(node, hideText);
          EN.notification("contextExpanded", {module:moduleName, expanded:true});
        }
      }
      onScreenHandler(true);
    });
  };
})();
goog.provide("uno.realtime.Plugin");
goog.require("goog.functions");
(function() {
  var Plugin = uno.realtime.Plugin = function(yjsmodule) {
    this.yjsmodule = yjsmodule;
  };
  Plugin.prototype.y = function() {
    return this.yjsmodule.y;
  };
  Plugin.prototype.setupConfig = function(yjsconfig) {
    return yjsconfig;
  };
  Plugin.prototype.setupObservation = function() {
  };
  Plugin.prototype.socketConnect = goog.functions.NULL;
  Plugin.prototype.socketConnectError = goog.functions.NULL;
  Plugin.prototype.socketReconnect = goog.functions.NULL;
  Plugin.prototype.socketReconnectAttempt = goog.functions.NULL;
  Plugin.prototype.socketReconnectError = goog.functions.NULL;
  Plugin.prototype.socketDisconnect = goog.functions.NULL;
  Plugin.prototype.realtimeNoteSaved = goog.functions.NULL;
  Plugin.prototype.execCommand = goog.functions.FALSE;
  Plugin.prototype.queryCommandEnabled = goog.functions.FALSE;
  Plugin.prototype.queryCommandValue = goog.functions.NULL;
  Plugin.prototype.isSupportedCommand = goog.functions.FALSE;
})();
goog.provide("uno.realtime.Users");
goog.require("uno.realtime.Plugin");
goog.require("goog.array");
(function() {
  var Users = uno.realtime.Users = function(yjsmodule) {
    uno.realtime.Plugin.call(this, yjsmodule);
  };
  goog.inherits(Users, uno.realtime.Plugin);
  Users.prototype.activeUsers = {};
  Users.prototype.setupConfig = function(yjsconfig) {
    yjsconfig.share.metadata = "Map";
    return yjsconfig;
  };
  Users.prototype.setupObservation = function() {
    setInterval(function(self) {
      goog.array.forEach(self.getAllSeenUsers(), function(user) {
        self.updateUserActivity({name:user});
      });
    }, 5000, this);
  };
  Users.prototype.updateUserActivity = function(event) {
    if (goog.isString(event.name)) {
      this.activeUsers[event.name] = (new Date).getTime();
    }
    this.renderOverlay();
  };
  Users.prototype.getAllSeenUsers = function() {
    var userMap = this.yjsmodule.y.share.metadata.get("Users");
    if (userMap == null) {
      return [];
    }
    return userMap.keys();
  };
  Users.prototype.getActive = function(activityCutoff) {
    activityCutoff = activityCutoff || 20000;
    var now = (new Date).getTime();
    return goog.array.filter(Object.keys(this.activeUsers), function(key) {
      var userStillInRoom = this.yjsmodule.y.share.metadata.get("Users").get(key) != null;
      var isNotCurrentUser = key !== this.yjsmodule.y.connector.clientID;
      return this.activeUsers[key] + activityCutoff > now && userStillInRoom && isNotCurrentUser;
    }, this);
  };
  Users.prototype.getUserColor = function(username) {
    var color = "black";
    try {
      color = this.yjsmodule.y.share.metadata.get("Users").get(username).get("Color");
    } catch (e) {
      console.log("Dont have color (yet) for", username);
    }
    return color;
  };
  Users.prototype.getUserPrettyName = function(username) {
    var name = null;
    try {
      name = this.yjsmodule.y.share.metadata.get("Users").get(username).get("Name");
    } catch (e) {
      console.log("Dont have name (yet?) for", username);
    }
    return name || username;
  };
  Users.prototype.renderOverlay = function() {
    var activeUsers = this.getActive();
    var tools = document.querySelector("en-tools");
    var activityUI = tools.querySelector(".realtime-activity-ui");
    if (activityUI == null) {
      activityUI = document.createElement("div");
      activityUI.setAttribute("class", "realtime-activity-ui");
      tools.appendChild(activityUI);
    }
    goog.dom.removeChildren(activityUI);
    goog.array.forEach(activeUsers, function(user) {
      var userColor = this.getUserColor(user);
      var userName = this.getUserPrettyName(user);
      var userDiv = document.createElement("div");
      var textDiv = document.createElement("div");
      var colorDiv = document.createElement("div");
      userDiv.setAttribute("data-user", user);
      textDiv.textContent = userName;
      textDiv.setAttribute("class", "text");
      textDiv.style.color = userColor;
      colorDiv.style.backgroundColor = userColor;
      colorDiv.setAttribute("class", "color");
      userDiv.appendChild(colorDiv);
      userDiv.appendChild(textDiv);
      activityUI.appendChild(userDiv);
    }, this);
  };
})();
goog.provide("uno.realtime.util.hyperjson");
goog.require("goog.debug.Logger");
goog.require("goog.object");
goog.require("uno.util.dom");
(function() {
  var log = goog.debug.Logger.getLogger("uno.realtime.util.hyperjson");
  var rutil = uno.realtime.util;
  var util = uno.util;
  var isUnusualNode = function(node) {
    return !!(node && node.nodeType != null && goog.isNumber(node.nodeType) && node.nodeType > Node.TEXT_NODE);
  };
  rutil.hyperjson.fromDOM = function(element, acceptFilter, afterTransforms) {
    var result = [];
    if (goog.isFunction(acceptFilter) && acceptFilter(element) === false) {
      return null;
    }
    if (util.dom.isTextNode(element)) {
      return element.textContent;
    } else {
      if (util.dom.isElementNode(element)) {
        result.push(util.dom.getTagName(element).toUpperCase());
        var clonedAttrs = {};
        for (var i = 0; i < element.attributes.length; i++) {
          clonedAttrs[element.attributes[i].name] = element.attributes[i].value;
        }
        result.push(clonedAttrs);
        var children = [];
        var tmpchild = null;
        for (var x = 0; x < element.childNodes.length; x++) {
          tmpchild = rutil.hyperjson.fromDOM(element.childNodes[x], acceptFilter, afterTransforms);
          if (tmpchild != null) {
            children.push(tmpchild);
          }
        }
        result.push(children);
      } else {
        if (isUnusualNode(element)) {
          log.warning("Cool, hyperjson saw a weird node (OK, skipped): " + element);
          return null;
        } else {
          log.error("Could not parse dom (skipped): " + element);
          return null;
        }
      }
    }
    if (goog.isFunction(afterTransforms)) {
      result = afterTransforms(result);
    }
    return result;
  };
  var isValidHyperJsonElement = function(hyperjson) {
    return goog.isString(hyperjson) || goog.isArray(hyperjson) && hyperjson.length === 3 && goog.isString(hyperjson[0]) && goog.isObject(hyperjson[1]) && goog.isArray(hyperjson[2]);
  };
  var tryFixJsonElement = function(hyperjson) {
    return false;
  };
  rutil.hyperjson.toDOM = function(hyperjson) {
    if (goog.isString(hyperjson)) {
      return goog.dom.createTextNode(hyperjson);
    }
    if (!isValidHyperJsonElement(hyperjson) && !tryFixJsonElement(hyperjson)) {
      console.log("Invalid HyperJSON structure (toDOM): ", hyperjson, JSON.stringify(hyperjson));
      return null;
    }
    var elem = goog.dom.createDom(hyperjson[0]);
    var keys = Object.keys(hyperjson[1]);
    for (var i = 0; i < keys.length; i++) {
      elem.setAttribute(keys[i], hyperjson[1][keys[i]]);
    }
    var tmpchild = null;
    for (var x = 0; x < hyperjson[2].length; x++) {
      tmpchild = rutil.hyperjson.toDOM(hyperjson[2][x]);
      if (tmpchild != null) {
        elem.appendChild(tmpchild);
      } else {
        return null;
      }
    }
    return elem;
  };
})();
goog.provide("uno.realtime.util.convert");
goog.require("goog.array");
goog.require("uno.util.copy.plain");
goog.require("uno.util.dom");
goog.require("uno.realtime.util.hyperjson");
(function() {
  var rutil = uno.realtime.util;
  var util = uno.util;
  var DEBUG_MODEL = true;
  rutil.convert.domToJson = function(dom) {
    return rutil.hyperjson.fromDOM(dom, null, function(h) {
      if (h[0] === "EN-NOTE") {
        h[1] = {};
      }
      return h;
    });
  };
  rutil.convert.isEmptyNoteJson = function(json) {
    return goog.isArray(json) && json.length === 3 && json[0] === "EN-NOTE" && goog.isObject(json[1]) && goog.object.isEmpty(json[1]) && goog.isArray(json[2]) && json[2].length === 0;
  };
  rutil.convert.jsonToDom = function(json) {
    if (json == null) {
      return null;
    }
    var res = null;
    try {
      res = rutil.hyperjson.toDOM(json);
    } catch (e) {
      console.warn("Couldnt DOMize invalid JSON", e, json);
    }
    return res;
  };
  rutil.convert.yjsModelToJson = function(model) {
    var output = null;
    if (typeof model.length !== "undefined") {
      if (output == null) {
        output = model.toArray();
      }
      for (var i = 0; i < output.length; i++) {
        if (goog.isObject(output[i])) {
          output[i] = rutil.convert.yjsModelToJson(output[i]);
        }
      }
    } else {
      output = {};
      goog.array.forEach(model.keys(), function(key) {
        output[key] = model.get(key);
      });
    }
    return output;
  };
  var diffKeysInApplyOrder = function(diffObj) {
    var keys = goog.array.filter(Object.keys(diffObj), function(key) {
      return key !== "_t";
    });
    var parse = function(key) {
      var isDeletion = key.length >= 2 && key[0] === "_";
      var value = null;
      if (isDeletion) {
        value = parseInt(key.slice(1), 10);
      } else {
        value = parseInt(key, 10);
      }
      return {isDeletion:isDeletion, value:value};
    };
    goog.array.sort(keys, function(first, second) {
      var firstParse = parse(first);
      var secondParse = parse(second);
      if (firstParse.value < secondParse.value) {
        return 1;
      } else {
        if (firstParse.value > secondParse.value) {
          return -1;
        } else {
          if (firstParse.value === secondParse.value) {
            if (firstParse.isDeletion && !secondParse.isDeletion) {
              return -1;
            } else {
              if (!firstParse.isDeletion && secondParse.isDeletion) {
                return 1;
              }
            }
          }
        }
      }
      return 0;
    });
    return keys;
  };
  var addPaddingToModelArray = function(model, changeKey) {
    var sizeDiff = changeKey - model.length;
    while (sizeDiff > 0) {
      model.push([null]);
      sizeDiff--;
    }
  };
  rutil.convert.addToModel = function(toAdd, model, changeKey) {
    if (goog.isArray(toAdd)) {
      if (changeKey != null) {
        addPaddingToModelArray(model, changeKey);
        model.insert(changeKey, [window.Y.Array]);
        model = model.get(changeKey);
        if (DEBUG_MODEL) {
          console.log("+ array to model @", changeKey);
        }
      } else {
        model.push([window.Y.Array]);
        model = model.get(model.length - 1);
        if (DEBUG_MODEL) {
          console.log("+ array to model @ end");
        }
      }
      goog.array.forEach(toAdd, function(elem) {
        rutil.convert.addToModel(elem, model);
      });
    } else {
      if (goog.isObject(toAdd)) {
        if (changeKey != null) {
          model.insert(changeKey, [window.Y.Map]);
          model = model.get(changeKey);
          if (DEBUG_MODEL) {
            console.log("+ map to model @", changeKey);
          }
        } else {
          model.push([window.Y.Map]);
          model = model.get(model.length - 1);
          if (DEBUG_MODEL) {
            console.log("+ map to model @ end");
          }
        }
        goog.object.forEach(toAdd, function(elem, key) {
          model.set(key, elem);
          if (DEBUG_MODEL) {
            console.log("+ map." + key, "=", elem);
          }
        });
      } else {
        if (changeKey == null) {
          model.push([toAdd]);
          if (DEBUG_MODEL) {
            console.log("+ basictype @", "end", "=", toAdd);
          }
        } else {
          addPaddingToModelArray(model, changeKey);
          model.insert(changeKey, [toAdd]);
          if (DEBUG_MODEL) {
            console.log("+ basictype @", changeKey, "=", toAdd);
          }
        }
      }
    }
  };
  rutil.convert.applyDiffToModel = function(jsonDiff, model, changeKey) {
    if (jsonDiff == null) {
      return;
    }
    var isChange = goog.isArray(jsonDiff);
    var isArray = jsonDiff._t != null && jsonDiff._t === "a";
    var isAttrs = !isChange && !isArray && goog.isObject(jsonDiff);
    if (isAttrs) {
      goog.array.forEach(Object.keys(jsonDiff), function(key) {
        var value = jsonDiff[key];
        if (value.length === 1) {
          model.set(key, value[0]);
          if (DEBUG_MODEL) {
            console.log("+ map." + key, "=", value[0]);
          }
        } else {
          if (value.length === 2) {
            model.set(key, value[1]);
            if (DEBUG_MODEL) {
              console.log("+ map." + key, "=", value[1]);
            }
          } else {
            if (value.length === 3) {
              model.delete(key);
              if (DEBUG_MODEL) {
                console.log("+ map." + key, "deleted");
              }
            } else {
              console.error("Impossible attribute diff");
            }
          }
        }
      });
    } else {
      if (isChange) {
        if (jsonDiff.length === 1) {
          if (model.get(changeKey) === null) {
            model.delete(changeKey);
            if (DEBUG_MODEL) {
              console.log("+ map." + changeKey, "deleted");
            }
          }
          rutil.convert.addToModel(jsonDiff[0], model, changeKey);
        } else {
          if (jsonDiff.length === 2) {
            if (changeKey != null && model.length > changeKey) {
              model.delete(changeKey);
              if (DEBUG_MODEL) {
                console.log("+ map." + changeKey, "deleted");
              }
            }
            rutil.convert.addToModel(jsonDiff[1][0], model, changeKey);
          } else {
            if (jsonDiff.length === 3) {
              if (changeKey != null && model.length > changeKey) {
                model.delete(changeKey);
                if (DEBUG_MODEL) {
                  console.log("+ map." + changeKey, "deleted");
                }
              } else {
                console.error("Changekey mandatory for delete!");
              }
            }
          }
        }
      } else {
        if (isArray) {
          var diffKeys = diffKeysInApplyOrder(jsonDiff);
          var key = null;
          for (var n = 0; n < diffKeys.length; n++) {
            key = diffKeys[n];
            var keyNum = parseInt(key[0] === "_" ? key.slice(1) : key, 10);
            if (isNaN(keyNum)) {
              console.error("Impossible key for model", key);
            }
            if (goog.isArray(jsonDiff[key])) {
              rutil.convert.applyDiffToModel(jsonDiff[key], model, keyNum);
            } else {
              rutil.convert.applyDiffToModel(jsonDiff[key], model.get(keyNum));
            }
          }
        }
      }
    }
  };
  rutil.convert.snapToServerState = function(editor, model) {
    var contentJSON = rutil.convert.yjsModelToJson(model.get(0));
    var editorElem = editor.getElement();
    goog.dom.removeChildren(editorElem);
    if (contentJSON != null && !(goog.isArray(contentJSON) && contentJSON.length === 0)) {
      var serverDOM = rutil.convert.jsonToDom(contentJSON);
      if (util.dom.getTagName(serverDOM) !== "en-note") {
        console.error("No en-note in server JSON!!");
      }
      while (serverDOM.firstChild) {
        editorElem.appendChild(serverDOM.firstChild);
      }
    }
    if (goog.isArray(contentJSON) && contentJSON.length !== 0) {
      editor.updateEmpty();
    }
  };
})();
goog.provide("uno.realtime.util.range");
goog.require("goog.dom");
goog.require("uno.util.dom");
(function() {
  var util = uno.util;
  var rutil = uno.realtime.util;
  var domToXPath = function(node) {
    var stopAt = "en-note";
    var path = "";
    while (util.dom.getTagName(node) !== stopAt) {
      if (node == null || node.parentNode == null) {
        console.warn("Ran out of parent nodes while getting xpath?");
        break;
      }
      if (node.nodeType === 1) {
        path = "/" + util.dom.getTagName(node) + "[" + util.dom.index(node) + "]" + path;
      } else {
        if (node.nodeType === 3) {
          path = "/" + "#text" + "[" + util.dom.index(node) + "]" + path;
        }
      }
      node = node.parentNode;
    }
    return path === "" ? "/" : path;
  };
  var xpathToDom = function(xpath) {
    var startAt = document.querySelector("en-note");
    if (startAt == null) {
      return document.body;
    }
    var pathSegments = xpath.split("/").slice(1);
    var segment = null;
    while (segment = pathSegments.shift()) {
      var offsetSegment = segment.split("[");
      var tagname = offsetSegment[0];
      var offset = parseInt(offsetSegment[1], 10);
      startAt = startAt.childNodes[offset];
      if (startAt && (startAt.nodeType === 1 && util.dom.getTagName(startAt) !== tagname || startAt.nodeType === 3 && tagname !== "#text")) {
        console.warn("Couldnt restore cursor perfectly, nodes moved.");
        break;
      }
    }
    return startAt;
  };
  rutil.range.saveUsingXPath = function(googRange) {
    if (googRange == null) {
      return null;
    }
    return {startPath:domToXPath(googRange.getStartNode()), endPath:domToXPath(googRange.getEndNode()), startOffset:googRange.getStartOffset(), endOffset:googRange.getEndOffset()};
  };
  rutil.range.restoreFromXPath = function(xpathRange) {
    if (xpathRange == null) {
      return null;
    }
    return goog.dom.Range.createFromNodes(xpathToDom(xpathRange.startPath), xpathRange.startOffset, xpathToDom(xpathRange.endPath), xpathRange.endOffset);
  };
})();
goog.provide("uno.realtime.Editing");
goog.require("uno.realtime.Plugin");
goog.require("uno.realtime.util.convert");
goog.require("uno.realtime.util.range");
goog.require("goog.functions");
goog.require("goog.dom");
goog.require("goog.array");
goog.require("goog.dom.Range");
goog.require("uno.util.dom");
(function() {
  var util = uno.util;
  var rutil = uno.realtime.util;
  var Editing = uno.realtime.Editing = function(yjsmodule) {
    uno.realtime.Plugin.call(this, yjsmodule);
  };
  goog.inherits(Editing, uno.realtime.Plugin);
  Editing.prototype.setupConfig = function(yjsconfig) {
    yjsconfig.share.content = "Array";
    return yjsconfig;
  };
  var exclusionToken = true;
  var mutualExclusive = function(f) {
    if (exclusionToken) {
      exclusionToken = false;
      try {
        f();
      } catch (e) {
        exclusionToken = true;
        throw new Error(e);
      }
      exclusionToken = true;
    }
  };
  Editing.prototype.setupObservation = function() {
    var self = this;
    var contentShare = self.yjsmodule.y.share.content;
    mutualExclusive(function() {
      rutil.convert.snapToServerState(self.yjsmodule.editor, contentShare);
    });
    var localUpdateHelper = function() {
      mutualExclusive(self.handleLocalUpdate.bind(self));
    };
    self.yjsmodule.editor.getElement().addEventListener("keydown", localUpdateHelper);
    self.yjsmodule.editor.listen("delayedchange", localUpdateHelper);
    contentShare.observeDeep(function(event) {
      mutualExclusive(self.handleRemoteUpdate.bind(self, event));
    });
  };
  var isModelElement = function(model) {
    return model.length && model.length === 3 && goog.isString(model.get(0)) && model.get(1).keys != null && model.get(2).length != null;
  };
  var getEventLocationModelAndDom = function(modelStart, domStart, path) {
    return {model:modelStart, dom:domStart};
  };
  Editing.prototype.handleRemoteUpdate = function(event) {
    if (event.path == null || event.path.length <= 0) {
      console.error("Invalid change event.path!", event);
      return;
    }
    console.log("REMOTE EVENT PATH IS:", event.path);
    var model = this.yjsmodule.y.share.content;
    var ennote = this.yjsmodule.editor.field;
    var changeLoc = getEventLocationModelAndDom(model, ennote, event.path);
    if (changeLoc == null) {
      return;
    }
    var xpathRange = rutil.range.saveUsingXPath(this.yjsmodule.editor.getRange());
    var serverJSON = rutil.convert.yjsModelToJson(changeLoc.model);
    var serverDOM = rutil.convert.jsonToDom(serverJSON[0]);
    if (serverDOM == null) {
      return;
    }
    if (util.dom.getTagName(serverDOM) === "en-note") {
      rutil.convert.snapToServerState(this.yjsmodule.editor, model);
    } else {
      var parent = changeLoc.dom.parentNode;
      if (parent != null) {
        parent.replaceChild(serverDOM, changeLoc.dom);
      } else {
        console.error("NO PARENT FOR REPLACE NODE??");
      }
    }
    var googRange = rutil.range.restoreFromXPath(xpathRange);
    if (googRange != null && googRange.getStartNode() != null) {
      try {
        googRange.select();
      } catch (e) {
        console.log("FAILED to re-apply range", e);
      }
    }
  };
  Editing.prototype.handleLocalUpdate = function() {
    var contentShare = this.yjsmodule.y.share.content;
    var localJSON = [rutil.convert.domToJson(this.yjsmodule.editor.field)];
    var serverJSON = rutil.convert.yjsModelToJson(contentShare);
    if (goog.isArray(serverJSON) && serverJSON.length === 0) {
      serverJSON = null;
    }
    var diff = window.jsondiffpatch.diff(serverJSON, localJSON);
    console.log("LOCAL DIFF:", diff);
    rutil.convert.applyDiffToModel(diff, contentShare);
  };
})();
goog.provide("uno.realtime.Connector");
goog.require("uno.realtime.Plugin");
var COMMAND_DELETE_REALTIME_NOTE = "realtime.deletenote";
(function() {
  var Connector = uno.realtime.Connector = function(yjsmodule) {
    uno.realtime.Plugin.call(this, yjsmodule);
  };
  goog.inherits(Connector, uno.realtime.Plugin);
  Connector.prototype.isSupportedCommand = function(command) {
    return command === COMMAND_DELETE_REALTIME_NOTE;
  };
  Connector.prototype.execCommandInternal = function(command, options) {
    if (command === COMMAND_DELETE_REALTIME_NOTE) {
      this.yjsmodule.y.connector.sendDeleteNoteMessage();
    }
  };
})();
goog.provide("uno.realtime.Ghost");
goog.require("uno.realtime.Plugin");
goog.require("uno.util.tools");
goog.require("goog.dom");
(function() {
  var ANIMATION_TRANSITION_DELAY = 300;
  var ANIMATION_TRANSITION_DELAY_LONG = 1200;
  var Ghost = uno.realtime.Ghost = function(yjsmodule) {
    uno.realtime.Plugin.call(this, yjsmodule);
    this.ghostSays = goog.dom.createDom("div", {class:"realtime-ghost-says"});
    this.ghostContainer = goog.dom.createDom("div", {class:"realtime-ghost"}, this.ghostSays);
    uno.util.tools.getContainer().appendChild(this.ghostContainer);
  };
  goog.inherits(Ghost, uno.realtime.Plugin);
  Ghost.prototype.setupObservation = function() {
    var self = this;
    var editor = this.yjsmodule.editor;
    editor.getElement().addEventListener("keydown", self.changeHandler.bind(self));
    editor.listen("delayedchange", self.changeHandler.bind(self));
  };
  Ghost.prototype.socketConnect = function(success, reason) {
    if (success) {
      this.ghostSays.setAttribute("class", "realtime-ghost-says online");
    } else {
      this.ghostSays.setAttribute("class", "realtime-ghost-says offline");
    }
  };
  Ghost.prototype.socketConnectError = function() {
    this.ghostSays.setAttribute("class", "realtime-ghost-says offline");
  };
  Ghost.prototype.socketReconnect = function() {
    this.ghostSays.setAttribute("class", "realtime-ghost-says reconnect");
    setTimeout(function() {
      this.ghostSays.setAttribute("class", "realtime-ghost-says online");
    }.bind(this), ANIMATION_TRANSITION_DELAY);
  };
  Ghost.prototype.socketReconnectAttempt = function() {
    this.ghostSays.setAttribute("class", "realtime-ghost-says reconnect-attempt");
  };
  var showDisconnect = function(ghostElement) {
    if (goog.dom.classlist.contains(ghostElement, "offline")) {
      return;
    }
    ghostElement.setAttribute("class", "realtime-ghost-says disconnect");
    setTimeout(function() {
      ghostElement.setAttribute("class", "realtime-ghost-says offline");
    }, ANIMATION_TRANSITION_DELAY);
  };
  Ghost.prototype.socketDisconnect = function() {
    showDisconnect(this.ghostSays);
  };
  Ghost.prototype.realtimeNoteSaved = function() {
    goog.dom.classlist.add(this.ghostContainer, "note-saved");
  };
  Ghost.prototype.changeHandler = function() {
    goog.dom.classlist.remove(this.ghostContainer, "note-saved");
  };
})();
goog.provide("uno.realtime.YJS");
goog.require("goog.string");
goog.require("goog.functions");
goog.require("uno.PluginManager");
goog.require("uno.realtime.Users");
goog.require("uno.realtime.Editing");
goog.require("uno.realtime.Connector");
goog.require("uno.realtime.Ghost");
goog.require("uno.util.crypto");
(function() {
  var YJSConfig = {db:{name:"memory", gc:false, repairCheckInterval:5000}, connector:{name:"websockets-client", room:"en-webrtc-test", socketHandlers:{}, utilities:{}, url:"http://rtes-p.kundures.com", generateUserId:false}, share:{}};
  var YJS = uno.realtime.YJS = function(editor, globalOptions) {
    var self = this;
    self.editor = editor;
    self.globalOptions = globalOptions;
    if (window.Y == null) {
      console.error("YJS not available, did you run npm install?");
      return;
    }
    self.PM = new uno.PluginManager;
    self.users = new uno.realtime.Users(self);
    self.PM.add(self.users);
    self.PM.add(new uno.realtime.Editing(self));
    self.PM.add(new uno.realtime.Connector(self));
    self.PM.add(new uno.realtime.Ghost(self));
    var metadata = self.globalOptions.metadata;
    if (metadata && metadata.guid) {
      YJSConfig.connector.room = metadata.guid;
    } else {
      var letters = "0123456789ABCDEF";
      var roomname = "no-guid-";
      for (var i = 0; i < 6; i++) {
        roomname += letters[Math.floor(Math.random() * 16)];
      }
      YJSConfig.connector.room = roomname;
    }
    console.log("YJS Using Room:", YJSConfig.connector.room);
    YJSConfig.connector.socketHandlers.connect = function(success, reason) {
      console.log("SOCKET EVENT:", "connect", success, reason);
      self.editor.dispatchEvent({type:"realtimeConnection", event:success ? "established" : "failed", reason:reason});
      if (success) {
        self.editor.dispatchEvent({type:"contentloaded"});
      }
      self.PM.forEach(function(plugin) {
        self.PM.tryToRun(plugin, "socketConnect", [success, reason]);
      });
    };
    YJSConfig.connector.socketHandlers.connectError = function(errorCode, errorDescription) {
      console.log("SOCKET EVENT:", "connect_error", errorCode, errorDescription);
      self.editor.dispatchEvent({type:"realtimeErrorHandler", code:errorCode, description:errorDescription});
      self.PM.forEach(function(plugin) {
        self.PM.tryToRun(plugin, "socketConnectError", [errorCode, errorDescription]);
      });
    };
    YJSConfig.connector.socketHandlers.reconnect = function(numAttempts) {
      console.log("SOCKET EVENT:", "reconnect(ed)", numAttempts);
      self.PM.forEach(function(plugin) {
        self.PM.tryToRun(plugin, "socketReconnect", [numAttempts]);
      });
    };
    YJSConfig.connector.socketHandlers.reconnectAttempt = function() {
      console.log("SOCKET EVENT:", "reconnect_attempt");
      self.PM.forEach(function(plugin) {
        self.PM.tryToRun(plugin, "socketReconnectAttempt");
      });
    };
    YJSConfig.connector.socketHandlers.reconnectError = function(err) {
      console.log("SOCKET EVENT:", "reconnect_error", err);
      self.PM.forEach(function(plugin) {
        self.PM.tryToRun(plugin, "socketReconnectError", [err]);
      });
    };
    YJSConfig.connector.socketHandlers.disconnect = function() {
      console.log("SOCKET EVENT:", "disconnect");
      self.PM.forEach(function(plugin) {
        self.PM.tryToRun(plugin, "socketDisconnect");
      });
    };
    YJSConfig.connector.utilities.noteSavedNotification = function() {
      console.log("CE-YJS NOTIFICATION:", "note saved");
      self.PM.forEach(function(plugin) {
        self.PM.tryToRun(plugin, "realtimeNoteSaved");
      });
    };
    YJSConfig.connector.utilities.resetYjsModel = function() {
      console.log("CE-YJS NOTIFICATION:", "reload");
      self.editor.dispatchEvent({type:"reload"});
    };
    YJSConfig.connector.utilities.handshakeTimeoutHandler = function() {
      self.editor.dispatchEvent({type:"realtimeConnection", event:"failed"});
    };
    if (metadata && metadata.authToken) {
      YJSConfig.connector.authToken = metadata.authToken;
      YJSConfig.connector.serviceURL = metadata.serviceURL;
      YJSConfig.connector.url = metadata.url || YJSConfig.connector.url;
      YJSConfig.connector.userName = metadata.name;
      window.YINFO = {guid:metadata.guid, name:metadata.name, authToken:metadata.authToken, serviceURL:metadata.serviceURL, url:YJSConfig.connector.url, debugURL:"http://localhost:8888/demo/index.html?client=mac" + "&room=" + metadata.guid + "&authToken=" + metadata.authToken + "&serviceURL=" + metadata.serviceURL + "&name=DBG-" + goog.string.urlEncode(metadata.name)};
    }
    self.PM.forEach(function(plugin) {
      var update = self.PM.tryToRun(plugin, "setupConfig", [YJSConfig]);
      if (update != null) {
        YJSConfig = update;
      }
    });
    var yjsErrorHandler = function(error) {
      console.error("There is a critical error has happened in YJS. Reload editor to reset y-model.");
      self.editor.dispatchEvent({type:"reload"});
    };
    console.log("Launching YJS with config", YJSConfig);
    window.Y(YJSConfig).then(function(y) {
      console.log("YJS LOADED!!");
      window.YINSTANCE = self.y = y;
      y.on("error", yjsErrorHandler);
      self.editor.execCommand("active", true);
      self.execCommand = self.PM.execCommand.bind(self.PM);
      self.queryCommandEnabled = self.PM.queryCommandEnabled.bind(self.PM);
      self.queryCommandValue = self.PM.queryCommandValue.bind(self.PM);
      self.isSupportedCommand = self.PM.isSupportedCommand.bind(self.PM);
      self.PM.forEach(function(plugin) {
        self.PM.tryToRun(plugin, "setupObservation");
      });
    }).catch(function(reason) {
      self.editor.dispatchEvent({type:"realtimeConnection", event:"failed", reason:reason});
      console.error("Failed to connect to YJS:", reason);
    });
  };
  YJS.prototype.editor = null;
  YJS.prototype.globalOptions = null;
  YJS.prototype.y = null;
  YJS.prototype.PM = null;
  YJS.prototype.execCommand = goog.functions.FALSE;
  YJS.prototype.queryCommandEnabled = goog.functions.FALSE;
  YJS.prototype.queryCommandValue = goog.functions.NULL;
  YJS.prototype.isSupportedCommand = goog.functions.FALSE;
})();
goog.provide("uno.api.ce");
goog.provide("EN");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.classlist");
goog.require("goog.style");
goog.require("goog.editor.Command");
goog.require("goog.events");
goog.require("goog.object");
goog.require("uno.api.celogger");
goog.require("uno.Auth");
goog.require("uno.Cache");
goog.require("uno.debug");
goog.require("uno.Editor");
goog.require("uno.template.Template");
goog.require("uno.Router");
goog.require("uno.context.Context");
goog.require("uno.context.Info");
goog.require("uno.context.Upsell");
goog.require("uno.PluginManager");
goog.require("uno.realtime.YJS");
(function() {
  EN.version = "1.28.2184";
  var options;
  var log = goog.debug.Logger.getLogger("uno.api.ce");
  var ted = null;
  window.DEBUG = false;
  window.onerror = function(error) {
    log.severe("Unhandled error: " + (error.stack || error));
    return false;
  };
  var consoleLogger = new uno.ConsoleLogger({cachingEnabled:true});
  consoleLogger.setCapturing(true);
  var purgeLogsOnSetup = false;
  var Editor = uno.Editor;
  var Template = uno.template.Template;
  var rxRedundantPrefixes = /^(?:rte|content|richlinks)\./;
  var router = new uno.Router({sendMessage:function(name, info) {
    return EN.notification(name, info);
  }, routesToHost:{requestAuth:{identifier:"serviceName"}, showOptions:{identifier:"correlationId"}, getFromCache:{identifier:"correlationId"}, saveInCache:{identifier:"correlationId", oneway:true}}, routesFromHost:{authtoken:{identifier:"service"}, optionselected:{identifier:"showEvent.correlationId"}, cacheddata:{identifier:"cacheRequest.correlationId"}}});
  var cache = new uno.Cache({router:router});
  var auth = new uno.Auth({router:router});
  var PM = new uno.PluginManager;
  EN.logs = consoleLogger;
  EN.getLogs = function() {
    return EN.logs.cache.map(function(record) {
      return record.formattedText;
    }).join("\n");
  };
  EN.setup = function(opt) {
    opt = opt || {};
    options = goog.isObject(opt) ? opt : JSON.parse(opt);
    DEBUG = options.debug === true;
    start("EN.setup");
    EN.cleanup();
    var id;
    options.logging = options.logging || {};
    options.logging.consoleLogger = consoleLogger;
    configLogging(options);
    cache.diskEnabled = options.rte && options.rte.richLink && options.rte.richLinksCaching;
    goog.object.extend(options, {cache:cache, auth:auth, router:router});
    id = options.id || "en-note";
    if (DEBUG) {
      initDebug();
    } else {
      clearDebug();
    }
    window.ed = new Editor(id, options);
    ted = new Template(id, options);
    ed.listen(Editor.EventType.DELAYEDCHANGE, onEditorDelayedChange);
    ed.listen(Editor.EventType.FOCUS, onEditorFocus);
    ed.listen(Editor.EventType.BLUR, onEditorBlur);
    ed.listen(Editor.EventType.STYLE_CHANGED, onEditorStyleChanged);
    ed.listen(Editor.EventType.PRINT_READY, onPrintReady);
    ed.listen(Editor.EventType.ENCRYPT, onEncrypt);
    ed.listen(Editor.EventType.DECRYPT, onDecrypt);
    ed.listen(Editor.EventType.CONTENT_LOADED, onEditorContentLoaded);
    ed.listen(Editor.EventType.ACTION_DENIED, onActionDenied);
    if (DEBUG) {
      ed.listen(Editor.EventType.EDIT_MODE_CHANGED, onEditorEditModeChanged);
    }
    if (options.rte != null) {
      options.rte = options.rte || {};
      options.rte.imageConfig = options.rte.imageConfig || {};
      if (options.rte.imageConfig.imageClickEvents) {
        ed.listen(Editor.EventType.IMAGE_CLICK, onImageClick);
        ed.listen(Editor.EventType.IMAGE_DOUBLECLICK, onImageDoubleClick);
      }
      if (options.rte.imageConfig.annotate) {
        ed.listen(Editor.EventType.IMAGE_ANNOTATE, onImageEvent);
      }
      if (options.rte.imageConfig.preview) {
        ed.listen(Editor.EventType.IMAGE_PREVIEW, onImageEvent);
      }
      if (options.rte.imageConfig.rotate) {
        ed.listen(Editor.EventType.IMAGE_ROTATE, onImageEvent);
      }
      ed.listen(Editor.EventType.LINK_CLICK, onLinkClick);
      ed.listen(Editor.EventType.CRYPT_DOUBLECLICK, onCryptDoubleClick);
    }
    options.rte.trackStateChanges = (options.rte.trackStateChanges || []).concat(["bold", "italic", "underline", "highlight", "strikethrough", "subscript", "superscript"]);
    options.rte.trackValueChanges = (options.rte.trackValueChanges || []).concat(["justifyleft", "justifyright", "justifycenter", "fontsize", "fontname", "forecolor"]);
    goog.array.removeDuplicates(options.rte.trackStateChanges);
    goog.array.removeDuplicates(options.rte.trackValueChanges);
    ed.setup();
    var rteElement = ed.getElement();
    var templateElement = ted.getElement();
    if (options.template != null) {
      options.template = options.template || {};
      if (!options.template.html && !options.template.enml && options.rte) {
        options.template.html = options.html || options.rte.html || "";
        options.template.enml = options.enml || options.rte.enml || "";
      }
      ed.clearListeners();
      ted.setup(options);
      if (rteElement) {
        goog.style.setElementShown(rteElement, false);
      }
      if (templateElement) {
        goog.style.setElementShown(templateElement, true);
      }
    } else {
      if (rteElement) {
        goog.style.setElementShown(rteElement, true);
      }
      if (templateElement) {
        goog.style.setElementShown(templateElement, false);
      }
    }
    start("Setup Context");
    PM.add(new uno.context.Context(options.context || {}));
    stop("Setup Context");
    start("Setup Context Upsell");
    PM.add(new uno.context.Upsell(options["context-upsell"] || {}));
    stop("Setup Context Upsell");
    start("Setup Context Info");
    PM.add(new uno.context.Info(options["context-info"] || {}));
    stop("Setup Context Info");
    PM.add(ted);
    PM.add(ed);
    if (options.realtime != null) {
      EN.setupRealtime(options);
    }
    EN.notification("setupDone", {module:"document"});
    if (DEBUG) {
      updateDebug();
    }
    stop("EN.setup");
    return true;
  };
  EN.setupRealtime = function(opt) {
    var ed = window.ed;
    if (!options || !ed || !ed.isSetup) {
      return;
    }
    EN.cleanupRealtime();
    ed.listen("usnUpdated", onUSNUpdated);
    ed.listen("realtimeConnection", onRealtimeConnection);
    ed.listen("realtimeErrorHandler", onRealtimeErrorHandler);
    ed.listen("reload", onReload);
    opt = opt || {};
    options = goog.isObject(opt) ? opt : JSON.parse(opt);
    EN.realtimeModule = new uno.realtime.YJS(ed, options);
    PM.add(EN.realtimeModule);
  };
  EN.cleanupRealtime = function() {
    var ed = window.ed;
    PM.filterRemove(function(module) {
      return module !== EN.realtimeModule;
    });
    ed.unlisten("usnUpdated");
    ed.unlisten("realtimeConnection");
    ed.unlisten("realtimeErrorHandler");
    ed.unlisten("reload");
    EN.realtimeModule = null;
  };
  EN.cleanup = function() {
    start("EN.cleanup");
    if (window.ed && goog.isFunction(window.ed.cleanup)) {
      window.ed.cleanup();
    }
    if (ted && goog.isFunction(ted.cleanup)) {
      ted.cleanup();
    }
    if (PM) {
      PM.clear();
    }
    document.body.scrollLeft = 0;
    document.body.scrollTop = 0;
    stop("EN.cleanup");
    return true;
  };
  function setLogLevel(level) {
    var rootLogger = goog.debug.Logger.getLogger(goog.debug.Logger.ROOT_LOGGER_NAME);
    var googLevel = goog.debug.Logger.Level.getPredefinedLevel(level || "ALL");
    rootLogger.setLevel(googLevel);
  }
  EN.setLogLevel = setLogLevel;
  EN.getLogLevel = function() {
    var rootLogger = goog.debug.Logger.getLogger(goog.debug.Logger.ROOT_LOGGER_NAME);
    return rootLogger.getLevel().name;
  };
  function configLogging(opt) {
    opt.logging = opt.logging || {};
    opt.logging.level = opt.logging.level || "CONFIG";
    setLogLevel(opt.logging.level);
    consoleLogger.configure({cachingEnabled:opt.logging.cachingEnabled != null ? opt.logging.cachingEnabled : true, maxEntries:typeof opt.logging.maxEntries !== "undefined" ? opt.logging.maxEntries : 1000});
    purgeLogsOnSetup = opt.logging.purgeLogsOnSetup != null ? opt.logging.purgeLogsOnSetup : true;
  }
  EN.execCommand = function(command, value, opt) {
    var normalizedCommand = filterCommandPrefix(command);
    var parsedValue = valueToObject(value);
    var parsedOpt = valueToObject(opt);
    if (router.fromHost(normalizedCommand, parsedValue)) {
      return true;
    }
    return PM.execCommand(normalizedCommand, parsedValue, parsedOpt, true);
  };
  EN.queryCommandEnabled = function(command, opt) {
    return PM.queryCommandEnabled(filterCommandPrefix(command), opt, true);
  };
  EN.queryCommandValue = function(command, opt) {
    var normalizedCommand = filterCommandPrefix(command);
    var parsedOptions = valueToObject(opt);
    var result = PM.queryCommandValue(normalizedCommand, parsedOptions, true);
    if (options && options.realtime != null && normalizedCommand === "content") {
      try {
        var obj = JSON.parse(result);
        var realtimeUSN = PM.queryCommandValue("realtime-usn");
        if (realtimeUSN) {
          obj.realtimeUSN = realtimeUSN;
        }
        result = JSON.stringify(obj);
      } catch (e) {
      }
    }
    if (DEBUG) {
      showDebugDirty();
    }
    return result;
  };
  EN.queryCommandState = queryCommandStateInternal;
  function queryCommandStateInternal(command, opt) {
    var normalizedCommand = filterCommandPrefix(command);
    var result = PM.queryCommandValue(normalizedCommand, opt || null);
    if (result === "true") {
      result = true;
    }
    if (result === "false") {
      result = false;
    }
    if (normalizedCommand === "justifyleft") {
      result = result === "left";
    } else {
      if (normalizedCommand === "justifycenter") {
        result = result === "center";
      } else {
        if (normalizedCommand === "justifyright") {
          result = result === "right";
        } else {
          if (normalizedCommand === "justifyfull") {
            result = result === "justify";
          } else {
            if (normalizedCommand === "insertorderedlist") {
              result = result === "ol";
            } else {
              if (normalizedCommand === "insertunorderedlist") {
                result = result === "ul";
              }
            }
          }
        }
      }
    }
    return !!result;
  }
  EN.fireUpAndroid = function() {
    if (document && document.body) {
      if (!window.noteEditor || !noteEditor.onWebViewLoaded) {
        log.severe("Native did not set up `noteEditor` correctly");
      } else {
        noteEditor.onWebViewLoaded();
      }
    } else {
      if (DEBUG) {
        log.info("Will wait another while until document.body is ready");
      }
      window.setTimeout(EN.fireUpAndroid, 100);
    }
  };
  EN.enablePrint = function(localization, opt) {
    EN.execCommand("printpreview", localization, opt);
  };
  EN.disablePrint = function() {
    return true;
  };
  EN.getVersion = function() {
    return EN.version;
  };
  EN.notification = function(name, info) {
    setTimeout(EN.notify.bind(EN, name, info));
  };
  EN.notify = function(name, info) {
    info = info || {};
    info.version = "1.0";
    if (window.Evernote && Evernote.handleJavascriptEvent) {
      Evernote.handleJavascriptEvent(name, JSON.stringify({name:name, info:info}));
    } else {
      if (window.evernoteClient && evernoteClient.postNotification) {
        evernoteClient.postNotification(name, JSON.stringify(info));
      } else {
        if (window.noteEditor && window.noteEditor.handleJavascriptEvent) {
          window.noteEditor.handleJavascriptEvent(name, JSON.stringify(info) || null);
        } else {
          if (window.evernoteClient && evernoteClient.handleNotificationInfo) {
            evernoteClient.handleNotificationInfo(name, info);
          }
        }
      }
    }
  };
  function valueToObject(value) {
    if (typeof value === "string" && value.length > 0 && (value[0] === "{" || value[0] === "[")) {
      try {
        return JSON.parse(value);
      } catch (err$14) {
        log.fine(err$14.stack || err$14);
      }
    }
    return value;
  }
  function filterCommandPrefix(command) {
    return command.replace(rxRedundantPrefixes, "");
  }
  function onEditorDelayedChange() {
    EN.notification("contentChanged", {module:"content"});
    if (DEBUG) {
      showDebugDirty();
    }
  }
  function onEditorFocus() {
    EN.notification("focusChanged", {focus:true, module:"content"});
    if (DEBUG) {
      updateDebug();
    }
  }
  function onEditorBlur() {
    EN.notification("focusChanged", {focus:false, module:"content"});
    if (DEBUG) {
      updateDebug();
    }
  }
  function onEditorStyleChanged(e) {
    updateStyleChanges.call(this, e.style);
  }
  function onPrintReady() {
    EN.notification("printReady", {module:"print"});
  }
  function onEncrypt(e) {
    EN.notification("encrypt", e.cryptInfo);
  }
  function onDecrypt(e) {
    EN.notification("decrypt", e.cryptInfo);
  }
  function onEditorContentLoaded() {
    EN.notification("contentLoaded", {module:"content"});
  }
  function onEditorEditModeChanged() {
    if (DEBUG) {
      updateDebug();
    }
  }
  function onActionDenied(e) {
    EN.notification("actionDenied", e.reason);
  }
  function onImageClick(e) {
    EN.notification("clicked", {name:e.name, src:e.src, tagname:e.tagname, reference:e.reference});
  }
  function onImageDoubleClick(e) {
    EN.notification("doubleClicked", {name:e.name, src:e.src, tagname:e.tagname, reference:e.reference});
  }
  function onImageEvent(e) {
    EN.notification(e.type, {module:e.module, src:e.src, tagname:e.tagname});
  }
  function onLinkClick(e) {
    EN.notification("openLink", e.data);
  }
  function onUSNUpdated(e) {
    EN.notification("usnUpdated", e.usn);
  }
  function onRealtimeConnection(e) {
    EN.notification("realtimeConnection", {event:e.event, reason:e.reason});
  }
  function onRealtimeErrorHandler(e) {
    EN.notification("realtimeErrorHandler", {code:e.code, description:e.description});
  }
  function onReload(e) {
    EN.notification("reload");
  }
  function onCryptDoubleClick(e) {
    EN.notification("doubleClicked", {id:e.id, src:e.src});
  }
  function updateStyleChanges(styleOverrides) {
    var rte = options.rte;
    var style = ed.context.style;
    var hasChanges = false;
    styleOverrides = styleOverrides || {state:{}, value:{}, enabled:{}};
    if (rte && goog.isArray(rte.trackStateChanges)) {
      rte.trackStateChanges.map(filterCommandPrefix).forEach(function(command) {
        var result = typeof styleOverrides.state[command] !== "undefined" ? styleOverrides.state[command] : queryCommandStateInternal(command);
        if (style.state[command] !== result) {
          style.state[command] = result;
          hasChanges = true;
        }
      });
    }
    if (rte && goog.isArray(rte.trackValueChanges)) {
      rte.trackValueChanges.map(filterCommandPrefix).forEach(function(command) {
        var result = typeof styleOverrides.value[command] !== "undefined" ? styleOverrides.value[command] : ed.queryCommandValue(command);
        if (style.value[command] !== result) {
          style.value[command] = result;
          hasChanges = true;
        }
      });
    }
    if (rte && goog.isArray(rte.trackEnabledChanges)) {
      rte.trackEnabledChanges.map(filterCommandPrefix).forEach(function(command) {
        var result = typeof styleOverrides.enabled[command] !== "undefined" ? styleOverrides.enabled[command] : ed.queryCommandEnabled(command);
        if (style.enabled[command] !== result) {
          style.enabled[command] = result;
          hasChanges = true;
        }
      });
    }
    if (hasChanges) {
      style.module = "content";
      EN.notification("styleChanged", style);
    }
  }
  function initDebug() {
    if (document.querySelector("en-debug")) {
      updateDebug();
    } else {
      goog.dom.appendChild(document.body, goog.dom.createDom("en-debug", null, "CE " + EN.version));
    }
  }
  function clearDebug() {
    goog.dom.removeNode(document.querySelector("en-debug"));
  }
  function updateDebug() {
    var endebug = document.querySelector("en-debug");
    if (!endebug || !window.ed) {
      return;
    }
    if (ed.inEditMode()) {
      goog.dom.classlist.add(endebug, "editmode");
    } else {
      goog.dom.classlist.remove(endebug, "editmode");
    }
    if (ed.strictMode) {
      endebug.textContent = "CE " + EN.version + " (strict)";
    } else {
      endebug.textContent = "CE " + EN.version;
    }
    if (ed.isFocused()) {
      goog.dom.classlist.add(endebug, "focused");
    } else {
      goog.dom.classlist.remove(endebug, "focused");
    }
  }
  function showDebugDirty() {
    var endebug = document.querySelector("en-debug");
    if (endebug && window.ed) {
      if (ed.dirty) {
        goog.dom.classlist.add(endebug, "dirty");
      } else {
        goog.dom.classlist.remove(endebug, "dirty");
      }
      if (ed.strictMode) {
        endebug.textContent = "CE " + EN.version + " (strict)";
      } else {
        endebug.textContent = "CE " + EN.version;
      }
    }
  }
  uno.api.celogger.wrap(EN);
  (function() {
    var setup = EN.setup;
    EN.setup = function(opt) {
      if (purgeLogsOnSetup) {
        consoleLogger.clear();
      }
      return setup(opt);
    };
  })();
  window.enLoadState = "didLoad";
  goog.events.listenOnce(document, "DOMContentLoaded", function(e) {
    EN.notification("ready");
  });
})();

