// ce-1.19.1543 a9e6020ab13c935a354c3aad5501226a5301dce1
// 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(t){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var e;"undefined"!=typeof window?e=window:"undefined"!=typeof global?e=global:"undefined"!=typeof self&&(e=self),e.Promise=t()}}(function(){var t,e,n;return function r(t,e,n){function i(s,a){if(!e[s]){if(!t[s]){var c="function"==typeof _dereq_&&_dereq_;if(!a&&c)return c(s,!0);if(o)return o(s,!0);var l=new Error("Cannot find module '"+s+"'");throw l.code="MODULE_NOT_FOUND",l}var u=e[s]={exports:{}};t[s][0].call(u.exports,function(e){var n=t[s][1][e];return i(n?n:e)},u,u.exports,r,t,e,n)}return e[s].exports}for(var o="function"==typeof _dereq_&&_dereq_,s=0;s<n.length;s++)i(n[s]);return i}({1:[function(t,e,n){"use strict";e.exports=function(t){function e(t){var e=new n(t),r=e.promise();return e.setHowMany(1),e.setUnwrap(),e.init(),r}var n=t._SomePromiseArray;t.any=function(t){return e(t)},t.prototype.any=function(){return e(this)}}},{}],2:[function(t,e,n){"use strict";function r(){this._customScheduler=!1,this._isTickUsed=!1,this._lateQueue=new u(16),this._normalQueue=new u(16),this._haveDrainedQueues=!1,this._trampolineEnabled=!0;var t=this;this.drainQueues=function(){t._drainQueues()},this._schedule=l}function i(t,e,n){this._lateQueue.push(t,e,n),this._queueTick()}function o(t,e,n){this._normalQueue.push(t,e,n),this._queueTick()}function s(t){this._normalQueue._pushOne(t),this._queueTick()}var a;try{throw new Error}catch(c){a=c}var l=t("./schedule"),u=t("./queue"),p=t("./util");r.prototype.setScheduler=function(t){var e=this._schedule;return this._schedule=t,this._customScheduler=!0,e},r.prototype.hasCustomScheduler=function(){return this._customScheduler},r.prototype.enableTrampoline=function(){this._trampolineEnabled=!0},r.prototype.disableTrampolineIfNecessary=function(){p.hasDevTools&&(this._trampolineEnabled=!1)},r.prototype.haveItemsQueued=function(){return this._isTickUsed||this._haveDrainedQueues},r.prototype.fatalError=function(t,e){e?(process.stderr.write("Fatal "+(t instanceof Error?t.stack:t)+"\n"),process.exit(2)):this.throwLater(t)},r.prototype.throwLater=function(t,e){if(1===arguments.length&&(e=t,t=function(){throw e}),"undefined"!=typeof setTimeout)setTimeout(function(){t(e)},0);else try{this._schedule(function(){t(e)})}catch(n){throw new Error("No async scheduler available\n\n    See http://goo.gl/MqrFmX\n")}},p.hasDevTools?(r.prototype.invokeLater=function(t,e,n){this._trampolineEnabled?i.call(this,t,e,n):this._schedule(function(){setTimeout(function(){t.call(e,n)},100)})},r.prototype.invoke=function(t,e,n){this._trampolineEnabled?o.call(this,t,e,n):this._schedule(function(){t.call(e,n)})},r.prototype.settlePromises=function(t){this._trampolineEnabled?s.call(this,t):this._schedule(function(){t._settlePromises()})}):(r.prototype.invokeLater=i,r.prototype.invoke=o,r.prototype.settlePromises=s),r.prototype.invokeFirst=function(t,e,n){this._normalQueue.unshift(t,e,n),this._queueTick()},r.prototype._drainQueue=function(t){for(;t.length()>0;){var e=t.shift();if("function"==typeof e){var n=t.shift(),r=t.shift();e.call(n,r)}else e._settlePromises()}},r.prototype._drainQueues=function(){this._drainQueue(this._normalQueue),this._reset(),this._haveDrainedQueues=!0,this._drainQueue(this._lateQueue)},r.prototype._queueTick=function(){this._isTickUsed||(this._isTickUsed=!0,this._schedule(this.drainQueues))},r.prototype._reset=function(){this._isTickUsed=!1},e.exports=r,e.exports.firstLineError=a},{"./queue":26,"./schedule":29,"./util":36}],3:[function(t,e,n){"use strict";e.exports=function(t,e,n,r){var i=!1,o=function(t,e){this._reject(e)},s=function(t,e){e.promiseRejectionQueued=!0,e.bindingPromise._then(o,o,null,this,t)},a=function(t,e){0===(50397184&this._bitField)&&this._resolveCallback(e.target)},c=function(t,e){e.promiseRejectionQueued||this._reject(t)};t.prototype.bind=function(o){i||(i=!0,t.prototype._propagateFrom=r.propagateFromFunction(),t.prototype._boundValue=r.boundValueFunction());var l=n(o),u=new t(e);u._propagateFrom(this,1);var p=this._target();if(u._setBoundTo(l),l instanceof t){var h={promiseRejectionQueued:!1,promise:u,target:p,bindingPromise:l};p._then(e,s,void 0,u,h),l._then(a,c,void 0,u,h),u._setOnCancel(l)}else u._resolveCallback(p);return u},t.prototype._setBoundTo=function(t){void 0!==t?(this._bitField=2097152|this._bitField,this._boundTo=t):this._bitField=-2097153&this._bitField},t.prototype._isBound=function(){return 2097152===(2097152&this._bitField)},t.bind=function(e,n){return t.resolve(n).bind(e)}}},{}],4:[function(t,e,n){"use strict";function r(){try{Promise===o&&(Promise=i)}catch(t){}return o}var i;"undefined"!=typeof Promise&&(i=Promise);var o=t("./promise")();o.noConflict=r,e.exports=o},{"./promise":22}],5:[function(t,e,n){"use strict";var r=Object.create;if(r){var i=r(null),o=r(null);i[" size"]=o[" size"]=0}e.exports=function(e){function n(t,n){var r;if(null!=t&&(r=t[n]),"function"!=typeof r){var i="Object "+a.classString(t)+" has no method '"+a.toString(n)+"'";throw new e.TypeError(i)}return r}function r(t){var e=this.pop(),r=n(t,e);return r.apply(t,this)}function i(t){return t[this]}function o(t){var e=+this;return 0>e&&(e=Math.max(0,e+t.length)),t[e]}var s,a=t("./util"),c=a.canEvaluate;a.isIdentifier;e.prototype.call=function(t){var e=[].slice.call(arguments,1);return e.push(t),this._then(r,void 0,void 0,e,void 0)},e.prototype.get=function(t){var e,n="number"==typeof t;if(n)e=o;else if(c){var r=s(t);e=null!==r?r:i}else e=i;return this._then(e,void 0,void 0,t,void 0)}}},{"./util":36}],6:[function(t,e,n){"use strict";e.exports=function(e,n,r,i){var o=t("./util"),s=o.tryCatch,a=o.errorObj,c=e._async;e.prototype["break"]=e.prototype.cancel=function(){if(!i.cancellation())return this._warn("cancellation is disabled");for(var t=this,e=t;t._isCancellable();){if(!t._cancelBy(e)){e._isFollowing()?e._followee().cancel():e._cancelBranched();break}var n=t._cancellationParent;if(null==n||!n._isCancellable()){t._isFollowing()?t._followee().cancel():t._cancelBranched();break}t._isFollowing()&&t._followee().cancel(),t._setWillBeCancelled(),e=t,t=n}},e.prototype._branchHasCancelled=function(){this._branchesRemainingToCancel--},e.prototype._enoughBranchesHaveCancelled=function(){return void 0===this._branchesRemainingToCancel||this._branchesRemainingToCancel<=0},e.prototype._cancelBy=function(t){return t===this?(this._branchesRemainingToCancel=0,this._invokeOnCancel(),!0):(this._branchHasCancelled(),this._enoughBranchesHaveCancelled()?(this._invokeOnCancel(),!0):!1)},e.prototype._cancelBranched=function(){this._enoughBranchesHaveCancelled()&&this._cancel()},e.prototype._cancel=function(){this._isCancellable()&&(this._setCancelled(),c.invoke(this._cancelPromises,this,void 0))},e.prototype._cancelPromises=function(){this._length()>0&&this._settlePromises()},e.prototype._unsetOnCancel=function(){this._onCancelField=void 0},e.prototype._isCancellable=function(){return this.isPending()&&!this._isCancelled()},e.prototype.isCancellable=function(){return this.isPending()&&!this.isCancelled()},e.prototype._doInvokeOnCancel=function(t,e){if(o.isArray(t))for(var n=0;n<t.length;++n)this._doInvokeOnCancel(t[n],e);else if(void 0!==t)if("function"==typeof t){if(!e){var r=s(t).call(this._boundValue());r===a&&(this._attachExtraTrace(r.e),c.throwLater(r.e))}}else t._resultCancelled(this)},e.prototype._invokeOnCancel=function(){var t=this._onCancel();this._unsetOnCancel(),c.invoke(this._doInvokeOnCancel,this,t)},e.prototype._invokeInternalOnCancel=function(){this._isCancellable()&&(this._doInvokeOnCancel(this._onCancel(),!0),this._unsetOnCancel())},e.prototype._resultCancelled=function(){this.cancel()}}},{"./util":36}],7:[function(t,e,n){"use strict";e.exports=function(e){function n(t,n,a){return function(c){var l=a._boundValue();t:for(var u=0;u<t.length;++u){var p=t[u];if(p===Error||null!=p&&p.prototype instanceof Error){if(c instanceof p)return o(n).call(l,c)}else if("function"==typeof p){var h=o(p).call(l,c);if(h===s)return h;if(h)return o(n).call(l,c)}else if(r.isObject(c)){for(var f=i(p),_=0;_<f.length;++_){var d=f[_];if(p[d]!=c[d])continue t}return o(n).call(l,c)}}return e}}var r=t("./util"),i=t("./es5").keys,o=r.tryCatch,s=r.errorObj;return n}},{"./es5":13,"./util":36}],8:[function(t,e,n){"use strict";e.exports=function(t){function e(){this._trace=new e.CapturedTrace(r())}function n(){return i?new e:void 0}function r(){var t=o.length-1;return t>=0?o[t]:void 0}var i=!1,o=[];return t.prototype._promiseCreated=function(){},t.prototype._pushContext=function(){},t.prototype._popContext=function(){return null},t._peekContext=t.prototype._peekContext=function(){},e.prototype._pushContext=function(){void 0!==this._trace&&(this._trace._promiseCreated=null,o.push(this._trace))},e.prototype._popContext=function(){if(void 0!==this._trace){var t=o.pop(),e=t._promiseCreated;return t._promiseCreated=null,e}return null},e.CapturedTrace=null,e.create=n,e.deactivateLongStackTraces=function(){},e.activateLongStackTraces=function(){var n=t.prototype._pushContext,o=t.prototype._popContext,s=t._peekContext,a=t.prototype._peekContext,c=t.prototype._promiseCreated;e.deactivateLongStackTraces=function(){t.prototype._pushContext=n,t.prototype._popContext=o,t._peekContext=s,t.prototype._peekContext=a,t.prototype._promiseCreated=c,i=!1},i=!0,t.prototype._pushContext=e.prototype._pushContext,t.prototype._popContext=e.prototype._popContext,t._peekContext=t.prototype._peekContext=r,t.prototype._promiseCreated=function(){var t=this._peekContext();t&&null==t._promiseCreated&&(t._promiseCreated=this)}},e}},{}],9:[function(t,e,n){"use strict";e.exports=function(e,n){function r(t,e){return{promise:e}}function i(){return!1}function o(t,e,n){var r=this;try{t(e,n,function(t){if("function"!=typeof t)throw new TypeError("onCancel must be a function, got: "+H.toString(t));r._attachCancellationCallback(t)})}catch(i){return i}}function s(t){if(!this._isCancellable())return this;var e=this._onCancel();void 0!==e?H.isArray(e)?e.push(t):this._setOnCancel([e,t]):this._setOnCancel(t)}function a(){return this._onCancelField}function c(t){this._onCancelField=t}function l(){this._cancellationParent=void 0,this._onCancelField=void 0}function u(t,e){if(0!==(1&e)){this._cancellationParent=t;var n=t._branchesRemainingToCancel;void 0===n&&(n=0),t._branchesRemainingToCancel=n+1}0!==(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}function p(t,e){0!==(2&e)&&t._isBound()&&this._setBoundTo(t._boundTo)}function h(){var t=this._boundTo;return void 0!==t&&t instanceof e?t.isFulfilled()?t.value():void 0:t}function f(){this._trace=new S(this._peekContext())}function _(t,e){if(N(t)){var n=this._trace;if(void 0!==n&&e&&(n=n._parent),void 0!==n)n.attachExtraTrace(t);else if(!t.__stackCleaned__){var r=j(t);H.notEnumerableProp(t,"stack",r.message+"\n"+r.stack.join("\n")),H.notEnumerableProp(t,"__stackCleaned__",!0)}}}function d(t,e,n,r,i){if(void 0===t&&null!==e&&W){if(void 0!==i&&i._returnedNonUndefined())return;if(0===(65535&r._bitField))return;n&&(n+=" ");var o="",s="";if(e._trace){for(var a=e._trace.stack.split("\n"),c=w(a),l=c.length-1;l>=0;--l){var u=c[l];if(!U.test(u)){var p=u.match(M);p&&(o="at "+p[1]+":"+p[2]+":"+p[3]+" ");break}}if(c.length>0)for(var h=c[0],l=0;l<a.length;++l)if(a[l]===h){l>0&&(s="\n"+a[l-1]);break}}var f="a promise was created in a "+n+"handler "+o+"but was not returned from it, see http://goo.gl/rRqMUw"+s;r._warn(f,!0,e)}}function v(t,e){var n=t+" is deprecated and will be removed in a future version.";return e&&(n+=" Use "+e+" instead."),y(n)}function y(t,n,r){if(ot.warnings){var i,o=new I(t);if(n)r._attachExtraTrace(o);else if(ot.longStackTraces&&(i=e._peekContext()))i.attachExtraTrace(o);else{var s=j(o);o.stack=s.message+"\n"+s.stack.join("\n")}tt("warning",o)||k(o,"",!0)}}function m(t,e){for(var n=0;n<e.length-1;++n)e[n].push("From previous event:"),e[n]=e[n].join("\n");return n<e.length&&(e[n]=e[n].join("\n")),t+"\n"+e.join("\n")}function g(t){for(var e=0;e<t.length;++e)(0===t[e].length||e+1<t.length&&t[e][0]===t[e+1][0])&&(t.splice(e,1),e--)}function b(t){for(var e=t[0],n=1;n<t.length;++n){for(var r=t[n],i=e.length-1,o=e[i],s=-1,a=r.length-1;a>=0;--a)if(r[a]===o){s=a;break}for(var a=s;a>=0;--a){var c=r[a];if(e[i]!==c)break;e.pop(),i--}e=r}}function w(t){for(var e=[],n=0;n<t.length;++n){var r=t[n],i="    (No stack trace)"===r||q.test(r),o=i&&nt(r);i&&!o&&($&&" "!==r.charAt(0)&&(r="    "+r),e.push(r))}return e}function C(t){for(var e=t.stack.replace(/\s+$/g,"").split("\n"),n=0;n<e.length;++n){var r=e[n];if("    (No stack trace)"===r||q.test(r))break}return n>0&&(e=e.slice(n)),e}function j(t){var e=t.stack,n=t.toString();return e="string"==typeof e&&e.length>0?C(t):["    (No stack trace)"],{message:n,stack:w(e)}}function k(t,e,n){if("undefined"!=typeof console){var r;if(H.isObject(t)){var i=t.stack;r=e+Q(i,t)}else r=e+String(t);"function"==typeof D?D(r,n):("function"==typeof console.log||"object"==typeof console.log)&&console.log(r)}}function E(t,e,n,r){var i=!1;try{"function"==typeof e&&(i=!0,"rejectionHandled"===t?e(r):e(n,r))}catch(o){L.throwLater(o)}"unhandledRejection"===t?tt(t,n,r)||i||k(n,"Unhandled rejection "):tt(t,r)}function F(t){var e;if("function"==typeof t)e="[function "+(t.name||"anonymous")+"]";else{e=t&&"function"==typeof t.toString?t.toString():H.toString(t);var n=/\[object [a-zA-Z0-9$_]+\]/;if(n.test(e))try{var r=JSON.stringify(t);e=r}catch(i){}0===e.length&&(e="(empty array)")}return"(<"+x(e)+">, no stack trace)"}function x(t){var e=41;return t.length<e?t:t.substr(0,e-3)+"..."}function T(){return"function"==typeof it}function P(t){var e=t.match(rt);return e?{fileName:e[1],line:parseInt(e[2],10)}:void 0}function R(t,e){if(T()){for(var n,r,i=t.stack.split("\n"),o=e.stack.split("\n"),s=-1,a=-1,c=0;c<i.length;++c){var l=P(i[c]);if(l){n=l.fileName,s=l.line;break}}for(var c=0;c<o.length;++c){var l=P(o[c]);if(l){r=l.fileName,a=l.line;break}}0>s||0>a||!n||!r||n!==r||s>=a||(nt=function(t){if(B.test(t))return!0;var e=P(t);return e&&e.fileName===n&&s<=e.line&&e.line<=a?!0:!1})}}function S(t){this._parent=t,this._promisesCreated=0;var e=this._length=1+(void 0===t?0:t._length);it(this,S),e>32&&this.uncycle()}var O,A,D,V=e._getDomain,L=e._async,I=t("./errors").Warning,H=t("./util"),N=H.canAttachTrace,B=/[\\\/]bluebird[\\\/]js[\\\/](release|debug|instrumented)/,U=/\((?:timers\.js):\d+:\d+\)/,M=/[\/<\(](.+?):(\d+):(\d+)\)?\s*$/,q=null,Q=null,$=!1,G=!(0==H.env("BLUEBIRD_DEBUG")||!H.env("BLUEBIRD_DEBUG")&&"development"!==H.env("NODE_ENV")),z=!(0==H.env("BLUEBIRD_WARNINGS")||!G&&!H.env("BLUEBIRD_WARNINGS")),X=!(0==H.env("BLUEBIRD_LONG_STACK_TRACES")||!G&&!H.env("BLUEBIRD_LONG_STACK_TRACES")),W=0!=H.env("BLUEBIRD_W_FORGOTTEN_RETURN")&&(z||!!H.env("BLUEBIRD_W_FORGOTTEN_RETURN"));e.prototype.suppressUnhandledRejections=function(){var t=this._target();t._bitField=-1048577&t._bitField|524288},e.prototype._ensurePossibleRejectionHandled=function(){0===(524288&this._bitField)&&(this._setRejectionIsUnhandled(),L.invokeLater(this._notifyUnhandledRejection,this,void 0))},e.prototype._notifyUnhandledRejectionIsHandled=function(){E("rejectionHandled",O,void 0,this)},e.prototype._setReturnedNonUndefined=function(){this._bitField=268435456|this._bitField},e.prototype._returnedNonUndefined=function(){return 0!==(268435456&this._bitField)},e.prototype._notifyUnhandledRejection=function(){if(this._isRejectionUnhandled()){var t=this._settledValue();this._setUnhandledRejectionIsNotified(),E("unhandledRejection",A,t,this)}},e.prototype._setUnhandledRejectionIsNotified=function(){this._bitField=262144|this._bitField},e.prototype._unsetUnhandledRejectionIsNotified=function(){this._bitField=-262145&this._bitField},e.prototype._isUnhandledRejectionNotified=function(){return(262144&this._bitField)>0},e.prototype._setRejectionIsUnhandled=function(){this._bitField=1048576|this._bitField},e.prototype._unsetRejectionIsUnhandled=function(){this._bitField=-1048577&this._bitField,this._isUnhandledRejectionNotified()&&(this._unsetUnhandledRejectionIsNotified(),this._notifyUnhandledRejectionIsHandled())},e.prototype._isRejectionUnhandled=function(){return(1048576&this._bitField)>0},e.prototype._warn=function(t,e,n){return y(t,e,n||this)},e.onPossiblyUnhandledRejection=function(t){var e=V();A="function"==typeof t?null===e?t:H.domainBind(e,t):void 0},e.onUnhandledRejectionHandled=function(t){var e=V();O="function"==typeof t?null===e?t:H.domainBind(e,t):void 0};var K=function(){};e.longStackTraces=function(){if(L.haveItemsQueued()&&!ot.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n    See http://goo.gl/MqrFmX\n");if(!ot.longStackTraces&&T()){var t=e.prototype._captureStackTrace,r=e.prototype._attachExtraTrace;ot.longStackTraces=!0,K=function(){if(L.haveItemsQueued()&&!ot.longStackTraces)throw new Error("cannot enable long stack traces after promises have been created\n\n    See http://goo.gl/MqrFmX\n");e.prototype._captureStackTrace=t,e.prototype._attachExtraTrace=r,n.deactivateLongStackTraces(),L.enableTrampoline(),ot.longStackTraces=!1},e.prototype._captureStackTrace=f,e.prototype._attachExtraTrace=_,n.activateLongStackTraces(),L.disableTrampolineIfNecessary()}},e.hasLongStackTraces=function(){return ot.longStackTraces&&T()};var J=function(){try{if("function"==typeof CustomEvent){var t=new CustomEvent("CustomEvent");return H.global.dispatchEvent(t),function(t,e){var n=new CustomEvent(t.toLowerCase(),{detail:e,cancelable:!0});return!H.global.dispatchEvent(n)}}if("function"==typeof Event){var t=new Event("CustomEvent");return H.global.dispatchEvent(t),function(t,e){var n=new Event(t.toLowerCase(),{cancelable:!0});return n.detail=e,!H.global.dispatchEvent(n)}}var t=document.createEvent("CustomEvent");return t.initCustomEvent("testingtheevent",!1,!0,{}),H.global.dispatchEvent(t),function(t,e){var n=document.createEvent("CustomEvent");return n.initCustomEvent(t.toLowerCase(),!1,!0,e),!H.global.dispatchEvent(n)}}catch(e){}return function(){return!1}}(),Y=function(){return H.isNode?function(){return process.emit.apply(process,arguments)}:H.global?function(t){var e="on"+t.toLowerCase(),n=H.global[e];return n?(n.apply(H.global,[].slice.call(arguments,1)),!0):!1}:function(){return!1}}(),Z={promiseCreated:r,promiseFulfilled:r,promiseRejected:r,promiseResolved:r,promiseCancelled:r,promiseChained:function(t,e,n){return{promise:e,child:n}},warning:function(t,e){return{warning:e}},unhandledRejection:function(t,e,n){return{reason:e,promise:n}},rejectionHandled:r},tt=function(t){var e=!1;try{e=Y.apply(null,arguments)}catch(n){L.throwLater(n),e=!0}var r=!1;try{r=J(t,Z[t].apply(null,arguments))}catch(n){L.throwLater(n),r=!0}return r||e};e.config=function(t){if(t=Object(t),"longStackTraces"in t&&(t.longStackTraces?e.longStackTraces():!t.longStackTraces&&e.hasLongStackTraces()&&K()),"warnings"in t){var n=t.warnings;ot.warnings=!!n,W=ot.warnings,H.isObject(n)&&"wForgottenReturn"in n&&(W=!!n.wForgottenReturn)}if("cancellation"in t&&t.cancellation&&!ot.cancellation){if(L.haveItemsQueued())throw new Error("cannot enable cancellation after promises are in use");e.prototype._clearCancellationData=l,e.prototype._propagateFrom=u,e.prototype._onCancel=a,e.prototype._setOnCancel=c,e.prototype._attachCancellationCallback=s,e.prototype._execute=o,et=u,ot.cancellation=!0}"monitoring"in t&&(t.monitoring&&!ot.monitoring?(ot.monitoring=!0,e.prototype._fireEvent=tt):!t.monitoring&&ot.monitoring&&(ot.monitoring=!1,e.prototype._fireEvent=i))},e.prototype._fireEvent=i,e.prototype._execute=function(t,e,n){try{t(e,n)}catch(r){return r}},e.prototype._onCancel=function(){},e.prototype._setOnCancel=function(t){},e.prototype._attachCancellationCallback=function(t){},e.prototype._captureStackTrace=function(){},e.prototype._attachExtraTrace=function(){},e.prototype._clearCancellationData=function(){},e.prototype._propagateFrom=function(t,e){};var et=p,nt=function(){return!1},rt=/[\/<\(]([^:\/]+):(\d+):(?:\d+)\)?\s*$/;H.inherits(S,Error),n.CapturedTrace=S,S.prototype.uncycle=function(){var t=this._length;if(!(2>t)){for(var e=[],n={},r=0,i=this;void 0!==i;++r)e.push(i),i=i._parent;t=this._length=r;for(var r=t-1;r>=0;--r){var o=e[r].stack;void 0===n[o]&&(n[o]=r)}for(var r=0;t>r;++r){var s=e[r].stack,a=n[s];if(void 0!==a&&a!==r){a>0&&(e[a-1]._parent=void 0,e[a-1]._length=1),e[r]._parent=void 0,e[r]._length=1;var c=r>0?e[r-1]:this;t-1>a?(c._parent=e[a+1],c._parent.uncycle(),c._length=c._parent._length+1):(c._parent=void 0,c._length=1);for(var l=c._length+1,u=r-2;u>=0;--u)e[u]._length=l,l++;return}}}},S.prototype.attachExtraTrace=function(t){if(!t.__stackCleaned__){this.uncycle();for(var e=j(t),n=e.message,r=[e.stack],i=this;void 0!==i;)r.push(w(i.stack.split("\n"))),i=i._parent;b(r),g(r),H.notEnumerableProp(t,"stack",m(n,r)),H.notEnumerableProp(t,"__stackCleaned__",!0)}};var it=function(){var t=/^\s*at\s*/,e=function(t,e){return"string"==typeof t?t:void 0!==e.name&&void 0!==e.message?e.toString():F(e)};if("number"==typeof Error.stackTraceLimit&&"function"==typeof Error.captureStackTrace){Error.stackTraceLimit+=6,q=t,Q=e;var n=Error.captureStackTrace;return nt=function(t){return B.test(t)},function(t,e){Error.stackTraceLimit+=6,n(t,e),Error.stackTraceLimit-=6}}var r=new Error;if("string"==typeof r.stack&&r.stack.split("\n")[0].indexOf("stackDetection@")>=0)return q=/@/,Q=e,$=!0,function(t){t.stack=(new Error).stack};var i;try{throw new Error}catch(o){i="stack"in o}return"stack"in r||!i||"number"!=typeof Error.stackTraceLimit?(Q=function(t,e){return"string"==typeof t?t:"object"!=typeof e&&"function"!=typeof e||void 0===e.name||void 0===e.message?F(e):e.toString()},null):(q=t,Q=e,function(t){Error.stackTraceLimit+=6;try{throw new Error}catch(e){t.stack=e.stack}Error.stackTraceLimit-=6})}([]);"undefined"!=typeof console&&"undefined"!=typeof console.warn&&(D=function(t){console.warn(t)},H.isNode&&process.stderr.isTTY?D=function(t,e){var n=e?"[33m":"[31m";console.warn(n+t+"[0m\n")}:H.isNode||"string"!=typeof(new Error).stack||(D=function(t,e){console.warn("%c"+t,e?"color: darkorange":"color: red")}));var ot={warnings:z,longStackTraces:!1,cancellation:!1,monitoring:!1};return X&&e.longStackTraces(),{longStackTraces:function(){return ot.longStackTraces},warnings:function(){return ot.warnings},cancellation:function(){return ot.cancellation},monitoring:function(){return ot.monitoring},propagateFromFunction:function(){return et},boundValueFunction:function(){return h},checkForgottenReturns:d,setBounds:R,warn:y,deprecated:v,CapturedTrace:S,fireDomEvent:J,fireGlobalEvent:Y}}},{"./errors":12,"./util":36}],10:[function(t,e,n){"use strict";e.exports=function(t){function e(){return this.value}function n(){throw this.reason}t.prototype["return"]=t.prototype.thenReturn=function(n){return n instanceof t&&n.suppressUnhandledRejections(),this._then(e,void 0,void 0,{value:n},void 0)},t.prototype["throw"]=t.prototype.thenThrow=function(t){return this._then(n,void 0,void 0,{reason:t},void 0)},t.prototype.catchThrow=function(t){if(arguments.length<=1)return this._then(void 0,n,void 0,{reason:t},void 0);var e=arguments[1],r=function(){throw e};return this.caught(t,r)},t.prototype.catchReturn=function(n){if(arguments.length<=1)return n instanceof t&&n.suppressUnhandledRejections(),this._then(void 0,e,void 0,{value:n},void 0);var r=arguments[1];r instanceof t&&r.suppressUnhandledRejections();var i=function(){return r};return this.caught(n,i)}}},{}],11:[function(t,e,n){"use strict";e.exports=function(t,e){function n(){return o(this)}function r(t,n){return i(t,n,e,e)}var i=t.reduce,o=t.all;t.prototype.each=function(t){return i(this,t,e,0)._then(n,void 0,void 0,this,void 0)},t.prototype.mapSeries=function(t){return i(this,t,e,e)},t.each=function(t,r){return i(t,r,e,0)._then(n,void 0,void 0,t,void 0)},t.mapSeries=r}},{}],12:[function(t,e,n){"use strict";function r(t,e){function n(r){return this instanceof n?(p(this,"message","string"==typeof r?r:e),p(this,"name",t),void(Error.captureStackTrace?Error.captureStackTrace(this,this.constructor):Error.call(this))):new n(r)}return u(n,Error),n}function i(t){return this instanceof i?(p(this,"name","OperationalError"),p(this,"message",t),this.cause=t,this.isOperational=!0,void(t instanceof Error?(p(this,"message",t.message),p(this,"stack",t.stack)):Error.captureStackTrace&&Error.captureStackTrace(this,this.constructor))):new i(t)}var o,s,a=t("./es5"),c=a.freeze,l=t("./util"),u=l.inherits,p=l.notEnumerableProp,h=r("Warning","warning"),f=r("CancellationError","cancellation error"),_=r("TimeoutError","timeout error"),d=r("AggregateError","aggregate error");try{o=TypeError,s=RangeError}catch(v){o=r("TypeError","type error"),s=r("RangeError","range error")}for(var y="join pop push shift unshift slice filter forEach some every map indexOf lastIndexOf reduce reduceRight sort reverse".split(" "),m=0;m<y.length;++m)"function"==typeof Array.prototype[y[m]]&&(d.prototype[y[m]]=Array.prototype[y[m]]);a.defineProperty(d.prototype,"length",{value:0,configurable:!1,writable:!0,enumerable:!0}),d.prototype.isOperational=!0;var g=0;d.prototype.toString=function(){var t=Array(4*g+1).join(" "),e="\n"+t+"AggregateError of:\n";g++,t=Array(4*g+1).join(" ");for(var n=0;n<this.length;++n){for(var r=this[n]===this?"[Circular AggregateError]":this[n]+"",i=r.split("\n"),o=0;o<i.length;++o)i[o]=t+i[o];r=i.join("\n"),e+=r+"\n"}return g--,e},u(i,Error);var b=Error.__BluebirdErrorTypes__;b||(b=c({CancellationError:f,TimeoutError:_,OperationalError:i,RejectionError:i,AggregateError:d}),a.defineProperty(Error,"__BluebirdErrorTypes__",{value:b,writable:!1,enumerable:!1,configurable:!1})),e.exports={Error:Error,TypeError:o,RangeError:s,CancellationError:b.CancellationError,OperationalError:b.OperationalError,TimeoutError:b.TimeoutError,AggregateError:b.AggregateError,Warning:h}},{"./es5":13,"./util":36}],13:[function(t,e,n){var r=function(){"use strict";return void 0===this}();if(r)e.exports={freeze:Object.freeze,defineProperty:Object.defineProperty,getDescriptor:Object.getOwnPropertyDescriptor,keys:Object.keys,names:Object.getOwnPropertyNames,getPrototypeOf:Object.getPrototypeOf,isArray:Array.isArray,isES5:r,propertyIsWritable:function(t,e){var n=Object.getOwnPropertyDescriptor(t,e);return!(n&&!n.writable&&!n.set)}};else{var i={}.hasOwnProperty,o={}.toString,s={}.constructor.prototype,a=function(t){var e=[];for(var n in t)i.call(t,n)&&e.push(n);return e},c=function(t,e){return{value:t[e]}},l=function(t,e,n){return t[e]=n.value,t},u=function(t){return t},p=function(t){try{return Object(t).constructor.prototype}catch(e){return s}},h=function(t){try{return"[object Array]"===o.call(t)}catch(e){return!1}};e.exports={isArray:h,keys:a,names:a,defineProperty:l,getDescriptor:c,freeze:u,getPrototypeOf:p,isES5:r,propertyIsWritable:function(){return!0}}}},{}],14:[function(t,e,n){"use strict";e.exports=function(t,e){var n=t.map;t.prototype.filter=function(t,r){return n(this,t,r,e)},t.filter=function(t,r,i){return n(t,r,i,e)}}},{}],15:[function(t,e,n){"use strict";e.exports=function(e,n){function r(t,e,n){this.promise=t,this.type=e,this.handler=n,this.called=!1,this.cancelPromise=null}function i(t){this.finallyHandler=t}function o(t,e){return null!=t.cancelPromise?(arguments.length>1?t.cancelPromise._reject(e):t.cancelPromise._cancel(),t.cancelPromise=null,!0):!1}function s(){return c.call(this,this.promise._target()._settledValue())}function a(t){return o(this,t)?void 0:(p.e=t,p)}function c(t){var r=this.promise,c=this.handler;if(!this.called){this.called=!0;var l=this.isFinallyHandler()?c.call(r._boundValue()):c.call(r._boundValue(),t);if(void 0!==l){r._setReturnedNonUndefined();var h=n(l,r);if(h instanceof e){if(null!=this.cancelPromise){if(h._isCancelled()){var f=new u("late cancellation observer");return r._attachExtraTrace(f),p.e=f,p}h.isPending()&&h._attachCancellationCallback(new i(this))}return h._then(s,a,void 0,this,void 0)}}}return r.isRejected()?(o(this),p.e=t,p):(o(this),t)}var l=t("./util"),u=e.CancellationError,p=l.errorObj;return r.prototype.isFinallyHandler=function(){return 0===this.type},i.prototype._resultCancelled=function(){o(this.finallyHandler)},e.prototype._passThrough=function(t,e,n,i){return"function"!=typeof t?this.then():this._then(n,i,void 0,new r(this,e,t),void 0)},e.prototype.lastly=e.prototype["finally"]=function(t){return this._passThrough(t,0,c,c)},e.prototype.tap=function(t){return this._passThrough(t,1,c)},r}},{"./util":36}],16:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){function a(t,n,r){for(var o=0;o<n.length;++o){r._pushContext();var s=f(n[o])(t);if(r._popContext(),s===h){r._pushContext();var a=e.reject(h.e);return r._popContext(),a}var c=i(s,r);if(c instanceof e)return c}return null}function c(t,n,i,o){if(s.cancellation()){var a=new e(r),c=this._finallyPromise=new e(r);this._promise=a.lastly(function(){return c}),a._captureStackTrace(),a._setOnCancel(this)}else{var l=this._promise=new e(r);l._captureStackTrace()}this._stack=o,this._generatorFunction=t,this._receiver=n,this._generator=void 0,this._yieldHandlers="function"==typeof i?[i].concat(_):_,this._yieldedPromise=null,this._cancellationPhase=!1}var l=t("./errors"),u=l.TypeError,p=t("./util"),h=p.errorObj,f=p.tryCatch,_=[];p.inherits(c,o),c.prototype._isResolved=function(){return null===this._promise},c.prototype._cleanup=function(){this._promise=this._generator=null,s.cancellation()&&null!==this._finallyPromise&&(this._finallyPromise._fulfill(),this._finallyPromise=null)},c.prototype._promiseCancelled=function(){if(!this._isResolved()){var t,n="undefined"!=typeof this._generator["return"];if(n)this._promise._pushContext(),t=f(this._generator["return"]).call(this._generator,void 0),this._promise._popContext();else{var r=new e.CancellationError("generator .return() sentinel");e.coroutine.returnSentinel=r,this._promise._attachExtraTrace(r),this._promise._pushContext(),t=f(this._generator["throw"]).call(this._generator,r),this._promise._popContext()}this._cancellationPhase=!0,this._yieldedPromise=null,this._continue(t)}},c.prototype._promiseFulfilled=function(t){this._yieldedPromise=null,this._promise._pushContext();var e=f(this._generator.next).call(this._generator,t);this._promise._popContext(),this._continue(e)},c.prototype._promiseRejected=function(t){this._yieldedPromise=null,this._promise._attachExtraTrace(t),this._promise._pushContext();var e=f(this._generator["throw"]).call(this._generator,t);this._promise._popContext(),this._continue(e)},c.prototype._resultCancelled=function(){if(this._yieldedPromise instanceof e){var t=this._yieldedPromise;this._yieldedPromise=null,t.cancel()}},c.prototype.promise=function(){return this._promise},c.prototype._run=function(){this._generator=this._generatorFunction.call(this._receiver),this._receiver=this._generatorFunction=void 0,this._promiseFulfilled(void 0)},c.prototype._continue=function(t){var n=this._promise;if(t===h)return this._cleanup(),this._cancellationPhase?n.cancel():n._rejectCallback(t.e,!1);var r=t.value;if(t.done===!0)return this._cleanup(),this._cancellationPhase?n.cancel():n._resolveCallback(r);var o=i(r,this._promise);if(!(o instanceof e)&&(o=a(o,this._yieldHandlers,this._promise),null===o))return void this._promiseRejected(new u("A value %s was yielded that could not be treated as a promise\n\n    See http://goo.gl/MqrFmX\n\n".replace("%s",r)+"From coroutine:\n"+this._stack.split("\n").slice(1,-7).join("\n")));o=o._target();var s=o._bitField;0===(50397184&s)?(this._yieldedPromise=o,o._proxy(this,null)):0!==(33554432&s)?e._async.invoke(this._promiseFulfilled,this,o._value()):0!==(16777216&s)?e._async.invoke(this._promiseRejected,this,o._reason()):this._promiseCancelled()},e.coroutine=function(t,e){if("function"!=typeof t)throw new u("generatorFunction must be a function\n\n    See http://goo.gl/MqrFmX\n");var n=Object(e).yieldHandler,r=c,i=(new Error).stack;return function(){var e=t.apply(this,arguments),o=new r(void 0,void 0,n,i),s=o.promise();return o._generator=e,
o._promiseFulfilled(void 0),s}},e.coroutine.addYieldHandler=function(t){if("function"!=typeof t)throw new u("expecting a function but got "+p.classString(t));_.push(t)},e.spawn=function(t){if(s.deprecated("Promise.spawn()","Promise.coroutine()"),"function"!=typeof t)return n("generatorFunction must be a function\n\n    See http://goo.gl/MqrFmX\n");var r=new c(t,this),i=r.promise();return r._run(e.spawn),i}}},{"./errors":12,"./util":36}],17:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){var a=t("./util");a.canEvaluate,a.tryCatch,a.errorObj;e.join=function(){var t,e=arguments.length-1;if(e>0&&"function"==typeof arguments[e]){t=arguments[e];var r}var i=[].slice.call(arguments);t&&i.pop();var r=new n(i).promise();return void 0!==t?r.spread(t):r}}},{"./util":36}],18:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){function a(t,e,n,r){this.constructor$(t),this._promise._captureStackTrace();var i=l();this._callback=null===i?e:u.domainBind(i,e),this._preservedValues=r===o?new Array(this.length()):null,this._limit=n,this._inFlight=0,this._queue=[],this._init$(void 0,-2)}function c(t,n,i,o){if("function"!=typeof n)return r("expecting a function but got "+u.classString(n));var s=0;if(void 0!==i){if("object"!=typeof i||null===i)return e.reject(new TypeError("options argument must be an object but it is "+u.classString(i)));if("number"!=typeof i.concurrency)return e.reject(new TypeError("'concurrency' must be a number but it is "+u.classString(i.concurrency)));s=i.concurrency}return s="number"==typeof s&&isFinite(s)&&s>=1?s:0,new a(t,n,s,o).promise()}var l=e._getDomain,u=t("./util"),p=u.tryCatch,h=u.errorObj;u.inherits(a,n),a.prototype._init=function(){},a.prototype._promiseFulfilled=function(t,n){var r=this._values,o=this.length(),a=this._preservedValues,c=this._limit;if(0>n){if(n=-1*n-1,r[n]=t,c>=1&&(this._inFlight--,this._drainQueue(),this._isResolved()))return!0}else{if(c>=1&&this._inFlight>=c)return r[n]=t,this._queue.push(n),!1;null!==a&&(a[n]=t);var l=this._promise,u=this._callback,f=l._boundValue();l._pushContext();var _=p(u).call(f,t,n,o),d=l._popContext();if(s.checkForgottenReturns(_,d,null!==a?"Promise.filter":"Promise.map",l),_===h)return this._reject(_.e),!0;var v=i(_,this._promise);if(v instanceof e){v=v._target();var y=v._bitField;if(0===(50397184&y))return c>=1&&this._inFlight++,r[n]=v,v._proxy(this,-1*(n+1)),!1;if(0===(33554432&y))return 0!==(16777216&y)?(this._reject(v._reason()),!0):(this._cancel(),!0);_=v._value()}r[n]=_}var m=++this._totalResolved;return m>=o?(null!==a?this._filter(r,a):this._resolve(r),!0):!1},a.prototype._drainQueue=function(){for(var t=this._queue,e=this._limit,n=this._values;t.length>0&&this._inFlight<e;){if(this._isResolved())return;var r=t.pop();this._promiseFulfilled(n[r],r)}},a.prototype._filter=function(t,e){for(var n=e.length,r=new Array(n),i=0,o=0;n>o;++o)t[o]&&(r[i++]=e[o]);r.length=i,this._resolve(r)},a.prototype.preservedValues=function(){return this._preservedValues},e.prototype.map=function(t,e){return c(this,t,e,null)},e.map=function(t,e,n,r){return c(t,e,n,r)}}},{"./util":36}],19:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o){var s=t("./util"),a=s.tryCatch;e.method=function(t){if("function"!=typeof t)throw new e.TypeError("expecting a function but got "+s.classString(t));return function(){var r=new e(n);r._captureStackTrace(),r._pushContext();var i=a(t).apply(this,arguments),s=r._popContext();return o.checkForgottenReturns(i,s,"Promise.method",r),r._resolveFromSyncValue(i),r}},e.attempt=e["try"]=function(t){if("function"!=typeof t)return i("expecting a function but got "+s.classString(t));var r=new e(n);r._captureStackTrace(),r._pushContext();var c;if(arguments.length>1){o.deprecated("calling Promise.try with more than 1 argument");var l=arguments[1],u=arguments[2];c=s.isArray(l)?a(t).apply(u,l):a(t).call(u,l)}else c=a(t)();var p=r._popContext();return o.checkForgottenReturns(c,p,"Promise.try",r),r._resolveFromSyncValue(c),r},e.prototype._resolveFromSyncValue=function(t){t===s.errorObj?this._rejectCallback(t.e,!1):this._resolveCallback(t,!0)}}},{"./util":36}],20:[function(t,e,n){"use strict";function r(t){return t instanceof Error&&u.getPrototypeOf(t)===Error.prototype}function i(t){var e;if(r(t)){e=new l(t),e.name=t.name,e.message=t.message,e.stack=t.stack;for(var n=u.keys(t),i=0;i<n.length;++i){var o=n[i];p.test(o)||(e[o]=t[o])}return e}return s.markAsOriginatingFromRejection(t),t}function o(t,e){return function(n,r){if(null!==t){if(n){var o=i(a(n));t._attachExtraTrace(o),t._reject(o)}else if(e){var s=[].slice.call(arguments,1);t._fulfill(s)}else t._fulfill(r);t=null}}}var s=t("./util"),a=s.maybeWrapAsError,c=t("./errors"),l=c.OperationalError,u=t("./es5"),p=/^(?:name|message|stack|cause)$/;e.exports=o},{"./errors":12,"./es5":13,"./util":36}],21:[function(t,e,n){"use strict";e.exports=function(e){function n(t,e){var n=this;if(!o.isArray(t))return r.call(n,t,e);var i=a(e).apply(n._boundValue(),[null].concat(t));i===c&&s.throwLater(i.e)}function r(t,e){var n=this,r=n._boundValue(),i=void 0===t?a(e).call(r,null):a(e).call(r,null,t);i===c&&s.throwLater(i.e)}function i(t,e){var n=this;if(!t){var r=new Error(t+"");r.cause=t,t=r}var i=a(e).call(n._boundValue(),t);i===c&&s.throwLater(i.e)}var o=t("./util"),s=e._async,a=o.tryCatch,c=o.errorObj;e.prototype.asCallback=e.prototype.nodeify=function(t,e){if("function"==typeof t){var o=r;void 0!==e&&Object(e).spread&&(o=n),this._then(o,i,void 0,this,t)}return this}}},{"./util":36}],22:[function(t,e,n){"use strict";e.exports=function(){function n(){}function r(t,e){if("function"!=typeof e)throw new m("expecting a function but got "+f.classString(e));if(t.constructor!==i)throw new m("the promise constructor cannot be invoked directly\n\n    See http://goo.gl/MqrFmX\n")}function i(t){this._bitField=0,this._fulfillmentHandler0=void 0,this._rejectionHandler0=void 0,this._promise0=void 0,this._receiver0=void 0,t!==b&&(r(this,t),this._resolveFromExecutor(t)),this._promiseCreated(),this._fireEvent("promiseCreated",this)}function o(t){this.promise._resolveCallback(t)}function s(t){this.promise._rejectCallback(t,!1)}function a(t){var e=new i(b);e._fulfillmentHandler0=t,e._rejectionHandler0=t,e._promise0=t,e._receiver0=t}var c,l=function(){return new m("circular promise resolution chain\n\n    See http://goo.gl/MqrFmX\n")},u=function(){return new i.PromiseInspection(this._target())},p=function(t){return i.reject(new m(t))},h={},f=t("./util");c=f.isNode?function(){var t=process.domain;return void 0===t&&(t=null),t}:function(){return null},f.notEnumerableProp(i,"_getDomain",c);var _=t("./es5"),d=t("./async"),v=new d;_.defineProperty(i,"_async",{value:v});var y=t("./errors"),m=i.TypeError=y.TypeError;i.RangeError=y.RangeError;var g=i.CancellationError=y.CancellationError;i.TimeoutError=y.TimeoutError,i.OperationalError=y.OperationalError,i.RejectionError=y.OperationalError,i.AggregateError=y.AggregateError;var b=function(){},w={},C={},j=t("./thenables")(i,b),k=t("./promise_array")(i,b,j,p,n),E=t("./context")(i),F=E.create,x=t("./debuggability")(i,E),T=(x.CapturedTrace,t("./finally")(i,j)),P=t("./catch_filter")(C),R=t("./nodeback"),S=f.errorObj,O=f.tryCatch;return i.prototype.toString=function(){return"[object Promise]"},i.prototype.caught=i.prototype["catch"]=function(t){var e=arguments.length;if(e>1){var n,r=new Array(e-1),i=0;for(n=0;e-1>n;++n){var o=arguments[n];if(!f.isObject(o))return p("expecting an object but got A catch statement predicate "+f.classString(o));r[i++]=o}return r.length=i,t=arguments[n],this.then(void 0,P(r,t,this))}return this.then(void 0,t)},i.prototype.reflect=function(){return this._then(u,u,void 0,this,void 0)},i.prototype.then=function(t,e){if(x.warnings()&&arguments.length>0&&"function"!=typeof t&&"function"!=typeof e){var n=".then() only accepts functions but was passed: "+f.classString(t);arguments.length>1&&(n+=", "+f.classString(e)),this._warn(n)}return this._then(t,e,void 0,void 0,void 0)},i.prototype.done=function(t,e){var n=this._then(t,e,void 0,void 0,void 0);n._setIsFinal()},i.prototype.spread=function(t){return"function"!=typeof t?p("expecting a function but got "+f.classString(t)):this.all()._then(t,void 0,void 0,w,void 0)},i.prototype.toJSON=function(){var t={isFulfilled:!1,isRejected:!1,fulfillmentValue:void 0,rejectionReason:void 0};return this.isFulfilled()?(t.fulfillmentValue=this.value(),t.isFulfilled=!0):this.isRejected()&&(t.rejectionReason=this.reason(),t.isRejected=!0),t},i.prototype.all=function(){return arguments.length>0&&this._warn(".all() was passed arguments but it does not take any"),new k(this).promise()},i.prototype.error=function(t){return this.caught(f.originatesFromRejection,t)},i.getNewLibraryCopy=e.exports,i.is=function(t){return t instanceof i},i.fromNode=i.fromCallback=function(t){var e=new i(b);e._captureStackTrace();var n=arguments.length>1?!!Object(arguments[1]).multiArgs:!1,r=O(t)(R(e,n));return r===S&&e._rejectCallback(r.e,!0),e._isFateSealed()||e._setAsyncGuaranteed(),e},i.all=function(t){return new k(t).promise()},i.cast=function(t){var e=j(t);return e instanceof i||(e=new i(b),e._captureStackTrace(),e._setFulfilled(),e._rejectionHandler0=t),e},i.resolve=i.fulfilled=i.cast,i.reject=i.rejected=function(t){var e=new i(b);return e._captureStackTrace(),e._rejectCallback(t,!0),e},i.setScheduler=function(t){if("function"!=typeof t)throw new m("expecting a function but got "+f.classString(t));return v.setScheduler(t)},i.prototype._then=function(t,e,n,r,o){var s=void 0!==o,a=s?o:new i(b),l=this._target(),u=l._bitField;s||(a._propagateFrom(this,3),a._captureStackTrace(),void 0===r&&0!==(2097152&this._bitField)&&(r=0!==(50397184&u)?this._boundValue():l===this?void 0:this._boundTo),this._fireEvent("promiseChained",this,a));var p=c();if(0!==(50397184&u)){var h,_,d=l._settlePromiseCtx;0!==(33554432&u)?(_=l._rejectionHandler0,h=t):0!==(16777216&u)?(_=l._fulfillmentHandler0,h=e,l._unsetRejectionIsUnhandled()):(d=l._settlePromiseLateCancellationObserver,_=new g("late cancellation observer"),l._attachExtraTrace(_),h=e),v.invoke(d,l,{handler:null===p?h:"function"==typeof h&&f.domainBind(p,h),promise:a,receiver:r,value:_})}else l._addCallbacks(t,e,a,r,p);return a},i.prototype._length=function(){return 65535&this._bitField},i.prototype._isFateSealed=function(){return 0!==(117506048&this._bitField)},i.prototype._isFollowing=function(){return 67108864===(67108864&this._bitField)},i.prototype._setLength=function(t){this._bitField=-65536&this._bitField|65535&t},i.prototype._setFulfilled=function(){this._bitField=33554432|this._bitField,this._fireEvent("promiseFulfilled",this)},i.prototype._setRejected=function(){this._bitField=16777216|this._bitField,this._fireEvent("promiseRejected",this)},i.prototype._setFollowing=function(){this._bitField=67108864|this._bitField,this._fireEvent("promiseResolved",this)},i.prototype._setIsFinal=function(){this._bitField=4194304|this._bitField},i.prototype._isFinal=function(){return(4194304&this._bitField)>0},i.prototype._unsetCancelled=function(){this._bitField=-65537&this._bitField},i.prototype._setCancelled=function(){this._bitField=65536|this._bitField,this._fireEvent("promiseCancelled",this)},i.prototype._setWillBeCancelled=function(){this._bitField=8388608|this._bitField},i.prototype._setAsyncGuaranteed=function(){v.hasCustomScheduler()||(this._bitField=134217728|this._bitField)},i.prototype._receiverAt=function(t){var e=0===t?this._receiver0:this[4*t-4+3];return e===h?void 0:void 0===e&&this._isBound()?this._boundValue():e},i.prototype._promiseAt=function(t){return this[4*t-4+2]},i.prototype._fulfillmentHandlerAt=function(t){return this[4*t-4+0]},i.prototype._rejectionHandlerAt=function(t){return this[4*t-4+1]},i.prototype._boundValue=function(){},i.prototype._migrateCallback0=function(t){var e=(t._bitField,t._fulfillmentHandler0),n=t._rejectionHandler0,r=t._promise0,i=t._receiverAt(0);void 0===i&&(i=h),this._addCallbacks(e,n,r,i,null)},i.prototype._migrateCallbackAt=function(t,e){var n=t._fulfillmentHandlerAt(e),r=t._rejectionHandlerAt(e),i=t._promiseAt(e),o=t._receiverAt(e);void 0===o&&(o=h),this._addCallbacks(n,r,i,o,null)},i.prototype._addCallbacks=function(t,e,n,r,i){var o=this._length();if(o>=65531&&(o=0,this._setLength(0)),0===o)this._promise0=n,this._receiver0=r,"function"==typeof t&&(this._fulfillmentHandler0=null===i?t:f.domainBind(i,t)),"function"==typeof e&&(this._rejectionHandler0=null===i?e:f.domainBind(i,e));else{var s=4*o-4;this[s+2]=n,this[s+3]=r,"function"==typeof t&&(this[s+0]=null===i?t:f.domainBind(i,t)),"function"==typeof e&&(this[s+1]=null===i?e:f.domainBind(i,e))}return this._setLength(o+1),o},i.prototype._proxy=function(t,e){this._addCallbacks(void 0,void 0,e,t,null)},i.prototype._resolveCallback=function(t,e){if(0===(117506048&this._bitField)){if(t===this)return this._rejectCallback(l(),!1);var n=j(t,this);if(!(n instanceof i))return this._fulfill(t);e&&this._propagateFrom(n,2);var r=n._target();if(r===this)return void this._reject(l());var o=r._bitField;if(0===(50397184&o)){var s=this._length();s>0&&r._migrateCallback0(this);for(var a=1;s>a;++a)r._migrateCallbackAt(this,a);this._setFollowing(),this._setLength(0),this._setFollowee(r)}else if(0!==(33554432&o))this._fulfill(r._value());else if(0!==(16777216&o))this._reject(r._reason());else{var c=new g("late cancellation observer");r._attachExtraTrace(c),this._reject(c)}}},i.prototype._rejectCallback=function(t,e,n){var r=f.ensureErrorObject(t),i=r===t;if(!i&&!n&&x.warnings()){var o="a promise was rejected with a non-error: "+f.classString(t);this._warn(o,!0)}this._attachExtraTrace(r,e?i:!1),this._reject(t)},i.prototype._resolveFromExecutor=function(t){var e=this;this._captureStackTrace(),this._pushContext();var n=!0,r=this._execute(t,function(t){e._resolveCallback(t)},function(t){e._rejectCallback(t,n)});n=!1,this._popContext(),void 0!==r&&e._rejectCallback(r,!0)},i.prototype._settlePromiseFromHandler=function(t,e,n,r){var i=r._bitField;if(0===(65536&i)){r._pushContext();var o;e===w?n&&"number"==typeof n.length?o=O(t).apply(this._boundValue(),n):(o=S,o.e=new m("cannot .spread() a non-array: "+f.classString(n))):o=O(t).call(e,n);var s=r._popContext();i=r._bitField,0===(65536&i)&&(o===C?r._reject(n):o===S?r._rejectCallback(o.e,!1):(x.checkForgottenReturns(o,s,"",r,this),r._resolveCallback(o)))}},i.prototype._target=function(){for(var t=this;t._isFollowing();)t=t._followee();return t},i.prototype._followee=function(){return this._rejectionHandler0},i.prototype._setFollowee=function(t){this._rejectionHandler0=t},i.prototype._settlePromise=function(t,e,r,o){var s=t instanceof i,a=this._bitField,c=0!==(134217728&a);0!==(65536&a)?(s&&t._invokeInternalOnCancel(),r instanceof T&&r.isFinallyHandler()?(r.cancelPromise=t,O(e).call(r,o)===S&&t._reject(S.e)):e===u?t._fulfill(u.call(r)):r instanceof n?r._promiseCancelled(t):s||t instanceof k?t._cancel():r.cancel()):"function"==typeof e?s?(c&&t._setAsyncGuaranteed(),this._settlePromiseFromHandler(e,r,o,t)):e.call(r,o,t):r instanceof n?r._isResolved()||(0!==(33554432&a)?r._promiseFulfilled(o,t):r._promiseRejected(o,t)):s&&(c&&t._setAsyncGuaranteed(),0!==(33554432&a)?t._fulfill(o):t._reject(o))},i.prototype._settlePromiseLateCancellationObserver=function(t){var e=t.handler,n=t.promise,r=t.receiver,o=t.value;"function"==typeof e?n instanceof i?this._settlePromiseFromHandler(e,r,o,n):e.call(r,o,n):n instanceof i&&n._reject(o)},i.prototype._settlePromiseCtx=function(t){this._settlePromise(t.promise,t.handler,t.receiver,t.value)},i.prototype._settlePromise0=function(t,e,n){var r=this._promise0,i=this._receiverAt(0);this._promise0=void 0,this._receiver0=void 0,this._settlePromise(r,t,i,e)},i.prototype._clearCallbackDataAtIndex=function(t){var e=4*t-4;this[e+2]=this[e+3]=this[e+0]=this[e+1]=void 0},i.prototype._fulfill=function(t){var e=this._bitField;if(!((117506048&e)>>>16)){if(t===this){var n=l();return this._attachExtraTrace(n),this._reject(n)}this._setFulfilled(),this._rejectionHandler0=t,(65535&e)>0&&(0!==(134217728&e)?this._settlePromises():v.settlePromises(this))}},i.prototype._reject=function(t){var e=this._bitField;if(!((117506048&e)>>>16))return this._setRejected(),this._fulfillmentHandler0=t,this._isFinal()?v.fatalError(t,f.isNode):void((65535&e)>0?v.settlePromises(this):this._ensurePossibleRejectionHandled())},i.prototype._fulfillPromises=function(t,e){for(var n=1;t>n;n++){var r=this._fulfillmentHandlerAt(n),i=this._promiseAt(n),o=this._receiverAt(n);this._clearCallbackDataAtIndex(n),this._settlePromise(i,r,o,e)}},i.prototype._rejectPromises=function(t,e){for(var n=1;t>n;n++){var r=this._rejectionHandlerAt(n),i=this._promiseAt(n),o=this._receiverAt(n);this._clearCallbackDataAtIndex(n),this._settlePromise(i,r,o,e)}},i.prototype._settlePromises=function(){var t=this._bitField,e=65535&t;if(e>0){if(0!==(16842752&t)){var n=this._fulfillmentHandler0;this._settlePromise0(this._rejectionHandler0,n,t),this._rejectPromises(e,n)}else{var r=this._rejectionHandler0;this._settlePromise0(this._fulfillmentHandler0,r,t),this._fulfillPromises(e,r)}this._setLength(0)}this._clearCancellationData()},i.prototype._settledValue=function(){var t=this._bitField;return 0!==(33554432&t)?this._rejectionHandler0:0!==(16777216&t)?this._fulfillmentHandler0:void 0},i.defer=i.pending=function(){x.deprecated("Promise.defer","new Promise");var t=new i(b);return{promise:t,resolve:o,reject:s}},f.notEnumerableProp(i,"_makeSelfResolutionError",l),t("./method")(i,b,j,p,x),t("./bind")(i,b,j,x),t("./cancel")(i,k,p,x),t("./direct_resolve")(i),t("./synchronous_inspection")(i),t("./join")(i,k,j,b,v,c),i.Promise=i,i.version="3.4.5",t("./map.js")(i,k,p,j,b,x),t("./call_get.js")(i),t("./using.js")(i,p,j,F,b,x),t("./timers.js")(i,b,x),t("./generators.js")(i,p,b,j,n,x),t("./nodeify.js")(i),t("./promisify.js")(i,b),t("./props.js")(i,k,j,p),t("./race.js")(i,b,j,p),t("./reduce.js")(i,k,p,j,b,x),t("./settle.js")(i,k,x),t("./some.js")(i,k,p),t("./filter.js")(i,b),t("./each.js")(i,b),t("./any.js")(i),f.toFastProperties(i),f.toFastProperties(i.prototype),a({a:1}),a({b:2}),a({c:3}),a(1),a(function(){}),a(void 0),a(!1),a(new i(b)),x.setBounds(d.firstLineError,f.lastLineError),i}},{"./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(t,e,n){"use strict";e.exports=function(e,n,r,i,o){function s(t){switch(t){case-2:return[];case-3:return{}}}function a(t){var r=this._promise=new e(n);t instanceof e&&r._propagateFrom(t,3),r._setOnCancel(this),this._values=t,this._length=0,this._totalResolved=0,this._init(void 0,-2)}var c=t("./util");c.isArray;return c.inherits(a,o),a.prototype.length=function(){return this._length},a.prototype.promise=function(){return this._promise},a.prototype._init=function l(t,n){var o=r(this._values,this._promise);if(o instanceof e){o=o._target();var a=o._bitField;if(this._values=o,0===(50397184&a))return this._promise._setAsyncGuaranteed(),o._then(l,this._reject,void 0,this,n);if(0===(33554432&a))return 0!==(16777216&a)?this._reject(o._reason()):this._cancel();o=o._value()}if(o=c.asArray(o),null===o){var u=i("expecting an array or an iterable object but got "+c.classString(o)).reason();return void this._promise._rejectCallback(u,!1)}return 0===o.length?void(-5===n?this._resolveEmptyArray():this._resolve(s(n))):void this._iterate(o)},a.prototype._iterate=function(t){var n=this.getActualLength(t.length);this._length=n,this._values=this.shouldCopyValues()?new Array(n):this._values;for(var i=this._promise,o=!1,s=null,a=0;n>a;++a){var c=r(t[a],i);c instanceof e?(c=c._target(),s=c._bitField):s=null,o?null!==s&&c.suppressUnhandledRejections():null!==s?0===(50397184&s)?(c._proxy(this,a),this._values[a]=c):o=0!==(33554432&s)?this._promiseFulfilled(c._value(),a):0!==(16777216&s)?this._promiseRejected(c._reason(),a):this._promiseCancelled(a):o=this._promiseFulfilled(c,a)}o||i._setAsyncGuaranteed()},a.prototype._isResolved=function(){return null===this._values},a.prototype._resolve=function(t){this._values=null,this._promise._fulfill(t)},a.prototype._cancel=function(){!this._isResolved()&&this._promise._isCancellable()&&(this._values=null,this._promise._cancel())},a.prototype._reject=function(t){this._values=null,this._promise._rejectCallback(t,!1)},a.prototype._promiseFulfilled=function(t,e){this._values[e]=t;var n=++this._totalResolved;return n>=this._length?(this._resolve(this._values),!0):!1},a.prototype._promiseCancelled=function(){return this._cancel(),!0},a.prototype._promiseRejected=function(t){return this._totalResolved++,this._reject(t),!0},a.prototype._resultCancelled=function(){if(!this._isResolved()){var t=this._values;if(this._cancel(),t instanceof e)t.cancel();else for(var n=0;n<t.length;++n)t[n]instanceof e&&t[n].cancel()}},a.prototype.shouldCopyValues=function(){return!0},a.prototype.getActualLength=function(t){return t},a}},{"./util":36}],24:[function(t,e,n){"use strict";e.exports=function(e,n){function r(t){return!C.test(t)}function i(t){try{return t.__isPromisified__===!0}catch(e){return!1}}function o(t,e,n){var r=f.getDataPropertyOrDefault(t,e+n,b);return r?i(r):!1}function s(t,e,n){for(var r=0;r<t.length;r+=2){var i=t[r];if(n.test(i))for(var o=i.replace(n,""),s=0;s<t.length;s+=2)if(t[s]===o)throw new m("Cannot promisify an API that has normal methods with '%s'-suffix\n\n    See http://goo.gl/MqrFmX\n".replace("%s",e))}}function a(t,e,n,r){for(var a=f.inheritedDataKeys(t),c=[],l=0;l<a.length;++l){var u=a[l],p=t[u],h=r===j?!0:j(u,p,t);"function"!=typeof p||i(p)||o(t,u,e)||!r(u,p,t,h)||c.push(u,p)}return s(c,e,n),c}function c(t,r,i,o,s,a){function c(){var i=r;r===h&&(i=this);var o=new e(n);o._captureStackTrace();var s="string"==typeof u&&this!==l?this[u]:t,c=_(o,a);try{s.apply(i,d(arguments,c))}catch(p){o._rejectCallback(v(p),!0,!0)}return o._isFateSealed()||o._setAsyncGuaranteed(),o}var l=function(){return this}(),u=t;return"string"==typeof u&&(t=o),f.notEnumerableProp(c,"__isPromisified__",!0),c}function l(t,e,n,r,i){for(var o=new RegExp(k(e)+"$"),s=a(t,e,o,n),c=0,l=s.length;l>c;c+=2){var u=s[c],p=s[c+1],_=u+e;if(r===E)t[_]=E(u,h,u,p,e,i);else{var d=r(p,function(){return E(u,h,u,p,e,i)});f.notEnumerableProp(d,"__isPromisified__",!0),t[_]=d}}return f.toFastProperties(t),t}function u(t,e,n){return E(t,e,void 0,t,null,n)}var p,h={},f=t("./util"),_=t("./nodeback"),d=f.withAppended,v=f.maybeWrapAsError,y=f.canEvaluate,m=t("./errors").TypeError,g="Async",b={__isPromisified__:!0},w=["arity","length","name","arguments","caller","callee","prototype","__isPromisified__"],C=new RegExp("^(?:"+w.join("|")+")$"),j=function(t){return f.isIdentifier(t)&&"_"!==t.charAt(0)&&"constructor"!==t},k=function(t){return t.replace(/([$])/,"\\$")},E=y?p:c;e.promisify=function(t,e){if("function"!=typeof t)throw new m("expecting a function but got "+f.classString(t));if(i(t))return t;e=Object(e);var n=void 0===e.context?h:e.context,o=!!e.multiArgs,s=u(t,n,o);return f.copyDescriptors(t,s,r),s},e.promisifyAll=function(t,e){if("function"!=typeof t&&"object"!=typeof t)throw new m("the target of promisifyAll must be an object or a function\n\n    See http://goo.gl/MqrFmX\n");e=Object(e);var n=!!e.multiArgs,r=e.suffix;"string"!=typeof r&&(r=g);var i=e.filter;"function"!=typeof i&&(i=j);var o=e.promisifier;if("function"!=typeof o&&(o=E),!f.isIdentifier(r))throw new RangeError("suffix must be a valid identifier\n\n    See http://goo.gl/MqrFmX\n");for(var s=f.inheritedDataKeys(t),a=0;a<s.length;++a){var c=t[s[a]];"constructor"!==s[a]&&f.isClass(c)&&(l(c.prototype,r,i,o,n),l(c,r,i,o,n))}return l(t,r,i,o,n)}}},{"./errors":12,"./nodeback":20,"./util":36}],25:[function(t,e,n){"use strict";e.exports=function(e,n,r,i){function o(t){var e,n=!1;if(void 0!==a&&t instanceof a)e=p(t),n=!0;else{var r=u.keys(t),i=r.length;e=new Array(2*i);for(var o=0;i>o;++o){var s=r[o];e[o]=t[s],e[o+i]=s}}this.constructor$(e),this._isMap=n,this._init$(void 0,-3)}function s(t){var n,s=r(t);return l(s)?(n=s instanceof e?s._then(e.props,void 0,void 0,void 0,void 0):new o(s).promise(),s instanceof e&&n._propagateFrom(s,2),n):i("cannot await properties of a non-object\n\n    See http://goo.gl/MqrFmX\n")}var a,c=t("./util"),l=c.isObject,u=t("./es5");"function"==typeof Map&&(a=Map);var p=function(){function t(t,r){this[e]=t,this[e+n]=r,e++}var e=0,n=0;return function(r){n=r.size,e=0;var i=new Array(2*r.size);return r.forEach(t,i),i}}(),h=function(t){for(var e=new a,n=t.length/2|0,r=0;n>r;++r){var i=t[n+r],o=t[r];e.set(i,o)}return e};c.inherits(o,n),o.prototype._init=function(){},o.prototype._promiseFulfilled=function(t,e){this._values[e]=t;var n=++this._totalResolved;if(n>=this._length){var r;if(this._isMap)r=h(this._values);else{r={};for(var i=this.length(),o=0,s=this.length();s>o;++o)r[this._values[o+i]]=this._values[o]}return this._resolve(r),!0}return!1},o.prototype.shouldCopyValues=function(){return!1},o.prototype.getActualLength=function(t){return t>>1},e.prototype.props=function(){return s(this)},e.props=function(t){return s(t)}}},{"./es5":13,"./util":36}],26:[function(t,e,n){"use strict";function r(t,e,n,r,i){for(var o=0;i>o;++o)n[o+r]=t[o+e],t[o+e]=void 0}function i(t){this._capacity=t,this._length=0,this._front=0}i.prototype._willBeOverCapacity=function(t){return this._capacity<t},i.prototype._pushOne=function(t){var e=this.length();this._checkCapacity(e+1);var n=this._front+e&this._capacity-1;this[n]=t,this._length=e+1},i.prototype._unshiftOne=function(t){var e=this._capacity;this._checkCapacity(this.length()+1);var n=this._front,r=(n-1&e-1^e)-e;this[r]=t,this._front=r,this._length=this.length()+1},i.prototype.unshift=function(t,e,n){this._unshiftOne(n),this._unshiftOne(e),this._unshiftOne(t)},i.prototype.push=function(t,e,n){var r=this.length()+3;if(this._willBeOverCapacity(r))return this._pushOne(t),this._pushOne(e),void this._pushOne(n);var i=this._front+r-3;this._checkCapacity(r);var o=this._capacity-1;this[i+0&o]=t,this[i+1&o]=e,this[i+2&o]=n,this._length=r},i.prototype.shift=function(){var t=this._front,e=this[t];return this[t]=void 0,this._front=t+1&this._capacity-1,this._length--,e},i.prototype.length=function(){return this._length},i.prototype._checkCapacity=function(t){this._capacity<t&&this._resizeTo(this._capacity<<1)},i.prototype._resizeTo=function(t){var e=this._capacity;this._capacity=t;var n=this._front,i=this._length,o=n+i&e-1;r(this,0,this,e,o)},e.exports=i},{}],27:[function(t,e,n){"use strict";e.exports=function(e,n,r,i){function o(t,o){var c=r(t);if(c instanceof e)return a(c);if(t=s.asArray(t),null===t)return i("expecting an array or an iterable object but got "+s.classString(t));var l=new e(n);void 0!==o&&l._propagateFrom(o,3);for(var u=l._fulfill,p=l._reject,h=0,f=t.length;f>h;++h){var _=t[h];(void 0!==_||h in t)&&e.cast(_)._then(u,p,void 0,l,null)}return l}var s=t("./util"),a=function(t){return t.then(function(e){return o(e,t)})};e.race=function(t){return o(t,void 0)},e.prototype.race=function(){return o(this,void 0)}}},{"./util":36}],28:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){function a(t,n,r,i){this.constructor$(t);var s=h();this._fn=null===s?n:f.domainBind(s,n),void 0!==r&&(r=e.resolve(r),r._attachCancellationCallback(this)),this._initialValue=r,this._currentCancellable=null,i===o?this._eachValues=Array(this._length):0===i?this._eachValues=null:this._eachValues=void 0,this._promise._captureStackTrace(),this._init$(void 0,-5)}function c(t,e){this.isFulfilled()?e._resolve(t):e._reject(t)}function l(t,e,n,i){if("function"!=typeof e)return r("expecting a function but got "+f.classString(e));var o=new a(t,e,n,i);return o.promise()}function u(t){this.accum=t,this.array._gotAccum(t);var n=i(this.value,this.array._promise);return n instanceof e?(this.array._currentCancellable=n,n._then(p,void 0,void 0,this,void 0)):p.call(this,n)}function p(t){var n=this.array,r=n._promise,i=_(n._fn);r._pushContext();var o;o=void 0!==n._eachValues?i.call(r._boundValue(),t,this.index,this.length):i.call(r._boundValue(),this.accum,t,this.index,this.length),o instanceof e&&(n._currentCancellable=o);var a=r._popContext();return s.checkForgottenReturns(o,a,void 0!==n._eachValues?"Promise.each":"Promise.reduce",r),o}var h=e._getDomain,f=t("./util"),_=f.tryCatch;f.inherits(a,n),a.prototype._gotAccum=function(t){void 0!==this._eachValues&&null!==this._eachValues&&t!==o&&this._eachValues.push(t)},a.prototype._eachComplete=function(t){return null!==this._eachValues&&this._eachValues.push(t),this._eachValues},a.prototype._init=function(){},a.prototype._resolveEmptyArray=function(){this._resolve(void 0!==this._eachValues?this._eachValues:this._initialValue)},a.prototype.shouldCopyValues=function(){return!1},a.prototype._resolve=function(t){this._promise._resolveCallback(t),this._values=null},a.prototype._resultCancelled=function(t){return t===this._initialValue?this._cancel():void(this._isResolved()||(this._resultCancelled$(),this._currentCancellable instanceof e&&this._currentCancellable.cancel(),this._initialValue instanceof e&&this._initialValue.cancel()))},a.prototype._iterate=function(t){this._values=t;var n,r,i=t.length;if(void 0!==this._initialValue?(n=this._initialValue,r=0):(n=e.resolve(t[0]),r=1),this._currentCancellable=n,!n.isRejected())for(;i>r;++r){var o={accum:null,value:t[r],index:r,length:i,array:this};n=n._then(u,void 0,void 0,o,void 0)}void 0!==this._eachValues&&(n=n._then(this._eachComplete,void 0,void 0,this,void 0)),n._then(c,c,void 0,n,this)},e.prototype.reduce=function(t,e){return l(this,t,e,null)},e.reduce=function(t,e,n,r){return l(t,e,n,r)}}},{"./util":36}],29:[function(t,e,n){"use strict";var r,i=t("./util"),o=function(){throw new Error("No async scheduler available\n\n    See http://goo.gl/MqrFmX\n")},s=i.getNativePromise();if(i.isNode&&"undefined"==typeof MutationObserver){var a=global.setImmediate,c=process.nextTick;r=i.isRecentNode?function(t){a.call(global,t)}:function(t){c.call(process,t)}}else if("function"==typeof s&&"function"==typeof s.resolve){var l=s.resolve();r=function(t){l.then(t)}}else r="undefined"==typeof MutationObserver||"undefined"!=typeof window&&window.navigator&&(window.navigator.standalone||window.cordova)?"undefined"!=typeof setImmediate?function(t){setImmediate(t)}:"undefined"!=typeof setTimeout?function(t){setTimeout(t,0)}:o:function(){var t=document.createElement("div"),e={attributes:!0},n=!1,r=document.createElement("div"),i=new MutationObserver(function(){t.classList.toggle("foo"),n=!1});i.observe(r,e);var o=function(){n||(n=!0,r.classList.toggle("foo"))};return function(n){var r=new MutationObserver(function(){r.disconnect(),n()});r.observe(t,e),o()}}();e.exports=r},{"./util":36}],30:[function(t,e,n){"use strict";e.exports=function(e,n,r){function i(t){this.constructor$(t)}var o=e.PromiseInspection,s=t("./util");s.inherits(i,n),i.prototype._promiseResolved=function(t,e){this._values[t]=e;var n=++this._totalResolved;return n>=this._length?(this._resolve(this._values),!0):!1},i.prototype._promiseFulfilled=function(t,e){var n=new o;return n._bitField=33554432,n._settledValueField=t,this._promiseResolved(e,n)},i.prototype._promiseRejected=function(t,e){var n=new o;return n._bitField=16777216,n._settledValueField=t,this._promiseResolved(e,n)},e.settle=function(t){return r.deprecated(".settle()",".reflect()"),new i(t).promise()},e.prototype.settle=function(){return e.settle(this)}}},{"./util":36}],31:[function(t,e,n){"use strict";e.exports=function(e,n,r){function i(t){this.constructor$(t),this._howMany=0,this._unwrap=!1,this._initialized=!1}function o(t,e){if((0|e)!==e||0>e)return r("expecting a positive integer\n\n    See http://goo.gl/MqrFmX\n");
var n=new i(t),o=n.promise();return n.setHowMany(e),n.init(),o}var s=t("./util"),a=t("./errors").RangeError,c=t("./errors").AggregateError,l=s.isArray,u={};s.inherits(i,n),i.prototype._init=function(){if(this._initialized){if(0===this._howMany)return void this._resolve([]);this._init$(void 0,-5);var t=l(this._values);!this._isResolved()&&t&&this._howMany>this._canPossiblyFulfill()&&this._reject(this._getRangeError(this.length()))}},i.prototype.init=function(){this._initialized=!0,this._init()},i.prototype.setUnwrap=function(){this._unwrap=!0},i.prototype.howMany=function(){return this._howMany},i.prototype.setHowMany=function(t){this._howMany=t},i.prototype._promiseFulfilled=function(t){return this._addFulfilled(t),this._fulfilled()===this.howMany()?(this._values.length=this.howMany(),1===this.howMany()&&this._unwrap?this._resolve(this._values[0]):this._resolve(this._values),!0):!1},i.prototype._promiseRejected=function(t){return this._addRejected(t),this._checkOutcome()},i.prototype._promiseCancelled=function(){return this._values instanceof e||null==this._values?this._cancel():(this._addRejected(u),this._checkOutcome())},i.prototype._checkOutcome=function(){if(this.howMany()>this._canPossiblyFulfill()){for(var t=new c,e=this.length();e<this._values.length;++e)this._values[e]!==u&&t.push(this._values[e]);return t.length>0?this._reject(t):this._cancel(),!0}return!1},i.prototype._fulfilled=function(){return this._totalResolved},i.prototype._rejected=function(){return this._values.length-this.length()},i.prototype._addRejected=function(t){this._values.push(t)},i.prototype._addFulfilled=function(t){this._values[this._totalResolved++]=t},i.prototype._canPossiblyFulfill=function(){return this.length()-this._rejected()},i.prototype._getRangeError=function(t){var e="Input array must contain at least "+this._howMany+" items but contains only "+t+" items";return new a(e)},i.prototype._resolveEmptyArray=function(){this._reject(this._getRangeError(0))},e.some=function(t,e){return o(t,e)},e.prototype.some=function(t){return o(this,t)},e._SomePromiseArray=i}},{"./errors":12,"./util":36}],32:[function(t,e,n){"use strict";e.exports=function(t){function e(t){void 0!==t?(t=t._target(),this._bitField=t._bitField,this._settledValueField=t._isFateSealed()?t._settledValue():void 0):(this._bitField=0,this._settledValueField=void 0)}e.prototype._settledValue=function(){return this._settledValueField};var n=e.prototype.value=function(){if(!this.isFulfilled())throw new TypeError("cannot get fulfillment value of a non-fulfilled promise\n\n    See http://goo.gl/MqrFmX\n");return this._settledValue()},r=e.prototype.error=e.prototype.reason=function(){if(!this.isRejected())throw new TypeError("cannot get rejection reason of a non-rejected promise\n\n    See http://goo.gl/MqrFmX\n");return this._settledValue()},i=e.prototype.isFulfilled=function(){return 0!==(33554432&this._bitField)},o=e.prototype.isRejected=function(){return 0!==(16777216&this._bitField)},s=e.prototype.isPending=function(){return 0===(50397184&this._bitField)},a=e.prototype.isResolved=function(){return 0!==(50331648&this._bitField)};e.prototype.isCancelled=function(){return 0!==(8454144&this._bitField)},t.prototype.__isCancelled=function(){return 65536===(65536&this._bitField)},t.prototype._isCancelled=function(){return this._target().__isCancelled()},t.prototype.isCancelled=function(){return 0!==(8454144&this._target()._bitField)},t.prototype.isPending=function(){return s.call(this._target())},t.prototype.isRejected=function(){return o.call(this._target())},t.prototype.isFulfilled=function(){return i.call(this._target())},t.prototype.isResolved=function(){return a.call(this._target())},t.prototype.value=function(){return n.call(this._target())},t.prototype.reason=function(){var t=this._target();return t._unsetRejectionIsUnhandled(),r.call(t)},t.prototype._value=function(){return this._settledValue()},t.prototype._reason=function(){return this._unsetRejectionIsUnhandled(),this._settledValue()},t.PromiseInspection=e}},{}],33:[function(t,e,n){"use strict";e.exports=function(e,n){function r(t,r){if(u(t)){if(t instanceof e)return t;var i=o(t);if(i===l){r&&r._pushContext();var c=e.reject(i.e);return r&&r._popContext(),c}if("function"==typeof i){if(s(t)){var c=new e(n);return t._then(c._fulfill,c._reject,void 0,c,null),c}return a(t,i,r)}}return t}function i(t){return t.then}function o(t){try{return i(t)}catch(e){return l.e=e,l}}function s(t){try{return p.call(t,"_promise0")}catch(e){return!1}}function a(t,r,i){function o(t){a&&(a._resolveCallback(t),a=null)}function s(t){a&&(a._rejectCallback(t,p,!0),a=null)}var a=new e(n),u=a;i&&i._pushContext(),a._captureStackTrace(),i&&i._popContext();var p=!0,h=c.tryCatch(r).call(t,o,s);return p=!1,a&&h===l&&(a._rejectCallback(h.e,!0,!0),a=null),u}var c=t("./util"),l=c.errorObj,u=c.isObject,p={}.hasOwnProperty;return r}},{"./util":36}],34:[function(t,e,n){"use strict";e.exports=function(e,n,r){function i(t){this.handle=t}function o(t){return clearTimeout(this.handle),t}function s(t){throw clearTimeout(this.handle),t}var a=t("./util"),c=e.TimeoutError;i.prototype._resultCancelled=function(){clearTimeout(this.handle)};var l=function(t){return u(+this).thenReturn(t)},u=e.delay=function(t,o){var s,a;return void 0!==o?(s=e.resolve(o)._then(l,null,null,t,void 0),r.cancellation()&&o instanceof e&&s._setOnCancel(o)):(s=new e(n),a=setTimeout(function(){s._fulfill()},+t),r.cancellation()&&s._setOnCancel(new i(a)),s._captureStackTrace()),s._setAsyncGuaranteed(),s};e.prototype.delay=function(t){return u(t,this)};var p=function(t,e,n){var r;r="string"!=typeof e?e instanceof Error?e:new c("operation timed out"):new c(e),a.markAsOriginatingFromRejection(r),t._attachExtraTrace(r),t._reject(r),null!=n&&n.cancel()};e.prototype.timeout=function(t,e){t=+t;var n,a,c=new i(setTimeout(function(){n.isPending()&&p(n,e,a)},t));return r.cancellation()?(a=this.then(),n=a._then(o,s,void 0,c,void 0),n._setOnCancel(c)):n=this._then(o,s,void 0,c,void 0),n}}},{"./util":36}],35:[function(t,e,n){"use strict";e.exports=function(e,n,r,i,o,s){function a(t){setTimeout(function(){throw t},0)}function c(t){var e=r(t);return e!==t&&"function"==typeof t._isDisposable&&"function"==typeof t._getDisposer&&t._isDisposable()&&e._setDisposable(t._getDisposer()),e}function l(t,n){function i(){if(s>=l)return u._fulfill();var o=c(t[s++]);if(o instanceof e&&o._isDisposable()){try{o=r(o._getDisposer().tryDispose(n),t.promise)}catch(p){return a(p)}if(o instanceof e)return o._then(i,a,null,null,null)}i()}var s=0,l=t.length,u=new e(o);return i(),u}function u(t,e,n){this._data=t,this._promise=e,this._context=n}function p(t,e,n){this.constructor$(t,e,n)}function h(t){return u.isDisposer(t)?(this.resources[this.index]._setDisposable(t),t.promise()):t}function f(t){this.length=t,this.promise=null,this[t-1]=null}var _=t("./util"),d=t("./errors").TypeError,v=t("./util").inherits,y=_.errorObj,m=_.tryCatch,g={};u.prototype.data=function(){return this._data},u.prototype.promise=function(){return this._promise},u.prototype.resource=function(){return this.promise().isFulfilled()?this.promise().value():g},u.prototype.tryDispose=function(t){var e=this.resource(),n=this._context;void 0!==n&&n._pushContext();var r=e!==g?this.doDispose(e,t):null;return void 0!==n&&n._popContext(),this._promise._unsetDisposable(),this._data=null,r},u.isDisposer=function(t){return null!=t&&"function"==typeof t.resource&&"function"==typeof t.tryDispose},v(p,u),p.prototype.doDispose=function(t,e){var n=this.data();return n.call(t,t,e)},f.prototype._resultCancelled=function(){for(var t=this.length,n=0;t>n;++n){var r=this[n];r instanceof e&&r.cancel()}},e.using=function(){var t=arguments.length;if(2>t)return n("you must pass at least 2 arguments to Promise.using");var i=arguments[t-1];if("function"!=typeof i)return n("expecting a function but got "+_.classString(i));var o,a=!0;2===t&&Array.isArray(arguments[0])?(o=arguments[0],t=o.length,a=!1):(o=arguments,t--);for(var c=new f(t),p=0;t>p;++p){var d=o[p];if(u.isDisposer(d)){var v=d;d=d.promise(),d._setDisposable(v)}else{var g=r(d);g instanceof e&&(d=g._then(h,null,null,{resources:c,index:p},void 0))}c[p]=d}for(var b=new Array(c.length),p=0;p<b.length;++p)b[p]=e.resolve(c[p]).reflect();var w=e.all(b).then(function(t){for(var e=0;e<t.length;++e){var n=t[e];if(n.isRejected())return y.e=n.error(),y;if(!n.isFulfilled())return void w.cancel();t[e]=n.value()}C._pushContext(),i=m(i);var r=a?i.apply(void 0,t):i(t),o=C._popContext();return s.checkForgottenReturns(r,o,"Promise.using",C),r}),C=w.lastly(function(){var t=new e.PromiseInspection(w);return l(c,t)});return c.promise=C,C._setOnCancel(c),C},e.prototype._setDisposable=function(t){this._bitField=131072|this._bitField,this._disposer=t},e.prototype._isDisposable=function(){return(131072&this._bitField)>0},e.prototype._getDisposer=function(){return this._disposer},e.prototype._unsetDisposable=function(){this._bitField=-131073&this._bitField,this._disposer=void 0},e.prototype.disposer=function(t){if("function"==typeof t)return new p(t,this,i());throw new d}}},{"./errors":12,"./util":36}],36:[function(t,e,n){"use strict";function r(){try{var t=P;return P=null,t.apply(this,arguments)}catch(e){return T.e=e,T}}function i(t){return P=t,r}function o(t){return null==t||t===!0||t===!1||"string"==typeof t||"number"==typeof t}function s(t){return"function"==typeof t||"object"==typeof t&&null!==t}function a(t){return o(t)?new Error(v(t)):t}function c(t,e){var n,r=t.length,i=new Array(r+1);for(n=0;r>n;++n)i[n]=t[n];return i[n]=e,i}function l(t,e,n){if(!F.isES5)return{}.hasOwnProperty.call(t,e)?t[e]:void 0;var r=Object.getOwnPropertyDescriptor(t,e);return null!=r?null==r.get&&null==r.set?r.value:n:void 0}function u(t,e,n){if(o(t))return t;var r={value:n,configurable:!0,enumerable:!1,writable:!0};return F.defineProperty(t,e,r),t}function p(t){throw t}function h(t){try{if("function"==typeof t){var e=F.names(t.prototype),n=F.isES5&&e.length>1,r=e.length>0&&!(1===e.length&&"constructor"===e[0]),i=A.test(t+"")&&F.names(t).length>0;if(n||r||i)return!0}return!1}catch(o){return!1}}function f(t){function e(){}e.prototype=t;for(var n=8;n--;)new e;return t}function _(t){return D.test(t)}function d(t,e,n){for(var r=new Array(t),i=0;t>i;++i)r[i]=e+i+n;return r}function v(t){try{return t+""}catch(e){return"[no string representation]"}}function y(t){return null!==t&&"object"==typeof t&&"string"==typeof t.message&&"string"==typeof t.name}function m(t){try{u(t,"isOperational",!0)}catch(e){}}function g(t){return null==t?!1:t instanceof Error.__BluebirdErrorTypes__.OperationalError||t.isOperational===!0}function b(t){return y(t)&&F.propertyIsWritable(t,"stack")}function w(t){return{}.toString.call(t)}function C(t,e,n){for(var r=F.names(t),i=0;i<r.length;++i){var o=r[i];if(n(o))try{F.defineProperty(e,o,F.getDescriptor(t,o))}catch(s){}}}function j(t,e){return H?process.env[t]:e}function k(){if("function"==typeof Promise)try{var t=new Promise(function(){});if("[object Promise]"==={}.toString.call(t))return Promise}catch(e){}}function E(t,e){return t.bind(e)}var F=t("./es5"),x="undefined"==typeof navigator,T={e:{}},P,R="undefined"!=typeof self?self:"undefined"!=typeof window?window:"undefined"!=typeof global?global:void 0!==this?this:null,S=function(t,e){function n(){this.constructor=t,this.constructor$=e;for(var n in e.prototype)r.call(e.prototype,n)&&"$"!==n.charAt(n.length-1)&&(this[n+"$"]=e.prototype[n])}var r={}.hasOwnProperty;return n.prototype=e.prototype,t.prototype=new n,t.prototype},O=function(){var t=[Array.prototype,Object.prototype,Function.prototype],e=function(e){for(var n=0;n<t.length;++n)if(t[n]===e)return!0;return!1};if(F.isES5){var n=Object.getOwnPropertyNames;return function(t){for(var r=[],i=Object.create(null);null!=t&&!e(t);){var o;try{o=n(t)}catch(s){return r}for(var a=0;a<o.length;++a){var c=o[a];if(!i[c]){i[c]=!0;var l=Object.getOwnPropertyDescriptor(t,c);null!=l&&null==l.get&&null==l.set&&r.push(c)}}t=F.getPrototypeOf(t)}return r}}var r={}.hasOwnProperty;return function(n){if(e(n))return[];var i=[];t:for(var o in n)if(r.call(n,o))i.push(o);else{for(var s=0;s<t.length;++s)if(r.call(t[s],o))continue t;i.push(o)}return i}}(),A=/this\s*\.\s*\S+\s*=/,D=/^[a-z$_][a-z$_0-9]*$/i,V=function(){return"stack"in new Error?function(t){return b(t)?t:new Error(v(t))}:function(t){if(b(t))return t;try{throw new Error(v(t))}catch(e){return e}}}(),L=function(t){return F.isArray(t)?t:null};if("undefined"!=typeof Symbol&&Symbol.iterator){var I="function"==typeof Array.from?function(t){return Array.from(t)}:function(t){for(var e,n=[],r=t[Symbol.iterator]();!(e=r.next()).done;)n.push(e.value);return n};L=function(t){return F.isArray(t)?t:null!=t&&"function"==typeof t[Symbol.iterator]?I(t):null}}var H="undefined"!=typeof process&&"[object process]"===w(process).toLowerCase(),N={isClass:h,isIdentifier:_,inheritedDataKeys:O,getDataPropertyOrDefault:l,thrower:p,isArray:F.isArray,asArray:L,notEnumerableProp:u,isPrimitive:o,isObject:s,isError:y,canEvaluate:x,errorObj:T,tryCatch:i,inherits:S,withAppended:c,maybeWrapAsError:a,toFastProperties:f,filledRange:d,toString:v,canAttachTrace:b,ensureErrorObject:V,originatesFromRejection:g,markAsOriginatingFromRejection:m,classString:w,copyDescriptors:C,hasDevTools:"undefined"!=typeof chrome&&chrome&&"function"==typeof chrome.loadTimes,isNode:H,env:j,global:R,getNativePromise:k,domainBind:E};N.isRecentNode=N.isNode&&function(){var t=process.versions.node.split(".").map(Number);return 0===t[0]&&t[1]>10||t[0]>0}(),N.isNode&&N.toFastProperties(process);try{throw new Error}catch(B){N.lastLineError=B}e.exports=N},{"./es5":13}]},{},[4])(4)}),"undefined"!=typeof window&&null!==window?window.P=window.Promise:"undefined"!=typeof self&&null!==self&&(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.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 = cur[part];
      } else {
        cur = cur[part] = {};
      }
    }
  }
};
goog.define = function(name, defaultValue) {
  var value = defaultValue;
  if (!COMPILED) {
    if (goog.global.CLOSURE_UNCOMPILED_DEFINES && Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_UNCOMPILED_DEFINES, name)) {
      value = goog.global.CLOSURE_UNCOMPILED_DEFINES[name];
    } else {
      if (goog.global.CLOSURE_DEFINES && Object.prototype.hasOwnProperty.call(goog.global.CLOSURE_DEFINES, name)) {
        value = goog.global.CLOSURE_DEFINES[name];
      }
    }
  }
  goog.exportPath_(name, value);
};
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.basePath = goog.global.CLOSURE_BASE_PATH;
      return;
    } else {
      if (!goog.inHtmlDocument_()) {
        return;
      }
    }
    var doc = goog.global.document;
    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.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.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 {
          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.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)) {
        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 && goog.isObject(exports)) {
        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.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.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.isString = function(val) {
  return typeof val == "string";
};
goog.isBoolean = function(val) {
  return typeof val == "boolean";
};
goog.isNumber = function(val) {
  return typeof val == "number";
};
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.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;
    }
  }
  addNewerLanguageTranspilationCheck("es5", function() {
    return evalCheck("[1,].length==1");
  });
  addNewerLanguageTranspilationCheck("es6", function() {
    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(Array.prototype, arguments);
};
goog.array.join = function(var_args) {
  return Array.prototype.concat.apply(Array.prototype, 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.dom.TagName");
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.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) {
  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)) {
    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.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.SafeUrl");
goog.require("goog.asserts");
goog.require("goog.fs.url");
goog.require("goog.i18n.bidi.Dir");
goog.require("goog.i18n.bidi.DirectionalString");
goog.require("goog.string");
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.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.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.:[\]-]+\/|^\/[^\/\\]/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.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.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.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.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.isEmpty(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.structs");
goog.require("goog.array");
goog.require("goog.object");
goog.structs.getCount = function(col) {
  if (col.getCount && typeof col.getCount == "function") {
    return col.getCount();
  }
  if (goog.isArrayLike(col) || goog.isString(col)) {
    return col.length;
  }
  return goog.object.getCount(col);
};
goog.structs.getValues = function(col) {
  if (col.getValues && typeof col.getValues == "function") {
    return col.getValues();
  }
  if (goog.isString(col)) {
    return col.split("");
  }
  if (goog.isArrayLike(col)) {
    var rv = [];
    var l = col.length;
    for (var i = 0;i < l;i++) {
      rv.push(col[i]);
    }
    return rv;
  }
  return goog.object.getValues(col);
};
goog.structs.getKeys = function(col) {
  if (col.getKeys && typeof col.getKeys == "function") {
    return col.getKeys();
  }
  if (col.getValues && typeof col.getValues == "function") {
    return undefined;
  }
  if (goog.isArrayLike(col) || goog.isString(col)) {
    var rv = [];
    var l = col.length;
    for (var i = 0;i < l;i++) {
      rv.push(i);
    }
    return rv;
  }
  return goog.object.getKeys(col);
};
goog.structs.contains = function(col, val) {
  if (col.contains && typeof col.contains == "function") {
    return col.contains(val);
  }
  if (col.containsValue && typeof col.containsValue == "function") {
    return col.containsValue(val);
  }
  if (goog.isArrayLike(col) || goog.isString(col)) {
    return goog.array.contains((col), val);
  }
  return goog.object.containsValue(col, val);
};
goog.structs.isEmpty = function(col) {
  if (col.isEmpty && typeof col.isEmpty == "function") {
    return col.isEmpty();
  }
  if (goog.isArrayLike(col) || goog.isString(col)) {
    return goog.array.isEmpty((col));
  }
  return goog.object.isEmpty(col);
};
goog.structs.clear = function(col) {
  if (col.clear && typeof col.clear == "function") {
    col.clear();
  } else {
    if (goog.isArrayLike(col)) {
      goog.array.clear((col));
    } else {
      goog.object.clear(col);
    }
  }
};
goog.structs.forEach = function(col, f, opt_obj) {
  if (col.forEach && typeof col.forEach == "function") {
    col.forEach(f, opt_obj);
  } else {
    if (goog.isArrayLike(col) || goog.isString(col)) {
      goog.array.forEach((col), f, opt_obj);
    } else {
      var keys = goog.structs.getKeys(col);
      var values = goog.structs.getValues(col);
      var l = values.length;
      for (var i = 0;i < l;i++) {
        f.call((opt_obj), values[i], keys && keys[i], col);
      }
    }
  }
};
goog.structs.filter = function(col, f, opt_obj) {
  if (typeof col.filter == "function") {
    return col.filter(f, opt_obj);
  }
  if (goog.isArrayLike(col) || goog.isString(col)) {
    return goog.array.filter((col), f, opt_obj);
  }
  var rv;
  var keys = goog.structs.getKeys(col);
  var values = goog.structs.getValues(col);
  var l = values.length;
  if (keys) {
    rv = {};
    for (var i = 0;i < l;i++) {
      if (f.call((opt_obj), values[i], keys[i], col)) {
        rv[keys[i]] = values[i];
      }
    }
  } else {
    rv = [];
    for (var i = 0;i < l;i++) {
      if (f.call(opt_obj, values[i], undefined, col)) {
        rv.push(values[i]);
      }
    }
  }
  return rv;
};
goog.structs.map = function(col, f, opt_obj) {
  if (typeof col.map == "function") {
    return col.map(f, opt_obj);
  }
  if (goog.isArrayLike(col) || goog.isString(col)) {
    return goog.array.map((col), f, opt_obj);
  }
  var rv;
  var keys = goog.structs.getKeys(col);
  var values = goog.structs.getValues(col);
  var l = values.length;
  if (keys) {
    rv = {};
    for (var i = 0;i < l;i++) {
      rv[keys[i]] = f.call((opt_obj), values[i], keys[i], col);
    }
  } else {
    rv = [];
    for (var i = 0;i < l;i++) {
      rv[i] = f.call((opt_obj), values[i], undefined, col);
    }
  }
  return rv;
};
goog.structs.some = function(col, f, opt_obj) {
  if (typeof col.some == "function") {
    return col.some(f, opt_obj);
  }
  if (goog.isArrayLike(col) || goog.isString(col)) {
    return goog.array.some((col), f, opt_obj);
  }
  var keys = goog.structs.getKeys(col);
  var values = goog.structs.getValues(col);
  var l = values.length;
  for (var i = 0;i < l;i++) {
    if (f.call((opt_obj), values[i], keys && keys[i], col)) {
      return true;
    }
  }
  return false;
};
goog.structs.every = function(col, f, opt_obj) {
  if (typeof col.every == "function") {
    return col.every(f, opt_obj);
  }
  if (goog.isArrayLike(col) || goog.isString(col)) {
    return goog.array.every((col), f, opt_obj);
  }
  var keys = goog.structs.getKeys(col);
  var values = goog.structs.getValues(col);
  var l = values.length;
  for (var i = 0;i < l;i++) {
    if (!f.call((opt_obj), values[i], keys && keys[i], col)) {
      return false;
    }
  }
  return true;
};
goog.provide("goog.structs.Collection");
goog.structs.Collection = function() {
};
goog.structs.Collection.prototype.add;
goog.structs.Collection.prototype.remove;
goog.structs.Collection.prototype.contains;
goog.structs.Collection.prototype.getCount;
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.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) && !isNaN(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.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$1) {
      if (ex$1 !== goog.iter.StopIteration) {
        throw ex$1;
      }
    }
  }
};
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.structs.Map");
goog.require("goog.iter.Iterator");
goog.require("goog.iter.StopIteration");
goog.require("goog.object");
goog.structs.Map = function(opt_map, var_args) {
  this.map_ = {};
  this.keys_ = [];
  this.count_ = 0;
  this.version_ = 0;
  var argLength = arguments.length;
  if (argLength > 1) {
    if (argLength % 2) {
      throw Error("Uneven number of arguments");
    }
    for (var i = 0;i < argLength;i += 2) {
      this.set(arguments[i], arguments[i + 1]);
    }
  } else {
    if (opt_map) {
      this.addAll((opt_map));
    }
  }
};
goog.structs.Map.prototype.getCount = function() {
  return this.count_;
};
goog.structs.Map.prototype.getValues = function() {
  this.cleanupKeysArray_();
  var rv = [];
  for (var i = 0;i < this.keys_.length;i++) {
    var key = this.keys_[i];
    rv.push(this.map_[key]);
  }
  return rv;
};
goog.structs.Map.prototype.getKeys = function() {
  this.cleanupKeysArray_();
  return (this.keys_.concat());
};
goog.structs.Map.prototype.containsKey = function(key) {
  return goog.structs.Map.hasKey_(this.map_, key);
};
goog.structs.Map.prototype.containsValue = function(val) {
  for (var i = 0;i < this.keys_.length;i++) {
    var key = this.keys_[i];
    if (goog.structs.Map.hasKey_(this.map_, key) && this.map_[key] == val) {
      return true;
    }
  }
  return false;
};
goog.structs.Map.prototype.equals = function(otherMap, opt_equalityFn) {
  if (this === otherMap) {
    return true;
  }
  if (this.count_ != otherMap.getCount()) {
    return false;
  }
  var equalityFn = opt_equalityFn || goog.structs.Map.defaultEquals;
  this.cleanupKeysArray_();
  for (var key, i = 0;key = this.keys_[i];i++) {
    if (!equalityFn(this.get(key), otherMap.get(key))) {
      return false;
    }
  }
  return true;
};
goog.structs.Map.defaultEquals = function(a, b) {
  return a === b;
};
goog.structs.Map.prototype.isEmpty = function() {
  return this.count_ == 0;
};
goog.structs.Map.prototype.clear = function() {
  this.map_ = {};
  this.keys_.length = 0;
  this.count_ = 0;
  this.version_ = 0;
};
goog.structs.Map.prototype.remove = function(key) {
  if (goog.structs.Map.hasKey_(this.map_, key)) {
    delete this.map_[key];
    this.count_--;
    this.version_++;
    if (this.keys_.length > 2 * this.count_) {
      this.cleanupKeysArray_();
    }
    return true;
  }
  return false;
};
goog.structs.Map.prototype.cleanupKeysArray_ = function() {
  if (this.count_ != this.keys_.length) {
    var srcIndex = 0;
    var destIndex = 0;
    while (srcIndex < this.keys_.length) {
      var key = this.keys_[srcIndex];
      if (goog.structs.Map.hasKey_(this.map_, key)) {
        this.keys_[destIndex++] = key;
      }
      srcIndex++;
    }
    this.keys_.length = destIndex;
  }
  if (this.count_ != this.keys_.length) {
    var seen = {};
    var srcIndex = 0;
    var destIndex = 0;
    while (srcIndex < this.keys_.length) {
      var key = this.keys_[srcIndex];
      if (!goog.structs.Map.hasKey_(seen, key)) {
        this.keys_[destIndex++] = key;
        seen[key] = 1;
      }
      srcIndex++;
    }
    this.keys_.length = destIndex;
  }
};
goog.structs.Map.prototype.get = function(key, opt_val) {
  if (goog.structs.Map.hasKey_(this.map_, key)) {
    return this.map_[key];
  }
  return opt_val;
};
goog.structs.Map.prototype.set = function(key, value) {
  if (!goog.structs.Map.hasKey_(this.map_, key)) {
    this.count_++;
    this.keys_.push((key));
    this.version_++;
  }
  this.map_[key] = value;
};
goog.structs.Map.prototype.addAll = function(map) {
  var keys, values;
  if (map instanceof goog.structs.Map) {
    keys = map.getKeys();
    values = map.getValues();
  } else {
    keys = goog.object.getKeys(map);
    values = goog.object.getValues(map);
  }
  for (var i = 0;i < keys.length;i++) {
    this.set(keys[i], values[i]);
  }
};
goog.structs.Map.prototype.forEach = function(f, opt_obj) {
  var keys = this.getKeys();
  for (var i = 0;i < keys.length;i++) {
    var key = keys[i];
    var value = this.get(key);
    f.call(opt_obj, value, key, this);
  }
};
goog.structs.Map.prototype.clone = function() {
  return new goog.structs.Map(this);
};
goog.structs.Map.prototype.transpose = function() {
  var transposed = new goog.structs.Map;
  for (var i = 0;i < this.keys_.length;i++) {
    var key = this.keys_[i];
    var value = this.map_[key];
    transposed.set(value, key);
  }
  return transposed;
};
goog.structs.Map.prototype.toObject = function() {
  this.cleanupKeysArray_();
  var obj = {};
  for (var i = 0;i < this.keys_.length;i++) {
    var key = this.keys_[i];
    obj[key] = this.map_[key];
  }
  return obj;
};
goog.structs.Map.prototype.getKeyIterator = function() {
  return this.__iterator__(true);
};
goog.structs.Map.prototype.getValueIterator = function() {
  return this.__iterator__(false);
};
goog.structs.Map.prototype.__iterator__ = function(opt_keys) {
  this.cleanupKeysArray_();
  var i = 0;
  var version = this.version_;
  var selfObj = this;
  var newIter = new goog.iter.Iterator;
  newIter.next = function() {
    if (version != selfObj.version_) {
      throw Error("The map has changed since the iterator was created");
    }
    if (i >= selfObj.keys_.length) {
      throw goog.iter.StopIteration;
    }
    var key = selfObj.keys_[i++];
    return opt_keys ? key : selfObj.map_[key];
  };
  return newIter;
};
goog.structs.Map.hasKey_ = function(obj, key) {
  return Object.prototype.hasOwnProperty.call(obj, key);
};
goog.provide("goog.structs.Set");
goog.require("goog.structs");
goog.require("goog.structs.Collection");
goog.require("goog.structs.Map");
goog.structs.Set = function(opt_values) {
  this.map_ = new goog.structs.Map;
  if (opt_values) {
    this.addAll(opt_values);
  }
};
goog.structs.Set.getKey_ = function(val) {
  var type = typeof val;
  if (type == "object" && val || type == "function") {
    return "o" + goog.getUid((val));
  } else {
    return type.substr(0, 1) + val;
  }
};
goog.structs.Set.prototype.getCount = function() {
  return this.map_.getCount();
};
goog.structs.Set.prototype.add = function(element) {
  this.map_.set(goog.structs.Set.getKey_(element), element);
};
goog.structs.Set.prototype.addAll = function(col) {
  var values = goog.structs.getValues(col);
  var l = values.length;
  for (var i = 0;i < l;i++) {
    this.add(values[i]);
  }
};
goog.structs.Set.prototype.removeAll = function(col) {
  var values = goog.structs.getValues(col);
  var l = values.length;
  for (var i = 0;i < l;i++) {
    this.remove(values[i]);
  }
};
goog.structs.Set.prototype.remove = function(element) {
  return this.map_.remove(goog.structs.Set.getKey_(element));
};
goog.structs.Set.prototype.clear = function() {
  this.map_.clear();
};
goog.structs.Set.prototype.isEmpty = function() {
  return this.map_.isEmpty();
};
goog.structs.Set.prototype.contains = function(element) {
  return this.map_.containsKey(goog.structs.Set.getKey_(element));
};
goog.structs.Set.prototype.containsAll = function(col) {
  return goog.structs.every(col, this.contains, this);
};
goog.structs.Set.prototype.intersection = function(col) {
  var result = new goog.structs.Set;
  var values = goog.structs.getValues(col);
  for (var i = 0;i < values.length;i++) {
    var value = values[i];
    if (this.contains(value)) {
      result.add(value);
    }
  }
  return result;
};
goog.structs.Set.prototype.difference = function(col) {
  var result = this.clone();
  result.removeAll(col);
  return result;
};
goog.structs.Set.prototype.getValues = function() {
  return this.map_.getValues();
};
goog.structs.Set.prototype.clone = function() {
  return new goog.structs.Set(this);
};
goog.structs.Set.prototype.equals = function(col) {
  return this.getCount() == goog.structs.getCount(col) && this.isSubsetOf(col);
};
goog.structs.Set.prototype.isSubsetOf = function(col) {
  var colCount = goog.structs.getCount(col);
  if (this.getCount() > colCount) {
    return false;
  }
  if (!(col instanceof goog.structs.Set) && colCount > 5) {
    col = new goog.structs.Set(col);
  }
  return goog.structs.every(this, function(value) {
    return goog.structs.contains(col, value);
  });
};
goog.structs.Set.prototype.__iterator__ = function(opt_keys) {
  return this.map_.__iterator__(false);
};
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.html.SafeHtml");
goog.require("goog.html.SafeUrl");
goog.require("goog.html.uncheckedconversions");
goog.require("goog.string.Const");
goog.require("goog.structs.Set");
goog.require("goog.userAgent");
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 helper = function(obj, space, parentSeen) {
    var nestspace = space + "  ";
    var seen = new goog.structs.Set(parentSeen);
    var indentMultiline = function(str) {
      return str.replace(/\n/g, "\n" + space);
    };
    try {
      if (!goog.isDef(obj)) {
        str.push("undefined");
      } else {
        if (goog.isNull(obj)) {
          str.push("NULL");
        } else {
          if (goog.isString(obj)) {
            str.push('"' + indentMultiline(obj) + '"');
          } else {
            if (goog.isFunction(obj)) {
              str.push(indentMultiline(String(obj)));
            } else {
              if (goog.isObject(obj)) {
                if (seen.contains(obj)) {
                  str.push("*** reference loop detected ***");
                } else {
                  seen.add(obj);
                  str.push("{");
                  for (var x in obj) {
                    if (!opt_showFn && goog.isFunction(obj[x])) {
                      continue;
                    }
                    str.push("\n");
                    str.push(nestspace);
                    str.push(x + " = ");
                    helper(obj[x], nestspace, seen);
                  }
                  str.push("\n" + space + "}");
                }
              } else {
                str.push(obj);
              }
            }
          }
        }
      }
    } catch (e) {
      str.push("*** " + e + " ***");
    }
  };
  helper(obj, "", new goog.structs.Set);
  return str.join("");
};
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.exposeException = function(err, opt_fn) {
  var html = goog.debug.exposeExceptionAsHtml(err, opt_fn);
  return goog.html.SafeHtml.unwrap(html);
};
goog.debug.exposeExceptionAsHtml = function(err, opt_fn) {
  try {
    var e = goog.debug.normalizeErrorObject(err);
    var viewSourceUrl = goog.debug.createViewSourceUrl_(e.fileName);
    var error = goog.html.SafeHtml.concat(goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces("Message: " + e.message + "\nUrl: "), goog.html.SafeHtml.create("a", {href:viewSourceUrl, target:"_new"}, e.fileName), goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces("\nLine: " + e.lineNumber + "\n\nBrowser stack:\n" + e.stack + "-> " + "[end]\n\nJS stack traversal:\n" + goog.debug.getStacktrace(opt_fn) + "-> "));
    return error;
  } catch (e2) {
    return goog.html.SafeHtml.htmlEscapePreservingNewlinesAndSpaces("Exception trying to expose exception! You win, we lose. " + e2);
  }
};
goog.debug.createViewSourceUrl_ = function(opt_fileName) {
  if (!goog.isDefAndNotNull(opt_fileName)) {
    opt_fileName = "";
  }
  if (!/^https?:\/\//i.test(opt_fileName)) {
    return goog.html.SafeUrl.fromConstant(goog.string.Const.from("sanitizedviewsrc"));
  }
  var sanitizedFileName = goog.html.SafeUrl.sanitize(opt_fileName);
  return goog.html.uncheckedconversions.safeUrlFromStringKnownToSatisfyTypeContract(goog.string.Const.from("view-source scheme plus HTTP/HTTPS URL"), "view-source:" + goog.html.SafeUrl.unwrap(sanitizedFileName));
};
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$2) {
    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(opt_fn) {
  var stack;
  if (!goog.debug.FORCE_SLOPPY_STACKS) {
    var contextFn = opt_fn || goog.debug.getStacktrace;
    stack = goog.debug.getNativeStackTrace_(contextFn);
  }
  if (!stack) {
    stack = goog.debug.getStacktraceHelper_(opt_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.safe");
goog.provide("goog.dom.safe.InsertAdjacentHtmlPosition");
goog.require("goog.asserts");
goog.require("goog.html.SafeHtml");
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.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.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 (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.BrowserEvent");
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() {
  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.creationStack;
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", 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", 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", 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:"textInput", COMPOSITIONSTART:"compositionstart", COMPOSITIONUPDATE:"compositionupdate", COMPOSITIONEND:"compositionend", 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.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.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;
      });
    } else {
      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("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.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 = function(node, opt_allowPartial) {
  return this.containsRange(goog.dom.Range.createFromNodeContents(node), opt_allowPartial);
};
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.AbstractMultiRange");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("goog.dom.AbstractRange");
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.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.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.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.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.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) {
    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.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.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.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) {
  return this.listen_(src, type, opt_fn, opt_capture);
};
goog.events.EventHandler.prototype.listenWithScope = function(src, type, fn, capture, scope) {
  return this.listen_(src, type, fn, capture, scope);
};
goog.events.EventHandler.prototype.listen_ = function(src, type, opt_fn, opt_capture, opt_scope) {
  if (!goog.isArray(type)) {
    if (type) {
      goog.events.EventHandler.typeArray_[0] = type.toString();
    }
    type = goog.events.EventHandler.typeArray_;
  }
  for (var i = 0;i < type.length;i++) {
    var listenerObj = goog.events.listen(src, type[i], opt_fn || this.handleEvent, opt_capture || false, opt_scope || this.handler_ || this);
    if (!listenerObj) {
      return this;
    }
    var key = listenerObj.key;
    this.keys_[key] = listenerObj;
  }
  return this;
};
goog.events.EventHandler.prototype.listenOnce = function(src, type, opt_fn, opt_capture) {
  return this.listenOnce_(src, type, opt_fn, opt_capture);
};
goog.events.EventHandler.prototype.listenOnceWithScope = function(src, type, fn, capture, scope) {
  return this.listenOnce_(src, type, fn, capture, scope);
};
goog.events.EventHandler.prototype.listenOnce_ = function(src, type, opt_fn, opt_capture, opt_scope) {
  if (goog.isArray(type)) {
    for (var i = 0;i < type.length;i++) {
      this.listenOnce_(src, type[i], opt_fn, opt_capture, opt_scope);
    }
  } else {
    var listenerObj = goog.events.listenOnce(src, type, opt_fn || this.handleEvent, opt_capture, opt_scope || this.handler_ || this);
    if (!listenerObj) {
      return this;
    }
    var key = listenerObj.key;
    this.keys_[key] = listenerObj;
  }
  return this;
};
goog.events.EventHandler.prototype.listenWithWrapper = function(src, wrapper, listener, opt_capt) {
  return this.listenWithWrapper_(src, wrapper, listener, opt_capt);
};
goog.events.EventHandler.prototype.listenWithWrapperAndScope = function(src, wrapper, listener, capture, scope) {
  return this.listenWithWrapper_(src, wrapper, listener, capture, scope);
};
goog.events.EventHandler.prototype.listenWithWrapper_ = function(src, wrapper, listener, opt_capt, opt_scope) {
  wrapper.listen(src, listener, opt_capt, opt_scope || this.handler_ || this, this);
  return this;
};
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) {
  if (goog.isArray(type)) {
    for (var i = 0;i < type.length;i++) {
      this.unlisten(src, type[i], opt_fn, opt_capture, opt_scope);
    }
  } else {
    var listener = goog.events.getListener(src, type, opt_fn || this.handleEvent, opt_capture, opt_scope || this.handler_ || this);
    if (listener) {
      goog.events.unlistenByKey(listener);
      delete this.keys_[listener.key];
    }
  }
  return this;
};
goog.events.EventHandler.prototype.unlistenWithWrapper = function(src, wrapper, listener, opt_capt, opt_scope) {
  wrapper.unlisten(src, listener, opt_capt, opt_scope || this.handler_ || this, this);
  return this;
};
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.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.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) {
  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 = "<p>" + html + "</p>";
  }
  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, 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.installStyles(this.cssStyles, this.getElement());
  }
};
goog.editor.Field.prototype.dispatchLoadEvent_ = function() {
  var field = this.getElement();
  this.installStyles();
  this.startChangeEvents();
  goog.log.info(this.logger, "Dispatching load " + this.id);
  this.dispatchEvent(goog.editor.Field.EventType.LOAD);
};
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.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.installStyles(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.installStyles(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.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) {
  if (goog.DEBUG && (uri.indexOf("#") >= 0 || uri.indexOf("?") >= 0)) {
    throw Error("goog.uri.utils: Fragment or query identifiers are not " + "supported: [" + 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.appendQueryData_ = function(buffer) {
  if (buffer[1]) {
    var baseUri = (buffer[0]);
    var hashIndex = baseUri.indexOf("#");
    if (hashIndex >= 0) {
      buffer.push(baseUri.substr(hashIndex));
      buffer[0] = baseUri = baseUri.substr(0, hashIndex);
    }
    var questionIndex = baseUri.indexOf("?");
    if (questionIndex < 0) {
      buffer[1] = "?";
    } else {
      if (questionIndex == baseUri.length - 1) {
        buffer[1] = undefined;
      }
    }
  }
  return buffer.join("");
};
goog.uri.utils.appendKeyValuePairs_ = function(key, value, pairs) {
  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.buildQueryDataBuffer_ = function(buffer, 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.");
  for (var i = opt_startIndex || 0;i < keysAndValues.length;i += 2) {
    goog.uri.utils.appendKeyValuePairs_(keysAndValues[i], keysAndValues[i + 1], buffer);
  }
  return buffer;
};
goog.uri.utils.buildQueryData = function(keysAndValues, opt_startIndex) {
  var buffer = goog.uri.utils.buildQueryDataBuffer_([], keysAndValues, opt_startIndex);
  buffer[0] = "";
  return buffer.join("");
};
goog.uri.utils.buildQueryDataBufferFromMap_ = function(buffer, map) {
  for (var key in map) {
    goog.uri.utils.appendKeyValuePairs_(key, map[key], buffer);
  }
  return buffer;
};
goog.uri.utils.buildQueryDataFromMap = function(map) {
  var buffer = goog.uri.utils.buildQueryDataBufferFromMap_([], map);
  buffer[0] = "";
  return buffer.join("");
};
goog.uri.utils.appendParams = function(uri, var_args) {
  return goog.uri.utils.appendQueryData_(arguments.length == 2 ? goog.uri.utils.buildQueryDataBuffer_([uri], arguments[1], 0) : goog.uri.utils.buildQueryDataBuffer_([uri], arguments, 1));
};
goog.uri.utils.appendParamsFromMap = function(uri, map) {
  return goog.uri.utils.appendQueryData_(goog.uri.utils.buildQueryDataBufferFromMap_([uri], map));
};
goog.uri.utils.appendParam = function(uri, key, opt_value) {
  var paramArr = [uri, "&", key];
  if (goog.isDefAndNotNull(opt_value)) {
    paramArr.push("=", goog.string.urlEncode(opt_value));
  }
  return goog.uri.utils.appendQueryData_(paramArr);
};
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.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.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 (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.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.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.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);
    this.print(logRecord.getLevel(), logRecord.formattedText);
    if (this.cachingEnabled) {
      if (this.maxEntries != null && this.maxEntries <= this.cache.length) {
        this.cache.shift();
      }
      this.cache.push(logRecord);
    }
  };
  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.getLevel(), record.formattedText);
    });
  };
  ConsoleLogger.prototype.clear = function() {
    this.cache = [];
  };
})();
goog.provide("uno.defs");
(function() {
  uno.defs = {unicode:{ZERO_WIDTH_SPACE:"\u200b"}, 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", PLATFORM_HTML:"platform_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+)" + "|" + "(?:\\S+\\.(?: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:{BACKGROUND_COLOR_IOS:"rgb(255, 204, 102)", BACKGROUND_COLOR_MAC:"rgb(255, 250, 165)", BACKGROUND_COLOR_CLEARLY:"rgb(246, 238, 150)", regex:/rgb\(255, 204, 102\)|rgb\(255, 250, 165\)|rgb\(246, 238, 150\)/, STYLE_LEGACY:"-evernote-highlighted", 
  STYLE:"-evernote-highlight", STYLE_VALUE:"true", BACKGROUND_STYLE:"background-color", BACKGROUND_SELECTOR:"*[style*='background-color']"}, table:{FIXED_WIDTH:792, CELL_MIN:48, CELL_WIDTH:264, CELL_PADDING:10, CELL_MARGIN:0, BORDER_COLLAPSE:"collapse", BORDER_STYLE:"solid", BORDER_COLOR:"rgb(219,219,219)", BORDER_WIDTH:1, TABLE_LAYOUT:"fixed"}, multirange:{PLUGIN_MODE:{APPLY_TO_ALL:"apply-to-all", APPLY_TO_FIRST:"apply-to-first"}}, 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}};
})();
goog.provide("uno.env");
goog.require("goog.userAgent");
(function() {
  var ua = goog.userAgent;
  var env = uno.env;
  env.getPlatform = 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.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() {
    var container = util.tools.getContainer();
    container.appendChild(goog.dom.createDom("en-preload", {"class":"en-preload"}));
  };
})();
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.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");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.dom");
  var dom = uno.util.dom;
  dom.inlineObjects = ["en-media", "en-todo", "en-crypt", "en-cursor", "img", "embed", "object", "input", "param", "hr", "br", "en-container", "en-adornment"];
  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.textContent.length || dom.isEmptyOrNewlines(node);
    }
    if (node.querySelectorAll("br").length > 1) {
      return false;
    }
    if (node.querySelectorAll("li, blockquote", "table").length > 0) {
      return false;
    }
    if (node.childNodes.length > 0) {
      return Array.prototype.every.call(node.childNodes, function(childNode) {
        return dom.isEmpty(childNode);
      });
    }
    var tagName = node.tagName.toLowerCase();
    var components = ["img", "embed", "object", "input", "param", "hr", "en-media", "table", "en-todo", "en-crypt"];
    var isObject = components.indexOf(tagName) > -1;
    return !isObject;
  };
  dom.getNodeLeaves = function(root, forcedLeaves) {
    var deepestNodes = [];
    var forcedLeaves = forcedLeaves || [];
    var getNodeLeaves = function(node, forcedLeaves) {
      var isForcedLeaf = node.tagName && forcedLeaves.indexOf(node.tagName.toLowerCase()) > -1;
      if (!node.childNodes || !node.childNodes.length || isForcedLeaf) {
        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.getRightMostLeafNode = 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) {
        return;
      }
      if (!element.childNodes || !element.childNodes.length) {
        leafNode = element;
      } else {
        leafNode = dom.getRightMostLeafNode(element);
      }
    });
    return leafNode;
  };
  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;
  };
  dom.isTextNode = function(node) {
    return !!(node && node.nodeType === Node.TEXT_NODE);
  };
  dom.isElementNode = function(node) {
    return !!(node && node.nodeType === Node.ELEMENT_NODE);
  };
  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.isBlockNode = function(node) {
    return !!(node && (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.isFragment = function(node) {
    return !!(node.nodeType === Node.DOCUMENT_FRAGMENT_NODE);
  };
  dom.getTagName = function(node) {
    return node && node.tagName && node.tagName.toLowerCase() || "";
  };
  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.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) {
    while (node && !node.nextSibling) {
      node = node.parentNode;
    }
    if (!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.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.isEmptyOrNewlines = function(node) {
    return !!(node && node.nodeType === Node.TEXT_NODE && (node.data === "" || /^[\n\r]+$/.test(node.data)));
  };
  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 (dom.isHtmlElement(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.isHtmlElement = function(node, opt_tagName) {
    if (goog.dom.isElement(node)) {
      if (opt_tagName) {
        return opt_tagName.toLowerCase() === node.tagName.toLowerCase();
      } else {
        return true;
      }
    }
    return false;
  };
  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;
  };
  dom.getContainedNodes = function(range, condition) {
    if (typeof condition == "undefined") {
      condition = function() {
        return true;
      };
    }
    var node = range.getStartNode();
    if (node.hasChildNodes() && range.getStartOffset() < node.childNodes.length) {
      node = node.childNodes[range.getStartOffset()];
    } else {
      if (range.getStartOffset() == dom.getNodeLength(node)) {
        node = dom.nextNodeDescendants(node);
      } else {
        node = dom.nextNode(node);
      }
    }
    var stop = range.getEndNode();
    if (stop.hasChildNodes() && range.getEndOffset() < stop.childNodes.length) {
      stop = stop.childNodes[range.getEndOffset()];
    } else {
      stop = dom.nextNodeDescendants(stop);
    }
    var nodeList = [];
    while (dom.isBefore(node, stop)) {
      if (range.containsNode(node) && condition(node)) {
        nodeList.push(node);
        node = dom.nextNodeDescendants(node);
        continue;
      }
      node = dom.nextNode(node);
    }
    return nodeList;
  };
  var 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.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, platform) {
    var offsetLeft;
    var offsetTop;
    if (rect == null) {
      return null;
    }
    goog.object.extend(opt, {absolute:false, zoomScale:1.0, ignoreOffset:false}, opt);
    if (platform === "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 (platform === "android" && opt.ignoreOffset !== true) {
      var offsetElement = document.getElementById("offset");
      if (offsetElement != null) {
        offsetTop -= parseInt(offsetElement.style.height, 10);
      }
    }
    var clientRect;
    if (platform === "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.selectable = function(el, selectable) {
    var selectableClass = "en-unselectable";
    if (selectable) {
      goog.dom.classes.remove(el, selectableClass);
    } else {
      goog.dom.classes.add(el, selectableClass);
    }
  };
  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;
    }
    var box = node.getBoundingClientRect();
    return dom.isBoundingBoxOnScreen(box.top, box.bottom, onScreenAmount);
  };
  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);
  };
})();
goog.provide("uno.util.range");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("uno.util.dom");
goog.require("uno.defs");
(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.selectNode = function(node) {
    var range = goog.dom.Range.createFromNodeContents(node);
    range.select();
  };
  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();
        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.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;
  };
})();
goog.provide("uno.util.table");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.editor.Table");
goog.require("goog.object");
goog.require("goog.style");
goog.require("uno.defs");
goog.require("uno.util.range");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.table");
  var util = uno.util;
  var dom = util.dom;
  util.table.createDomTable = function(options, editor) {
    if (options == null) {
      options = {};
    }
    var opt = {rows:options.rows || 2, columns:options.columns || 2, align:options.align || "left", borderColor:options.borderColor, borderWidth:options.borderWidth, cellColor:options.cellColor};
    var table = goog.editor.Table.createDomTable(document, opt.columns, opt.rows);
    util.table.initCellContent(table, editor.config.defaults.tableCellHtml);
    util.table.initStyles(table, opt);
    return table;
  };
  util.table.remove = function(table) {
    if (table == null || table.parentElement == null) {
      return;
    }
    var tableIndex = util.dom.index(table);
    var tableParent = table.parentElement;
    goog.dom.removeNode(table);
    goog.dom.Range.createCaret(tableParent, tableIndex).select();
  };
  util.table.dimensions = function(table) {
    if (table == null || !util.dom.isHtmlElement(table) || table.tagName.toLowerCase() !== "table" || table.querySelector("table") != null) {
      return {rows:-1, columns:-1};
    }
    var rows = table.querySelectorAll("tr");
    if (rows.length <= 0) {
      return {rows:0, columns:0};
    }
    var cols = rows[0].querySelectorAll("td,th");
    return {rows:rows.length, columns:cols.length};
  };
  util.table.selected = function(editor) {
    var range = null;
    if (editor.multirange.active()) {
      range = editor.multirange.getTextRanges()[0];
    } else {
      range = editor.getRange();
    }
    return util.table["for"](range == null ? null : range.getAnchorNode());
  };
  util.table.selectedCells = function(editor, fullySelected) {
    var table = util.table.selected(editor);
    if (editor.multirange.active()) {
      return util.table.multirange.selectedCells(editor);
    }
    if (table == null) {
      return [];
    }
    var selection = editor.getRange();
    var partiallySelectedTDs = [];
    var completelySelectedTDs = [];
    var allTDs = [];
    goog.array.forEach(table.querySelectorAll("td"), function(td) {
      if (selection.containsNode(td, false)) {
        completelySelectedTDs.push(td);
        allTDs.push(td);
      } else {
        if (selection.containsNode(td, true)) {
          partiallySelectedTDs.push(td);
          allTDs.push(td);
        }
      }
    });
    if (fullySelected == null) {
      return allTDs;
    } else {
      if (fullySelected === true) {
        return completelySelectedTDs;
      }
    }
    return partiallySelectedTDs;
  };
  util.table["for"] = function(node) {
    if (node == null) {
      return null;
    }
    var tableNode = util.dom.compareTagName(node, "table") ? node : goog.dom.getAncestorByTagNameAndClass(node, "table");
    return tableNode;
  };
  util.table.rowFor = function(node) {
    if (node == null) {
      return null;
    }
    var tr = util.dom.compareTagName(node, "tr") ? node : goog.dom.getAncestorByTagNameAndClass(node, "tr");
    return tr;
  };
  util.table.cellFor = function(node) {
    if (node == null) {
      return null;
    }
    var td = util.dom.compareTagName(node, "td") ? node : goog.dom.getAncestorByTagNameAndClass(node, "td");
    return td;
  };
  util.table.cellForRange = function(textrange) {
    var foundTD = util.range.commonAncestors(textrange, "td");
    if (foundTD && foundTD.length === 2 && foundTD[0] === foundTD[1]) {
      return foundTD[0];
    }
    return null;
  };
  util.table.column = function(table, columnIndex) {
    var tableDims = util.table.dimensions(table);
    if (columnIndex < 0 || columnIndex >= tableDims.columns) {
      log.severe("Invalid columnIndex given to util.table.column");
      return [];
    }
    var result = [];
    for (var i = 0;i < tableDims.rows;i++) {
      result.push(util.table.cellAtPosition(table, i, columnIndex));
    }
    return result;
  };
  util.table.subtable = function(cellOne, cellTwo) {
    var cellOnePos = util.table.positionInTable(cellOne);
    var cellTwoPos = util.table.positionInTable(cellTwo);
    if (cellOnePos.table == null || cellOnePos.table !== cellTwoPos.table) {
      return [];
    }
    var topmost = Math.min(cellOnePos.row, cellTwoPos.row);
    var bottommost = Math.max(cellOnePos.row, cellTwoPos.row);
    var leftmost = Math.min(cellOnePos.column, cellTwoPos.column);
    var rightmost = Math.max(cellOnePos.column, cellTwoPos.column);
    var cells = [];
    for (var i = topmost;i <= bottommost;i++) {
      for (var j = leftmost;j <= rightmost;j++) {
        cells.push(util.table.cellAtPosition(cellOnePos.table, i, j));
      }
    }
    return cells;
  };
  util.table.metrics = function(node) {
    var bounds = util.zoomscale.normalizeRect(goog.style.getBounds(node));
    var padding = util.zoomscale.normalizeRect(goog.style.getPaddingBox(node));
    var border = util.zoomscale.normalizeRect(goog.style.getBorderBox(node));
    return {left:bounds.left, top:bounds.top, width:bounds.width, height:bounds.height, padding:padding, border:border};
  };
  util.table.prevRow = function(node) {
    var result;
    var tr = util.table.rowFor(node);
    if (tr != null) {
      result = goog.dom.getPreviousElementSibling(tr);
    }
    if (util.dom.compareTagName(result, "tr")) {
      return result;
    }
    return null;
  };
  util.table.nextRow = function(node) {
    var result;
    var tr = util.table.rowFor(node);
    if (tr != null) {
      result = goog.dom.getNextElementSibling(tr);
    }
    if (util.dom.compareTagName(result, "tr")) {
      return result;
    }
    return null;
  };
  util.table.prevCell = function(node, sameRow) {
    var result;
    var td = util.table.cellFor(node);
    var tr;
    if (td == null) {
      return null;
    }
    result = goog.dom.getPreviousElementSibling(td);
    if (sameRow === true) {
      return result;
    }
    if (result == null) {
      tr = util.table.prevRow(td);
      if (tr != null) {
        result = goog.array.last(tr.querySelectorAll("td"));
      }
    }
    if (util.dom.compareTagName(td, "td")) {
      return result;
    }
    return null;
  };
  util.table.nextCell = function(node) {
    var result;
    var td = util.table.cellFor(node);
    var tr;
    if (td == null) {
      return null;
    }
    result = goog.dom.getNextElementSibling(td);
    if (result == null) {
      tr = util.table.nextRow(td);
      if (tr != null) {
        result = tr.querySelector("td");
      }
    }
    if (util.dom.compareTagName(td, "td")) {
      return result;
    }
    return null;
  };
  util.table.initCellContent = function(tableOrCell, tableCellHtml) {
    if (util.dom.compareTagName(tableOrCell, "td")) {
      tableOrCell.innerHTML = tableCellHtml;
    } else {
      goog.array.forEach(tableOrCell.querySelectorAll("td"), function(td) {
        td.innerHTML = tableCellHtml;
      });
    }
  };
  util.table.initStyles = function(table, opt) {
    var tds = table.querySelectorAll("td");
    var firstRow = table.querySelector("tr");
    var cellWidthStyle = 100 / firstRow.querySelectorAll("td").length + "%";
    var tableStyleWidth = table.style.width;
    table.setAttribute("style", "");
    table.removeAttribute("border");
    table.removeAttribute("bordercolor");
    table.removeAttribute("cellspacing");
    table.style.width = tableStyleWidth || "100%";
    table.style.borderCollapse = opt.borderCollapse || uno.defs.table.BORDER_COLLAPSE;
    table.style.tableLayout = opt.tableLayout || uno.defs.table.TABLE_LAYOUT;
    if (["left", "right", "center"].indexOf(opt.align) > 0) {
      util.table.setAlignment(table, opt.align);
    }
    goog.array.forEach(tds, function(td) {
      var borderColor = opt.borderColor || uno.defs.table.BORDER_COLOR;
      var borderWidth = (opt.borderWidth || uno.defs.table.BORDER_WIDTH) + "px";
      var width = td.parentNode === firstRow ? cellWidthStyle : "";
      td.style.borderColor = opt.useDefault && td.style.borderColor || borderColor;
      td.style.borderWidth = opt.useDefault && td.style.borderWidth || borderWidth;
      td.style.borderStyle = opt.borderStyle || uno.defs.table.BORDER_STYLE;
      if (opt.cellColor) {
        td.style.background = opt.cellColor;
      }
      td.style.padding = (opt.padding || uno.defs.table.CELL_PADDING) + "px";
      td.style.margin = (opt.margin || uno.defs.table.CELL_MARGIN) + "px";
      td.style.width = opt.useDefault && td.style.width || width;
      td.style.minWidth = opt.useDefault && td.style.width || width;
    });
  };
  util.table.cellIndex = function(td) {
    var tr = util.table.rowFor(td);
    var colIndex;
    goog.array.some(tr.querySelectorAll("td"), function(cell, index) {
      if (td === cell) {
        colIndex = index;
        return true;
      }
      return false;
    });
    return colIndex;
  };
  util.table.cellAt = function(row, index) {
    return row.querySelectorAll("td").item(index);
  };
  util.table.cellAtPosition = function(table, row, col) {
    var rows = table.querySelectorAll("tr");
    if (rows.length < row + 1) {
      return null;
    }
    var cols = rows[row].querySelectorAll("td");
    if (cols.length < col + 1) {
      return null;
    }
    return cols[col];
  };
  util.table.getAlignment = function(table) {
    var alignment = "UNKNOWN";
    var float = table.style["float"];
    var align = table.getAttribute("align");
    var marginLeft = table.style.marginLeft;
    var marginRight = table.style.marginRight;
    if (float && float !== "none") {
      alignment = float;
    } else {
      if (align) {
        alignment = align;
      } else {
        if (marginLeft === "auto" && marginRight === "auto") {
          alignment = "center";
        } else {
          if (marginLeft === "auto") {
            alignment = "right";
          } else {
            alignment = "left";
          }
        }
      }
    }
    return alignment;
  };
  util.table.setAlignment = function(table, align) {
    table.removeAttribute("align");
    goog.style.setStyle(table, "float", "");
    goog.style.setStyle(table, "margin", "");
    goog.style.setStyle(table, "margin-right", "");
    goog.style.setStyle(table, "margin-left", "");
    if (align === "left") {
      goog.style.setStyle(table, "margin-left", "0px");
    } else {
      if (align === "right") {
        goog.style.setStyle(table, "margin-left", "auto");
        goog.style.setStyle(table, "margin-right", "0px");
      } else {
        if (align === "center") {
          goog.style.setStyle(table, "margin-left", "auto");
          goog.style.setStyle(table, "margin-right", "auto");
        }
      }
    }
  };
  util.table.positionInTable = function(node) {
    var failure = {table:null, cell:null, row:-1, column:-1};
    var table = util.dom.parent(node, "table");
    var tr = util.dom.parent(node, "tr");
    var cell = util.dom.parent(node, "td,th");
    if (table == null || tr == null || cell == null) {
      return failure;
    }
    var rowIndex = -1;
    var colIndex = -1;
    var trs = table.querySelectorAll("tr");
    for (var j = 0;j < trs.length;j++) {
      if (trs[j] === tr) {
        rowIndex = j;
      }
    }
    if (rowIndex === -1) {
      return failure;
    }
    var cells = tr.querySelectorAll("td,th");
    for (var i = 0;i < cells.length;i++) {
      if (cells[i] === cell) {
        colIndex = i;
      }
    }
    if (colIndex === -1) {
      return failure;
    }
    return {table:table, cell:cell, row:rowIndex, column:colIndex};
  };
  util.table.ensureColumnMinWidth = function(table) {
    var tableDims = util.table.dimensions(table);
    if (tableDims.rows <= 0 || tableDims.columns <= 0) {
      return;
    }
    var tableWidthPx = util.table.metrics(table).width;
    if (tableWidthPx < tableDims.columns * uno.defs.table.CELL_MIN) {
      tableWidthPx = tableDims.columns * uno.defs.table.CELL_MIN;
    }
    var firstRow = table.querySelector("tr").querySelectorAll("td");
    var containerMetrics = util.table.metrics(table.parentElement);
    var containerWidthPx = containerMetrics.width - containerMetrics.padding.left - containerMetrics.padding.right - containerMetrics.border.left - containerMetrics.border.right;
    var tableWidthPercent = tableWidthPx / containerWidthPx * 100;
    tableWidthPercent = Math.max(0, Math.min(100, tableWidthPercent));
    var zoom = uno.util.zoomscale.getZoomScale(table);
    tableWidthPercent /= zoom;
    goog.style.setStyle(table, "width", tableWidthPercent + "%");
    var newWidthsPx = [];
    var totalExpansionPx = 0;
    var numLargeCells = 0;
    goog.array.forEach(firstRow, function(td) {
      var tdWidthPx = goog.style.getBounds(td).width;
      if (tdWidthPx < uno.defs.table.CELL_MIN) {
        totalExpansionPx += uno.defs.table.CELL_MIN - tdWidthPx;
        tdWidthPx = uno.defs.table.CELL_MIN;
      } else {
        numLargeCells += 1;
      }
      newWidthsPx.push(tdWidthPx);
    });
    var scalingFactor = totalExpansionPx / numLargeCells;
    if (scalingFactor > 0) {
      goog.array.forEach(firstRow, function(td, index) {
        var newWidthPx = newWidthsPx[index];
        if (newWidthPx > uno.defs.table.CELL_MIN) {
          newWidthPx -= scalingFactor;
          if (newWidthPx < uno.defs.table.CELL_MIN) {
            newWidthPx = uno.defs.table.CELL_MIN;
          }
        }
        var newWidthPercent = newWidthPx / tableWidthPx * 100;
        goog.style.setStyle(td, "width", newWidthPercent + "%");
      });
    }
  };
  util.table.equalizeColumns = function(table) {
    var tableWidth = util.table.metrics(table).width;
    if (tableWidth < 0) {
      return;
    }
    var firstTr = table.querySelector("tr");
    if (firstTr == null) {
      return;
    }
    var firstRowCells = firstTr.querySelectorAll("td");
    if (firstRowCells.length < 0) {
      return;
    }
    var newCellWidth = Math.floor(tableWidth / firstRowCells.length);
    goog.array.forEach(firstRowCells, function(cell) {
      goog.style.setStyle(cell, "width", newCellWidth + "px");
      goog.style.setStyle(cell, "min-width", newCellWidth + "px");
    });
    util.table.ensureColumnMinWidth(table);
  };
  util.table.setTableWidth = function(table, newWidth) {
    goog.style.setStyle(table, "width", newWidth + "px");
    util.table.equalizeColumns(table);
  };
  util.table.updateTableWidth = function(table) {
    var firstRow = table.querySelector("tr");
    if (firstRow == null) {
      return;
    }
    var totalWidth = 0;
    goog.array.forEach(firstRow.querySelectorAll("td"), function(td) {
      totalWidth += parseInt(goog.style.getStyle(td, "width"), 10);
    });
    goog.style.setStyle(table, "width", totalWidth + "px");
  };
  util.table.normalizeTableBorders = function(table) {
    if (table == null) {
      return;
    }
    var firstTd = table.querySelector("td");
    if (firstTd == null) {
      return;
    }
    var borderWidth = parseInt(goog.style.getComputedStyle(firstTd, "borderWidth"), 10) || 1;
    var borderColor = goog.style.getComputedStyle(firstTd, "borderColor") || "black";
    goog.object.forEach(table.style, function(value, style) {
      if (style.indexOf("border") >= 0) {
        goog.style.setStyle(table, style, "");
      }
    });
    table.removeAttribute("border");
    goog.style.setStyle(table, "border-style", "solid");
    goog.style.setStyle(table, "border-width", borderWidth + "px");
    goog.style.setStyle(table, "border-color", borderColor);
    goog.style.setStyle(table, "border-collapse", "collapse");
    goog.array.forEach(table.querySelectorAll("tr"), function(tr) {
      goog.object.forEach(tr.style, function(value, style) {
        if (style.indexOf("border") >= 0) {
          goog.style.setStyle(tr, style, "");
        }
      });
    });
    goog.array.forEach(table.querySelectorAll("td"), function(td) {
      goog.object.forEach(td.style, function(value, style) {
        if (style.indexOf("border") >= 0) {
          goog.style.setStyle(td, style, "");
        }
      });
      goog.style.setStyle(td, "border-style", "solid");
      goog.style.setStyle(td, "border-width", borderWidth + "px");
      goog.style.setStyle(td, "border-color", borderColor);
    });
  };
  util.table.getParagraphs = function(table) {
    var paragraphs = [];
    if (util.dom.isTable(table)) {
      var tds = table.querySelectorAll("td");
      goog.array.forEach(tds, function(td) {
        paragraphs = paragraphs.concat(goog.array.toArray(td.childNodes));
      });
    }
    return goog.array.toArray(paragraphs);
  };
  util.table.setMode = function(table, modeName) {
    if (table == null) {
      return;
    }
    table.setAttribute("data-table-mode", modeName);
  };
  util.table.getMode = function(table) {
    if (table == null) {
      return null;
    }
    return table.getAttribute("data-table-mode");
  };
  util.table.clearMode = function(table) {
    table.removeAttribute("data-table-mode");
  };
  util.table.normalize = function(root) {
    util.table.removeOldTableTags(root);
    util.table.ensureNoEmptyTd(root);
    util.table.validateTableStructure(root);
    util.table.validateTableStyles(root);
  };
  util.table.validateTableStructure = function(frag) {
    var tables = frag.querySelectorAll("table");
    var headers = frag.querySelectorAll("thead, tbody, tfoot");
    goog.array.forEachRight(tables || [], function(table) {
      goog.array.forEachRight(table.childNodes || [], function(child) {
        if (dom.isThead(child) || dom.isTbody(child) || dom.isTfoot(child)) {
          return;
        }
        goog.dom.removeNode(child);
      });
    });
    goog.array.forEachRight(headers || [], function(header) {
      goog.array.forEachRight(header.childNodes || [], function(child) {
        if (!dom.isTr(child)) {
          goog.dom.removeNode(child);
        }
      });
    });
    goog.array.forEach(tables, function(table) {
      var trs = table.querySelectorAll("tr");
      var maxNumberOfColumns = 0;
      goog.array.forEach(trs || [], function(tr) {
        var tdMax = 0;
        goog.array.forEach(tr.childNodes || [], function(td) {
          tdMax += td.colSpan;
        });
        if (tdMax > maxNumberOfColumns) {
          maxNumberOfColumns = tdMax;
        }
      });
      goog.array.forEach(trs || [], function(tr) {
        var numberOfColumns = 0;
        goog.array.forEach(tr.childNodes || [], function(td) {
          numberOfColumns += td.colSpan;
        });
        var delta = maxNumberOfColumns - numberOfColumns;
        for (var i = 0;i < delta;i++) {
          var td = goog.dom.createDom("td");
          td.innerHTML = "<div><br></div>";
          tr.appendChild(td);
        }
      });
    });
  };
  util.table.removeOldTableTags = function(frag) {
    var ths = frag.querySelectorAll("th");
    goog.array.forEachRight(ths, function(th) {
      var td = goog.dom.createDom("td");
      goog.dom.append(td, th.childNodes);
      goog.dom.insertSiblingAfter(td, th);
      goog.dom.removeNode(th);
    });
  };
  util.table.validateTableStyles = function(frag) {
    var tables = frag.querySelectorAll("table");
    goog.array.forEach(tables, function(table) {
      util.table.initStyles(table, {useDefault:true});
    });
  };
  util.table.ensureNoEmptyTd = function(frag) {
    var tds = frag.querySelectorAll("td");
    goog.array.forEach(tds, function(td) {
      if (util.dom.isEmpty(td)) {
        td.innerHTML = "<div><br></div>";
      }
    });
  };
  util.table.convertColumnsToFixedWidth = function(table) {
    var tableWidth = parseInt(table.style.width, 10);
    var isTableWidthPercent = table.style.width.indexOf("%") > -1;
    if (isTableWidthPercent) {
      tableWidth = uno.defs.table.FIXED_WIDTH * (tableWidth / 100);
    }
    if (!tableWidth) {
      tableWidth = uno.defs.table.FIXED_WIDTH;
    }
    tableWidth = Math.floor(tableWidth);
    var columns = [];
    goog.array.forEach(table.querySelectorAll("tr"), function(tr) {
      goog.array.forEach(tr.querySelectorAll("td"), function(td, index) {
        if (!columns[index]) {
          var cellWidth = parseInt(td.style.width, 10);
          var isCellWidthPercent = td.style.width.indexOf("%") > -1;
          if (isCellWidthPercent) {
            cellWidth = tableWidth * (cellWidth / 100);
          }
          if (cellWidth) {
            cellWidth = Math.floor(cellWidth);
            var padding = uno.defs.table.CELL_PADDING * 2;
            if (cellWidth + padding < uno.defs.table.CELL_MIN) {
              cellWidth = uno.defs.table.CELL_MIN;
            }
          } else {
            cellWidth = uno.defs.table.CELL_WIDTH;
          }
          goog.style.setStyle(td, "width", cellWidth + "px");
          goog.style.setStyle(td, "min-width", cellWidth + "px");
          columns[index] = cellWidth;
        } else {
          util.dom.removeStyleValue(td, "width");
          util.dom.removeStyleValue(td, "min-width");
        }
      });
    });
  };
})();
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("goog.fx.Transition");
goog.provide("goog.fx.Transition.EventType");
goog.fx.Transition = function() {
};
goog.fx.Transition.EventType = {PLAY:"play", BEGIN:"begin", RESUME:"resume", END:"end", STOP:"stop", FINISH:"finish", PAUSE:"pause"};
goog.fx.Transition.prototype.play;
goog.fx.Transition.prototype.stop;
goog.provide("goog.fx.TransitionBase");
goog.provide("goog.fx.TransitionBase.State");
goog.require("goog.events.EventTarget");
goog.require("goog.fx.Transition");
goog.fx.TransitionBase = function() {
  goog.fx.TransitionBase.base(this, "constructor");
  this.state_ = goog.fx.TransitionBase.State.STOPPED;
  this.startTime = null;
  this.endTime = null;
};
goog.inherits(goog.fx.TransitionBase, goog.events.EventTarget);
goog.fx.TransitionBase.State = {STOPPED:0, PAUSED:-1, PLAYING:1};
goog.fx.TransitionBase.prototype.play = goog.abstractMethod;
goog.fx.TransitionBase.prototype.stop = goog.abstractMethod;
goog.fx.TransitionBase.prototype.pause = goog.abstractMethod;
goog.fx.TransitionBase.prototype.getStateInternal = function() {
  return this.state_;
};
goog.fx.TransitionBase.prototype.setStatePlaying = function() {
  this.state_ = goog.fx.TransitionBase.State.PLAYING;
};
goog.fx.TransitionBase.prototype.setStatePaused = function() {
  this.state_ = goog.fx.TransitionBase.State.PAUSED;
};
goog.fx.TransitionBase.prototype.setStateStopped = function() {
  this.state_ = goog.fx.TransitionBase.State.STOPPED;
};
goog.fx.TransitionBase.prototype.isPlaying = function() {
  return this.state_ == goog.fx.TransitionBase.State.PLAYING;
};
goog.fx.TransitionBase.prototype.isPaused = function() {
  return this.state_ == goog.fx.TransitionBase.State.PAUSED;
};
goog.fx.TransitionBase.prototype.isStopped = function() {
  return this.state_ == goog.fx.TransitionBase.State.STOPPED;
};
goog.fx.TransitionBase.prototype.onBegin = function() {
  this.dispatchAnimationEvent(goog.fx.Transition.EventType.BEGIN);
};
goog.fx.TransitionBase.prototype.onEnd = function() {
  this.dispatchAnimationEvent(goog.fx.Transition.EventType.END);
};
goog.fx.TransitionBase.prototype.onFinish = function() {
  this.dispatchAnimationEvent(goog.fx.Transition.EventType.FINISH);
};
goog.fx.TransitionBase.prototype.onPause = function() {
  this.dispatchAnimationEvent(goog.fx.Transition.EventType.PAUSE);
};
goog.fx.TransitionBase.prototype.onPlay = function() {
  this.dispatchAnimationEvent(goog.fx.Transition.EventType.PLAY);
};
goog.fx.TransitionBase.prototype.onResume = function() {
  this.dispatchAnimationEvent(goog.fx.Transition.EventType.RESUME);
};
goog.fx.TransitionBase.prototype.onStop = function() {
  this.dispatchAnimationEvent(goog.fx.Transition.EventType.STOP);
};
goog.fx.TransitionBase.prototype.dispatchAnimationEvent = function(type) {
  this.dispatchEvent(type);
};
goog.provide("goog.async.AnimationDelay");
goog.require("goog.Disposable");
goog.require("goog.events");
goog.require("goog.functions");
goog.async.AnimationDelay = function(listener, opt_window, opt_handler) {
  goog.async.AnimationDelay.base(this, "constructor");
  this.id_ = null;
  this.usingListeners_ = false;
  this.listener_ = listener;
  this.handler_ = opt_handler;
  this.win_ = opt_window || window;
  this.callback_ = goog.bind(this.doAction_, this);
};
goog.inherits(goog.async.AnimationDelay, goog.Disposable);
goog.async.AnimationDelay.TIMEOUT = 20;
goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_ = "MozBeforePaint";
goog.async.AnimationDelay.prototype.start = function() {
  this.stop();
  this.usingListeners_ = false;
  var raf = this.getRaf_();
  var cancelRaf = this.getCancelRaf_();
  if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) {
    this.id_ = goog.events.listen(this.win_, goog.async.AnimationDelay.MOZ_BEFORE_PAINT_EVENT_, this.callback_);
    this.win_.mozRequestAnimationFrame(null);
    this.usingListeners_ = true;
  } else {
    if (raf && cancelRaf) {
      this.id_ = raf.call(this.win_, this.callback_);
    } else {
      this.id_ = this.win_.setTimeout(goog.functions.lock(this.callback_), goog.async.AnimationDelay.TIMEOUT);
    }
  }
};
goog.async.AnimationDelay.prototype.stop = function() {
  if (this.isActive()) {
    var raf = this.getRaf_();
    var cancelRaf = this.getCancelRaf_();
    if (raf && !cancelRaf && this.win_.mozRequestAnimationFrame) {
      goog.events.unlistenByKey(this.id_);
    } else {
      if (raf && cancelRaf) {
        cancelRaf.call(this.win_, (this.id_));
      } else {
        this.win_.clearTimeout((this.id_));
      }
    }
  }
  this.id_ = null;
};
goog.async.AnimationDelay.prototype.fire = function() {
  this.stop();
  this.doAction_();
};
goog.async.AnimationDelay.prototype.fireIfActive = function() {
  if (this.isActive()) {
    this.fire();
  }
};
goog.async.AnimationDelay.prototype.isActive = function() {
  return this.id_ != null;
};
goog.async.AnimationDelay.prototype.doAction_ = function() {
  if (this.usingListeners_ && this.id_) {
    goog.events.unlistenByKey(this.id_);
  }
  this.id_ = null;
  this.listener_.call(this.handler_, goog.now());
};
goog.async.AnimationDelay.prototype.disposeInternal = function() {
  this.stop();
  goog.async.AnimationDelay.base(this, "disposeInternal");
};
goog.async.AnimationDelay.prototype.getRaf_ = function() {
  var win = this.win_;
  return win.requestAnimationFrame || win.webkitRequestAnimationFrame || win.mozRequestAnimationFrame || win.oRequestAnimationFrame || win.msRequestAnimationFrame || null;
};
goog.async.AnimationDelay.prototype.getCancelRaf_ = function() {
  var win = this.win_;
  return win.cancelAnimationFrame || win.cancelRequestAnimationFrame || win.webkitCancelRequestAnimationFrame || win.mozCancelRequestAnimationFrame || win.oCancelRequestAnimationFrame || win.msCancelRequestAnimationFrame || null;
};
goog.provide("goog.fx.anim");
goog.provide("goog.fx.anim.Animated");
goog.require("goog.async.AnimationDelay");
goog.require("goog.async.Delay");
goog.require("goog.object");
goog.fx.anim.Animated = function() {
};
goog.fx.anim.Animated.prototype.onAnimationFrame;
goog.fx.anim.TIMEOUT = goog.async.AnimationDelay.TIMEOUT;
goog.fx.anim.activeAnimations_ = {};
goog.fx.anim.animationWindow_ = null;
goog.fx.anim.animationDelay_ = null;
goog.fx.anim.registerAnimation = function(animation) {
  var uid = goog.getUid(animation);
  if (!(uid in goog.fx.anim.activeAnimations_)) {
    goog.fx.anim.activeAnimations_[uid] = animation;
  }
  goog.fx.anim.requestAnimationFrame_();
};
goog.fx.anim.unregisterAnimation = function(animation) {
  var uid = goog.getUid(animation);
  delete goog.fx.anim.activeAnimations_[uid];
  if (goog.object.isEmpty(goog.fx.anim.activeAnimations_)) {
    goog.fx.anim.cancelAnimationFrame_();
  }
};
goog.fx.anim.tearDown = function() {
  goog.fx.anim.animationWindow_ = null;
  goog.dispose(goog.fx.anim.animationDelay_);
  goog.fx.anim.animationDelay_ = null;
  goog.fx.anim.activeAnimations_ = {};
};
goog.fx.anim.setAnimationWindow = function(animationWindow) {
  var hasTimer = goog.fx.anim.animationDelay_ && goog.fx.anim.animationDelay_.isActive();
  goog.dispose(goog.fx.anim.animationDelay_);
  goog.fx.anim.animationDelay_ = null;
  goog.fx.anim.animationWindow_ = animationWindow;
  if (hasTimer) {
    goog.fx.anim.requestAnimationFrame_();
  }
};
goog.fx.anim.requestAnimationFrame_ = function() {
  if (!goog.fx.anim.animationDelay_) {
    if (goog.fx.anim.animationWindow_) {
      goog.fx.anim.animationDelay_ = new goog.async.AnimationDelay(function(now) {
        goog.fx.anim.cycleAnimations_(now);
      }, goog.fx.anim.animationWindow_);
    } else {
      goog.fx.anim.animationDelay_ = new goog.async.Delay(function() {
        goog.fx.anim.cycleAnimations_(goog.now());
      }, goog.fx.anim.TIMEOUT);
    }
  }
  var delay = goog.fx.anim.animationDelay_;
  if (!delay.isActive()) {
    delay.start();
  }
};
goog.fx.anim.cancelAnimationFrame_ = function() {
  if (goog.fx.anim.animationDelay_) {
    goog.fx.anim.animationDelay_.stop();
  }
};
goog.fx.anim.cycleAnimations_ = function(now) {
  goog.object.forEach(goog.fx.anim.activeAnimations_, function(anim) {
    anim.onAnimationFrame(now);
  });
  if (!goog.object.isEmpty(goog.fx.anim.activeAnimations_)) {
    goog.fx.anim.requestAnimationFrame_();
  }
};
goog.provide("goog.fx.Animation");
goog.provide("goog.fx.Animation.EventType");
goog.provide("goog.fx.Animation.State");
goog.provide("goog.fx.AnimationEvent");
goog.require("goog.array");
goog.require("goog.asserts");
goog.require("goog.events.Event");
goog.require("goog.fx.Transition");
goog.require("goog.fx.TransitionBase");
goog.require("goog.fx.anim");
goog.require("goog.fx.anim.Animated");
goog.fx.Animation = function(start, end, duration, opt_acc) {
  goog.fx.Animation.base(this, "constructor");
  if (!goog.isArray(start) || !goog.isArray(end)) {
    throw Error("Start and end parameters must be arrays");
  }
  if (start.length != end.length) {
    throw Error("Start and end points must be the same length");
  }
  this.startPoint = start;
  this.endPoint = end;
  this.duration = duration;
  this.accel_ = opt_acc;
  this.coords = [];
  this.useRightPositioningForRtl_ = false;
  this.fps_ = 0;
  this.progress = 0;
  this.lastFrame = null;
};
goog.inherits(goog.fx.Animation, goog.fx.TransitionBase);
goog.fx.Animation.prototype.enableRightPositioningForRtl = function(useRightPositioningForRtl) {
  this.useRightPositioningForRtl_ = useRightPositioningForRtl;
};
goog.fx.Animation.prototype.isRightPositioningForRtlEnabled = function() {
  return this.useRightPositioningForRtl_;
};
goog.fx.Animation.EventType = {PLAY:goog.fx.Transition.EventType.PLAY, BEGIN:goog.fx.Transition.EventType.BEGIN, RESUME:goog.fx.Transition.EventType.RESUME, END:goog.fx.Transition.EventType.END, STOP:goog.fx.Transition.EventType.STOP, FINISH:goog.fx.Transition.EventType.FINISH, PAUSE:goog.fx.Transition.EventType.PAUSE, ANIMATE:"animate", DESTROY:"destroy"};
goog.fx.Animation.TIMEOUT = goog.fx.anim.TIMEOUT;
goog.fx.Animation.State = goog.fx.TransitionBase.State;
goog.fx.Animation.setAnimationWindow = function(animationWindow) {
  goog.fx.anim.setAnimationWindow(animationWindow);
};
goog.fx.Animation.prototype.play = function(opt_restart) {
  if (opt_restart || this.isStopped()) {
    this.progress = 0;
    this.coords = this.startPoint;
  } else {
    if (this.isPlaying()) {
      return false;
    }
  }
  goog.fx.anim.unregisterAnimation(this);
  var now = (goog.now());
  this.startTime = now;
  if (this.isPaused()) {
    this.startTime -= this.duration * this.progress;
  }
  this.endTime = this.startTime + this.duration;
  this.lastFrame = this.startTime;
  if (!this.progress) {
    this.onBegin();
  }
  this.onPlay();
  if (this.isPaused()) {
    this.onResume();
  }
  this.setStatePlaying();
  goog.fx.anim.registerAnimation(this);
  this.cycle(now);
  return true;
};
goog.fx.Animation.prototype.stop = function(opt_gotoEnd) {
  goog.fx.anim.unregisterAnimation(this);
  this.setStateStopped();
  if (opt_gotoEnd) {
    this.progress = 1;
  }
  this.updateCoords_(this.progress);
  this.onStop();
  this.onEnd();
};
goog.fx.Animation.prototype.pause = function() {
  if (this.isPlaying()) {
    goog.fx.anim.unregisterAnimation(this);
    this.setStatePaused();
    this.onPause();
  }
};
goog.fx.Animation.prototype.getProgress = function() {
  return this.progress;
};
goog.fx.Animation.prototype.setProgress = function(progress) {
  this.progress = progress;
  if (this.isPlaying()) {
    var now = goog.now();
    this.startTime = now - this.duration * this.progress;
    this.endTime = this.startTime + this.duration;
  }
};
goog.fx.Animation.prototype.disposeInternal = function() {
  if (!this.isStopped()) {
    this.stop(false);
  }
  this.onDestroy();
  goog.fx.Animation.base(this, "disposeInternal");
};
goog.fx.Animation.prototype.destroy = function() {
  this.dispose();
};
goog.fx.Animation.prototype.onAnimationFrame = function(now) {
  this.cycle(now);
};
goog.fx.Animation.prototype.cycle = function(now) {
  goog.asserts.assertNumber(this.startTime);
  goog.asserts.assertNumber(this.endTime);
  goog.asserts.assertNumber(this.lastFrame);
  if (now < this.startTime) {
    this.endTime = now + this.endTime - this.startTime;
    this.startTime = now;
  }
  this.progress = (now - this.startTime) / (this.endTime - this.startTime);
  if (this.progress > 1) {
    this.progress = 1;
  }
  this.fps_ = 1000 / (now - this.lastFrame);
  this.lastFrame = now;
  this.updateCoords_(this.progress);
  if (this.progress == 1) {
    this.setStateStopped();
    goog.fx.anim.unregisterAnimation(this);
    this.onFinish();
    this.onEnd();
  } else {
    if (this.isPlaying()) {
      this.onAnimate();
    }
  }
};
goog.fx.Animation.prototype.updateCoords_ = function(t) {
  if (goog.isFunction(this.accel_)) {
    t = this.accel_(t);
  }
  this.coords = new Array(this.startPoint.length);
  for (var i = 0;i < this.startPoint.length;i++) {
    this.coords[i] = (this.endPoint[i] - this.startPoint[i]) * t + this.startPoint[i];
  }
};
goog.fx.Animation.prototype.onAnimate = function() {
  this.dispatchAnimationEvent(goog.fx.Animation.EventType.ANIMATE);
};
goog.fx.Animation.prototype.onDestroy = function() {
  this.dispatchAnimationEvent(goog.fx.Animation.EventType.DESTROY);
};
goog.fx.Animation.prototype.dispatchAnimationEvent = function(type) {
  this.dispatchEvent(new goog.fx.AnimationEvent(type, this));
};
goog.fx.AnimationEvent = function(type, anim) {
  goog.fx.AnimationEvent.base(this, "constructor", type);
  this.coords = anim.coords;
  this.x = anim.coords[0];
  this.y = anim.coords[1];
  this.z = anim.coords[2];
  this.duration = anim.duration;
  this.progress = anim.getProgress();
  this.fps = anim.fps_;
  this.state = anim.getStateInternal();
  this.anim = anim;
};
goog.inherits(goog.fx.AnimationEvent, goog.events.Event);
goog.fx.AnimationEvent.prototype.coordsAsInts = function() {
  return goog.array.map(this.coords, Math.round);
};
goog.provide("goog.style.bidi");
goog.require("goog.dom");
goog.require("goog.style");
goog.require("goog.userAgent");
goog.style.bidi.getScrollLeft = function(element) {
  var isRtl = goog.style.isRightToLeft(element);
  if (isRtl && goog.userAgent.GECKO) {
    return -element.scrollLeft;
  } else {
    if (isRtl && !(goog.userAgent.EDGE_OR_IE && goog.userAgent.isVersionOrHigher("8"))) {
      var overflowX = goog.style.getComputedOverflowX(element);
      if (overflowX == "visible") {
        return element.scrollLeft;
      } else {
        return element.scrollWidth - element.clientWidth - element.scrollLeft;
      }
    }
  }
  return element.scrollLeft;
};
goog.style.bidi.getOffsetStart = function(element) {
  element = (element);
  var offsetLeftForReal = element.offsetLeft;
  var bestParent = element.offsetParent;
  if (!bestParent && goog.style.getComputedPosition(element) == "fixed") {
    bestParent = goog.dom.getOwnerDocument(element).documentElement;
  }
  if (!bestParent) {
    return offsetLeftForReal;
  }
  if (goog.userAgent.GECKO) {
    var borderWidths = goog.style.getBorderBox(bestParent);
    offsetLeftForReal += borderWidths.left;
  } else {
    if (goog.userAgent.isDocumentModeOrHigher(8) && !goog.userAgent.isDocumentModeOrHigher(9)) {
      var borderWidths = goog.style.getBorderBox(bestParent);
      offsetLeftForReal -= borderWidths.left;
    }
  }
  if (goog.style.isRightToLeft(bestParent)) {
    var elementRightOffset = offsetLeftForReal + element.offsetWidth;
    return bestParent.clientWidth - elementRightOffset;
  }
  return offsetLeftForReal;
};
goog.style.bidi.setScrollOffset = function(element, offsetStart) {
  offsetStart = Math.max(offsetStart, 0);
  if (!goog.style.isRightToLeft(element)) {
    element.scrollLeft = offsetStart;
  } else {
    if (goog.userAgent.GECKO) {
      element.scrollLeft = -offsetStart;
    } else {
      if (!(goog.userAgent.EDGE_OR_IE && goog.userAgent.isVersionOrHigher("8"))) {
        element.scrollLeft = element.scrollWidth - offsetStart - element.clientWidth;
      } else {
        element.scrollLeft = offsetStart;
      }
    }
  }
};
goog.style.bidi.setPosition = function(elem, left, top, isRtl) {
  if (!goog.isNull(top)) {
    elem.style.top = top + "px";
  }
  if (isRtl) {
    elem.style.right = left + "px";
    elem.style.left = "";
  } else {
    elem.style.left = left + "px";
    elem.style.right = "";
  }
};
goog.provide("goog.fx.dom");
goog.provide("goog.fx.dom.BgColorTransform");
goog.provide("goog.fx.dom.ColorTransform");
goog.provide("goog.fx.dom.Fade");
goog.provide("goog.fx.dom.FadeIn");
goog.provide("goog.fx.dom.FadeInAndShow");
goog.provide("goog.fx.dom.FadeOut");
goog.provide("goog.fx.dom.FadeOutAndHide");
goog.provide("goog.fx.dom.PredefinedEffect");
goog.provide("goog.fx.dom.Resize");
goog.provide("goog.fx.dom.ResizeHeight");
goog.provide("goog.fx.dom.ResizeWidth");
goog.provide("goog.fx.dom.Scroll");
goog.provide("goog.fx.dom.Slide");
goog.provide("goog.fx.dom.SlideFrom");
goog.provide("goog.fx.dom.Swipe");
goog.require("goog.color");
goog.require("goog.events");
goog.require("goog.fx.Animation");
goog.require("goog.fx.Transition");
goog.require("goog.style");
goog.require("goog.style.bidi");
goog.forwardDeclare("goog.events.EventHandler");
goog.fx.dom.PredefinedEffect = function(element, start, end, time, opt_acc) {
  goog.fx.Animation.call(this, start, end, time, opt_acc);
  this.element = element;
  this.rightToLeft_;
};
goog.inherits(goog.fx.dom.PredefinedEffect, goog.fx.Animation);
goog.fx.dom.PredefinedEffect.prototype.updateStyle = goog.nullFunction;
goog.fx.dom.PredefinedEffect.prototype.isRightToLeft = function() {
  if (!goog.isDef(this.rightToLeft_)) {
    this.rightToLeft_ = goog.style.isRightToLeft(this.element);
  }
  return this.rightToLeft_;
};
goog.fx.dom.PredefinedEffect.prototype.onAnimate = function() {
  this.updateStyle();
  goog.fx.dom.PredefinedEffect.superClass_.onAnimate.call(this);
};
goog.fx.dom.PredefinedEffect.prototype.onEnd = function() {
  this.updateStyle();
  goog.fx.dom.PredefinedEffect.superClass_.onEnd.call(this);
};
goog.fx.dom.PredefinedEffect.prototype.onBegin = function() {
  this.updateStyle();
  goog.fx.dom.PredefinedEffect.superClass_.onBegin.call(this);
};
goog.fx.dom.Slide = function(element, start, end, time, opt_acc) {
  if (start.length != 2 || end.length != 2) {
    throw Error("Start and end points must be 2D");
  }
  goog.fx.dom.PredefinedEffect.apply(this, arguments);
};
goog.inherits(goog.fx.dom.Slide, goog.fx.dom.PredefinedEffect);
goog.fx.dom.Slide.prototype.updateStyle = function() {
  var pos = this.isRightPositioningForRtlEnabled() && this.isRightToLeft() ? "right" : "left";
  this.element.style[pos] = Math.round(this.coords[0]) + "px";
  this.element.style.top = Math.round(this.coords[1]) + "px";
};
goog.fx.dom.SlideFrom = function(element, end, time, opt_acc) {
  this.startPoint;
  var offsetLeft = this.isRightPositioningForRtlEnabled() ? goog.style.bidi.getOffsetStart(element) : (element).offsetLeft;
  var start = [offsetLeft, (element).offsetTop];
  goog.fx.dom.Slide.call(this, element, start, end, time, opt_acc);
};
goog.inherits(goog.fx.dom.SlideFrom, goog.fx.dom.Slide);
goog.fx.dom.SlideFrom.prototype.onBegin = function() {
  var offsetLeft = this.isRightPositioningForRtlEnabled() ? goog.style.bidi.getOffsetStart(this.element) : this.element.offsetLeft;
  this.startPoint = [offsetLeft, (this.element).offsetTop];
  goog.fx.dom.SlideFrom.superClass_.onBegin.call(this);
};
goog.fx.dom.Swipe = function(element, start, end, time, opt_acc) {
  if (start.length != 2 || end.length != 2) {
    throw Error("Start and end points must be 2D");
  }
  goog.fx.dom.PredefinedEffect.apply(this, arguments);
  this.maxWidth_ = Math.max(this.endPoint[0], this.startPoint[0]);
  this.maxHeight_ = Math.max(this.endPoint[1], this.startPoint[1]);
};
goog.inherits(goog.fx.dom.Swipe, goog.fx.dom.PredefinedEffect);
goog.fx.dom.Swipe.prototype.updateStyle = function() {
  var x = this.coords[0];
  var y = this.coords[1];
  this.clip_(Math.round(x), Math.round(y), this.maxWidth_, this.maxHeight_);
  this.element.style.width = Math.round(x) + "px";
  var marginX = this.isRightPositioningForRtlEnabled() && this.isRightToLeft() ? "marginRight" : "marginLeft";
  this.element.style[marginX] = Math.round(x) - this.maxWidth_ + "px";
  this.element.style.marginTop = Math.round(y) - this.maxHeight_ + "px";
};
goog.fx.dom.Swipe.prototype.clip_ = function(x, y, w, h) {
  this.element.style.clip = "rect(" + (h - y) + "px " + w + "px " + h + "px " + (w - x) + "px)";
};
goog.fx.dom.Scroll = function(element, start, end, time, opt_acc) {
  if (start.length != 2 || end.length != 2) {
    throw Error("Start and end points must be 2D");
  }
  goog.fx.dom.PredefinedEffect.apply(this, arguments);
};
goog.inherits(goog.fx.dom.Scroll, goog.fx.dom.PredefinedEffect);
goog.fx.dom.Scroll.prototype.updateStyle = function() {
  if (this.isRightPositioningForRtlEnabled()) {
    goog.style.bidi.setScrollOffset(this.element, Math.round(this.coords[0]));
  } else {
    this.element.scrollLeft = Math.round(this.coords[0]);
  }
  this.element.scrollTop = Math.round(this.coords[1]);
};
goog.fx.dom.Resize = function(element, start, end, time, opt_acc) {
  if (start.length != 2 || end.length != 2) {
    throw Error("Start and end points must be 2D");
  }
  goog.fx.dom.PredefinedEffect.apply(this, arguments);
};
goog.inherits(goog.fx.dom.Resize, goog.fx.dom.PredefinedEffect);
goog.fx.dom.Resize.prototype.updateStyle = function() {
  this.element.style.width = Math.round(this.coords[0]) + "px";
  this.element.style.height = Math.round(this.coords[1]) + "px";
};
goog.fx.dom.ResizeWidth = function(element, start, end, time, opt_acc) {
  goog.fx.dom.PredefinedEffect.call(this, element, [start], [end], time, opt_acc);
};
goog.inherits(goog.fx.dom.ResizeWidth, goog.fx.dom.PredefinedEffect);
goog.fx.dom.ResizeWidth.prototype.updateStyle = function() {
  this.element.style.width = Math.round(this.coords[0]) + "px";
};
goog.fx.dom.ResizeHeight = function(element, start, end, time, opt_acc) {
  goog.fx.dom.PredefinedEffect.call(this, element, [start], [end], time, opt_acc);
};
goog.inherits(goog.fx.dom.ResizeHeight, goog.fx.dom.PredefinedEffect);
goog.fx.dom.ResizeHeight.prototype.updateStyle = function() {
  this.element.style.height = Math.round(this.coords[0]) + "px";
};
goog.fx.dom.Fade = function(element, start, end, time, opt_acc) {
  if (goog.isNumber(start)) {
    start = [start];
  }
  if (goog.isNumber(end)) {
    end = [end];
  }
  goog.fx.dom.Fade.base(this, "constructor", element, start, end, time, opt_acc);
  if (start.length != 1 || end.length != 1) {
    throw Error("Start and end points must be 1D");
  }
  this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
};
goog.inherits(goog.fx.dom.Fade, goog.fx.dom.PredefinedEffect);
goog.fx.dom.Fade.TOLERANCE_ = 1.0 / 1024;
goog.fx.dom.Fade.OPACITY_UNSET_ = -1;
goog.fx.dom.Fade.prototype.updateStyle = function() {
  var opacity = this.coords[0];
  var delta = Math.abs(opacity - this.lastOpacityUpdate_);
  if (delta >= goog.fx.dom.Fade.TOLERANCE_) {
    goog.style.setOpacity(this.element, opacity);
    this.lastOpacityUpdate_ = opacity;
  }
};
goog.fx.dom.Fade.prototype.onBegin = function() {
  this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
  goog.fx.dom.Fade.base(this, "onBegin");
};
goog.fx.dom.Fade.prototype.onEnd = function() {
  this.lastOpacityUpdate_ = goog.fx.dom.Fade.OPACITY_UNSET_;
  goog.fx.dom.Fade.base(this, "onEnd");
};
goog.fx.dom.Fade.prototype.show = function() {
  this.element.style.display = "";
};
goog.fx.dom.Fade.prototype.hide = function() {
  this.element.style.display = "none";
};
goog.fx.dom.FadeOut = function(element, time, opt_acc) {
  goog.fx.dom.Fade.call(this, element, 1, 0, time, opt_acc);
};
goog.inherits(goog.fx.dom.FadeOut, goog.fx.dom.Fade);
goog.fx.dom.FadeIn = function(element, time, opt_acc) {
  goog.fx.dom.Fade.call(this, element, 0, 1, time, opt_acc);
};
goog.inherits(goog.fx.dom.FadeIn, goog.fx.dom.Fade);
goog.fx.dom.FadeOutAndHide = function(element, time, opt_acc) {
  goog.fx.dom.Fade.call(this, element, 1, 0, time, opt_acc);
};
goog.inherits(goog.fx.dom.FadeOutAndHide, goog.fx.dom.Fade);
goog.fx.dom.FadeOutAndHide.prototype.onBegin = function() {
  this.show();
  goog.fx.dom.FadeOutAndHide.superClass_.onBegin.call(this);
};
goog.fx.dom.FadeOutAndHide.prototype.onEnd = function() {
  this.hide();
  goog.fx.dom.FadeOutAndHide.superClass_.onEnd.call(this);
};
goog.fx.dom.FadeInAndShow = function(element, time, opt_acc) {
  goog.fx.dom.Fade.call(this, element, 0, 1, time, opt_acc);
};
goog.inherits(goog.fx.dom.FadeInAndShow, goog.fx.dom.Fade);
goog.fx.dom.FadeInAndShow.prototype.onBegin = function() {
  this.show();
  goog.fx.dom.FadeInAndShow.superClass_.onBegin.call(this);
};
goog.fx.dom.BgColorTransform = function(element, start, end, time, opt_acc) {
  if (start.length != 3 || end.length != 3) {
    throw Error("Start and end points must be 3D");
  }
  goog.fx.dom.PredefinedEffect.apply(this, arguments);
};
goog.inherits(goog.fx.dom.BgColorTransform, goog.fx.dom.PredefinedEffect);
goog.fx.dom.BgColorTransform.prototype.setColor = function() {
  var coordsAsInts = [];
  for (var i = 0;i < this.coords.length;i++) {
    coordsAsInts[i] = Math.round(this.coords[i]);
  }
  var color = "rgb(" + coordsAsInts.join(",") + ")";
  this.element.style.backgroundColor = color;
};
goog.fx.dom.BgColorTransform.prototype.updateStyle = function() {
  this.setColor();
};
goog.fx.dom.bgColorFadeIn = function(element, start, time, opt_eventHandler) {
  var initialBgColor = element.style.backgroundColor || "";
  var computedBgColor = goog.style.getBackgroundColor(element);
  var end;
  if (computedBgColor && computedBgColor != "transparent" && computedBgColor != "rgba(0, 0, 0, 0)") {
    end = goog.color.hexToRgb(goog.color.parse(computedBgColor).hex);
  } else {
    end = [255, 255, 255];
  }
  var anim = new goog.fx.dom.BgColorTransform(element, start, end, time);
  function setBgColor() {
    element.style.backgroundColor = initialBgColor;
  }
  if (opt_eventHandler) {
    opt_eventHandler.listen(anim, goog.fx.Transition.EventType.END, setBgColor);
  } else {
    goog.events.listen(anim, goog.fx.Transition.EventType.END, setBgColor);
  }
  anim.play();
};
goog.fx.dom.ColorTransform = function(element, start, end, time, opt_acc) {
  if (start.length != 3 || end.length != 3) {
    throw Error("Start and end points must be 3D");
  }
  goog.fx.dom.PredefinedEffect.apply(this, arguments);
};
goog.inherits(goog.fx.dom.ColorTransform, goog.fx.dom.PredefinedEffect);
goog.fx.dom.ColorTransform.prototype.updateStyle = function() {
  var coordsAsInts = [];
  for (var i = 0;i < this.coords.length;i++) {
    coordsAsInts[i] = Math.round(this.coords[i]);
  }
  var color = "rgb(" + coordsAsInts.join(",") + ")";
  this.element.style.color = color;
};
goog.provide("uno.util.adornment");
goog.require("uno.util.dom");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.fx.dom");
goog.require("goog.object");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.adornment");
  var util = uno.util;
  var domWrapperTag = "en-container";
  var uiWrapperTag = "en-adornments";
  util.adornment.create = function(element, name, rules) {
    if (name == null) {
      log.severe("Name is mandatory for adorn elements");
      return null;
    }
    rules = rules || {};
    goog.object.extend(rules, {above:true, redrawFunc:null});
    var uiWrap = getUIWrapper(element);
    var adorn = util.adornment.find(element, name);
    if (adorn != null) {
      log.warning("Already have an element named " + name);
      return adorn;
    }
    adorn = goog.dom.createDom("div");
    adorn.style.position = "absolute";
    adorn.setAttribute("class", "adornment" + (rules.above ? " above" : ""));
    adorn.setAttribute("data-name", name);
    uiWrap.appendChild(adorn);
    return adorn;
  };
  util.adornment.find = function(element, name) {
    var uiWrap = getUIWrapper(element, true);
    if (uiWrap == null) {
      return null;
    }
    return uiWrap.querySelector('[data-name="' + name + '"]');
  };
  util.adornment.globalFind = function(editor, name) {
    var ennote = editor.getElement();
    if (ennote == null) {
      return [];
    }
    return ennote.querySelectorAll('[data-name="' + name + '"]');
  };
  util.adornment.parent = function(adorn) {
    var elemWrap = util.adornment.getElementWrapper(adorn, true);
    if (elemWrap == null) {
      return null;
    }
    return elemWrap.childNodes.length > 0 ? elemWrap.childNodes[0] : null;
  };
  util.adornment.destroy = function(adorn) {
    var inAdornments = !!util.dom.getFirstAncestor(adorn, [uiWrapperTag]);
    if (!inAdornments) {
      log.severe("Called util.adornment.destroy on non-adornment!");
      return;
    }
    goog.dom.removeNode(adorn);
  };
  util.adornment.destroyAllByName = function(editor, name) {
    goog.array.forEach(util.adornment.globalFind(editor, name), util.adornment.destroy);
  };
  util.adornment.makePristine = function(parent) {
    var uiWrap = getUIWrapper(parent, true);
    if (uiWrap) {
      goog.dom.removeNode(uiWrap);
    }
    var domWrap = util.adornment.getElementWrapper(parent, true);
    if (domWrap) {
      goog.dom.flattenElement(domWrap);
    }
  };
  util.adornment.show = function(adorn) {
    goog.fx.dom.FadeOutAndHide(adorn, 500).show();
  };
  util.adornment.hide = function(adorn) {
    goog.fx.dom.FadeOutAndHide(adorn, 500).hide();
  };
  util.adornment.getElementWrapper = function(element, optDontCreate) {
    var wrapper = util.dom.getFirstAncestor(element, [domWrapperTag], true);
    if (optDontCreate == null) {
      optDontCreate = false;
    }
    var topMostBlock = null;
    if (wrapper == null) {
      if (optDontCreate) {
        return null;
      }
      if (!document.body.contains(element)) {
        return null;
      }
      topMostBlock = element;
      while (true) {
        if (topMostBlock.parentElement == null) {
          topMostBlock = null;
          break;
        } else {
          if (util.dom.getTagName(topMostBlock.parentElement) === "en-note") {
            break;
          } else {
            topMostBlock = topMostBlock.parentElement;
          }
        }
      }
    }
    if (topMostBlock != null) {
      wrapper = goog.dom.createDom(domWrapperTag);
      goog.dom.replaceNode(wrapper, topMostBlock);
      wrapper.appendChild(topMostBlock);
    }
    return wrapper;
  };
  var getUIWrapper = function(element, optDontCreate) {
    if (optDontCreate == null) {
      optDontCreate = false;
    }
    var elementWrap = util.adornment.getElementWrapper(element, optDontCreate);
    if (elementWrap == null) {
      return null;
    }
    var uiWrap = elementWrap.querySelector(uiWrapperTag);
    if (uiWrap == null) {
      if (optDontCreate) {
        return null;
      }
      elementWrap.style.position = "relative";
      uiWrap = goog.dom.createDom(uiWrapperTag);
      uiWrap.style.position = "absolute";
      uiWrap.style.left = "0px";
      uiWrap.style.top = "0px";
      uiWrap.style.right = "0px";
      uiWrap.style.bottom = "0px";
      uiWrap.setAttribute("contenteditable", "false");
      elementWrap.appendChild(uiWrap);
    }
    return uiWrap;
  };
})();
goog.provide("uno.util.table.multirange");
goog.require("goog.debug.Logger");
goog.require("goog.array");
goog.require("goog.dom");
goog.require("uno.util.adornment");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.table.multirange");
  var util = uno.util;
  var CELL_SEL = "fake-selection";
  var HAS_MENU = "has-menu";
  var MENU_HOVER = "menu-hover";
  util.table.multirange.toggleTD = function(editor, td) {
    var foundRangeIndex = null;
    var textRanges = editor.multirange.getTextRanges();
    goog.array.forEach(textRanges, function(textrange, index) {
      var curTD = util.table.cellForRange(textrange);
      if (curTD === td) {
        foundRangeIndex = index;
      }
    });
    if (foundRangeIndex == null) {
      var childLen = td.childNodes.length;
      var newRange = goog.dom.Range.createFromNodes(td, 0, td, childLen);
      editor.multirange.push(newRange);
    } else {
      editor.multirange.removeAt(foundRangeIndex);
    }
  };
  util.table.multirange.addTD = function(editor, td) {
    if (editor == null || td == null) {
      return;
    }
    var childLen = td.childNodes.length;
    var newRange = goog.dom.Range.createFromNodes(td, 0, td, childLen);
    editor.multirange.push(newRange);
  };
  util.table.multirange.rightMostTopCell = function(multirange) {
    var ranges = multirange.getTextRanges();
    var highScore = -1;
    return goog.array.reduce(ranges, function(highest, next) {
      var cell = util.table.cellForRange(next);
      if (cell == null) {
        return highest;
      }
      var cellPos = util.table.positionInTable(cell);
      if (cellPos.table == null) {
        return highest;
      }
      var cellScore = (1 + cellPos.column) * 100000 - cellPos.row;
      if (cellScore > highScore) {
        highScore = cellScore;
        return cell;
      }
      return highest;
    }, null);
  };
  util.table.multirange.renderMultiRange = function(multirange) {
    var selectCell = function(cell) {
      var parent = util.dom.getFirstAncestor(cell, "table", true);
      if (parent == null) {
        return;
      }
      util.table.setMode(parent, "multirange");
      goog.dom.classlist.add(cell, CELL_SEL);
    };
    goog.array.forEach(multirange.getTextRanges(), function(range) {
      var cell = util.table.cellForRange(range);
      if (cell != null) {
        selectCell(cell);
      } else {
        log.severe("We only support table cell multiranges!");
      }
    });
    var rightTopCell = util.table.multirange.rightMostTopCell(multirange);
    if (rightTopCell != null) {
      goog.dom.classlist.add(rightTopCell, HAS_MENU);
    }
  };
  util.table.multirange.clear = function() {
    goog.array.forEach(document.body.querySelectorAll("." + CELL_SEL), function(element) {
      var parent = util.dom.getFirstAncestor(element, "table", true);
      if (parent) {
        util.table.clearMode(parent);
      }
      goog.dom.classlist.remove(element, CELL_SEL);
      goog.dom.classlist.remove(element, HAS_MENU);
      goog.dom.classlist.remove(element, MENU_HOVER);
    });
  };
  util.table.multirange.createControls = function(editor, table) {
    var saveRange = editor.multirange.active() ? editor.multirange.getTextRanges()[0] : editor.getRange();
    var saved = null;
    if (saveRange && saveRange.saveUsingCarets) {
      saved = saveRange.saveUsingCarets();
    }
    var adorn = util.adornment.create(table, "table-controls");
    adorn.appendChild(goog.dom.createDom("table-selection"));
    adorn.appendChild(goog.dom.createDom("row-selection"));
    adorn.appendChild(goog.dom.createDom("column-selection"));
    util.table.multirange.updateControls(table, false);
    if (saved != null) {
      saved.restore();
    }
    return adorn;
  };
  util.table.multirange.updateAllControls = function(editor) {
    goog.array.forEach(util.adornment.globalFind(editor, "table-controls"), util.table.multirange.updateControls);
  };
  util.table.multirange.updateControls = function(tableRef, onlyScroll) {
    if (onlyScroll == null) {
      onlyScroll = false;
    }
    var adorn = util.adornment.find(tableRef, "table-controls");
    if (!adorn) {
      return;
    }
    var elementWrapper = util.adornment.getElementWrapper(tableRef, true);
    if (!elementWrapper) {
      return;
    }
    var table = elementWrapper.querySelector("table");
    if (!table) {
      return;
    }
    var tableScrollWrapper = elementWrapper.querySelector("en-table");
    if (!tableScrollWrapper) {
      return;
    }
    var columnSelection = adorn.querySelector("column-selection");
    if (!columnSelection) {
      return;
    }
    var rowSelection = adorn.querySelector("row-selection");
    if (!rowSelection) {
      return;
    }
    var firstRow = table.querySelector("tr");
    if (firstRow == null) {
      goog.dom.removeChildren(columnSelection);
      return;
    }
    var firstRowTDs = firstRow.querySelectorAll("td");
    var colPips = columnSelection.querySelector("pips");
    var firstColTDs = util.table.column(table, 0);
    var rowPips = rowSelection.querySelector("pips");
    if (!onlyScroll || colPips == null) {
      goog.dom.removeChildren(columnSelection);
      colPips = goog.dom.createDom("pips", {style:"width:" + (util.dom.getBoundingBox(table).width + 1) + "px"});
      goog.array.forEach(firstRowTDs, function(td) {
        var tdBounds = util.dom.getBoundingBox(td);
        if (tdBounds != null) {
          colPips.appendChild(goog.dom.createDom("pip", {style:"width:" + tdBounds.width + "px;"}));
        }
      });
      columnSelection.append(colPips);
    }
    if (!onlyScroll || rowPips == null) {
      goog.dom.removeChildren(rowSelection);
      rowPips = goog.dom.createDom("pips");
      goog.array.forEach(firstColTDs, function(td) {
        var tdBounds = util.dom.getBoundingBox(td);
        if (tdBounds != null) {
          rowPips.appendChild(goog.dom.createDom("pip", {style:"height:" + tdBounds.height + "px;"}));
        }
      });
      rowSelection.append(rowPips);
    }
    colPips.style.left = 0 - tableScrollWrapper.scrollLeft + "px";
  };
  util.table.multirange.selectedCells = function(editor) {
    if (!editor.multirange.active()) {
      return [];
    }
    var ranges = editor.multirange.getTextRanges();
    return goog.array.filter(goog.array.map(ranges, util.table.cellForRange), goog.dom.isNodeLike);
  };
  util.table.multirange.shouldClear = function(editor, latestRange) {
    var selectedCells = util.table.multirange.selectedCells(editor);
    if (selectedCells.length <= 0) {
      return true;
    }
    var latestRangeWrapper = util.adornment.getElementWrapper(latestRange.getStartNode(), true);
    var multiRangeWrapper = util.adornment.getElementWrapper(selectedCells[0], true);
    return latestRangeWrapper !== multiRangeWrapper;
  };
})();
goog.provide("uno.MultiRange");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.dom.MultiRange");
goog.require("uno.util.tools");
goog.require("uno.util.range");
goog.require("uno.util.table");
goog.require("uno.util.table.multirange");
(function() {
  var util = uno.util;
  var MultiRange = uno.MultiRange = function(textRanges) {
    if (textRanges == null) {
      textRanges = [];
    }
    goog.base(this);
    this.ranges_ = textRanges;
    this.browserRanges_ = goog.array.map(textRanges, function(range) {
      return range.getBrowserRangeObject();
    });
  };
  goog.inherits(MultiRange, goog.dom.MultiRange);
  MultiRange.prototype.getTextRanges = function() {
    return this.ranges_;
  };
  MultiRange.prototype.setTextRanges = function(textranges) {
    this.ranges_ = textranges;
    this.select();
  };
  MultiRange.prototype.push = function(textrange) {
    this.ranges_.push(textrange);
    this.select();
  };
  MultiRange.prototype.removeAt = function(index) {
    goog.array.removeAt(this.ranges_, index);
    this.select();
  };
  MultiRange.prototype.select = function() {
    util.table.multirange.clear();
    var firstRange = this.ranges_.length > 0 ? this.ranges_[0] : null;
    if (firstRange == null) {
      return;
    }
    window.getSelection().removeAllRanges();
    window.getSelection().addRange(firstRange.getBrowserRangeObject());
    util.table.multirange.renderMultiRange(this);
  };
})();
goog.provide("uno.EditorMultiRange");
goog.require("uno.MultiRange");
(function() {
  var EditorMultiRange = uno.EditorMultiRange = function(editor) {
    this.editor = editor;
    this.multi = new uno.MultiRange;
    this.getTextRanges = this.multi.getTextRanges.bind(this.multi);
    this.select = this.multi.select.bind(this.multi);
    this.push = this.multi.push.bind(this.multi);
    this.removeAt = this.multi.removeAt.bind(this.multi);
  };
  EditorMultiRange.prototype.active = function() {
    return this.multi.getTextRanges().length > 0;
  };
  EditorMultiRange.prototype.clear = function() {
    this.multi.setTextRanges([]);
    this.multi.select();
  };
})();
goog.provide("uno.BasePlugin");
goog.require("uno.defs");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Plugin");
goog.require("goog.editor.Plugin");
(function() {
  var Plugin = goog.editor.Plugin;
  var BasePlugin = uno.BasePlugin = function(trogClassId) {
    Plugin.call(this);
    this.trogClassId = trogClassId;
    this.platform = null;
    this.multiRangeMode = uno.defs.multirange.PLUGIN_MODE.APPLY_TO_FIRST;
  };
  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.platform = namespace[fieldObject.config.platform] || namespace.generic || {};
      Object.keys(this.platform).forEach(function(key) {
        if (typeof me.platform[key] === "function") {
          me.platform[key] = me.platform[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.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("uno.commands.BasicTextFormatter");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("goog.functions");
goog.require("goog.dom");
goog.require("uno.defs");
goog.require("uno.BasePlugin");
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.defs.multirange.PLUGIN_MODE.APPLY_TO_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, inserthorizontalrule:goog.editor.Command.HORIZONTAL_RULE, 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) {
      swappedObjects = util.resource.toggleObjectsInRange(range, false);
    }
    this.editor.execCommand(googleCommand, value);
    this.fixFloatingUnwrappedBR();
    removeTextSizeAdjust(this.editor);
    var newRange = this.editor.getRange();
    if ((isOrderedListCommand || isUnorderedListCommand || isIndentCommand || isOutdentCommand) && swappedObjects) {
      util.resource.toggleObjectsInRange(newRange, swappedObjects);
    }
    if (newRange) {
      if (newRange.isCollapsed()) {
        if (["indent", "inserthorizontalrule", "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() {
    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());
  };
  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(paraNode) {
    return !!util.paragraph.leadingTodo(paraNode);
  };
  util.paragraph.leadingTodo = function(paraNode) {
    var child = paraNode;
    while (child && child.firstChild) {
      child = child.firstChild;
      while (child && child.nodeType === Node.TEXT_NODE && child.textContent.length === 0) {
        child = child.nextSibling;
      }
    }
    if (util.todo.isTodo(child)) {
      return child;
    }
  };
  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"));
  };
  util.paragraph.split = function(range, paraNode) {
    if (!range.isCollapsed()) {
      return null;
    }
    paraNode = util.paragraph["for"](paraNode);
    paraNode = util.paragraph["for"](paraNode || range.getContainer());
    if (util.dom.isEnnote(paraNode)) {
      return null;
    }
    var breakNode = goog.dom.createDom("div");
    range.insertNode(breakNode);
    var restOfParagraph = goog.editor.node.splitDomTreeAt(breakNode, null, paraNode);
    goog.dom.removeNode(breakNode);
    if (!util.dom.isEmpty(restOfParagraph)) {
      goog.dom.insertSiblingAfter(restOfParagraph, paraNode);
    }
    return paraNode;
  };
})();
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.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$8) {
      log.fine(err$8.stack || err$8);
    }
    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;
  };
})();
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.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("uno.util.copy.table");
(function() {
  var util = uno.util;
  util.copy.table.getPastableHtml = function(ranges) {
    var minX = 9999;
    var minY = 9999;
    var maxX = 1;
    var maxY = 1;
    var cells = {};
    var widths = {};
    goog.iter.forEach(ranges, function(r) {
      var node = r.getStartNode();
      if (node && node.parentNode) {
        var x = node.parentNode.rowIndex + 1;
        var y = node.cellIndex + 1;
        if (x < minX) {
          minX = x;
        }
        if (x > maxX) {
          maxX = x;
        }
        if (y < minY) {
          minY = y;
        }
        if (y > maxY) {
          maxY = y;
        }
        var index = x.toString() + y.toString();
        cells[index] = node;
        if (!widths[x]) {
          var style = getComputedStyle(node);
          widths[x] = style.width;
        }
      }
    });
    var tableSize = {rows:maxX - minX + 1, columns:maxY - minY + 1};
    if (tableSize.rows === 1 && tableSize.columns === 1) {
      var html = "";
      if (ranges[0]) {
        var node = ranges[0].getStartNode();
        if (node) {
          html = node.innerHTML;
        }
      }
      return html;
    }
    var table = goog.dom.createDom("table", null);
    var tbody = goog.dom.createDom("tbody", null);
    table.appendChild(tbody);
    for (var i = 0;i < tableSize.rows;i++) {
      var tr = goog.dom.createDom("tr", null);
      for (var j = 0;j < tableSize.columns;j++) {
        var x = i + minX;
        var y = j + minY;
        var index = x.toString() + y.toString();
        var cell = cells[index];
        var width = (parseInt(widths[i + 1], 10) || uno.defs.table.CELL_MIN) + "px";
        var td = goog.dom.createDom("td", {width:width, "min-width":width});
        td.innerHTML = cell ? cell.innerHTML : "<div><br></div>";
        tr.appendChild(td);
      }
      tbody.appendChild(tr);
    }
    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.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 platform = uno.util.font.generic;
  var util = uno.util;
  util.font.setPlatform = function(platformName) {
    platform = uno.util.font[platformName] || platform;
  };
  util.font.getSize = function(node) {
    return platform.getSize(node);
  };
  util.font.getColor = function(node) {
    return goog.style.getComputedStyle(node, "color");
  };
  util.font.prepareSize = function(size) {
    return platform.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.BACKGROUND_COLOR_MAC;
  var knownAttributes = /data-.*|face|border|name|href|rev|start|title|color|class/;
  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 = {};
  };
  styles.setInlineStyles = function(line, style, defaults) {
    var hadParent = true;
    if (util.dom.isTextNode(line) || util.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 util.dom.isTextNode(n) || util.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" && 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") {
              if (["sub"].indexOf(attr.value) > -1) {
                style.subscript = true;
              }
              if (["super"].indexOf(attr.value) > -1) {
                style.superscript = true;
              }
            } else {
              var supportedStyle = "-evernote.*|-en-.*|background-color|color|font-weight|font-size|font-family|text-align";
              if (dom.isTd(node)) {
                supportedStyle += "|min-width|width|border|border-style|border-width|border-color|padding|margin";
              } else {
                if (dom.isTable(node)) {
                  supportedStyle += "|width|border-collapse|table-layout|margin-left|margin-right";
                }
              }
              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);
      }
    }
  };
  styles.getStyleString = function(nodeStyles) {
    var finalStyle = "";
    var textDecoration = "";
    Object.keys(nodeStyles).forEach(function(key) {
      var style = nodeStyles[key];
      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 {
                    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;
  };
})();
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.styles");
goog.require("uno.util.zoomscale");
(function() {
  var BORDER_WIDTH = 2;
  var MIN_WIDTH = 50 + BORDER_WIDTH * 2;
  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("resizing");
    this.layout();
    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";
    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), 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("resizing");
  }
  function handleContextMenu(evt) {
    if (this.resizing) {
      evt.preventDefault();
    }
  }
})();
goog.provide("uno.util.observer");
goog.require("uno.defs");
(function() {
  var util = uno.util;
  var handlers = [];
  var target = null;
  var targetScrollHeight = null;
  var sharedObserver = new MutationObserver(invokeHandlers);
  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 scrollHeight = target.scrollHeight;
    if (targetScrollHeight !== scrollHeight) {
      targetScrollHeight = scrollHeight;
      handlers.forEach(function(handler) {
        handler();
      });
    }
  }
  function observeIfNeeded() {
    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);
      targetScrollHeight = target.scrollHeight;
      sharedObserver.observe(target, {childList:true, subtree:true});
      goog.events.listen(window, "resize", invokeHandlers);
      goog.events.listen(window, "input", invokeHandlers);
    }
  }
})();
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) {
    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.width = props.width;
    }
    if (goog.isNumber(img.width) && +img.width > 0) {
      img.dataset.width = img.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.convertPlatformElementToSlug = 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.loadFromPlatformAsync = function(src, platform) {
    var fixtures = platform && platform.fixtures ? platform.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.findResourcesInPlatformHtml = 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.convertPlatformElementToSlug = function(el) {
    return el;
  };
  generic.convertSlugToPlatformElement = 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.findResourcesInPlatformHtml = 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.convertPlatformElementToSlug = function(el) {
    return el;
  };
  android.convertSlugToPlatformElement = 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.findResourcesInPlatformHtml = 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.convertPlatformElementToSlug = function(el) {
    return el;
  };
  ios.convertSlugToPlatformElement = 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.findResourcesInPlatformHtml = 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.findResourcesInPlatformHtml(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.convertPlatformElementToSlug = function(el, props, editor) {
    if (util.resource.isImage(props.type)) {
      return util.img.convertPlatformElementToSlug(el, props, editor);
    }
    return el;
  };
  mac.convertSlugToPlatformElement = 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.findResourcesInPlatformHtml = 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.findResourcesInPlatformHtml(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]");
    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.convertPlatformElementToSlug = function(el) {
    return el;
  };
  win.convertSlugToPlatformElement = 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 platform = uno.util.resource.generic;
  util.resource.setPlatform = function(platformName) {
    platform = uno.util.resource[platformName] || platform;
  };
  util.resource.all = function(root) {
    return root.querySelectorAll(".en-media");
  };
  util.resource.findResourcesInPlatformHtml = function(root) {
    return platform.findResourcesInPlatformHtml(root);
  };
  util.resource.findResourcesInClipboardHtml = function(root) {
    return platform.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 = platform.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.convertPlatformElementToSlug = function(el, editor) {
    var dict = platform.dictFromElement(el);
    var props = util.resource.propsFromDict(dict);
    props.reference = props.reference || el.dataset.reference || util.resource.createUid();
    var slug = platform.convertPlatformElementToSlug(el, props, editor);
    if (util.resource.isImage(props.type)) {
      slug.removeAttribute("height");
    }
    util.resource.addMetaData(slug, props);
    goog.dom.replaceNode(slug, el);
    addCssClasses(slug, props.type);
  };
  util.resource.convertSlugToPlatformElement = function(slug) {
    var el = platform.convertSlugToPlatformElement(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 = platform.convertMediaToSlug(enmedia, props, editor);
    if (util.resource.isImage(props.type)) {
      slug.removeAttribute("height");
    }
    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 (!slug.nextSibling) {
      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) {
      enmedia.setAttribute("hash", slug.dataset.hash);
    }
    if (slug.dataset.type) {
      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.dataset.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.formatPlatformHtmlForExport = function(html) {
    return platform.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 platform.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.active()) {
      pastableHtml = util.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 enclipboard = goog.dom.createDom("en-clipboard");
      richNode.appendChild(enclipboard);
    }
    return {resources:options.resources ? copy.resources.copy(resourcesNode) : [], html:options.html ? util.copy.rich.copy(richNode) : "", plain:options.plain ? util.copy.plain.copy(plainNode) : ""};
  };
  function addContext(root, range, editor) {
    if (editor.multirange.active()) {
      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.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.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: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;
      util.range.selectNode(node);
      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.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 || {}};
    var content = value.content;
    editor.context.format = value.type;
    if (editor.context.format === uno.defs.format.PLATFORM_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);
    editor.setHtml(false, content, true);
    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.PLATFORM_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.PLATFORM_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.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.findTodosInPlatformHtml = function() {
    return [];
  };
  generic.convertTodoToPlatformElement = function() {
  };
})();
goog.provide("uno.util.todo.mac");
goog.require("goog.dom");
goog.require("goog.dom.classes");
goog.require("uno.util.dom");
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.findTodosInPlatformHtml = function(frag) {
    return frag.querySelectorAll("img.en-todo");
  };
  mac.convertPlatformElementToTodo = function(el) {
    var checked = goog.dom.classes.has(el, "en-todo-checked");
    var entodo = util.todo.create(checked);
    goog.dom.replaceNode(entodo, el);
  };
  mac.convertTodoToPlatformElement = 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.findTodosInPlatformHtml = function() {
    return [];
  };
  ios.convertTodoToPlatformElement = 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.findTodosInPlatformHtml = function(frag) {
    return frag.querySelectorAll("img[src^=en-resource\\:\\/\\/database\\/check]");
  };
  win.convertPlatformElementToTodo = 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.convertTodoToPlatformElement = 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 platform = uno.util.todo.generic;
  util.todo.setPlatform = function(platformName) {
    platform = uno.util.todo[platformName] || platform;
  };
  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 platform.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.findTodosInPlatformHtml = function(root) {
    return platform.findTodosInPlatformHtml(root);
  };
  util.todo.convertPlatformElementToTodo = function(el) {
    platform.convertPlatformElementToTodo(el);
  };
  util.todo.convertTodoToPlatformElement = function(todo) {
    platform.convertTodoToPlatformElement(todo);
  };
  util.todo.convertTodoInClipboard = function(todo) {
    return platform.convertTodoInClipboard && platform.convertTodoInClipboard(todo);
  };
  util.todo.convertTodoToClipboardElement = function(todo) {
    return platform.convertTodoToClipboardElement && platform.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.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());
  };
  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 {
            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 url = goog.isObject(value) ? value.url : value;
    var title = goog.isObject(value) ? value.title || value.url : value;
    var range = this.editor.getRange();
    var dom = goog.dom;
    var node;
    if (range == null) {
      return;
    }
    if (url == null) {
      return;
    }
    if (!goog.editor.range.intersectsTag(range, goog.dom.TagName.A)) {
      if (range.isCollapsed()) {
        node = dom.createTextNode(title);
        range.replaceContentsWithNode(node);
        range = goog.dom.Range.createFromNodes(node, 0, node, title.length);
        range.select();
      }
      this.editor.execCommand(goog.editor.plugins.BasicTextFormatter.COMMAND.CREATE_LINK, range, url);
    }
    range = this.editor.getRange();
    container = range.getContainerElement();
    if (util.dom.compareTagName(container, "a")) {
      container.setAttribute("href", url);
      util.richlink.decorate(container, this.editor);
    }
    goog.array.forEach(container.querySelectorAll("a"), function(a) {
      if (range.containsNode(a)) {
        a.setAttribute("href", url);
        util.richlink.decorate(a, this.editor);
      }
    });
    this.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.queryCommandValue(command);
  };
})();
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.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(node) {
    goog.array.forEachRight(node.querySelectorAll("li"), function(li) {
      var childNodes = goog.array.toArray(li.childNodes);
      goog.array.forEach(childNodes, function(child) {
        if (dom.isUl(child) || dom.isOl(child) || dom.isTable(child) || dom.isCodeBlock(child)) {
          var currentNode = child;
          var prevItem = li;
          while (currentNode) {
            var nextSibling = currentNode.nextSibling;
            if (dom.isDiv(currentNode)) {
              currentNode = dom.changeTagName(currentNode, "li");
            }
            goog.dom.insertSiblingAfter(currentNode, prevItem);
            prevItem = currentNode;
            currentNode = nextSibling;
          }
        }
      });
      if (!li.childNodes.length) {
        goog.dom.removeNode(li);
      }
    });
  };
  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);
        }
      });
      if (list.childNodes.length > 1 && util.dom.isBr(list.lastChild) && !util.dom.isBr(list.lastChild.previousSibling)) {
        goog.dom.removeNode(list.lastChild);
      }
    });
  };
})();
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");
    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.util.dom");
goog.require("uno.defs");
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());
  };
  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 (isCursorInEmptyCell(focusNode, focusOffset) && range.isCollapsed()) {
        result = true;
      } else {
        if (isCursorAfterTable(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 (isCursorAfterCodeBlock(focusNode, focusOffset) && range.isCollapsed()) {
                result = moveCursorToEndOfCodeBlock(focusNode, this.editor);
              } else {
                if (isCursorAtBeginningOfCodeBlock(focusNode, focusOffset) && range.isCollapsed()) {
                  result = moveFirstLineOutOfCodeBlock(focusNode, this.editor);
                } 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(node) {
    var previousSibling = node.previousSibling;
    util.paragraph.remove(node);
    if (previousSibling) {
      goog.editor.range.placeCursorNextTo(previousSibling.lastChild || previousSibling);
    }
    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 isCursorOnTable(node, currentNode) {
    return util.dom.isElementNode(node) && util.dom.isTable(currentNode);
  }
  function isCursorWithinTable(range) {
    var startNode = range.getStartNode();
    var endNode = range.getEndNode();
    var startNodeTable = goog.dom.getAncestor(startNode, function(ancestor) {
      return uno.util.dom.isTable(ancestor);
    }, true);
    var endNodeTable = goog.dom.getAncestor(endNode, function(ancestor) {
      return uno.util.dom.isTable(ancestor);
    }, true);
    return startNodeTable && startNodeTable === endNodeTable;
  }
  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(type, 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 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] === uno.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 isCursorInEmptyCell(node, offset) {
    var cell = goog.dom.getAncestor(node, function(ancestor) {
      return uno.util.dom.isTd(ancestor);
    }, true);
    return offset === 0 && cell && uno.util.dom.isEmpty(cell);
  }
  function isCursorAfterTable(node, offset) {
    if (offset > 0) {
      return false;
    }
    return getRangeOfTableBeforeNode(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 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 range = getRangeOfTableBeforeNode(node);
    if (range) {
      range.select();
      return true;
    }
    return false;
  }
  function deleteTable(node, forward) {
    var tableRange = goog.dom.Range.createFromNodeContents(node);
    var selection = window.getSelection();
    var currentRange = goog.dom.Range.createFromBrowserSelection(selection);
    var selectedNode = currentRange.getFocusNode();
    var selectedOffset = currentRange.getFocusOffset();
    if (selectedNode && selectedOffset && !currentRange.isCollapsed()) {
      var selectedElement = selectedNode.childNodes[selectedOffset - 1];
      if (selectedElement === node) {
        deleteSelection(forward);
        return true;
      }
    } else {
      tableRange.select();
      return true;
    }
    return false;
  }
  function emptyTableCells(range) {
    var node = range.getStartNode();
    var table = goog.dom.getAncestor(node, uno.util.dom.isTable);
    var tds = table.querySelectorAll("td");
    var tdsToEmpty = [];
    goog.iter.forEach(tds, function(td) {
      if (range.containsNode(td, true)) {
        tdsToEmpty.push(td);
      }
    });
    var firstTd = tdsToEmpty[0];
    var lastTd = tdsToEmpty[tdsToEmpty.length - 1];
    if (!range.containsNode(firstTd) || !range.containsNode(lastTd) && !util.dom.isEmpty(lastTd)) {
      return undefined;
    }
    tdsToEmpty.forEach(function(td) {
      td.innerHTML = "<div><br></div>";
    });
    var newRange = goog.dom.Range.createFromNodes(firstTd, 0, firstTd, 0);
    newRange.select();
    return true;
  }
  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 = util.table.selected(this.editor);
    if (table == null) {
      return false;
    }
    util.table.remove(table);
    return true;
  };
  DeleteTable.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
goog.provide("uno.commands.DeleteTableCol");
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.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 range = null;
    if (this.editor.multirange.active()) {
      range = this.editor.multirange.getTextRanges()[0];
    } else {
      range = this.editor.getRange();
    }
    if (range == null) {
      return false;
    }
    var cell = util.table.cellFor(range.getAnchorNode());
    if (cell == null) {
      return false;
    }
    var position = util.table.positionInTable(cell);
    if (position.row === -1) {
      return false;
    }
    var table = position.table;
    if (table == null) {
      return false;
    }
    goog.array.forEach(table.querySelectorAll("tr"), function(row) {
      var cells = row.querySelectorAll("td");
      if (cells.length < position.column + 1) {
        return;
      }
      goog.dom.removeNode(cells[position.column]);
    });
    util.table.ensureColumnMinWidth(table);
    if (table.querySelector("td") == null) {
      util.table.remove(table);
    }
    return true;
  };
  DeleteTableCol.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
goog.provide("uno.commands.DeleteTableRow");
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.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 range = null;
    if (this.editor.multirange.active()) {
      range = this.editor.multirange.getTextRanges()[0];
    } else {
      range = this.editor.getRange();
    }
    if (range == null) {
      return false;
    }
    var cell = util.table.cellFor(range.getAnchorNode());
    if (cell == null) {
      return false;
    }
    var position = util.table.positionInTable(cell);
    if (position.row === -1) {
      return false;
    }
    var table = position.table;
    if (table == null) {
      return false;
    }
    var dims = util.table.dimensions(table);
    var rows = table.querySelectorAll("tr");
    var row = util.table.rowFor(cell);
    if (position.row === 0 && dims.rows > 1) {
      var firstRowCells = row.querySelectorAll("td");
      var secondRowCells = rows[1].querySelectorAll("td");
      var width = null;
      for (var i = 0;i < firstRowCells.length;i++) {
        width = util.dom.getStyleValue(firstRowCells[i], "width");
        if (width != null) {
          util.dom.setStyleValue(secondRowCells[i], "width", width);
        }
      }
    }
    goog.dom.removeNode(row);
    if (table.querySelector("td") == null) {
      util.table.remove(table);
    }
    return true;
  };
  DeleteTableRow.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
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());
  };
  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();
    }
    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;
    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();
      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");
(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.defs.multirange.PLUGIN_MODE.APPLY_TO_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();
    }
    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});
  };
})();
goog.provide("uno.commands.Highlight");
goog.require("goog.debug.Logger");
goog.require("goog.editor.Command");
goog.require("uno.BasePlugin");
(function() {
  var util = uno.util;
  var log = goog.debug.Logger.getLogger("uno.commands.Highlight");
  var highlightBackgroundColor = "rgb(255, 250, 165)";
  var highlightPlaceholder = "rgb(255, 255, 255)";
  var Highlight = uno.commands.Highlight = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(Highlight, uno.BasePlugin);
  Highlight.prototype.isSupportedCommand = function(command) {
    return command === "highlight";
  };
  Highlight.prototype.execCommand = function() {
    var range = this.editor.getRange();
    if (!range) {
      return false;
    }
    var isExpandedRange = !range.isCollapsed();
    var highlighted = this.editor.context.style.state.highlight;
    this.editor.dispatchBeforeChange();
    document.execCommand("backColor", null, highlighted ? highlightPlaceholder : highlightBackgroundColor);
    cleanupHighlight([range.getContainerElement()], range);
    this.dispatchEvent({type:uno.Editor.EventType.STYLE_CHANGED, style:{state:{highlight:!highlighted}, value:{}, enabled:{}}});
    if (isExpandedRange) {
      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.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.table");
goog.require("uno.util.list");
goog.require("uno.util.paragraph");
(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 table = util.table.createDomTable(options, this.editor);
    var range = this.editor.getRange();
    if (range) {
      this.editor.execCommand("delete");
    }
    range = this.editor.getRange();
    if (!util.dom.isEmpty(util.paragraph["for"](range.getStartNode()))) {
      this.editor.execCommand("insertparagraph", {cursorPosition:"new"});
      range = this.editor.getRange();
      if (!util.dom.isEmpty(util.paragraph["for"](range.getStartNode()))) {
        this.editor.execCommand("insertparagraph", {cursorPosition:"original"});
      }
    }
    range = this.editor.getRange();
    range.insertNode(table);
    var sibling = goog.dom.getNextElementSibling(table);
    if (util.dom.isBr(sibling)) {
      goog.dom.removeNode(sibling);
    }
    var parent = table.parentElement;
    if (util.dom.getTagName(parent) === "div" && parent.childNodes.length === 1) {
      goog.dom.insertSiblingAfter(table, parent);
      goog.dom.removeNode(parent);
    }
    if (table.parentElement && table.parentElement.firstChild === table) {
      goog.dom.insertSiblingBefore(goog.dom.createDom("div", null, goog.dom.createDom("br")), table);
    }
    var targetBr = table.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;
    }
    if (util.list.itemFor(range.getStartNode())) {
      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.array");
goog.require("goog.debug.Logger");
goog.require("goog.dom");
goog.require("goog.style");
goog.require("goog.editor.plugins.TableEditor");
goog.require("uno.BasePlugin");
goog.require("uno.util.table");
(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, direction) {
    var table = util.table.selected(this.editor);
    var before = direction.toString().toLowerCase().trim() === "before";
    var anchor = util.table.cellFor(this.editor.getRange().getAnchorNode());
    var defaultHtml = this.editor.config.defaults.tableCellHtml;
    if (anchor == null) {
      return false;
    }
    var cellIndex = util.table.cellIndex(anchor);
    goog.array.forEach(table.querySelectorAll("td"), function(cell) {
      if (util.table.cellIndex(cell) === cellIndex) {
        var newCell = cell.cloneNode(true);
        util.table.initCellContent(newCell, defaultHtml);
        var widthPx = parseFloat(goog.style.getComputedStyle(cell, "width")) || 0;
        widthPx = Math.floor(widthPx / 2);
        goog.style.setStyle(newCell, "width", widthPx + "px");
        goog.style.setStyle(newCell, "min-width", widthPx + "px");
        goog.style.setStyle(cell, "width", widthPx + "px");
        goog.style.setStyle(cell, "min-width", widthPx + "px");
        if (before) {
          goog.dom.insertSiblingBefore(newCell, cell);
        } else {
          goog.dom.insertSiblingAfter(newCell, cell);
        }
      }
    });
    util.table.ensureColumnMinWidth(table);
    return true;
  };
  InsertTableCol.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
goog.provide("uno.commands.InsertTableRow");
goog.require("goog.array");
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.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, direction) {
    var table = util.table.selected(this.editor);
    if (table == null) {
      return false;
    }
    var defaultHtml = this.editor.config.defaults.tableCellHtml;
    if (direction == null) {
      direction = "after";
    }
    var before = direction.toString().toLowerCase().trim() === "before";
    var anchorCell = util.table.cellFor(this.editor.getRange().getAnchorNode());
    if (anchorCell == null) {
      return false;
    }
    var anchorPosition = util.table.positionInTable(anchorCell);
    var tableDims = util.table.dimensions(table);
    if (tableDims.rows === -1 || anchorPosition.row === -1) {
      return false;
    }
    var currentRow = util.table.rowFor(anchorCell);
    if (currentRow == null) {
      return false;
    }
    var newRow = currentRow.cloneNode(true);
    goog.array.forEach(newRow.querySelectorAll("td"), function(cell) {
      util.table.initCellContent(cell, defaultHtml);
    });
    if (before) {
      goog.dom.insertSiblingBefore(newRow, currentRow);
    } else {
      goog.dom.insertSiblingAfter(newRow, currentRow);
    }
    return true;
  };
  InsertTableRow.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
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 BORDER_WIDTH = 2;
  var Preview = uno.components.Preview = function(opt) {
    this.items = [];
    this.index_ = -1;
    this.state_ = 0;
    this.resizeTimer_ = null;
    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 children = [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;
    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.animateTransition_(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.animateTransition_(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.animateTransition_ = 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 + BORDER_WIDTH * zoom;
    var y = ob.top * zoom - ib.top + BORDER_WIDTH * zoom;
    var sx = (ob.width * zoom - BORDER_WIDTH * 2 * zoom) / ib.width;
    var sy = (ob.height * zoom - BORDER_WIDTH * 2 * 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() {
        safetyTimer = setTimeout(function() {
          goog.events.unlisten(item, "transitionend", resolveHandler);
          resolveHandler();
        }, timerDuration);
        goog.events.listenOnce(item, "transitionend", resolveHandler);
        if (presenting) {
          self.element.classList.add("animated");
          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});
    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.container_.innerHTML = "";
      self.container_.appendChild(img);
      self.element.classList.remove("zoomable");
    });
  };
  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");
goog.require("goog.array");
goog.require("uno.components.Preview");
goog.require("uno.defs");
goog.require("uno.util.img");
goog.require("uno.util.tools");
goog.require("uno.util.zoomscale");
(function() {
  var util = uno.util;
  var preview = null;
  var pendingTimer = null;
  var clickNode = null;
  var scrollTop = 0;
  util.preview.requestOpen = function(node) {
    if (!node) {
      return;
    }
    clickNode = node || null;
    scrollTop = document.body.scrollTop;
    EN.notification("requestPreview", {action:"open"});
    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) {
      preview = new uno.components.Preview({onClose:util.preview.requestClose, onChange:handleOnChange});
    }
    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");
    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");
    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;
      }
    }
  }
})();
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.TableAlign");
goog.require("goog.debug.Logger");
goog.require("goog.style");
goog.require("goog.editor.plugins.TableEditor");
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 (direction !== "left" && direction !== "right" && direction !== "center") {
      log.severe("Invalid direction given to tablealign: " + direction);
      return false;
    }
    var table = util.table.selected(this.editor);
    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.selected(this.editor);
    if (!table) {
      return "";
    }
    return util.table.getAlignment(table);
  };
  TableAlign.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
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.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());
  };
  goog.inherits(TableBorderColor, uno.BasePlugin);
  TableBorderColor.prototype.isSupportedCommand = function(command) {
    return command === "tablebordercolor";
  };
  TableBorderColor.prototype.execCommand = function(command, color) {
    color = color || "black";
    var table = util.table.selected(this.editor);
    if (!table) {
      return false;
    }
    this.editor.dispatchBeforeChange();
    util.table.normalizeTableBorders(table);
    goog.style.setStyle(table, "border-color", color);
    goog.array.forEach(table.querySelectorAll("td"), function(td) {
      goog.style.setStyle(td, "border-color", color);
    });
    this.editor.dispatchChange();
    return true;
  };
  TableBorderColor.prototype.queryCommandValue = function() {
    var table = util.table.selected(this.editor);
    if (!table) {
      return "";
    }
    var firstTd = table.querySelector("td");
    var borderColor = goog.style.getComputedStyle(firstTd, "borderColor");
    if (!borderColor) {
      return "";
    }
    return "" + borderColor;
  };
  TableBorderColor.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
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 table = util.table.selected(this.editor);
    if (!table) {
      return false;
    }
    this.editor.dispatchBeforeChange();
    util.table.normalizeTableBorders(table);
    goog.style.setStyle(table, "border-width", borderWidth + "px");
    goog.array.forEach(table.querySelectorAll("td"), function(td) {
      goog.style.setStyle(td, "border-width", borderWidth + "px");
    });
    this.editor.dispatchChange();
    return true;
  };
  TableBorderWidth.prototype.queryCommandValue = function() {
    var table = util.table.selected(this.editor);
    if (!table) {
      return "";
    }
    var firstTd = table.querySelector("td");
    var compStyle = goog.style.getComputedStyle(firstTd, "borderWidth");
    var borderWidth = parseInt(compStyle, 10);
    if (!borderWidth) {
      return "0";
    }
    return "" + borderWidth;
  };
  TableBorderWidth.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
goog.provide("uno.commands.TableCellColor");
goog.require("goog.array");
goog.require("goog.color");
goog.require("goog.debug.Logger");
goog.require("goog.style");
goog.require("goog.color");
goog.require("uno.BasePlugin");
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.defs.multirange.PLUGIN_MODE.APPLY_TO_FIRST;
  };
  goog.inherits(TableCellColor, uno.BasePlugin);
  TableCellColor.prototype.isSupportedCommand = function(command) {
    return command === "tablecellcolor";
  };
  TableCellColor.prototype.execCommand = function(command, value) {
    value = value || "transparent";
    var cells = util.table.selectedCells(this.editor);
    if (!cells.length) {
      return false;
    }
    this.editor.dispatchBeforeChange();
    goog.array.forEach(cells, function(cell) {
      goog.style.setStyle(cell, "background", "");
      goog.style.setStyle(cell, "background-image", "");
      goog.style.setStyle(cell, "background-attachment", "");
      goog.style.setStyle(cell, "background-position", "");
      goog.style.setStyle(cell, "background-clip", "");
      goog.style.setStyle(cell, "background-repeat", "");
      if (goog.color.isValidColor(value)) {
        goog.style.setStyle(cell, "background-color", value);
        var rgbValue = goog.color.hexToRgb(goog.color.parse(value).hex);
        var contrastColor = goog.color.highContrast(rgbValue, [[0, 0, 0], [255, 255, 255]]);
        goog.dom.Range.createFromNodeContents(cell).select();
        this.editor.execCommand("forecolor", goog.color.rgbToHex.apply(goog.color, contrastColor));
      }
    }, this);
    this.editor.dispatchChange();
    return true;
  };
  TableCellColor.prototype.queryCommandValue = function() {
    var cells = util.table.selectedCells(this.editor);
    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 !!util.table.selected(this.editor);
  };
})();
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.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.defs.multirange.PLUGIN_MODE.APPLY_TO_FIRST;
  };
  goog.inherits(TableVerticalAlign, uno.BasePlugin);
  TableVerticalAlign.prototype.isSupportedCommand = function(command) {
    return command === "tableverticalalign";
  };
  TableVerticalAlign.prototype.execCommandInternal = function(command, align) {
    if (align != null && ["middle", "top", "bottom"].indexOf(align) < 0) {
      log.warning("Saw unexpected vertical-align value", align);
    }
    if (align == null) {
      align = null;
    }
    var cells = util.table.selectedCells(this.editor);
    goog.array.forEach(cells, function(cell) {
      goog.style.setStyle(cell, "vertical-align", align);
    });
    return true;
  };
  TableVerticalAlign.prototype.queryCommandEnabled = function() {
    return !!util.table.selected(this.editor);
  };
})();
goog.provide("uno.commands.InsertTodo");
goog.require("goog.debug.Logger");
goog.require("goog.editor.range");
goog.require("uno.BasePlugin");
goog.require("goog.string");
goog.require("uno.util.dom");
goog.require("uno.util.todo");
(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());
  };
  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);
        goog.editor.range.placeCursorNextTo(todo);
        util.styles.clearPendingStyles(editor);
      } else {
        var container = range.getBrowserRangeObject().commonAncestorContainer;
        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();
              var point = util.dom.getLastEquivalentPoint(node, 0);
              var parentNode = goog.dom.isElement(point[0]) ? point[0] : point[0].parentNode;
              util.dom.moveNode(entodo, parentNode, 0, range);
            });
            goog.dom.Range.createFromNodes(nodes[0], 0, range.getEndNode(), range.getEndOffset()).select();
          }
        }
      }
    }
  };
})();
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());
  };
  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.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");
(function() {
  var util = uno.util;
  var dom = util.dom;
  util.paste.paste = function(clipboardContent, range, options) {
    options = options || {};
    var startNode = range.getStartNode();
    var pasteTarget = util.paragraph["for"](startNode);
    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);
    util.paste.setStyles(clipboardContent, startNode, options);
    if (pastingInTable && (clipboardContent.childNodes.length > 1 || !dom.isTable(clipboardContent.firstChild))) {
      var tables = clipboardContent.querySelectorAll("table");
      goog.array.forEach(tables, util.paste.plainifyTable);
    }
    goog.array.forEach(clipboardContent.childNodes, function(child) {
      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(util.paste.plainifyCodeBlock(child));
        } else {
          if (dom.isRevealedCrypt(child)) {
            paragraphs = paragraphs.concat(util.paste.plainifyCrypt(child));
          } else {
            paragraphs.push(child);
          }
        }
      }
    });
    if (pastingInTable && paragraphs.length === 1 && dom.isTable(paragraphs[0])) {
      var table = paragraphs[0];
      util.paste.mergeTables(pasteTarget, table, range);
    } else {
      util.paste.mergeContent(pasteTarget, paragraphs, range);
    }
  };
  util.paste.isObject = function(node) {
    return dom.isTable(node) || dom.isHeader(node) || dom.isTable(node) || dom.isCodeBlock(node) || dom.isBlockquote(node) || dom.isRevealedCrypt(node) || dom.isUl(node) || dom.isOl(node);
  };
  util.paste.mergeContent = function(pasteTarget, paragraphs, range) {
    if (!paragraphs.length) {
      return;
    }
    var shouldSplit = !!(paragraphs.length > 1 || util.paste.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.getRightMostLeafNode(lastParagraph || firstParagraph);
    if (shouldSplit) {
      var placeholder = goog.dom.createTextNode("");
      if (pasteTarget.innerHTML === "<br>") {
        goog.dom.removeNode(pasteTarget.firstChild);
      }
      range.insertNode(placeholder);
      var restOfParagraph = goog.editor.node.splitDomTreeAt(placeholder, null, pasteTarget);
      var lastItemInserted = pasteTarget;
      if (util.paste.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 (util.paste.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 {
      range.insertNode(firstParagraph);
      goog.dom.flattenElement(firstParagraph);
      var newRange;
      if (lastWord && lastWord.parentNode) {
        newRange = goog.editor.range.placeCursorNextTo(lastWord);
      }
      util.normalize.normalizeNode(pasteTarget, {range:newRange});
    }
  };
  util.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) {
      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.getRightMostLeafNode(lastCell);
      if (lastWord && lastWord.parentNode) {
        goog.editor.range.placeCursorNextTo(lastWord);
      }
    }
  };
  util.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.paste.plainifyCodeBlock = function(node) {
    return goog.array.toArray(node.childNodes);
  };
  util.paste.plainifyCrypt = function(node) {
    return goog.array.toArray(node.childNodes);
  };
  util.paste.setStyles = function(clipboardContent, startNode, options) {
    var styledNode = dom.isTextNode(startNode) ? startNode.parentNode : startNode;
    var targetStyles = util.styles.getNodeStyle(styledNode);
    var paragraphs = util.paragraph.all(clipboardContent);
    goog.array.forEach(paragraphs, function(paragraph) {
      goog.array.forEach(paragraph.childNodes, function(child) {
        var sourceStyle = util.styles.getNodeStyle(child);
        if (options.matchStyle && !dom.isTextNode(child)) {
          sourceStyle = {};
        }
        if (!options.enclipboard) {
          delete sourceStyle.color;
          delete sourceStyle["font-size"];
          delete sourceStyle["font-family"];
          delete sourceStyle["background-color"];
        }
        Object.keys(targetStyles).forEach(function(key) {
          var value = targetStyles[key];
          if (options.matchStyle) {
            if (value) {
              sourceStyle[key] = value;
            }
          } else {
            if (options.enclipboard) {
              if (key === "color" && targetStyles.color || key === "background-color" && targetStyles["background-color"]) {
                return;
              }
            }
            if (value) {
              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");
          }
        }
      });
    });
  };
})();
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("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");
(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 (!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 clipboardMarker = "<en-clipboard></en-clipboard>";
    var enclipboard = options.value.indexOf(clipboardMarker) > -1;
    var value = "<div>" + options.value.replace(clipboardMarker, "") + "</div>";
    var cleanedContent = editor.prepareContentsHtml.call(editor, value, {});
    var clipboardContent = dom.nodeFromHtml(cleanedContent);
    range = editor.getRange();
    var pasteTarget = util.paragraph["for"](range.getStartNode());
    util.normalize.normalizeNode(pasteTarget, {range:range});
    Promise.all(goog.array.map(util.img.all(clipboardContent), util.img.ratioResizeIfNeeded)).then(function(resizes) {
      if (resizes.indexOf(true) > -1) {
        editor.dispatchChange();
      }
    });
    util.paste.paste(clipboardContent, editor.getRange(), {enclipboard:enclipboard, matchStyle:matchStyle});
    editor.dispatchChange();
    util.range.scrollSelectionIntoView(editor);
    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");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.RemoveFormat");
  var RemoveFormat = uno.commands.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() {
    return this.editor.execCommand(goog.editor.Command.REMOVE_FORMAT);
  };
})();
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$9) {
      log.warning("could not restore the range");
      log.fine(err$9.stack || err$9);
      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.util.simpletext.generic");
goog.require("uno.defs");
(function() {
  var generic = uno.util.simpletext.generic;
  generic.getHighlightColor = function() {
    return uno.defs.highlight.BACKGROUND_COLOR_MAC;
  };
  generic.handlePlatformSpecificElements = function(simplifier, node) {
    return false;
  };
  generic.supportSelectionWise = function() {
    return false;
  };
})();
goog.provide("uno.util.simpletext.ios");
goog.require("uno.defs");
goog.require("uno.util.simpletext.generic");
(function() {
  var ios = uno.util.simpletext.ios;
  var util = uno.util;
  var generic = util.simpletext.generic;
  ios.getHighlightColor = function() {
    return uno.defs.highlight.BACKGROUND_COLOR_MAC;
  };
  ios.handlePlatformSpecificElements = function(simplifier, node) {
    return false;
  };
  ios.supportSelectionWise = function() {
    return generic.supportSelectionWise();
  };
})();
goog.provide("uno.util.simpletext.mac");
goog.require("uno.defs");
goog.require("uno.util.simpletext.generic");
(function() {
  var util = uno.util;
  var mac = util.simpletext.mac;
  var dom = util.dom;
  var generic = util.simpletext.generic;
  mac.getHighlightColor = function() {
    return uno.defs.highlight.BACKGROUND_COLOR_MAC;
  };
  mac.handlePlatformSpecificElements = function(simplifier, node) {
    var tag = node.tagName.toLowerCase();
    if (tag === "div" && /^en-revealed-crypto:\d+$/.test(node.id)) {
      simplifier.startNewBlock();
      simplifier.appendInlineElement(node, node.cloneNode(true), true);
      simplifier.startNewBlock();
      simplifier.skipNodes.push(node);
      return true;
    }
    if (tag === "embed") {
      var attrs = dom.attributes(node);
      var objectType = attrs.type.toLowerCase();
      if (objectType === "evernote/x-crypto" || objectType === "evernote/x-todo" || objectType === "evernote/x-attachment" || objectType === "evernote/x-pdf") {
        simplifier.appendInlineElement(node);
      }
      return true;
    }
    return false;
  };
  mac.supportSelectionWise = function() {
    return true;
  };
})();
goog.provide("uno.util.simpletext.win");
goog.require("uno.defs");
goog.require("uno.util.simpletext.generic");
(function() {
  var util = uno.util;
  var win = util.simpletext.win;
  var dom = util.dom;
  var generic = util.simpletext.generic;
  win.getHighlightColor = function() {
    return uno.defs.highlight.BACKGROUND_COLOR_MAC;
  };
  win.handlePlatformSpecificElements = function(simplifier, node) {
    var tag = node.tagName.toLowerCase();
    if (tag === "img") {
      var attrs = dom.attributes(node);
      var src = attrs.src.toLowerCase();
      if (src.indexOf("en-resource://database/check") === 0) {
        simplifier.appendInlineElement(node);
        return true;
      }
    }
    if (tag === "object") {
      var attrs = dom.attributes(node);
      var objectType = attrs.type.toLowerCase();
      if (objectType === "application/x-evernote-pdf" || objectType === "application/x-evernote-attachment" || objectType === "application/x-evernote-audio" || objectType === "") {
        simplifier.appendInlineElement(node);
      }
      return true;
    }
  };
  win.supportSelectionWise = function() {
    return true;
  };
})();
goog.provide("uno.util.simpletext");
goog.require("goog.debug.Logger");
goog.require("goog.dom.classes");
goog.require("goog.editor.node");
goog.require("uno.defs");
goog.require("uno.util.crypto");
goog.require("uno.util.dom");
goog.require("uno.util.resource");
goog.require("uno.util.richlink");
goog.require("uno.util.simpletext.generic");
goog.require("uno.util.simpletext.ios");
goog.require("uno.util.simpletext.mac");
goog.require("uno.util.simpletext.win");
goog.require("uno.util.todo");
(function() {
  var log = goog.debug.Logger.getLogger("uno.util.simpletext");
  var SimpleText = uno.util.simpletext;
  var platform = uno.util.simpletext.generic;
  var util = uno.util;
  var dom = uno.util.dom;
  util.simpletext.setPlatform = function(platformName) {
    goog.asserts.assert(platformName);
    platform = uno.util.simpletext[platformName];
  };
  util.simpletext.supportSelectionWise = function() {
    return platform.supportSelectionWise();
  };
  SimpleText.getHighlightColor = function() {
    return platform.getHighlightColor();
  };
  SimpleText.handlePlatformSpecificElements = function(simplifier, node) {
    return platform.handlePlatformSpecificElements(simplifier, node);
  };
  var Simplifier = SimpleText.Simplifier = function(inputElement, outputElement, config, editor) {
    uno.BasePlugin.call(this, log.getName());
    if (editor == null) {
      log.severe("No editor instance given!");
      return;
    }
    this.editor = editor;
    if (config == null) {
      config = {};
    }
    this.config = config;
    if (this.config.cssBlockStyle != null) {
      this.cssBlockStyle = config.cssBlockStyle;
    } else {
      this.cssBlockStyle = this.EN_DEFAULT_PARAGRAPH_STYLE;
    }
    this.async = !!config.async;
    if (!inputElement) {
      inputElement = document.body;
    } else {
      if (inputElement instanceof DocumentFragment || !dom.isRenderedDOMNode(inputElement)) {
        var tmpNode = document.createElement("div");
        tmpNode.appendChild(inputElement);
        document.body.appendChild(tmpNode);
        inputElement = tmpNode;
        this.tmpNode = tmpNode;
      }
    }
    this.inputElement = inputElement;
    this.outputElement = outputElement;
    this.loopStart();
  };
  goog.inherits(Simplifier, uno.BasePlugin);
  Simplifier.prototype.EN_DEFAULT_PARAGRAPH_TAG = uno.defs.tags.BLOCK;
  Simplifier.prototype.EN_DEFAULT_PARAGRAPH_STYLE = null;
  Simplifier.prototype.EN_EMPTY_LINE_THRESHOLD_VALUE = 0.8;
  Simplifier.prototype.EN_TIMER_INTERRUPT = 150;
  Simplifier.prototype.EN_TIMER_DELAY = 10;
  Simplifier.prototype.EN_PROGRESS_MINIMUM_LIFETIME = 2000;
  Simplifier.prototype.EN_INTERNAL_LINK_PREFIX = "evernote://";
  Simplifier.prototype.EN_INTERNAL_LINK_COLOR = "rgb(105, 170, 53)";
  var isParagraph = function(node) {
    var tag = node.tagName.toLowerCase();
    return tag === "p" || tag === "div";
  };
  var isListContainer = function(node) {
    var tag = node.tagName.toLowerCase();
    return tag === "ul" || tag === "ol";
  };
  var isTableElementTag = function(tag) {
    goog.asserts.assert(tag.toLowerCase() === tag, "Tag lowercase error");
    return tag === "td" || tag === "th";
  };
  var copyAttributes = function(destinationElement, sourceElement, attrName, defaultValue) {
    var value = sourceElement.getAttribute(attrName);
    if (value == null) {
      if (defaultValue == null) {
        return;
      }
      value = defaultValue;
    }
    destinationElement.setAttribute(attrName, value);
  };
  Simplifier.prototype.cancel = function() {
    this.loopCancel = true;
  };
  Simplifier.prototype.loopStart = function() {
    var self = this;
    this.block = null;
    this.blockReferenceNode = null;
    this.listReferenceNode = null;
    this.lastTableReferenceBlock = null;
    this.tableReferenceNode = null;
    this.runningTableNode = null;
    this.resultElement = document.createElement("div");
    this.lastListItem = null;
    this.lastBBox = null;
    this.requiresEmptyLine = false;
    this.skipNodes = [];
    var bodyStyle = window.getComputedStyle(document.body);
    this.thresholdForEmptyLine = bodyStyle && bodyStyle.fontSize ? +bodyStyle.fontSize.replace(/px/gi, "") * this.EN_EMPTY_LINE_THRESHOLD_VALUE : 16.;
    goog.asserts.assert(this.thresholdForEmptyLine > 1, "Empty threshold error");
    if (this.async) {
      this.loopNodeCount = 0;
      this.loopCount = 0;
      this.loopProgress = 0.0;
      this.loopProgressStarted = false;
      this.loopStartTime = this.loopTime = (new Date).getTime();
      var iter = document.createNodeIterator(this.inputElement, uno.defs.bitfields.NODE_SHOW_ALL, null, true);
      var c = 0;
      while (iter.nextNode()) {
        ++c;
      }
      this.loopTotalCount = c;
    }
    this.treeWalker = document.createTreeWalker(this.inputElement, uno.defs.bitfields.NODE_SHOW_ALL, {"acceptNode":function(node) {
      for (var i = 0;i < self.skipNodes.length;i++) {
        if (dom.isChild(node, self.skipNodes[i])) {
          return uno.defs.bitfields.NODE_FILTER_REJECT;
        }
      }
      return uno.defs.bitfields.NODE_FILTER_ACCEPT;
    }}, true);
    this.loopContinue();
  };
  Simplifier.prototype.loopContinue = function() {
    var self = this;
    if (this.loopCancel) {
      this.cleanup();
      return;
    }
    var node;
    try {
      while (node = this.treeWalker.nextNode()) {
        if (util.dom.isTextNode(node)) {
          this.handleText(node);
        } else {
          if (util.dom.isElementNode(node)) {
            this.handleElement(node);
          }
        }
        if (this.async) {
          ++this.loopNodeCount;
          if ((new Date).getTime() - this.loopTime > this.EN_TIMER_INTERRUPT) {
            break;
          }
        }
      }
      ++this.loopCount;
    } catch (ex) {
      log.severe("Simplifier crashed on main loop! " + (ex.stack || ex));
      node = null;
    }
    if (node && this.async) {
      this.loopProgress = Math.min(1.0, this.loopNodeCount / this.loopTotalCount);
      if (!this.loopProgressStarted) {
        var elapsedTime = (new Date).getTime() - this.loopStartTime;
        var estimatedTime = elapsedTime / this.loopProgress;
        estimatedTime += (Math.ceil(this.loopCount / this.loopProgress) - this.loopCount) * this.EN_TIMER_DELAY;
        if (estimatedTime >= this.EN_PROGRESS_MINIMUM_LIFETIME) {
          this.loopProgressStarted = true;
        }
      }
      if (this.loopProgressStarted && this.config.onprogress) {
        this.config.onprogress(this, this.loopProgress);
      }
      setTimeout(function() {
        self.loopTime = (new Date).getTime();
        self.loopContinue();
      }, this.EN_TIMER_DELAY);
    } else {
      this.skipNodes = null;
      this.optimizeFinishedBlockElement(this.block);
      if (this.loopProgressStarted && this.config.onprogress) {
        this.config.onprogress(this, 1.0);
      }
      this.loopDone();
    }
  };
  Simplifier.prototype.loopDone = function() {
    if (this.outputElement) {
      goog.dom.removeChildren(this.outputElement);
      dom.moveChildren(this.resultElement, this.outputElement);
    } else {
      this.outputElement = this.resultElement;
    }
    this.cleanup();
    if (this.config.onready) {
      this.config.onready(this);
    }
  };
  Simplifier.prototype.cleanup = function() {
    if (this.tmpNode) {
      document.body.removeChild(this.tmpNode);
    }
  };
  Simplifier.prototype.stripTrailingBlanks = function(blockElement) {
    var n;
    var iter = document.createNodeIterator(blockElement, uno.defs.bitfields.NODE_SHOW_TEXT, null, true);
    while (n = iter.nextNode()) {
      n.textContent = n.textContent.replace(/^[ \t\u200b]/gi, "");
      if (n.textContent.length > 0) {
        break;
      } else {
        if (dom.isTextNode(n)) {
          n.parentNode.appendChild(document.createElement("br"));
        } else {
          n.appendChild(document.createElement("br"));
        }
      }
    }
    iter = document.createNodeIterator(blockElement, uno.defs.bitfields.NODE_SHOW_TEXT, null, true);
    var stack = [];
    while (n = iter.nextNode()) {
      stack.unshift(n);
    }
    for (var i = 0;i < stack.length;i++) {
      n = stack[i];
      n.textContent = n.textContent.replace(/[\s\u200b]+$/gi, "");
      if (n.textContent.length > 0) {
        break;
      } else {
        if (!dom.isTextNode(n)) {
          n.appendChild(document.createElement("br"));
        }
      }
    }
    if (blockElement.firstChild == null) {
      blockElement.appendChild(document.createElement("br"));
    }
  };
  Simplifier.prototype.optimizeFinishedBlockElement = function(blockElement) {
    if (!blockElement) {
      return;
    }
    this.stripTrailingBlanks(blockElement);
    blockElement.normalize();
  };
  Simplifier.prototype.createBlockElement = function(tag) {
    var el = document.createElement(!!tag ? tag : this.EN_DEFAULT_PARAGRAPH_TAG);
    if (this.cssBlockStyle) {
      el.setAttribute("style", this.cssBlockStyle);
    }
    return el;
  };
  Simplifier.prototype.appendEmptyLine = function() {
    var br = this.createBlockElement();
    br.appendChild(document.createElement("br"));
    this.resultElement.appendChild(br);
    this.requiresEmptyLine = false;
  };
  Simplifier.prototype.appendBlockElement = function(elemOrTag) {
    var el = this.createBlockElement();
    if (elemOrTag != null) {
      if (goog.isString(elemOrTag)) {
        el = this.createBlockElement(elemOrTag);
      } else {
        if (goog.dom.isElement(elemOrTag)) {
          el = elemOrTag;
        }
      }
    }
    if (this.resultElement.hasChildNodes() && this.requiresEmptyLine) {
      var last = this.resultElement.lastElementChild;
      if (last && last.textContent.length && isParagraph(last) && isParagraph(el)) {
        this.appendEmptyLine();
      }
    }
    this.requiresEmptyLine = false;
    this.resultElement.appendChild(el);
    return el;
  };
  Simplifier.prototype.startNewBlock = function(keepBlockReference) {
    this.optimizeFinishedBlockElement(this.block);
    this.block = null;
    if (!keepBlockReference) {
      this.blockReferenceNode = null;
    }
  };
  Simplifier.prototype.calculateExtraBlankLines = function(node) {
    var bbox = node.parentElement.getBoundingClientRect();
    if (this.lastBBox && bbox && !dom.isChild(node, this.blockReferenceNode)) {
      var deltaY = Math.abs(bbox.top - this.lastBBox.bottom);
      if (deltaY >= this.thresholdForEmptyLine) {
        this.requiresEmptyLine = true;
      }
    }
    if (bbox) {
      this.lastBBox = bbox;
    }
  };
  Simplifier.prototype.appendInlineElementInList = function(node) {
    var elementToInsert;
    var nodeListItem = dom.parent(node, "li");
    if (nodeListItem == null) {
      this.listReferenceNode = null;
      return;
    }
    if (dom.isTextNode(node)) {
      if (node.textContent.search(/^[\s\u200b]*$/i) !== -1) {
        return;
      }
    }
    if (this.lastListItem && this.listReferenceNode === nodeListItem) {
      this.block = this.lastListItem;
      if (!dom.isInlineNode(this.lastListItem.lastChild) || !dom.isInlineNode(node)) {
        this.block.appendChild(document.createElement("br"));
      }
    } else {
      var listLevel = 0;
      var listType = null;
      var cursor = nodeListItem;
      while (cursor && cursor !== this.inputElement) {
        if (isListContainer(cursor)) {
          ++listLevel;
          if (!listType) {
            listType = cursor.tagName.toLowerCase();
          }
        }
        cursor = cursor.parentNode;
      }
      listLevel = Math.max(0, listLevel);
      var lastListContainer = null;
      if (this.block && this.block.childNodes.length > 0) {
        cursor = this.block;
      } else {
        cursor = this.resultElement;
      }
      while (1) {
        cursor = cursor.lastElementChild;
        if (!cursor) {
          break;
        }
        if (isListContainer(cursor)) {
          lastListContainer = cursor;
          --listLevel;
          if (listLevel < 1) {
            break;
          }
        }
      }
      if (listLevel > 0 && lastListContainer) {
        var li = lastListContainer.lastElementChild;
        lastListContainer = this.appendBlockElement(listType || "ol");
        li.appendChild(lastListContainer);
      } else {
        if (!lastListContainer) {
          if (this.block != null) {
            lastListContainer = document.createElement(listType || "ol");
            this.block.appendChild(lastListContainer);
          } else {
            lastListContainer = this.appendBlockElement(listType || "ol");
          }
        } else {
          if (this.requiresEmptyLine || listType && listType !== lastListContainer.tagName.toLowerCase()) {
            if (this.block != null) {
              lastListContainer = document.createElement(listType || "ol");
              this.block.appendChild(lastListContainer);
            } else {
              lastListContainer = this.appendBlockElement(listType || "ol");
            }
          }
        }
      }
      if (this.block === null && listLevel > 0) {
        for (var i = listLevel - 1;i--;) {
          var newList = this.appendBlockElement(listType || "ol");
          lastListContainer.appendChild(newList);
          lastListContainer = newList;
        }
      }
      this.block = this.createBlockElement("li");
      if (nodeListItem && util.todo.isChecked(nodeListItem)) {
        util.todo.setChecked(this.block);
      }
      lastListContainer.appendChild(this.block);
      this.listReferenceNode = nodeListItem;
      this.lastListItem = this.block;
    }
  };
  Simplifier.prototype.appendInlineElementInTable = function(node) {
    var table = dom.parent(node, "table");
    if (table == null || !dom.isHtmlElement(table) || table.tagName.toLowerCase() !== "table") {
      log.warning("Couldn't simplify table. Look into this!");
      return;
    }
    var dimensions = util.table.dimensions(table);
    if (dimensions.rows === -1) {
      return;
    }
    if (this.tableReferenceNode !== table) {
      this.tableReferenceNode = table;
      this.runningTableNode = util.table.createDomTable(dimensions, this.editor);
      this.appendBlockElement(this.runningTableNode);
      this.lastTableReferenceBlock = null;
    }
    var positionInfo = util.table.positionInTable(node);
    if (positionInfo.table == null) {
      return;
    }
    var newTrs = this.runningTableNode.querySelectorAll("tr");
    var newTr = newTrs[positionInfo.row];
    var newTds = newTr.querySelectorAll("td");
    var newTd = newTds[positionInfo.column];
    var targetBlock = newTd;
    if (newTd == null) {
      log.warning("Something crazy happened with table simplify");
      return;
    }
    if (newTd.childNodes.length === 1 && newTd.childNodes[0].tagName.toLowerCase() === uno.defs.tags.BLOCK) {
      targetBlock = newTd.childNodes[0];
      if (targetBlock.childNodes.length === 1 && targetBlock.childNodes[0].tagName && targetBlock.childNodes[0].tagName.toLowerCase() === "br") {
        goog.dom.removeChildren(targetBlock);
      }
    }
    if (this.lastTableReferenceBlock && this.lastTableReferenceBlock.parentNode.tagName.toLowerCase() === "td" && this.lastTableReferenceBlock.parentNode === newTd && targetBlock.tagName.toLowerCase() !== "td" && (dom.isTextNode(node) && !dom.isInlineNode(node) && !dom.isInlineNode(node.parentNode))) {
      var newBlock = this.createBlockElement();
      var parent = dom.parent(targetBlock, "td");
      parent.appendChild(newBlock);
      targetBlock = newBlock;
    }
    this.lastTableReferenceBlock = targetBlock;
    this.block = targetBlock;
  };
  Simplifier.prototype.appendInlineElement = function(node, elementToInsert, onTopLevel, isWhiteSpace) {
    var tag;
    var isNewBlockContext = !dom.isChild(node, this.blockReferenceNode);
    if (isWhiteSpace && isNewBlockContext) {
      return null;
    }
    if (!elementToInsert) {
      elementToInsert = node.cloneNode(false);
    }
    if (!(dom.isElementNode(node) && node.tagName.toLowerCase() === "br")) {
      this.calculateExtraBlankLines(node);
    }
    if (isNewBlockContext) {
      if (goog.dom.isElement(this.blockReferenceNode)) {
        tag = this.blockReferenceNode.tagName.toLowerCase();
        if (isTableElementTag(tag)) {
          this.requiresEmptyLine = true;
        }
      }
      this.startNewBlock();
    }
    var container = node;
    while (container !== this.inputElement && (container = container.parentNode)) {
      this.blockReferenceNode = container;
      tag = container.tagName.toLowerCase();
      if (tag === "li") {
        break;
      }
      if (isTableElementTag(tag)) {
        break;
      }
      if (dom.isComputedBlock(container)) {
        break;
      }
    }
    if (dom.parent(node, "table")) {
      this.appendInlineElementInTable(node);
    }
    if (dom.parent(node, "li")) {
      this.appendInlineElementInList(node);
    }
    var flags = this.getStyleFlagsForNode(node);
    if (!this.block) {
      this.block = this.appendBlockElement();
    }
    this.block.appendChild(this.putNodeInsideStyleElements(elementToInsert, flags));
    return elementToInsert;
  };
  Simplifier.prototype.handleText = function(node) {
    if (!node) {
      log.warning("Node missing", node);
      return;
    }
    var txt;
    var style = window.getComputedStyle(node.parentNode);
    if (style && /pre/gi.test(style.whiteSpace)) {
      var lines = node.textContent.split(/\n\r|\r\n|\r|\n/gi);
      if (lines && lines.length > 0) {
        txt = lines[0].replace(/[\s\u200b]/gi, " ").replace(/[\s\u200b][\s\u200b]/gi, "\u00a0 ");
        var txtNode = this.appendInlineElement(node, document.createTextNode(txt));
        if (txtNode) {
          for (var i = 1;i < lines.length;i++) {
            var parent = txtNode.parentNode;
            parent.appendChild(document.createElement("br"));
            txt = lines[i].replace(/[\s\u200b]/gi, " ").replace(/[\s\u200b][\s\u200b]/gi, "\u00a0 ");
            parent.appendChild(document.createTextNode(txt));
          }
        }
      }
    } else {
      txt = node.textContent.replace(/[\ \n\r\t]+/gi, " ");
      var isWhiteSpace = false;
      if (txt.search(/^[\ \t\n]*$/i) !== -1) {
        isWhiteSpace = true;
      }
      this.appendInlineElement(node, document.createTextNode(txt), false, isWhiteSpace);
    }
  };
  Simplifier.prototype.handleElement = function(node) {
    if (!node) {
      log.warning("Node missing", node);
      return;
    }
    var tag = node.tagName.toLowerCase();
    if (SimpleText.handlePlatformSpecificElements(this, node)) {
      return;
    }
    if (tag === "div" && dom.isCodeBlock(node)) {
      this.startNewBlock();
      this.appendBlockElement(node.cloneNode(true));
      this.skipNodes.push(node);
      return;
    }
    if (tag === "script" || tag === "style") {
      this.skipNodes.push(node);
      return;
    }
    if (util.todo.isTodo(node)) {
      this.appendInlineElement(node);
      return;
    }
    if (util.resource.isResource(node) || util.crypto.isCrypt(node) || util.richlink.isRichLink(node)) {
      this.startNewBlock();
      this.appendInlineElement(node, node.cloneNode(true), true);
      this.startNewBlock();
      this.skipNodes.push(node);
      return;
    }
    if (tag === "img" && node.src) {
      this.startNewBlock();
      var img = document.createElement("img");
      copyAttributes(img, node, "src");
      copyAttributes(img, node, "alt", "");
      copyAttributes(img, node, "id");
      this.appendInlineElement(node, img, true);
      this.startNewBlock();
      return;
    }
    if (tag === "hr") {
      this.startNewBlock();
      var attrs = {};
      if (goog.style.getStyle(node, "-evernote-encp-section-break") === "true") {
        attrs = {"style":"display:none;-evernote-encp-section-break:true;"};
      }
      this.appendInlineElement(node, document.createElement("hr", attrs), true);
      this.startNewBlock();
      return;
    }
    if (tag === "br") {
      var parentLi = this.blockReferenceNode;
      if (parentLi && goog.editor.node.getRightMostLeaf(parentLi) === node) {
        return;
      } else {
        if (dom.parent(node, "table")) {
          this.startNewBlock();
          var br = this.createBlockElement();
          br.appendChild(document.createElement("br"));
          this.appendInlineElement(node, br, true);
        } else {
          this.startNewBlock();
          this.appendEmptyLine();
          return;
        }
      }
    }
    if (this.block && node && (dom.isComputedBlock(node) || !dom.isParent(this.blockReferenceNode, node))) {
      this.startNewBlock();
      return;
    }
  };
  Simplifier.prototype.getStyleFlagsForNode = function(node) {
    var flags = {a:0, m:0, e:0, b:0, i:0, u:0, s:0};
    while (node || node === this.inputElement) {
      var tag = null;
      if (node && node.tagName) {
        tag = node.tagName.toLowerCase();
      }
      if (tag === "del" || tag === "strike" || tag === "s") {
        flags.s = 1;
      } else {
        if (tag === "mark") {
          flags.m = 1;
        } else {
          if (tag === "a") {
            var href = node.href + "";
            if (href && href.length) {
              flags.a = href;
              flags.e = href.indexOf(this.EN_INTERNAL_LINK_PREFIX) === 0;
            }
          }
        }
      }
      var style = null;
      if (goog.dom.isElement(node)) {
        style = window.getComputedStyle(node);
      }
      if (style) {
        var bgColor = style.backgroundColor.toLowerCase();
        if (bgColor === uno.defs.highlight.BACKGROUND_COLOR_IOS || bgColor === uno.defs.highlight.BACKGROUND_COLOR_MAC || bgColor === uno.defs.highlight.BACKGROUND_COLOR_CLEARLY) {
          flags.m = 1;
        }
        var fontWeight = style.fontWeight.toLowerCase();
        var fontStyle = style.fontStyle.toLowerCase();
        var textDecorations = style.textDecoration.toLowerCase();
        if (fontWeight === "bold" || fontWeight === "bolder" || fontWeight === "700") {
          flags.b = 1;
        }
        if (fontStyle === "italic" || fontStyle === "oblique") {
          flags.i = 1;
        }
        if (!flags.a && textDecorations.indexOf("underline") >= 0) {
          flags.u = 1;
        }
        if (textDecorations.indexOf("line-through") >= 0) {
          flags.s = 1;
        }
      }
      node = node.parentNode;
    }
    if (flags.a && flags.u) {
      delete flags.u;
    }
    return flags;
  };
  Simplifier.prototype.putNodeInsideStyleElements = function(node, flags) {
    var el;
    if (flags.a) {
      el = document.createElement("a");
      el.setAttribute("href", flags.a);
      if (flags.e) {
        el.setAttribute("style", "color:" + this.EN_INTERNAL_LINK_COLOR + ";");
      }
      el.appendChild(node);
      node = el;
    }
    if (flags.b) {
      el = document.createElement(uno.defs.tags.BOLD);
      el.appendChild(node);
      node = el;
    }
    if (flags.i) {
      el = document.createElement(uno.defs.tags.ITALIC);
      el.appendChild(node);
      node = el;
    }
    if (flags.u) {
      el = document.createElement(uno.defs.tags.UNDERLINE);
      el.appendChild(node);
      node = el;
    }
    if (flags.s) {
      el = document.createElement(uno.defs.tags.STRIKETHROUGH);
      el.appendChild(node);
      node = el;
    }
    if (flags.m) {
      var styleString = uno.defs.highlight.STYLE + ":true; background-color:" + util.simpletext.getHighlightColor() + ";";
      el = document.createElement("span");
      el.setAttribute("style", styleString);
      el.appendChild(node);
      node = el;
    }
    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.range");
goog.require("uno.util.todo");
goog.require("uno.util.simpletext");
(function() {
  var log = goog.debug.Logger.getLogger("uno.commands.SimpleText");
  var util = uno.util;
  var Simplifier = uno.util.simpletext.Simplifier;
  var SimpleText = uno.commands.SimpleText = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(SimpleText, uno.BasePlugin);
  SimpleText.prototype.isSupportedCommand = function(command) {
    return command === "simpletext";
  };
  SimpleText.prototype.activeOnUneditableFields = goog.functions.TRUE;
  SimpleText.prototype.execCommand = function() {
    this.editor.enterEditMode(true);
    this.editor.dispatchBeforeChange();
    var range = this.editor.getRange();
    var transFormSelection = util.simpletext.supportSelectionWise() && range != null && !range.isCollapsed();
    var frag;
    var root = this.editor.getElement();
    if (transFormSelection) {
      var rangeAncestors = util.range.commonAncestors(range, "td", root);
      if (rangeAncestors[0] === rangeAncestors[1] && rangeAncestors[0].tagName.toLowerCase() === "td") {
        rangeAncestors = util.range.commonAncestors(range, "div", root);
      } else {
        rangeAncestors = util.range.commonAncestors(range, "table,ul,ol", root);
      }
      var blockRange = goog.dom.Range.createFromNodes(rangeAncestors[0], 0, rangeAncestors[1], goog.editor.node.getLength(rangeAncestors[1]));
      blockRange = goog.editor.range.expand(blockRange);
      var startBlock = blockRange.getStartNode().childNodes[blockRange.getStartOffset()];
      var endBlock = blockRange.getEndNode().childNodes[blockRange.getEndOffset() - 1];
      goog.dom.Range.createFromNodes(startBlock, 0, endBlock, endBlock.childNodes.length).select();
      frag = this.editor.getRange().getBrowserRangeObject().cloneContents();
      this.editor.execCommand("delete");
    }
    if (frag) {
      var resultNode = (new Simplifier(frag, null, null, this.editor)).outputElement;
      if (resultNode == null || resultNode.firstChild == null) {
        return true;
      }
      var firstChild = null;
      var lastChild = null;
      var insertRange = this.editor.getRange();
      log.info("insertRange " + insertRange);
      while (resultNode.lastChild) {
        var node = insertRange.insertNode(resultNode.lastChild, false);
        if (lastChild == null) {
          lastChild = node;
        }
        firstChild = node;
      }
      goog.dom.Range.createFromNodes(firstChild, 0, lastChild, goog.editor.node.getLength(lastChild)).select();
    } else {
      new Simplifier(root, root, null, this.editor);
      goog.editor.range.selectNodeStart(root);
    }
    this.editor.dispatchChange();
    if (!transFormSelection) {
      this.editor.placeCursorAtEnd();
      util.range.scrollSelectionIntoView(this.editor);
    }
    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());
  };
  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.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.defs.multirange.PLUGIN_MODE.APPLY_TO_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());
  };
  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.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.platform.importENML) {
        this.platform.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.PLATFORM_HTML) {
        if (this.platform.importHTML) {
          this.platform.importHTML(fragment, context);
        }
      }
    }
  };
  CryptFilter.prototype.cleanContentsDom = function(fragment) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.ENML) {
      if (this.platform.exportENML) {
        this.platform.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.PLATFORM_HTML) {
        if (this.platform.exportHTML) {
          this.platform.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 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);
    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);
        }
      });
    }
    goog.array.forEach(frag.querySelectorAll("*[id],*[class]"), function(el) {
      el.removeAttribute("id");
      el.removeAttribute("class");
      el.removeAttribute("data");
      Object.keys(el.dataset).forEach(function(key) {
        delete el.dataset[key];
      });
    });
    goog.array.forEachRight(frag.querySelectorAll("en-cursor,en-clipboard"), function(el) {
      el.parentNode.removeChild(el);
    });
    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.util.oldcenormalize");
goog.require("uno.util.dom");
(function() {
  var util = uno.util;
  util.oldcenormalize.normalizeHtml = function(html) {
    return html.replace(/(<li[^>]*>(?:(?!<\/li).)*?)(?:<div><br\s?\/><\/div>){6,}/g, "$1<div><br /></div>");
  };
  util.oldcenormalize.normalizeDom = function(frag) {
    util.oldcenormalize.normalizeBlockquotes(frag);
  };
  util.oldcenormalize.normalizeBlockquotes = function(frag) {
    var paragraphs = frag.querySelectorAll("div");
    goog.iter.forEach(paragraphs, function(paragraph) {
      var margin = parseInt(paragraph.style.marginLeft, 10);
      if (margin && margin % 40 === 0) {
        var levelOfNesting = margin / 40;
        var blockquote = goog.dom.createDom("blockquote", null, paragraph.childNodes);
        for (var i = 1;i < levelOfNesting;i++) {
          blockquote = goog.dom.createDom("blockquote", null, blockquote);
        }
        goog.dom.replaceNode(blockquote, paragraph);
      }
    });
  };
})();
goog.provide("uno.util.normalize");
goog.require("uno.defs");
goog.require("uno.util.oldcenormalize");
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("goog.array");
goog.require("goog.dom");
(function() {
  var util = uno.util;
  var dom = util.dom;
  var paragraphHolders = ["en-note", "td"];
  util.normalize.normalizeNode = function(node, options) {
    options = options || {};
    if (!node) {
      return false;
    }
    var savedCursor = null;
    if (options.range) {
      savedCursor = util.range.saveCursor(options.range);
    }
    node.innerHTML = util.normalize.normalizeHtml(node.innerHTML);
    util.normalize.normalizeDom(node, options);
    if (savedCursor) {
      savedCursor.restore();
    }
    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(nonVoidTag, "<$1$2></$1>");
    html = util.oldcenormalize.normalizeHtml(html);
    return html;
  };
  util.normalize.normalizeDom = function(root, options) {
    options = options || {};
    root.normalize();
    util.normalize.removeUnsupportedNodes(root);
    util.normalize.removeUnsupportedTags(root);
    util.normalize.normalizePreTags(root);
    util.oldcenormalize.normalizeDom(root);
    util.normalize.replaceBrsByParagraphs(root.querySelectorAll("br"));
    util.list.normalize(root);
    util.table.normalize(root);
    util.normalize.removeEmptyNodes(root);
    util.normalize.ensureValidParagraph(root.childNodes);
    util.normalize.flattenRedundantNodes(root);
    if (!options.ignoreInlineNodes) {
      util.normalize.inlineNodes(root, options);
    }
    util.list.convertParagraphsToBrs(root);
  };
  util.normalize.removeUnsupportedTags = function(frag) {
    goog.array.forEachRight(frag.querySelectorAll("en-note, script, meta, style"), function(el) {
      goog.dom.removeNode(el);
    });
    frag.querySelectorAll('a[x-apple-data-detectors="true"]', function(el) {
      goog.dom.flattenElement(el);
    });
  };
  util.normalize.normalizePreTags = function(frag) {
    var pres = frag.querySelectorAll("pre");
    goog.array.forEachRight(pres, function(pre) {
      if (pre.childNodes && pre.childNodes.length) {
        pre.innerHTML = pre.innerHTML.replace(/\r?\n/g, "<br>").replace(/\t/g, uno.defs.tab.CHARACTER_SEQUENCE);
      }
    });
    goog.array.forEachRight(frag.childNodes, function(child) {
      if (child.childNodes && child.childNodes.length) {
        child.innerHTML = child.innerHTML.replace(/[\n\t\r]/g, "");
      }
    });
  };
  util.normalize.replaceBrsByParagraphs = function(brs) {
    goog.array.forEachRight(brs, function(br) {
      var nodes = [];
      var current = br;
      if (br.nextSibling) {
        while (dom.isInlineNode(current.previousSibling) && !dom.isBr(current.previousSibling)) {
          nodes.unshift(current.previousSibling);
          current = current.previousSibling;
        }
        if (!nodes.length) {
          nodes.push(goog.dom.createDom("br"));
        }
        var paragraph = goog.dom.createDom("div", null, nodes);
        goog.dom.replaceNode(paragraph, br);
      } else {
        if (br.previousSibling && !dom.isBr(br.previousSibling) && !dom.isEncursor(br.previousSibling) && !dom.isHr(br.previousSibling)) {
          goog.dom.removeNode(br);
        }
      }
    });
  };
  util.normalize.removeEmptyNodes = function(root) {
    var deepestNodes = dom.getNodeLeaves(root, dom.inlineObjects);
    goog.array.forEachRight(deepestNodes, function(node) {
      var parent = node.parentNode;
      while (util.normalize.removeEmptyNode(node)) {
        node = parent;
        parent = node && node.parentNode;
      }
    });
  };
  util.normalize.removeEmptyNode = function(node) {
    var tagName = node && node.tagName && node.tagName.toLowerCase();
    if (!node || !tagName || dom.inlineObjects.indexOf(tagName) > -1 || paragraphHolders.indexOf(tagName) > -1 || !dom.isEmpty(node)) {
      return false;
    }
    goog.dom.removeNode(node);
    return true;
  };
  var isParentRoot = function(node) {
    return !node || dom.isEnnote(node) || dom.isTd(node) || dom.isCodeBlock(node) || dom.isLi(node) || dom.isRevealedCrypt(node) || dom.isBlockquote(node) || dom.isFragment(node);
  };
  util.normalize.ensureValidParagraph = function(nodes) {
    var paragraphNodes = [];
    goog.array.forEachRight(nodes, 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) || isParentRoot(parentNode))) {
        if (dom.isBlockNode(nextSibling)) {
          paragraphNodes.push(node);
          while (dom.isInlineNode(node.previousSibling)) {
            paragraphNodes.unshift(node.previousSibling);
            node = node.previousSibling;
          }
          paragraph = goog.dom.createDom("div", null, paragraphNodes);
          goog.dom.insertSiblingBefore(paragraph, nextSibling);
        } else {
          if (dom.isBlockNode(previousSibling)) {
            paragraphNodes.push(node);
            while (dom.isInlineNode(node.nextSibling)) {
              paragraphNodes.push(node.nextSibling);
              node = node.nextSibling;
            }
            paragraph = goog.dom.createDom("div", null, paragraphNodes);
            goog.dom.insertSiblingAfter(paragraph, previousSibling);
          } else {
            paragraph = goog.dom.createDom("div", null, parentNode.childNodes);
            goog.dom.insertChildAt(parentNode, paragraph, 0);
          }
        }
        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.isCodeBlock(parentNode) || dom.isRevealedCrypt(parentNode) || dom.isBlockquote(parentNode) || dom.isTextNode(node)) {
          if (dom.isBlockNode(node)) {
            util.styles.mergeAttributes(dumbParentNode, node, true);
            util.styles.mergeAttributes(dumbParentNode, parentNode, true);
          }
          if (dom.isTd(parentNode)) {
            var table = goog.dom.getAncestor(node, dom.isTable);
            node = table || parentNode;
          } else {
            node = parentNode;
          }
        } else {
          if (dom.isBlockNode(node)) {
            if (dom.isBlockNode(parentNode)) {
              goog.array.forEachRight(parentNode.childNodes, function(child) {
                util.styles.mergeAttributes(parentNode, child, true);
                goog.dom.insertSiblingAfter(child, parentNode);
              });
            } else {
              goog.array.forEachRight(parentNode.childNodes, function(child) {
                var paragraphs = dom.isTable(child) ? util.table.getParagraphs(child) : [child];
                goog.array.forEach(paragraphs, function(c) {
                  var newNode = goog.dom.createDom(parentNode.tagName, null, c.childNodes);
                  util.styles.mergeAttributes(parentNode, newNode, true);
                  c.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.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) {
      var deepestNodes = util.dom.getNodeLeaves(paragraph, dom.inlineObjects);
      var nodes = [];
      deepestNodes.forEach(function(node) {
        var link = goog.dom.getAncestor(node, function(element) {
          return element.attributes && element.getAttribute("href");
        }, true);
        if (util.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:"text-align", 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) {
        paragraph.innerHTML = "";
        util.styles.mergeAttributes(dumbNode, paragraph, false, {allowedStyles:"text-align", disallowedAttrs:"bgcolor"});
        nodes.forEach(paragraph.appendChild.bind(paragraph));
        if (dom.isP(paragraph)) {
          paragraph = dom.changeTagName(paragraph, "div");
          var newLine = goog.dom.createDom("div");
          newLine.innerHTML = "<br>";
          goog.dom.insertSiblingAfter(newLine, 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);
      }
    }
  };
})();
goog.provide("uno.filters.NormalizeFilter");
goog.require("goog.debug.Logger");
goog.require("uno.BasePlugin");
goog.require("uno.util.normalize");
(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) {
    if (this.shouldNormalize()) {
      util.normalize.normalizeDom(frag);
    }
  };
  NormalizeFilter.prototype.shouldNormalize = function() {
    var source = this.editor.config.note.source;
    var hasContentClass = !!this.editor.config.note.contentClass;
    var isWebclipSource = ["Clearly", "External", "web.clip", "web.clip7"].indexOf(source) > -1;
    var isEmailSource = /^e?mail/i.test(source);
    return !hasContentClass && !isWebclipSource && !isEmailSource;
  };
  NormalizeFilter.prototype.cleanContentsDom = function(frag) {
    var context = this.editor.context;
    if (context.format === uno.defs.format.CLIPBOARD) {
      util.normalize.normalizeDom(frag);
    }
  };
  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");
(function() {
  var log = goog.debug.Logger.getLogger("uno.filters.PasteFilter");
  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) {
      goog.array.forEach(frag.childNodes, function(child) {
        if (child.querySelector("a") || !child.childNodes || child.childNodes.length !== 1) {
          return;
        }
        var url = child.textContent && child.textContent.trim();
        var urlRegex = new RegExp("^" + uno.defs.regex.SIMPLE_URL + "$", "gi");
        var emailRegex = new RegExp("^" + uno.defs.regex.SIMPLE_EMAIL + "$", "gi");
        if (url.match(emailRegex) != null) {
          var mailto = /^[a-zA-Z]+:\/\//.test(url) ? url : "mailto:" + url;
          var email = goog.dom.createDom("a", {href:mailto}, child.childNodes);
          child.appendChild(email);
        } else {
          if (url.match(urlRegex) != null) {
            var href = /^[a-zA-Z]+:\/\//.test(url) ? url : "http://" + url;
            var anchor = goog.dom.createDom("a", {href:href}, child.childNodes);
            child.appendChild(anchor);
          }
        }
      });
    }
  };
})();
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");
(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.PLATFORM_HTML) {
        goog.array.forEach(util.resource.findResourcesInPlatformHtml(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.convertPlatformElementToSlug(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.PLATFORM_HTML) {
        goog.array.forEachRight(util.resource.all(frag), function(el) {
          util.resource.convertSlugToPlatformElement(el);
        });
      } else {
        if (context.format === defs.format.CLIPBOARD) {
          goog.array.forEachRight(util.resource.all(frag), function(el) {
            util.resource.convertSlugToPlatformElement(el);
          });
        }
      }
    }
  };
  ResourceFilter.prototype.cleanContentsHtml = function(html) {
    if (this.editor.context.format === defs.format.PLATFORM_HTML) {
      html = util.resource.formatPlatformHtmlForExport(html);
      html = html.replace(uno.defs.unicode.ZERO_WIDTH_SPACE, "");
    }
    return html;
  };
})();
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.TableFilter");
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.TableFilter");
  var util = uno.util;
  var TableFilter = uno.filters.TableFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TableFilter, uno.BasePlugin);
  TableFilter.prototype.cleanContentsDom = function(frag) {
    goog.array.forEach(frag.querySelectorAll("table[data-table-mode]"), function(table) {
      table.removeAttribute("data-table-mode");
    });
  };
})();
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.findTodosInPlatformHtml(frag), function(el) {
          util.todo.convertPlatformElementToTodo(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.convertTodoToPlatformElement(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.BACKGROUND_COLOR_MAC;
  var util = uno.util;
  var PLATFORM_HTML = uno.defs.format.PLATFORM_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, PLATFORM_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, PLATFORM_HTML].indexOf(context.format) > -1) {
      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, uno.defs.highlight.STYLE_VALUE);
          }
        }
      });
    }
  };
})();
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.AdornmentFilter");
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.AdornmentFilter");
  var AdornmentFilter = uno.filters.AdornmentFilter = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(AdornmentFilter, uno.BasePlugin);
  AdornmentFilter.prototype.cleanContentsDom = function(frag) {
    var each = goog.array.forEach;
    each(frag.querySelectorAll("en-adornments"), goog.dom.removeNode);
    each(frag.querySelectorAll("en-container"), goog.dom.flattenElement);
  };
})();
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.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)) {
      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 DeleteListener = uno.listeners.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})) {
        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})) {
        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("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) {
      util.preview.requestOpen(img);
      evt.preventDefault();
      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 = function() {
  };
})();
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.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) {
    return this.platform.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.platform.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");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("goog.style");
goog.require("uno.BasePlugin");
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}});
        }
        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 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();
    var KeyCodes = goog.events.KeyCodes;
    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("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", "#3f3f3f", "#737373", "#979797", "#8b65e0", "#c064d1", "#fc5356", "#fedec1", "#fce7c4", "#cdedd8", "#cdeef0", "#cde6f9", "#ccd7ea", "#fd7b39", "#f8b344", "#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) {
    uno.components.MenuAbstractItem.call(this);
    this.element = goog.dom.createDom("div", {"class":"menu-item"}, text);
  };
  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", "Set Width to Match Note":"\u0636\u0628\u0637 \u0627\u0644\u0639\u0631\u0636 \u0644\u064a\u062a\u0648\u0627\u0641\u0642 \u0645\u0639 \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)":"\u062a\u0645 \u062d\u0630\u0641 \u0627\u0644\u0623\u0639\u0645\u062f\u0629 \u0627\u0644\u0645\u062d\u062f\u062f\u0629", 
"Delete Table":"\u062d\u0630\u0641 \u0627\u0644\u062c\u062f\u0648\u0644"};
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":"Connect to see more", "Connect Google account":"Connect Google account", "Title not available":"N\u00e1zev nen\u00ed k dispozici", "Open containing folder":"Otev\u0159\u00edt slo\u017eku se soubory", "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", "Set Width to Match Note":"Set Width to Match Note", "Delete Selected Column(s)":"Delete Selected Column(s)", "Delete Selected Row(s)":"Delete Selected Row(s)", "Delete Table":"Delete Table"};
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", 
"Set Width to Match Note":"Indstil bredde til matche note", "Delete Selected Column(s)":"Slet valgte kolonne(r)", "Delete Selected Row(s)":"Slet valgte r\u00e6kker(r)", "Delete Table":"Slet tabel"};
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":"Zellhintergrund", "Cell Alignment":"Zellausrichtung", "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", "Set Width to Match Note":"Breite an Notiz anpassen", "Delete Selected Column(s)":"Ausgew\u00e4hlte Spalten l\u00f6schen", "Delete Selected Row(s)":"Ausgew\u00e4hlte Zeilen l\u00f6schen", "Delete Table":"Tabelle l\u00f6schen"};
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", "Set Width to Match Note":"Set Width to Match Note", 
"Delete Selected Column(s)":"Delete Selected Column(s)", "Delete Selected Row(s)":"Delete Selected Row(s)", "Delete Table":"Delete Table"};
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", "Set Width to Match Note":"Establecer ancho para igualar la nota", "Delete Selected Column(s)":"Eliminar columna(s) seleccionada(s)", "Delete Selected Row(s)":"Eliminar fila(s) seleccionada(s)", "Delete Table":"Eliminar Tabla"};
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", "Set Width to Match Note":"M\u00e4\u00e4rit\u00e4 leveys muistiinpanon mukaan", "Delete Selected Column(s)":"Poista valitut sarakkeet", "Delete Selected Row(s)":"Poista valitut rivit", "Delete Table":"Poista taulukko"};
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":"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", 
"Set Width to Match Note":"Set Width to Match Note", "Delete Selected Column(s)":"Delete Selected Column(s)", "Delete Selected Row(s)":"Delete Selected Row(s)", "Delete Table":"Supprimer le tableau"};
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", "Set Width to Match Note":"Atur Lebar Sesuai Catatan", 
"Delete Selected Column(s)":"Hapus Kolom yang Dipilih", "Delete Selected Row(s)":"Hapus Baris yang Dipilih", "Delete Table":"Hapus Tabel"};
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":"Allinea il contenuto in alto", "Align content to center":"Allinea contenuto al centro", "Align content to bottom":"Allinea il contenuto in basso", 
"Distribute Columns Evenly":"Distribuire colonne uniformemente", "Set Width to Match Note":"Adeguare la larghezza alla nota", "Delete Selected Column(s)":"Elimina colonne selezionate", "Delete Selected Row(s)":"Elimina righe selezionate", "Delete Table":"Elimina Tabella"};
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\u5217", "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\u4e00\u5316", "Set Width to Match Note":"\u5e45\u3092\u30ce\u30fc\u30c8\u306b\u5408\u308f\u305b\u3066\u8a2d\u5b9a", "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"};
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", "Set Width to Match Note":"\ub178\ud2b8\uc5d0 \ub9de\uac8c \ud3ed \uc9c0\uc815", "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"};
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", 
"Set Width to Match Note":"Tetapkan Lebar supaya Sepadan dengan Nota", "Delete Selected Column(s)":"Padamkan Lajur Dipilih", "Delete Selected Row(s)":"Padamkan Baris Dipilih", "Delete Table":"Padam Jadual"};
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":"Celachtergrond", "Cell Alignment":"Celuitlijning", "Align content to top":"Lijn content uit bovenin", "Align content to center":"Lijn content uit in het midden", "Align content to bottom":"Lijn content uit onderin", "Distribute Columns Evenly":"Verdeel kolommen gelijkmatig", 
"Set Width to Match Note":"Stel breedte in op notitie", "Delete Selected Column(s)":"Verwijder geselecteerde kolom(men)", "Delete Selected Row(s)":"Verwijder geselecteerde rij(en)", "Delete Table":"Verwijder tabel"};
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":"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", 
"Set Width to Match Note":"Set Width to Match Note", "Delete Selected Column(s)":"Delete Selected Column(s)", "Delete Selected Row(s)":"Delete Selected Row(s)", "Delete Table":"Delete Table"};
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", "Set Width to Match Note":"Dopasuj szeroko\u015b\u0107 do 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"};
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", "Set Width to Match Note":"Definir Largura para Combinar com a Nota", "Delete Selected Column(s)":"Excluir Coluna(s) Selecionada(s)", "Delete Selected Row(s)":"Excluir Fileira(s) Selecionada(s)", "Delete Table":"Excluir Tabela"};
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", "Set Width to Match Note":"Definir a largura para combinar com a 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"};
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 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \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 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443", 
"Align content to bottom":"\u0412\u044b\u0440\u043e\u0432\u043d\u044f\u0442\u044c \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u043c\u043e\u0435 \u044f\u0447\u0435\u0439\u043a\u0438 \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", "Set Width to Match Note":"\u0417\u0430\u0434\u0430\u0442\u044c \u0448\u0438\u0440\u0438\u043d\u0443 \u0434\u043b\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u044f \u0437\u0430\u043c\u0435\u0442\u043a\u0435", 
"Delete Selected Column(s)":"\u0423\u0434\u0430\u043b\u0438\u0442\u044c \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u043d\u0443\u044e \u043a\u043e\u043b\u043e\u043d\u043a\u0443", "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"};
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", "Set Width to Match Note":"St\u00e4ll in bredd efter anteckning", "Delete Selected Column(s)":"Radera markerade kolumner", "Delete Selected Row(s)":"Radera markerade rader", "Delete Table":"Radera tabell"};
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", "Set Width to Match Note":"\u0e15\u0e31\u0e49\u0e07\u0e04\u0e48\u0e32\u0e04\u0e27\u0e32\u0e21\u0e01\u0e27\u0e49\u0e32\u0e07\u0e43\u0e2b\u0e49\u0e1e\u0e2d\u0e14\u0e35\u0e01\u0e31\u0e1a\u0e1a\u0e31\u0e19\u0e17\u0e36\u0e01", 
"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"};
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", "Set Width to Match Note":"Geni\u015fli\u011fi Nota G\u00f6re Ayarla", "Delete Selected Column(s)":"Se\u00e7ili S\u00fctunlar\u0131 Sil", "Delete Selected Row(s)":"Se\u00e7ili Sat\u0131rlar\u0131 Sil", "Delete Table":"Tabloyu Sil"};
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 \u0432\u043c\u0456\u0441\u0442 \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 \u0432\u043c\u0456\u0441\u0442 \u043f\u043e \u0446\u0435\u043d\u0442\u0440\u0443", "Align content to bottom":"\u0412\u0438\u0440\u0456\u0432\u043d\u044f\u0442\u0438 \u0432\u043c\u0456\u0441\u0442 \u0437\u0430 \u043d\u0438\u0436\u043d\u0456\u043c \u043a\u0440\u0430\u0454\u043c", 
"Distribute Columns Evenly":"Delete Selected Column", "Set Width to Match Note":"\u0423\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0438 \u0448\u0438\u0440\u0438\u043d\u0443 \u0437\u0430 \u0440\u043e\u0437\u043c\u0456\u0440\u043e\u043c \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/\u0441\u0442\u043e\u0432\u043f\u0446\u0456", 
"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/\u0440\u044f\u0434\u043a\u0438", "Delete Table":"\u0412\u0438\u0434\u0430\u043b\u0438\u0442\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044e"};
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", "Set Width to Match Note":"\u0110\u1eb7t chi\u1ec1u r\u1ed9ng kh\u1edbp v\u1edbi 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"};
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", "Set Width to Match Note":"\u8bbe\u7f6e\u5bbd\u5ea6\u81ea\u9002\u5e94\u7b14\u8bb0", "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"};
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\u80cc\u666f\u984f\u8272", "Cell Alignment":"\u8868\u683c\u5c0d\u9f4a", 
"Align content to top":"\u5411\u9802\u5c0d\u9f4a", "Align content to center":"\u7f6e\u4e2d\u5c0d\u9f4a", "Align content to bottom":"Align content to bottom", "Distribute Columns Evenly":"Distribute Columns Evenly", "Set Width to Match Note":"Set Width to Match Note", "Delete Selected Column(s)":"Delete Selected Column(s)", "Delete Selected Row(s)":"Delete Selected Row(s)", "Delete Table":"\u522a\u9664\u8868\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 ]", "Set Width to Match Note":"[Set Width to Match Note xxxxxxxxxx]", "Delete Selected Column(s)":"[Delete Selected Column(s) xxxxxxxxxx ]", "Delete Selected Row(s)":"[Delete Selected Row(s) xxxxxxxxxx]", "Delete Table":"[Delete Table xxxxxxx]"};
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.zoomscale");
(function() {
  var util = uno.util;
  var instance = null;
  util.menu.presentTableContextMenu = function(cell, editor, event) {
    if (instance) {
      instance.dismiss();
    }
    var table = util.table["for"](cell);
    if (table == null) {
      return;
    }
    var defaultColor = "rgb(192, 100, 209)";
    var isTop = true;
    var isCenter = false;
    var isBottom = false;
    instance = new uno.components.Menu;
    instance.addItem(new uno.components.MenuColorPicker(util.loc.t("Cell Background"), defaultColor), function(color) {
      editor.execCommand("tablecellcolor", color);
    });
    instance.addItem(new uno.components.MenuSeparator);
    instance.addSubmenuItem(new uno.components.MenuItem(util.loc.t("Cell Alignment")), function(menu) {
      menu.addItem(new uno.components.MenuOption(util.loc.t("Align content to top"), isTop), editor.execCommand.bind(editor, "tableverticalalign", "top"));
      menu.addItem(new uno.components.MenuOption(util.loc.t("Align content to center"), isCenter), editor.execCommand.bind(editor, "tableverticalalign", "middle"));
      menu.addItem(new uno.components.MenuOption(util.loc.t("Align content to bottom"), isBottom), editor.execCommand.bind(editor, "tableverticalalign", "bottom"));
    });
    instance.addItem(new uno.components.MenuItem(util.loc.t("Distribute Columns Evenly")), function() {
      util.table.equalizeColumns(table);
    });
    instance.addItem(new uno.components.MenuItem(util.loc.t("Set Width to Match Note")), function() {
      var ennote = editor.getElement();
      var normalizeRect = util.zoomscale.normalizeRect;
      var bounds = normalizeRect(goog.style.getBounds(ennote));
      var padding = normalizeRect(goog.style.getPaddingBox(ennote));
      var border = normalizeRect(goog.style.getBorderBox(ennote));
      var noteWidth = bounds.width - padding.left - padding.right - border.left - border.right;
      if (noteWidth > 0) {
        util.table.setTableWidth(table, noteWidth - 2);
      }
    });
    instance.addItem(new uno.components.MenuItem(util.loc.t("Delete Selected Column(s)")), function() {
      editor.execCommand("deletetablecol");
    });
    instance.addItem(new uno.components.MenuItem(util.loc.t("Delete Selected Row(s)")), function() {
      editor.execCommand("deletetablerow");
    });
    instance.addItem(new uno.components.MenuItem(util.loc.t("Delete Table")), function() {
      editor.execCommand("deletetable");
    });
    instance.present(event.clientX, event.clientY);
  };
})();
goog.provide("uno.util.cursor");
goog.require("goog.style");
(function() {
  var currentCursor = "";
  var util = uno.util;
  util.cursor.lock = function(newCursorStyle) {
    if (currentCursor !== "") {
      return false;
    }
    goog.style.setStyle(document.body, "cursor", newCursorStyle);
    return true;
  };
  util.cursor.release = function(expectedCursor) {
    if (expectedCursor == null || expectedCursor === currentCursor) {
      goog.style.setStyle(document.body, "cursor", "");
      currentCursor = "";
    }
  };
})();
goog.provide("uno.listeners.TableListener");
goog.require("goog.debug.Logger");
goog.require("goog.events.KeyCodes");
goog.require("goog.dom");
goog.require("goog.array");
goog.require("goog.math");
goog.require("uno.BasePlugin");
goog.require("uno.util.paragraph");
goog.require("uno.util.dom");
goog.require("uno.util.adornment");
goog.require("uno.util.menu");
goog.require("uno.util.table");
goog.require("uno.util.cursor");
goog.require("uno.util.observer");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.TableListener");
  var util = uno.util;
  var mouseDownCell = null;
  var lastMouseHoverCell = null;
  var firstTimeHandler = true;
  var TableListener = uno.listeners.TableListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TableListener, uno.BasePlugin);
  var realTableForAdorn = function(adorn) {
    var table = util.adornment.parent(adorn);
    if (util.dom.getTagName(table) !== "table") {
      table = table.querySelector("table");
    }
    if (table == null) {
      log.severe("Have a table adorn with no parent table!!");
      return null;
    }
    return table;
  };
  var handleTableSelectionClick = function(adorn, editor) {
    var table = realTableForAdorn(adorn);
    if (table == null) {
      return;
    }
    editor.multirange.clear();
    goog.array.forEach(table.querySelectorAll("td"), util.table.multirange.toggleTD.bind(null, editor));
    editor.multirange.select();
  };
  var handleRowSelectionClick = function(adorn, editor, event) {
    var table = realTableForAdorn(adorn);
    if (table == null) {
      return;
    }
    var tableDims = util.table.dimensions(table);
    var closestRow = 0;
    for (var i = 0;i < tableDims.rows;i++) {
      var firstCell = util.table.cellAtPosition(table, i, 0);
      if (firstCell != null) {
        var cellBounds = util.dom.getBoundingBox(firstCell, true);
        if (event.clientY + document.body.scrollTop >= cellBounds.top && event.clientY + document.body.scrollTop <= cellBounds.top + cellBounds.height) {
          closestRow = i;
          break;
        }
      }
    }
    var row = table.querySelectorAll("tr")[closestRow];
    if (event.shiftKey) {
      goog.array.forEach(row.querySelectorAll("td"), util.table.multirange.addTD.bind(null, editor));
    } else {
      if (event.metaKey) {
        goog.array.forEach(row.querySelectorAll("td"), util.table.multirange.toggleTD.bind(null, editor));
      } else {
        editor.multirange.clear();
        goog.array.forEach(row.querySelectorAll("td"), util.table.multirange.addTD.bind(null, editor));
      }
    }
    editor.multirange.select();
  };
  var handleColumnSelectionClick = function(adorn, editor) {
    var table = realTableForAdorn(adorn);
    if (table == null) {
      return;
    }
    var tableDims = util.table.dimensions(table);
    var closestCol = 0;
    for (var i = 0;i < tableDims.columns;i++) {
      var firstCell = util.table.cellAtPosition(table, 0, i);
      if (firstCell != null) {
        var cellBounds = util.dom.getBoundingBox(firstCell, true);
        if (event.clientX >= cellBounds.left && event.clientX <= cellBounds.left + cellBounds.width) {
          closestCol = i;
          break;
        }
      }
    }
    var columnTDs = util.table.column(table, closestCol);
    if (event.shiftKey) {
      goog.array.forEach(columnTDs, util.table.multirange.addTD.bind(null, editor));
    } else {
      if (event.metaKey) {
        goog.array.forEach(columnTDs, util.table.multirange.toggleTD.bind(null, editor));
      } else {
        editor.multirange.clear();
        goog.array.forEach(columnTDs, util.table.multirange.addTD.bind(null, editor));
      }
    }
    editor.multirange.select();
  };
  TableListener.prototype.handleMouseDown = function(event) {
    var table = util.table["for"](event.target);
    if (table && util.table.getMode(table) === "resizing") {
      return;
    }
    mouseDownCell = util.table.cellFor(event.target);
  };
  TableListener.prototype.handleMouseMove = function(event) {
    var cell = util.table.cellFor(event.target);
    var table = util.table["for"](event.target);
    if (table && util.table.getMode(table) === "resizing") {
      mouseDownCell = null;
      lastMouseHoverCell = null;
      return;
    }
    if (cell != null && mouseDownCell != null) {
      var cellTable = util.table["for"](cell);
      var mouseDownCellTable = util.table["for"](mouseDownCell);
      if (cellTable != null && cellTable === mouseDownCellTable && lastMouseHoverCell !== cell) {
        util.dom.selectable(this.editor.getElement(), false);
        util.cursor.lock("cell");
        lastMouseHoverCell = cell;
        var cellSubtable = util.table.subtable(mouseDownCell, cell);
        this.editor.multirange.clear();
        goog.array.forEach(cellSubtable, util.table.multirange.toggleTD.bind(null, this.editor));
        event.stopPropagation();
        return;
      }
    }
    if (cell != null && isMouseOverCellMenu(event, cell)) {
      goog.dom.classlist.add(cell, "menu-hover");
    } else {
      var hovered = this.editor.getElement().querySelectorAll(".menu-hover");
      goog.array.forEach(hovered, function(element) {
        goog.dom.classlist.remove(element, "menu-hover");
      });
    }
  };
  TableListener.prototype.handleMouseUp = function(event) {
    var tableSelectionHandle = util.dom.getFirstAncestor(event.target, ["table-selection"], true);
    var rowSelectionHandle = util.dom.getFirstAncestor(event.target, ["row-selection"], true);
    var columnSelectionHandle = util.dom.getFirstAncestor(event.target, ["column-selection"], true);
    var cell = util.table.cellFor(event.target);
    var table = util.table["for"](event.target);
    if (table && util.table.getMode(table) === "resizing") {
      return;
    }
    util.dom.selectable(this.editor.getElement(), true);
    util.cursor.release();
    mouseDownCell = null;
    if (tableSelectionHandle != null) {
      handleTableSelectionClick(tableSelectionHandle, this.editor, event);
    } else {
      if (rowSelectionHandle != null) {
        handleRowSelectionClick(rowSelectionHandle, this.editor, event);
      } else {
        if (columnSelectionHandle != null) {
          handleColumnSelectionClick(columnSelectionHandle, this.editor, event);
        } else {
          if (cell != null) {
            if (isMouseOverCellMenu(event, cell)) {
              util.menu.presentTableContextMenu(cell, this.editor, event);
              event.preventDefault();
            } else {
              if (this.editor.multirange.active() && cell !== lastMouseHoverCell) {
                this.editor.multirange.clear();
              }
            }
          }
        }
      }
    }
  };
  TableListener.prototype.handleMouseOver = function(event) {
    var table = util.table["for"](event.target);
    var multiranges = this.editor.multirange.getTextRanges();
    if (multiranges && multiranges.length === 0 && table == null) {
      var elemWrap = util.adornment.getElementWrapper(event.target, true);
      table = elemWrap == null ? null : elemWrap.querySelector("table");
      if (table == null) {
        var controls = util.adornment.globalFind(this.editor, "table-controls");
        goog.array.forEach(controls, function(adorn) {
          var adornTable = realTableForAdorn(adorn);
          if (adornTable && util.table.getMode(adornTable) !== "resizing") {
            util.adornment.destroy(adorn);
          }
        });
        return;
      }
    }
    if (table == null) {
      return;
    }
    var adorn = util.adornment.find(table, "table-controls");
    if (adorn == null) {
      util.table.multirange.createControls(this.editor, table);
      if (firstTimeHandler === true) {
        firstTimeHandler = false;
        util.observer.addHandler(util.table.multirange.updateAllControls.bind(util.table.multirange.updateAllControls, this.editor));
      }
    }
  };
  var isMouseOverCellMenu = function(event, cell) {
    if (!goog.dom.classlist.contains(cell, "has-menu")) {
      return false;
    }
    var cellBounds = util.dom.getBoundingBox(cell, true);
    var size = 25;
    var cellRect = new goog.math.Rect(cellBounds.right - size, cellBounds.top, size, size);
    var mouseCoord = new goog.math.Coordinate(event.clientX + document.body.scrollLeft, event.clientY + document.body.scrollTop);
    return cellRect.contains(mouseCoord);
  };
  TableListener.prototype.handleScroll = function(event) {
    if (util.dom.getTagName(event.target) === "en-table") {
      util.table.multirange.updateControls(event.target, true);
    }
  };
})();
goog.provide("uno.listeners.TableCellListener");
goog.require("goog.debug.Logger");
goog.require("goog.editor.node");
goog.require("goog.editor.range");
goog.require("goog.events.KeyCodes");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.paragraph");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.TableCellListener");
  var UP_KEY = goog.events.KeyCodes.UP;
  var DOWN_KEY = goog.events.KeyCodes.DOWN;
  var ENTER_KEY = goog.events.KeyCodes.ENTER;
  var util = uno.util;
  var TableCellListener = uno.listeners.TableCellListener = function() {
    uno.BasePlugin.call(this, log.getName());
  };
  goog.inherits(TableCellListener, uno.BasePlugin);
  TableCellListener.prototype.handleKeyPress = function(event) {
    if (event.keyCode === ENTER_KEY && !event.altKey && !event.ctrlKey) {
      var range = this.editor.getRange();
      if (!range || !range.isCollapsed()) {
        return;
      }
      var startNode = range.getStartNode();
      var offset = range.getStartOffset();
      var table = startNode.childNodes[offset - 1];
      if (util.dom.isTable(table)) {
        var parentNode = util.dom.isEnnote(table.parentNode) ? table : table.parentNode;
        var newParagraph = util.paragraph.create();
        goog.dom.insertSiblingAfter(newParagraph, parentNode);
        var newRange = goog.dom.Range.createFromNodes(newParagraph, 0, newParagraph, 0);
        newRange.select();
        event.preventDefault();
      }
    }
  };
  TableCellListener.prototype.handleKeyboardShortcut = function(e) {
    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;
  };
  TableCellListener.prototype.handleTabKey = function(event) {
    var nextTd;
    var td = util.table.cellFor(this.editor.getRange().getStartNode());
    if (td == null) {
      return false;
    }
    if (event.shiftKey) {
      nextTd = util.table.prevCell(td);
    } else {
      nextTd = util.table.nextCell(td);
    }
    if (!nextTd && !event.shiftKey) {
      this.editor.execCommand("inserttablerow", "after");
      nextTd = util.table.nextRow(td).querySelector("td");
    }
    if (nextTd) {
      this.editor.stopChangeEvents(true, true);
      var startNode = goog.editor.node.getLeftMostLeaf(nextTd);
      if (startNode) {
        goog.editor.range.placeCursorNextTo(startNode, true);
      }
    }
    event.preventDefault();
    event.stopPropagation();
    setTimeout(function() {
      if (this.editor.isEventStopped(goog.editor.Field.EventType.CHANGE)) {
        this.editor.startChangeEvents();
      }
    }.bind(this));
    return true;
  };
  TableCellListener.prototype.handleUpOrDown = function(event) {
    var nextTd;
    var nextIndex;
    var tr;
    var siblings = [];
    var startNode = this.editor.getRange().getStartNode();
    var td = util.table.cellFor(startNode);
    var paragraph = util.paragraph["for"](startNode);
    if (td == null) {
      return;
    }
    goog.array.forEach(td.childNodes, function(node) {
      if (node.nodeType === Node.TEXT_NODE && node.textContent.trim().length === 0) {
        return;
      }
      siblings.push(node);
    });
    var index = siblings.indexOf(paragraph);
    var lastIndex = siblings.length - 1;
    if (index < 0) {
      return;
    }
    if (event.keyCode === UP_KEY && index > 0) {
      return;
    }
    if (event.keyCode === DOWN_KEY && index < lastIndex) {
      return;
    }
    tr = event.keyCode === UP_KEY ? util.table.prevRow(td) : util.table.nextRow(td);
    if (tr) {
      nextTd = util.table.cellAt(tr, util.table.cellIndex(td));
      if (nextTd != null) {
        nextIndex = event.keyCode === UP_KEY ? nextTd.childNodes.length : 0;
        if (nextTd.childNodes.length > 0) {
          goog.dom.Range.createCaret(nextTd, nextIndex).select();
        }
      }
      event.preventDefault();
      event.stopPropagation();
      return true;
    }
  };
})();
goog.provide("uno.listeners.TableResizeListener");
goog.require("goog.debug.Logger");
goog.require("goog.math");
goog.require("goog.dom");
goog.require("goog.style");
goog.require("uno.BasePlugin");
goog.require("uno.util.dom");
goog.require("uno.util.tools");
goog.require("uno.util.table");
goog.require("uno.util.cursor");
goog.require("uno.util.tools");
goog.require("uno.defs");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.TableResizeListener");
  var util = uno.util;
  var DRAG_ZONE_WIDTH = 6;
  var Zone = function(x, y, w, h, cell, type) {
    goog.math.Rect.call(this, x, y, w, h);
    this.type = type;
    this.table = util.table["for"](cell);
    this.tableMetrics = util.table.metrics(this.table);
    this.cell = cell;
    this.cellMetrics = util.table.metrics(this.cell);
    this.partnerCell = goog.dom.getNextElementSibling(cell);
    this.partnerCellMetrics = this.partnerCell ? util.table.metrics(this.partnerCell) : null;
  };
  goog.inherits(Zone, goog.math.Rect);
  var TableResizeListener = uno.listeners.TableResizeListener = function() {
    uno.BasePlugin.call(this, log.getName());
    this.mouseDownOnZone = null;
  };
  goog.inherits(TableResizeListener, uno.BasePlugin);
  TableResizeListener.prototype.handleMouseDown = function(event) {
    var table = this.nearestTable(event, 16);
    if (table == null || util.table.getMode(table) === "multirange") {
      return;
    }
    var hoverZones = this.getTableHoverZones(table);
    var cursorPos = getAbsoluteCoordFromEvent(event);
    for (var i = 0;i < hoverZones.length;i++) {
      if (hoverZones[i].contains(cursorPos)) {
        util.table.setMode(table, "resizing");
        util.dom.selectable(this.editor.getElement(), false);
        this.mouseDownOnZone = hoverZones[i];
        this.updateCursor(event);
        break;
      }
    }
  };
  TableResizeListener.prototype.handleWindowMouseUp = function() {
    this.updateCursor(event);
    if (this.mouseDownOnZone != null) {
      util.table.clearMode(this.mouseDownOnZone.table);
      util.dom.selectable(this.editor.getElement(), true);
      this.editor.dispatchChange();
      this.mouseDownOnZone = null;
    }
  };
  TableResizeListener.prototype.handleMouseMove = function(event) {
    this.updateCursor(event);
    if (this.mouseDownOnZone == null) {
      return;
    }
    var type = this.mouseDownOnZone.type;
    if (type === "left" || type === "right") {
      this.resizeWholeTable(event);
    } else {
      if (type === "inner") {
        this.resizeInnerCell(event);
      }
    }
  };
  TableResizeListener.prototype.updateCursor = function(event) {
    var table = this.nearestTable(event, DRAG_ZONE_WIDTH);
    if (table == null) {
      util.cursor.release("col-resize");
      return;
    }
    var hoverZones = this.getTableHoverZones(table);
    var cursorPos = getAbsoluteCoordFromEvent(event);
    var found = false;
    for (var i = 0;i < hoverZones.length;i++) {
      if (hoverZones[i].contains(cursorPos)) {
        found = true;
        break;
      }
    }
    if (found) {
      util.cursor.lock("col-resize");
    } else {
      util.cursor.release();
    }
  };
  TableResizeListener.prototype.nearestTable = function(event, optMaxDistance) {
    if (event == null) {
      return null;
    }
    var hoveredTable = util.table["for"](event.target);
    if (hoveredTable) {
      return hoveredTable;
    }
    var root = this.editor.getElement();
    var cursorPoint = getAbsoluteCoordFromEvent(event);
    var nearest = null;
    var dist = 99999999999;
    goog.array.forEach(root.querySelectorAll("table"), function(table) {
      var tableBounds = goog.style.getBounds(table);
      var newDist = tableBounds.distance(cursorPoint);
      if (newDist < dist) {
        dist = newDist;
        nearest = table;
      }
    });
    if (optMaxDistance != null && dist > optMaxDistance) {
      return null;
    }
    return nearest;
  };
  TableResizeListener.prototype.resizeWholeTable = function(event) {
    if (this.mouseDownOnZone == null) {
      return;
    }
    var table = this.mouseDownOnZone.table;
    var align = util.table.getAlignment(table);
    var scaleFactor;
    if (align === "left" || align === "right") {
      scaleFactor = 1;
    } else {
      if (align === "center") {
        scaleFactor = 2;
      } else {
        log.severe("Invalid table alignment: ", align);
      }
    }
    var resizeDirection;
    if (this.mouseDownOnZone.type === "left") {
      resizeDirection = -1;
    } else {
      if (this.mouseDownOnZone.type === "right") {
        resizeDirection = 1;
      } else {
        resizeDirection = 1;
      }
    }
    var originalTableMetrics = this.mouseDownOnZone.tableMetrics;
    var tableDims = util.table.dimensions(table);
    var minTableWidth = tableDims.columns * uno.defs.table.CELL_MIN;
    var parentMetrics = util.table.metrics(table.parentElement);
    var parentWidthPx = parentMetrics.width - parentMetrics.padding.left - parentMetrics.padding.right - parentMetrics.border.left - parentMetrics.border.right;
    var zoneCenter = this.mouseDownOnZone.getCenter();
    var cursorPos = getAbsoluteCoordFromEvent(event);
    var dragDelta = resizeDirection * scaleFactor * (cursorPos.x - zoneCenter.x);
    var newWidthPx = originalTableMetrics.width + dragDelta;
    if (newWidthPx < minTableWidth) {
      newWidthPx = minTableWidth;
    }
    if (newWidthPx > parentWidthPx) {
      newWidthPx = parentWidthPx;
    }
    var newWidthPercent = newWidthPx / parentWidthPx * 100;
    goog.style.setStyle(table, "width", newWidthPercent + "%");
    util.table.ensureColumnMinWidth(table);
  };
  TableResizeListener.prototype.resizeInnerCell = function(event) {
    var zone = this.mouseDownOnZone;
    var cursorPos = getAbsoluteCoordFromEvent(event);
    var dragDelta = cursorPos.x - zone.getCenter().x;
    if (zone.cell == null || zone.partnerCell == null) {
      log.severe("Bug: cell or partnerCell missing during resize!");
      return;
    }
    if (dragDelta < -zone.cellMetrics.width + uno.defs.table.CELL_MIN) {
      dragDelta = -zone.cellMetrics.width + uno.defs.table.CELL_MIN;
    }
    if (dragDelta > zone.partnerCellMetrics.width - uno.defs.table.CELL_MIN) {
      dragDelta = zone.partnerCellMetrics.width - uno.defs.table.CELL_MIN;
    }
    var newCellWidthPx = zone.cellMetrics.width + dragDelta;
    var newPartnerCellWidthPx = zone.partnerCellMetrics.width - dragDelta;
    var newCellWidthPct = newCellWidthPx / zone.tableMetrics.width * 100;
    var newPartnerCellWidthPct = newPartnerCellWidthPx / zone.tableMetrics.width * 100;
    goog.style.setStyle(zone.cell, "width", newCellWidthPct + "%");
    goog.style.setStyle(zone.partnerCell, "width", newPartnerCellWidthPct + "%");
  };
  TableResizeListener.prototype.getTableHoverZones = function(table) {
    if (table == null) {
      return null;
    }
    var align = util.table.getAlignment(table);
    var tableMetrics = util.table.metrics(table);
    var firstRow = table.querySelector("tr");
    if (firstRow == null) {
      return null;
    }
    var firstRowCells = firstRow.querySelectorAll("td");
    if (firstRowCells == null) {
      return null;
    }
    var zones = [];
    if (align === "left" || align === "center") {
      zones.push(new Zone(tableMetrics.left + tableMetrics.width - DRAG_ZONE_WIDTH / 2, tableMetrics.top - 16, DRAG_ZONE_WIDTH, tableMetrics.height + 16, firstRowCells[firstRowCells.length - 1], "right"));
    } else {
      if (align === "right") {
      } else {
        log.severe("Invalid table alignment: " + align);
        return null;
      }
    }
    var cellMetrics = null;
    for (var i = 0;i < firstRowCells.length - 1;i++) {
      cellMetrics = util.table.metrics(firstRowCells[i]);
      zones.push(new Zone(cellMetrics.left + cellMetrics.width - DRAG_ZONE_WIDTH / 2, tableMetrics.top - 16, DRAG_ZONE_WIDTH, tableMetrics.height + 16, firstRowCells[i], "inner"));
    }
    return zones;
  };
  TableResizeListener.prototype.drawRectangles = function(zones) {
    var debugClass = "en-table-resize-debug";
    var holder = util.tools.query("." + debugClass);
    goog.dom.removeNode(holder);
    holder = goog.dom.createDom("div", {"class":debugClass, style:"pointer-events: none;"});
    util.tools.append(holder);
    var randColorHex = function() {
      var color = goog.math.randomInt(16777215).toString(16);
      while (color.length < 6) {
        color = "0" + color;
      }
      return "#" + color;
    };
    goog.array.forEach(zones, function(zone) {
      var box = goog.dom.createDom("div", {"class":debugClass + "-zone"});
      goog.style.setStyle(box, "position", "absolute");
      goog.style.setStyle(box, "background", randColorHex());
      goog.style.setStyle(box, "left", zone.left + "px");
      goog.style.setStyle(box, "top", zone.top + "px");
      goog.style.setStyle(box, "width", zone.width + "px");
      goog.style.setStyle(box, "height", zone.height + "px");
      holder.appendChild(box);
    });
  };
  var getAbsoluteCoordFromEvent = function(event) {
    var absoluteX = window.pageXOffset + event.clientX;
    var absoluteY = window.pageYOffset + event.clientY;
    return new goog.math.Coordinate(absoluteX, absoluteY);
  };
})();
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.leadingTodo(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");
(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() {
    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":"\u2764\ufe0f", "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");
(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) {
    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");
(function() {
  var hr = uno.util.typebehind.hr;
  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) {
    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 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");
(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")) {
      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");
(function() {
  var table = uno.util.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) {
    range.getStartNode().replaceData(range.getStartOffset(), matchedText.length, "");
    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");
(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() {
    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.setTestOnly("goog.testing.JsUnitException");
goog.provide("goog.testing.JsUnitException");
goog.provide("goog.testing.asserts");
goog.require("goog.testing.stacktrace");
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 {
          var childPath = path + (isArray ? "[%s]" : path ? ".%s" : "%s");
          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.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.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$10) {
    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.MultiRangeListener");
goog.require("goog.array");
goog.require("goog.debug.Logger");
goog.require("goog.functions");
goog.require("goog.dom");
goog.require("uno.BasePlugin");
goog.require("uno.MultiRange");
goog.require("uno.util.dom");
goog.require("uno.util.range");
goog.require("uno.util.table");
(function() {
  var log = goog.debug.Logger.getLogger("uno.listeners.MultiRangeListener");
  var util = uno.util;
  var MultiRangeListener = uno.listeners.MultiRangeListener = function() {
    uno.BasePlugin.call(this, log.getName());
    this.multi = new uno.MultiRange;
  };
  goog.inherits(MultiRangeListener, uno.BasePlugin);
  MultiRangeListener.prototype.activeOnUneditableFields = goog.functions.TRUE;
  MultiRangeListener.prototype.handleNativeSelectionChange = function() {
    if (!this.editor.multirange.active()) {
      return;
    }
    var selection = window.getSelection();
    if (selection.rangeCount < 1) {
      return;
    }
    var nativeRange = selection.getRangeAt(0);
    var textRange = goog.dom.Range.createFromBrowserRange(nativeRange);
    if (util.table.multirange.shouldClear(this.editor, textRange)) {
      this.editor.multirange.clear();
    }
  };
})();
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;
  };
})();
goog.provide("uno.util.richlink.googledrive.ios");
goog.require("uno.util.loc");
(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;
  };
})();
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;
  };
})();
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");
(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.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 platform = googledrive.generic;
  var imagePath = "images";
  googledrive.name = "google-drive";
  googledrive.lastInfo = {};
  googledrive.lastImageUrl = {};
  googledrive.uniqueIdCounter = 0;
  googledrive.setPlatform = function(platformName) {
    platform = googledrive[platformName] || platform;
  };
  googledrive.canDecorate = function(url) {
    DRIVE_LINK_RX.lastIndex = 0;
    return url && DRIVE_LINK_RX.test(url);
  };
  googledrive.decorate = function(el, editor) {
    imagePath = editor.config.images.path;
    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);
        }
      });
    });
    platform.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.loadFromPlatformAsync(iconSrc, platform);
    if (showOverlay) {
      overlayPromise = util.img.loadFromPlatformAsync(imagePath + "/att_src_icon_google_28.svg", platform);
    } 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.loadFromPlatformAsync(imagePath + "/overflow_menu.svg", platform).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.loadFromPlatformAsync(thumbnailUrl, platform);
  };
  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 = platform.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 = platform.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.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.TableAlign");
goog.require("uno.commands.TableBorderColor");
goog.require("uno.commands.TableBorderWidth");
goog.require("uno.commands.TableCellColor");
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.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.ResourceFilter");
goog.require("uno.filters.RichlinkFilter");
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.AdornmentFilter");
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.TableCellListener");
goog.require("uno.listeners.TableResizeListener");
goog.require("uno.listeners.TodoListener");
goog.require("uno.listeners.TodoListListener");
goog.require("uno.listeners.TypeBehindListener");
goog.require("uno.listeners.SelectionListener");
goog.require("uno.listeners.MultiRangeListener");
goog.require("uno.util.dom");
goog.require("uno.util.font");
goog.require("uno.util.loc");
goog.require("uno.util.objects");
goog.require("uno.util.resource");
goog.require("uno.util.richlink.googledrive");
goog.require("uno.util.simpletext");
goog.require("uno.util.touch");
goog.require("uno.util.todo");
goog.require("uno.util.img");
goog.require("uno.util.tools");
goog.require("uno.util.canvas");
(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 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;
    goog.dom.classes.add(document.body, this.config.platform);
    util.font.setPlatform(this.config.platform);
    util.resource.setPlatform(this.config.platform);
    util.todo.setPlatform(this.config.platform);
    util.simpletext.setPlatform(this.config.platform);
    util.richlink.googledrive.setPlatform(this.config.platform);
    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:"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"}];
    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"};
  Object.keys(Field.EventType).forEach(function(key) {
    if (Field.EventType.hasOwnProperty(key)) {
      Editor.EventType[key] = Field.EventType[key];
    }
  });
  Editor.prototype.setup = function() {
    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 = new uno.EditorMultiRange(this);
    if (goog.isDef(this.config.initialContent)) {
      this.execCommand("content", options);
    } else {
      this.setHtml(false, this.config.defaults.html, true);
    }
    this.updateEmpty();
    this.isSetup = true;
  };
  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) {
    var me = this;
    SeamlessField.prototype.registerPlugin.call(me, plugin);
    me.handlers.forEach(function(property) {
      if (plugin[property.handler]) {
        me.listeners[property.name].push(plugin);
      }
    });
    me.allPluginsInOrder.push(plugin);
    if (plugin.prepareContentsDom) {
      me.importDomFilters.push(plugin);
    }
    if (plugin.queryCommandEnabled) {
      me.queryCommandEnabledPlugins.push(plugin);
    }
  };
  Editor.prototype.unregisterPlugin = function(plugin) {
    var me = this;
    SeamlessField.prototype.unregisterPlugin.call(me, plugin);
    me.handlers.forEach(function(property) {
      goog.array.remove(me.listeners[property.name], plugin);
    });
    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.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.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.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.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.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.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.TableFilter);
    this.registerPlugin(new uno.filters.TodoFilter);
    this.registerPlugin(new uno.filters.BasicTextFormatterFilter);
    this.registerPlugin(new uno.filters.CodeBlockFilter);
    this.registerPlugin(new uno.filters.FontSizeFilter);
    this.registerPlugin(new uno.filters.ZoomScaleFilter);
    this.registerPlugin(new uno.filters.CopyFilter);
    this.registerPlugin(new uno.filters.AdornmentFilter);
    if (this.config.multirange) {
      this.registerPlugin(new uno.listeners.MultiRangeListener);
      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.registerPlugin(new uno.listeners.DeleteListener);
    this.registerPlugin(new uno.listeners.ForwardDeleteListener);
    this.registerPlugin(new uno.listeners.HighlightListener);
    this.registerPlugin(new uno.listeners.RichlinkListener);
    this.registerPlugin(new uno.listeners.TodoListener);
    this.registerPlugin(new uno.listeners.LinkListener);
    this.registerPlugin(new uno.listeners.ImgListener);
    this.registerPlugin(new uno.listeners.ListListener);
    this.registerPlugin(new uno.listeners.PasteListener);
    this.registerPlugin(new uno.listeners.TableCellListener);
    this.registerPlugin(new goog.editor.plugins.SpacesTabHandler);
    this.registerPlugin(new uno.listeners.TableResizeListener);
    this.registerPlugin(new uno.listeners.TodoListListener);
    this.registerPlugin(new uno.listeners.TypeBehindListener);
    this.registerPlugin(new uno.listeners.NoteListener);
    this.registerPlugin(new uno.listeners.SmartScrollListener);
    this.registerPlugin(new uno.listeners.SelectionListener);
  };
  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 = {style:{state:{}, value:{}, enabled:{}}, crypt:{uniqueIdCounter:0, incrementUniqueId:function() {
      return ++this.uniqueIdCounter;
    }}, images:{annotateButton:null, annotateHoverButton:null, previewButton:null, previewHoverButton:null, rotateButton:null, rotateHoverButton:null}, pendingTodo:false, format:uno.defs.format.PLATFORM_HTML, resources:options.rte.resources || {}};
    this.config = {debug:!!options.debug, stayInEditMode:options.stayInEditMode !== false, smartScrollEnabled:options.rte.smartScroll, accentuate:options.accentuate || {clearOnClickSelector:"en-note"}, multirange:false, note:{contentClass:options.note.contentClass, source:options.note.source, sourceURL:options.note.sourceURL, sourceApplication:options.note.sourceApplication, title:options.note.title}, crypt:{unveilCryptElementOnClick:false, readOnly:options.rte.cryptReadOnly || false}, 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)", tableCellHtml:"<div><br></div>", fontSize:"", fontFamily:"", foreColor:"rgb(0, 0, 0)"}, 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}, resourceConfig:{openLinkNotifications:!!options.rte.resourceConfig.openLinkNotifications}, find:options.find || {}, initialContent:options.rte.enml || options.rte.html, initialContentFormat:options.rte.enml ? uno.defs.format.ENML : uno.defs.format.PLATFORM_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}}, platform:options.env.platform || uno.env.getPlatform(), 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) {
          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() {
    goog.array.forEach(Object.keys(this.plugins_), function(classId) {
      this.plugins_[classId].enable(this);
    }, this);
  };
  Editor.prototype.disablePlugins = function() {
    goog.array.forEach(Object.keys(this.plugins_), function(classId) {
      var plugin = this.plugins_[classId];
      if (!plugin.activeOnUneditableFields()) {
        plugin.disable(this);
      }
    }, this);
  };
  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.leaveEditMode = function() {
    if (!this.readOnly) {
      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) {
      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$11) {
          log.fine(err$11.stack || err$11);
        }
      }
      if (!didSetSelection) {
        this.placeCursorAtEnd();
      }
      this.savedRange = null;
    }
  };
  Editor.prototype.cleanup = function() {
    if (this.isSetup) {
      this.makeUneditable(true);
      this.dispose();
      document.querySelector("#" + this.id).innerHTML = "";
      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.PLATFORM_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 logic = 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;
    }.bind(this);
    if (isTopLevelCall && this.multirange.active()) {
      log.fine("Doing MULTI queryCommandEnabled: " + command);
      return goog.array.some(this.multirange.getTextRanges(), function(textrange) {
        textrange.select();
        return logic();
      }, this);
    }
    return logic();
  };
  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 == null) {
      return false;
    }
    var targetExecFunction = null;
    if (goog.isFunction(targetPlugin.execCommand)) {
      targetExecFunction = targetPlugin.execCommand;
    }
    var logic = function() {
      var result = null;
      this.dispatchEvent({type:"beforeexeccommand", command:command});
      result = targetExecFunction.call(targetPlugin, command, value, options);
      this.updateUndoCursorPosition();
      this.dispatchEvent({type:"afterexeccommand", command:command});
      return result;
    }.bind(this);
    try {
      var result = null;
      var pluginMultiMode = targetPlugin.multiRangeMode;
      var applyToAllMode = uno.defs.multirange.PLUGIN_MODE.APPLY_TO_ALL;
      if (isTopLevelCall && pluginMultiMode === applyToAllMode && this.multirange.active()) {
        log.fine("Doing MULTI execCommand: " + command);
        goog.array.forEach(this.multirange.getTextRanges(), function(textrange) {
          textrange.select();
          var tmpResult = logic(true);
          if (result == null && tmpResult != null) {
            result = tmpResult;
          }
        }, this);
        this.multirange.getTextRanges()[0].select();
      } else {
        result = logic();
      }
      return result;
    } catch (err$12) {
      console.error(err$12);
      log.severe(err$12.stack || err$12);
      return false;
    }
  };
  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);
    this.importDomFilters.forEach(function(filter) {
      filter.prepareContentsDom(frag);
    });
    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) {
    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.PLATFORM_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.PLATFORM_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) {
    if (immediate == null) {
      immediate = false;
    }
    var logic = function() {
      if (util.dom.isOnScreen(container, 75)) {
        if (contextSeen === false) {
          contextSeen = true;
          EN.notification("contextVisible", {module:moduleName});
        }
      }
    };
    if (immediate) {
      logic();
    } else {
      clearTimeout(contextViewDeJitterTimeoutRef);
      contextViewDeJitterTimeoutRef = setTimeout(logic, 100);
    }
  };
  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) {
    if (immediate == null) {
      immediate = false;
    }
    var logic = function() {
      if (util.dom.isOnScreen(container, 75)) {
        if (contextSeen === false) {
          contextSeen = true;
          EN.notification("contextVisible", {module:moduleName});
        }
      }
    };
    if (immediate) {
      logic();
    } else {
      clearTimeout(contextViewDeJitterTimeoutRef);
      contextViewDeJitterTimeoutRef = setTimeout(logic, 100);
    }
  };
  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.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.USN");
goog.require("uno.realtime.Plugin");
goog.require("goog.functions");
(function() {
  var USN = uno.realtime.USN = function(yjsmodule) {
    uno.realtime.Plugin.call(this, yjsmodule);
  };
  goog.inherits(USN, uno.realtime.Plugin);
  USN.prototype.currentUSN = null;
  USN.prototype.setupConfig = function(yjsconfig) {
    yjsconfig.share.metadata = "Map";
    return yjsconfig;
  };
  USN.prototype.setupObservation = function() {
    var self = this;
    var sharedMap = self.yjsmodule.y.share.metadata;
    this.handleUpdateUSN({type:"update", name:"USN", value:sharedMap.get("USN"), oldValue:null});
    sharedMap.observe(function(event) {
      self.handleUpdateUSN(event);
    });
  };
  USN.prototype.handleUpdateUSN = function(event) {
    if (event.name === "USN" && event.value !== this.currentUSN) {
      this.currentUSN = event.value;
      this.yjsmodule.editor.dispatchEvent({type:"usnUpdated", usn:this.currentUSN});
      console.log("USN REMOTE updated:", this.currentUSN);
    }
  };
  USN.prototype.isSupportedCommand = function(command) {
    return command === "realtime-usn";
  };
  USN.prototype.execCommand = function(command, value) {
    if (!value) {
      return false;
    }
    this.currentUSN = value;
    this.yjsmodule.y.share.metadata.set("USN", this.currentUSN);
    console.log("USN LOCAL updated:", this.currentUSN);
    return true;
  };
  USN.prototype.queryCommandValue = function() {
    return this.currentUSN;
  };
  USN.prototype.queryCommandEnabled = goog.functions.TRUE;
})();
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";
    yjsconfig.share.plaintextDemo = "Text";
    yjsconfig.share.plaintextSelection = "Map";
    return yjsconfig;
  };
  var randomColor = function() {
    var letters = "0123456789ABCDEF";
    var color = "#";
    for (var i = 0;i < 6;i++) {
      color += letters[Math.floor(Math.random() * 16)];
    }
    return color;
  };
  Users.prototype.setupObservation = function() {
    var self = this;
    var metadataMap = self.yjsmodule.y.share.metadata;
    var userMap = metadataMap.get("Users");
    if (userMap == null) {
      userMap = metadataMap.set("Users", window.Y.Map);
    }
    var userDataMap = userMap.set(this.yjsmodule.y.db.userId, window.Y.Map);
    userDataMap.set("Name", this.yjsmodule.globalOptions.metadata.name || this.yjsmodule.y.db.userId);
    userDataMap.set("Color", randomColor());
  };
  Users.prototype.updateUserActivity = function(event) {
    if (goog.isString(event.name)) {
      this.activeUsers[event.name] = (new Date).getTime();
    }
    this.renderOverlay();
  };
  Users.prototype.getActive = function(activityCutoff) {
    activityCutoff = activityCutoff || 20000;
    var now = (new Date).getTime();
    return goog.array.filter(Object.keys(this.activeUsers), function(key) {
      return this.activeUsers[key] + activityCutoff > now;
    }, 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.PlainTextDemo");
goog.require("uno.realtime.Plugin");
goog.require("goog.functions");
goog.require("goog.dom");
goog.require("goog.array");
goog.require("uno.util.dom");
goog.require("uno.util.copy");
goog.require("uno.util.range");
(function() {
  var PlainTextDemo = uno.realtime.PlainTextDemo = function(yjsmodule) {
    uno.realtime.Plugin.call(this, yjsmodule);
  };
  goog.inherits(PlainTextDemo, uno.realtime.Plugin);
  PlainTextDemo.prototype.lastPlainContent = "";
  PlainTextDemo.prototype.lastUserRanges = {};
  PlainTextDemo.prototype.setupConfig = function(yjsconfig) {
    yjsconfig.share.plaintextDemo = "Text";
    yjsconfig.share.plaintextSelection = "Map";
    return yjsconfig;
  };
  PlainTextDemo.prototype.setupObservation = function() {
    var self = this;
    var editor = self.yjsmodule.editor;
    var sharedEditing = self.yjsmodule.y.share.plaintextDemo;
    var sharedSelection = self.yjsmodule.y.share.plaintextSelection;
    editor.field.style.whiteSpace = "pre-wrap";
    var currentState = sharedEditing.toString();
    if (currentState) {
      this.setDomFromPlain(currentState);
    }
    var token = true;
    var mutualExclusive = function(f) {
      if (token) {
        token = false;
        try {
          f();
        } catch (e) {
          token = true;
          throw new Error(e);
        }
        token = true;
      }
    };
    editor.field.addEventListener("keyup", function() {
      mutualExclusive(self.handleLocalContentChange.bind(self));
    });
    sharedEditing.observe(function(event) {
      mutualExclusive(self.handleRemoteContentChange.bind(self, event));
    });
    editor.listen("selectionchange", function() {
      mutualExclusive(self.handleLocalSelectionChange.bind(self));
    });
    sharedSelection.observe(function(event) {
      mutualExclusive(self.handleRemoteSelectionChange.bind(self, event));
    });
  };
  var dejittercontentchange = 0;
  PlainTextDemo.prototype.setDomFromPlain = function(plain) {
    var editor = this.yjsmodule.editor;
    if (this.lastPlainContent === plain) {
      return;
    }
    this.lastPlainContent = plain;
    goog.dom.removeChildren(editor.field);
    var paragraphs = this.lastPlainContent.split("\n");
    if (paragraphs[paragraphs.length - 1] === "") {
      paragraphs = paragraphs.slice(0, paragraphs.length - 1);
    }
    var newHTML = "<div>" + paragraphs.join("</div><div>") + "</div>";
    var blankDivRx = new RegExp("<div>s*</div>", "ig");
    editor.field.innerHTML = newHTML.replace(blankDivRx, "<div><br></div>");
    editor.updateEmpty();
    clearTimeout(dejittercontentchange);
    dejittercontentchange = setTimeout(function() {
      editor.dispatchEvent("contentchanged");
    }, 100);
  };
  PlainTextDemo.prototype.handleRemoteContentChange = function(event) {
    var newContent = this.yjsmodule.y.share.plaintextDemo.toString();
    if (newContent) {
      var oldContent = this.lastPlainContent;
      var plainRange = this.browserRangeToPlainCoords(window.getSelection().getRangeAt(0));
      this.setDomFromPlain(newContent);
      this.reviseAndRedrawRanges(plainRange, event, oldContent, newContent);
    }
  };
  PlainTextDemo.prototype.handleLocalContentChange = function() {
    var shared = this.yjsmodule.y.share.plaintextDemo;
    var editor = this.yjsmodule.editor;
    var range = document.createRange();
    range.selectNodeContents(editor.field);
    var textrange = new goog.dom.TextRange;
    textrange.setBrowserRangeObject(range);
    var result = uno.util.copy.copy(editor, {plain:true}, textrange);
    var plaintext = result.plain;
    var diffs = window.FastDiff.diff(this.lastPlainContent, plaintext);
    var pos = 0;
    for (var i = 0;i < diffs.length;i++) {
      var d = diffs[i];
      if (d[0] === window.FastDiff.EQUAL) {
        pos += d[1].length;
      } else {
        if (d[0] === window.FastDiff.DELETE) {
          this.reviseAndRedrawRanges(null, {type:"delete", index:pos, length:d[1].length}, this.lastPlainContent, plaintext, true);
          shared["delete"](pos, d[1].length);
        } else {
          this.reviseAndRedrawRanges(null, {type:"insert", index:pos, length:d[1].length}, this.lastPlainContent, plaintext, true);
          shared.insert(pos, d[1]);
          pos += d[1].length;
        }
      }
    }
    this.lastPlainContent = plaintext;
  };
  PlainTextDemo.prototype.browserRangeToPlainCoords = function(range) {
    var editor = this.yjsmodule.editor;
    var rows = editor.field.querySelectorAll("div");
    var result = {startRow:0, endRow:0, startCol:0, endCol:0};
    if (range.startContainer == null || range.endContainer == null || editor.field.contains(range.startContainer) === false || editor.field.contains(range.endContainer) === false) {
      console.log("Ignoring invalid selection");
      return null;
    }
    for (var i = 0;i < rows.length;i++) {
      var row = rows[i];
      row.normalize();
      if (row.contains(range.startContainer)) {
        result.startRow = i;
        result.startCol = range.startOffset;
      }
      if (row.contains(range.endContainer)) {
        result.endRow = i;
        result.endCol = range.endOffset;
      }
    }
    return result;
  };
  PlainTextDemo.prototype.plainCoordsToBrowserRange = function(plain) {
    var editor = this.yjsmodule.editor;
    var rows = editor.field.querySelectorAll("div");
    var range = document.createRange();
    var startRow = rows[plain.startRow];
    var endRow = rows[plain.endRow];
    if (startRow == null || endRow == null) {
      return null;
    }
    startRow.normalize();
    endRow.normalize();
    var startTextNode = startRow.firstChild;
    var endTextNode = endRow.firstChild;
    var startMaxPos = startTextNode.data != null ? startTextNode.data.length : 0;
    var endMaxPos = endTextNode.data != null ? endTextNode.data.length : 0;
    range.setStart(startTextNode, Math.min(plain.startCol, startMaxPos));
    range.setEnd(endTextNode, Math.min(plain.endCol, endMaxPos));
    return range;
  };
  var getToolsSection = function(section) {
    var tools = document.querySelector("en-tools");
    var specific = tools.querySelector(".realtime-" + section);
    if (specific == null) {
      specific = document.createElement("div");
      specific.setAttribute("class", "realtime-" + section);
      tools.appendChild(specific);
    }
    return specific;
  };
  PlainTextDemo.prototype.fakeRenderRange = function(range, color, user) {
    var clientrects = range.getClientRects();
    var tools = getToolsSection("selections");
    var userSels = tools.querySelectorAll('[data-user="' + user + '"]');
    for (var j = 0;j < userSels.length;j++) {
      goog.dom.removeNode(userSels[j]);
    }
    for (var i = 0;i < clientrects.length;i++) {
      var clientrect = clientrects[i];
      var box = document.createElement("div");
      box.setAttribute("data-user", user);
      box.style.backgroundColor = color;
      box.style.position = "absolute";
      box.style.top = clientrect.top + "px";
      box.style.left = clientrect.left + "px";
      box.style.height = clientrect.height + "px";
      box.style.width = (clientrect.width < 2 ? 2 : clientrect.width) + "px";
      tools.appendChild(box);
    }
  };
  PlainTextDemo.prototype.updatePlainCoordsByRemoteContent = function(plainRange, event, beforeContent, afterContent) {
    var beforeRows = beforeContent.split("\n");
    beforeRows = beforeRows.slice(0, beforeRows.length - 1);
    var linearize = function(row, col) {
      var linear = 0;
      for (var i = 0;i < row;i++) {
        try {
          var plainRow = beforeRows[i];
          linear += plainRow.length + 1;
        } catch (e) {
          console.log("Unexpected lack of rows compared to range");
          return plainRange;
        }
      }
      return linear + col;
    };
    var delinearize = function(linear) {
      var textChunk = afterContent.slice(0, linear);
      var chunkRows = textChunk.split("\n");
      return {row:chunkRows.length - 1, col:chunkRows[chunkRows.length - 1].length};
    };
    var linearStart = linearize(plainRange.startRow, plainRange.startCol);
    var linearEnd = linearize(plainRange.endRow, plainRange.endCol);
    if (event.type === "insert") {
      if (event.index <= linearStart) {
        linearStart += event.length;
      }
      if (event.index <= linearEnd) {
        linearEnd += event.length;
      }
    } else {
      if (event.type === "delete") {
        if (event.index <= linearStart && event.index + event.length <= linearStart) {
          linearStart -= event.length;
        } else {
          if (event.index <= linearStart && event.index + event.length > linearStart) {
            linearStart = event.index;
          }
        }
        if (event.index <= linearEnd && event.index + event.length <= linearEnd) {
          linearEnd -= event.length;
        } else {
          if (event.index <= linearEnd && event.index + event.length > linearEnd) {
            linearEnd = event.index;
          }
        }
      }
    }
    var delinearStart = delinearize(linearStart);
    var delinearEnd = delinearize(linearEnd);
    return {startRow:delinearStart.row, startCol:delinearStart.col, endRow:delinearEnd.row, endCol:delinearEnd.col};
  };
  PlainTextDemo.prototype.reviseAndRedrawRanges = function(myPlainRange, contentEvent, oldContent, newContent, optSkipLocal) {
    optSkipLocal = optSkipLocal == null ? false : optSkipLocal;
    goog.dom.removeChildren(getToolsSection("selections"));
    goog.array.forEach(Object.keys(this.lastUserRanges), function(key) {
      var revisedPlainRange = this.updatePlainCoordsByRemoteContent(this.lastUserRanges[key], contentEvent, oldContent, newContent);
      var browserRange = this.plainCoordsToBrowserRange(revisedPlainRange);
      if (browserRange != null) {
        this.lastUserRanges[key] = revisedPlainRange;
        this.fakeRenderRange(browserRange, this.getUserColor(key), key);
      }
    }, this);
    if (!optSkipLocal) {
      var updatedRange = this.updatePlainCoordsByRemoteContent(myPlainRange, contentEvent, oldContent, newContent);
      var newRange = this.plainCoordsToBrowserRange(updatedRange);
      if (newRange != null) {
        var selection = window.getSelection();
        selection.removeAllRanges();
        selection.addRange(newRange);
      }
    }
  };
  PlainTextDemo.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;
  };
  PlainTextDemo.prototype.handleRemoteSelectionChange = function(event) {
    var username = event.name;
    var plainRange = JSON.parse(event.value);
    var browserRange = this.plainCoordsToBrowserRange(plainRange);
    if (browserRange != null) {
      this.lastUserRanges[username] = plainRange;
      this.fakeRenderRange(browserRange, this.getUserColor(username), username);
    }
    if (this.yjsmodule.users != null) {
      this.yjsmodule.users.updateUserActivity(event);
    }
  };
  PlainTextDemo.prototype.handleLocalSelectionChange = function() {
    var sharedSelection = this.yjsmodule.y.share.plaintextSelection;
    var range = window.getSelection().getRangeAt(0);
    var plainRange = this.browserRangeToPlainCoords(range);
    if (plainRange == null) {
      return;
    }
    sharedSelection.set(this.yjsmodule.y.db.userId, JSON.stringify(plainRange));
  };
})();
goog.provide("uno.realtime.YJS");
goog.require("goog.functions");
goog.require("uno.PluginManager");
goog.require("uno.realtime.USN");
goog.require("uno.realtime.Users");
goog.require("uno.realtime.PlainTextDemo");
(function() {
  var YJSConfig = {db:{name:"memory"}, connector:{name:"websockets-client", room:"en-webrtc-test", url:"104.196.233.61:443"}, 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;
    }
    if (self.globalOptions.metadata && self.globalOptions.metadata.guid) {
      YJSConfig.connector.room = self.globalOptions.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);
    self.PM = new uno.PluginManager;
    self.PM.add(new uno.realtime.USN(self));
    self.users = new uno.realtime.Users(self);
    self.PM.add(self.users);
    self.PM.add(new uno.realtime.PlainTextDemo(self));
    self.PM.forEach(function(plugin) {
      var update = self.PM.tryToRun(plugin, "setupConfig", [YJSConfig]);
      if (update != null) {
        YJSConfig = update;
      }
    });
    window.Y(YJSConfig).then(function(y) {
      self.y = y;
      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");
      });
    });
  };
  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.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.19.1543";
  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) {
    EN.cleanup();
    var id;
    opt = opt || {};
    options = goog.isObject(opt) ? opt : JSON.parse(opt);
    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";
    DEBUG = options.debug === true;
    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.realtime != null) {
      ed.listen("usnUpdated", onUSNUpdated);
    }
    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);
      }
    }
    PM.add(new uno.context.Context(options.context || {}));
    PM.add(new uno.context.Upsell(options["context-upsell"] || {}));
    PM.add(new uno.context.Info(options["context-info"] || {}));
    PM.add(ted);
    PM.add(ed);
    if (options.realtime != null) {
      PM.add(new uno.realtime.YJS(ed, options));
    }
    document.body.scrollLeft = 0;
    document.body.scrollTop = 0;
    EN.notification("setupDone", {module:"document"});
    if (DEBUG) {
      updateDebug();
    }
    return true;
  };
  EN.cleanup = function() {
    if (window.ed && goog.isFunction(window.ed.cleanup)) {
      window.ed.cleanup();
    }
    if (ted && goog.isFunction(ted.cleanup)) {
      ted.cleanup();
    }
    if (PM) {
      PM.clear();
    }
    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$13) {
        log.fine(err$13.stack || err$13);
      }
    }
    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 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) {
      return;
    }
    if (window.ed && ed.inEditMode()) {
      goog.dom.classlist.add(endebug, "editmode");
    } else {
      goog.dom.classlist.remove(endebug, "editmode");
    }
    if (window.ed && 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) {
      if (ed.dirty) {
        goog.dom.classlist.add(endebug, "dirty");
      } else {
        goog.dom.classlist.remove(endebug, "dirty");
      }
    }
  }
  uno.api.celogger.wrap(EN);
  (function() {
    var setup = EN.setup;
    EN.setup = function(options) {
      if (purgeLogsOnSetup) {
        consoleLogger.clear();
      }
      return setup(options);
    };
  })();
  window.enLoadState = "didLoad";
  goog.events.listenOnce(document, "DOMContentLoaded", function(e) {
    EN.notification("ready");
  });
})();

