/*
 * Ephox EditLive! JavaScript Library
 * Copyright (c) 1999-2011 Ephox Corp. All rights reserved.
 * This software is provided "AS IS," without a warranty of any kind.
 *
 * Version: 7.6.0.73
 */
 
(function(e){var f={};var d=function(j,l){var k=l.split(".");for(var i=0;i<k.length;i++){var h=k[i];if(j[h]==undefined){j[h]={}}j=j[h]}return(j)};var b=function(){return function(h){if(this instanceof arguments.callee){if(typeof this.initialize=="function"){this.initialize.apply(this,h.callee?h:arguments)}}else{return(new arguments.callee(arguments))}}};var c=function(m,l,h,i){var k=d(e,m);k._namespace=m;k._private={};k._moduleVersion=1;var j=[k,k._private].concat(i||[]);h.apply(e,j);f[m]=h};var g=function(j){var h=f[j];var i={_private:{}};return function(){var k=Array.prototype.slice.call(arguments);var l=[i,i._private].concat(k);h.apply(e,l);return i}};var a=function(i,h){return g(i).apply(e,h)};c("Ephox.core.module",[],function(h){h.addNamespace=d;h.createObject=b;h.define=c;h.getDefinition=g;h.mock=a})})(this);Ephox.core.module.define("Ephox.core.include",[],function(f){f.require=function(l,m,k){c(l,m,j);if(k!==undefined){c(l,k,j)}};f.requireModules=f.require;f.requireStylesheets=function(k,l){c(k,l,b)};f.requireComponentStylesheets=function(u,m,s){var q=a("javascriptcore",document)+"/javascriptcore_css.js";var o=a(u,document);var r=(m==="")?"":"/"+m;var n=o+r;var k="";for(var p=0;p<s.length;p++){var l=(p!==s.length-1)?",\n        ":"";k+='"'+s[p]+'"'+l}var t='<script type="text/javascript">\n  (function() { \n    Ephox.core.utility.httpRequest("${javascriptcore_css}", "text/javascript", function(data) {\n      eval(data);\n      Ephox.core.css.processCssUrls(\n        "${absoluteBasePathname}",\n        [\n          ${cssUrls}\n        ]\n      );\n    });\n  })();\n<\/script>';document.write(i(t,{javascriptcore_css:q,absoluteBasePathname:n,cssUrls:k}))};function i(l,k){return l.replace(/\${([^{}]*)}/g,function(o,m){var n=k[m];return typeof n==="string"||typeof n==="number"?n:o})}function c(l,o,k){var n=a(l,document);var m=d(n,o,k);document.write(m)}function e(l){var k=l.lastIndexOf("/");if(k==-1){return(l)}return(l.substring(k+1))}function g(l){var k=l.lastIndexOf("/");if(k==-1){return("")}return(l.substring(0,k))}function h(k){return(k.getElementsByTagName("script"))}function a(t,r){var l=t+".js";var m=h(r);var p;var s=0;for(var q=0;q<m.length;q++){var k=m[q].src;if(k&&e(k)===l){p=g(k);s++}}if(s==0){var o="Ephox.core.include.getBase(): Couldn't find: "+l;throw new TypeError(o)}else{if(s>1&&t!=="javascriptcore"){var n="Ephox.core.include.getBase(): More than one match for: "+l+", project name used by more than one file";throw new TypeError(n)}}return p}function j(k){return'<script type="text/javascript" src="'+k+'"><\/script>\n'}function b(k){return'<link rel="stylesheet" type="text/css" href="'+k+'"></link>\n'}function d(p,q,k){var o="";for(var m=0;m<q.length;m++){var n=q[m];var l=n.indexOf("/")===0?n:p+"/"+n;o+=k(l)}return(o)}});Ephox.core.module.define("Ephox.core.css.StyleResolver",[],function(a){a.namespaceToCssNs=function(b){return b.replace(/\./g,"-")};a.prependCssNamespace=function(c,b){return c+"-"+b};a.create=function(c){var d=a.namespaceToCssNs(c);var b=function(e){return a.prependCssNamespace(d,e)};return{resolve:b}}});Ephox.core.module.define("Ephox.core.utility",[],function(a){a.appendStyleTag=function(d){var e=document.createElement("style");e.setAttribute("type","text/css");if(e.styleSheet){e.styleSheet.cssText=d}else{var f=document.createTextNode(d);e.appendChild(f)}var c=document.getElementsByTagName("head")[0];c.appendChild(e)};a.httpRequest=function(d,f,h,c){var g=b();g.open("GET",d,true);g.setRequestHeader("Accept",f||"*/*");g.send(null);g.onreadystatechange=function(){if(g.readyState==4){e(g,h,c)}};function e(j,k,i){if(j.status>=200&&j.status<300){k(j.responseText,j.getResponseHeader("Last-Modified"))}else{if(typeof(i)==="function"){i(j.status,d)}}}};var b=function(){if(window.XMLHttpRequest){return new (XMLHttpRequest)}else{try{return new (ActiveXObject)("MSXML2.XMLHTTP.3.0")}catch(c){throw"Ephox.core.utility.getXMLHttpRequest(): browser doesn't support XMLHttpRequest"}}}});
Ephox.core.module.define("Ephox.Violin",[],function(f){f.supplant=function(k,i){function j(l){var m=typeof l;return m==="string"||m==="number"}return k.replace(/\${([^{}]*)}/g,function(m,l){var n=i[l];return j(n)?n:m})};function b(k,j,l){if(j===""){return true}if(k.length<j.length){return false}var i=k.substr(l,l+j.length);return i===j}function h(j,l){var m=[];for(var k=0;k<j.length;k++){m.push(l(j[k]))}return m}function e(i){return function(){var j=h(arguments,function(k){return typeof k==="string"?k.toLowerCase():k});return i.apply(this,j)}}f.startsWith=function(j,i){return b(j,i,0)};f.startsWithIgnoringCase=e(f.startsWith);f.endsWith=function(j,i){return b(j,i,j.length-i.length)};f.endsWithIgnoringCase=e(f.endsWith);f.first=function(j,i){return j.substr(0,i)};f.last=function(j,i){return j.substr(j.length-i,j.length)};function g(i,j){return function(l,k){return i.call(f,l,k)?j.call(f,l,l.length-k.length):l}}f.removeLeading=g(f.startsWith,f.last);f.removeTrailing=g(f.endsWith,f.first);function a(j,i){return j+i}function d(j,i){return i+j}function c(i,j){return function(l,k){return i.call(f,l,k)?l:j(l,k)}}f.ensureLeading=c(f.startsWith,d);f.ensureTrailing=c(f.endsWith,a);f.trim=function(i){return i.replace(/^\s+|\s+$/g,"")};f.lTrim=function(i){return i.replace(/^\s+/g,"")};f.rTrim=function(i){return i.replace(/\s+$/g,"")};f.contains=function(j,i){return j.indexOf(i)!=-1};f.containsIgnoringCase=e(f.contains);f.htmlEncodeDoubleQuotes=function(i){return i.replace(/\"/gm,"&quot;")};f.equals=function(j,i){return j===i};f.equalsIgnoringCase=e(f.equals);f.head=function(i){if(i===""){throw"head on empty string"}return i.substr(0,1)};f.toe=function(i){if(i===""){throw"toe on empty string"}return i.substr(i.length-1,i.length)};f.tail=function(i){if(i===""){throw"tail on empty string"}return i.substr(1,i.length-1)};f.torso=function(i){if(i===""){throw"torso on empty string"}return i.substr(0,i.length-1)};f.capitalize=function(k){if(k===""){return k}var j=f.head(k);var i=f.tail(k);return j.toUpperCase()+i}});
Ephox.core.module.define("Ephox.PlatformDetection.Core.Fn",[],function(a,c){var b=function(h,g,e){for(var f=0;f<h.length;f++){var d=h[f];if(e(d,f,h)){return d}}return g};a.findOneInArrayOr=b});Ephox.core.module.define("Ephox.PlatformDetection.Core.Result",[],function(b,c){var a=function(f,h,e){var g=Ephox.PlatformDetection.Core.GetterHelper.attachGetters;var d={};d.current=h;d.version=e;g(d,d.current,f);return d};b.create=a});Ephox.core.module.define("Ephox.PlatformDetection.Core.GetterHelper",[],function(b,d){var a=function(e){return function(){return e}};var c=function(g,h,e){for(var f=0;f<e.length;f++){g["is"+e[f].name]=a(e[f].name===h)}};b.getter=a;b.attachGetters=c});Ephox.core.module.define("Ephox.PlatformDetection.Core.SpecTester",[],function(b,c){var a=function(d,e){var g=typeof d;if(g==="boolean"){return !!d}else{if(g==="object"){var f=d.minimum;return e.major>f.major||(e.major===f.major&&e.minor>=f.minor)}}throw ("invalid spec")};b.meetsSpec=a});Ephox.core.module.define("Ephox.PlatformDetection.Core.UaStringDetector",[],function(b,c){var a=function(e,g){var f=Ephox.PlatformDetection.Core.Fn.findOneInArrayOr;var d=String(g).toLowerCase();return f(e,{name:undefined},function(h){return h.search(d)})};b.detect=a});Ephox.core.module.define("Ephox.PlatformDetection.Core.SearchInfo",[],function(f,g){var d=Ephox.Violin.contains;var a=function(h){return function(i){return d(i,h)}};var e=function(){try{var h=new ActiveXObject("ChromeTab.ChromeFrame");return !!h}catch(j){return false}};var c=/.*?version\/\ ?([0-9]+)\.([0-9]+).*/;var b=function(i){var h=[{name:"ChromeFrame",versionRegexes:[/.*?chromeframe\/([0-9]+)\.([0-9]+).*/,c],search:function(k){return d(k,"chromeframe")?i():false}},{name:"Chrome",versionRegexes:[/.*?chrome\/([0-9]+)\.([0-9]+).*/,c],search:function(k){return d(k,"chrome")&&!d(k,"chromeframe")}},{name:"IE",versionRegexes:[/.*?msie\ ?([0-9]+)\.([0-9]+).*/],search:function(k){var l=d(k,"msie");var m=d(k,"chromeframe");return m?l&&!i():l}},{name:"Opera",versionRegexes:[c,/.*?opera\/([0-9]+)\.([0-9]+).*/],search:a("opera")},{name:"Firefox",versionRegexes:[/.*?firefox\/\ ?([0-9]+)\.([0-9]+).*/],search:a("firefox")},{name:"Safari",versionRegexes:[c],search:a("safari")}];var j=[{name:"Windows",search:function(k){return d(k,"win")}},{name:"iOS",search:function(k){return d(k,"iphone")||d(k,"ipad")}},{name:"OSX",search:function(k){return d(k,"os x")}},{name:"Linux",search:function(k){return d(k,"linux")}},{name:"Solaris",search:function(k){return d(k,"sunos")}}];return{browsers:h,oses:j}};f.create=b;f.chromeFrameChecker=e});Ephox.core.module.define("Ephox.PlatformDetection.Core.Platform",[],function(a){a.create=function(d,b,c){return{browser:{current:d,version:b},os:{current:c}}}});Ephox.core.module.define("Ephox.PlatformDetection.Core.VersionDetector",[],function(b,c){var a=function(f,g){function d(k,m){for(var l=0;l<k.length;l++){var j=k[l];if(j.test(m)){return j}}return undefined}function i(j,k){var l=d(j,k);if(!l){return{major:0,minor:0}}var m=function(n){return Number(k.replace(l,"$"+n))};return{major:m(1),minor:m(2)}}var h=String(g).toLowerCase();var e=f.versionRegexes;if(!e){return{major:0,minor:0}}return i(e,h)};b.detectVersion=a});Ephox.core.module.define("Ephox.PlatformDetection",[],function(e,l){var a=Ephox.PlatformDetection.Core.SearchInfo;var j=Ephox.PlatformDetection.Core.VersionDetector.detectVersion;var g=Ephox.PlatformDetection.Core.Result.create;var h=Ephox.PlatformDetection.Core.SpecTester.meetsSpec;var i=Ephox.PlatformDetection.Core.UaStringDetector.detect;var k=Ephox.PlatformDetection.Core.Platform;var c=function(o,p,n,m){return !!(o[p])&&!!(o[p][n])&&h(o[p][n],m)};var f=function(n,m){var o=m.browser;var p=m.os;return c(n,p.current,o.current,o.version)};var d=function(y,n){var r=a.create(n);var p=r.browsers;var x=r.oses;var q=i(x,y);var s=q.name;var t=i(p,y);var u=t.name;var w=j(t,y);var v=g(x,s,undefined);var o=g(p,u,w);var m=function(z){return c(z,s,u,w)};return{browser:o,os:v,isSupported:m}};var b=function(){return d(navigator.userAgent,a.chromeFrameChecker)};e.Platform=k;e.detect=b;l.doDetect=d;e.isSupported=c;e.isSupportedPlatform=f});Ephox.platformDetection=Ephox.PlatformDetection;
(function(){var c=(function(){return this})();var b=(c.TheDLibrary!==undefined)?c.TheDLibrary:undefined;var a={};function d(g){if(g&&g.isEphoxDWrapper){return g}var f=d.typeOf(g);var e=d.factories[f];if(!e){d.error("unable to wrap: "+g)}return e.create.apply(e,arguments)}d.global=c;c.TheDLibrary={D:d,oldD:b}})();(function(i){i.$A=function(r){var w=Array.prototype.slice;var v=w.call(arguments,1);return w.apply(r,v)};i.toString=function(){return"TheDLibrary.D"};function l(v,r){if(!v.hasOwnProperty(r)){v[r]={}}return v[r]}function u(w,y){if(y.length==0){return w}var v=y[0];var r=y.slice(1);var x=l(w,v);return u(x,r)}i.namespace=function(r){var v=r.split(".");return u(i.global,v)};i.cloneObject=function(x){var w={};for(var v in x){if(x.hasOwnProperty(v)){w[v]=x[v]}}return w};i.flag=function(r){r.isEphoxDWrapper=true};i.factories={};i.object=function t(v){function r(){}r.prototype=v;return new r()};i.createWithDefaults=function(x,v,w){var r=x.create.apply(x,v);i(w).each(function(y,z){r[z]=r[z]||y});return r};i.Curriers={};i.Curriers.partial=function(x,w){var A=[];for(var v=0,y=0;v<x.length||y<w.length;v++){function z(){if(x[v]!==undefined){return x[v]}return w[y++]}A.push(z())}return A};i.Curriers.thai=function(v,r){var y=r[0];var x=v;var w=r.length>1?r.slice(1):[];return[y].concat(x).concat(w)};var d=function(v){var w=v.slice();w.reverse();return w};i.Curriers.stirFry=function(v,r){return r.concat(d(v))};i.Curriers.curry=function(v,r){return v.concat(r)};i.Curriers.satay=function(v,r){return r.concat(v)};i.mixin=function(w,r){for(var v in w){if(w.hasOwnProperty(v)&&typeof w[v]==="function"){r[v]=r[v]||i(w[v]).curry(r)}}};i.mixinToPrototype=function(y,w){var z=w.prototype;function v(A){return i(function(B){return A.apply(y,[this].concat([B]))})}function r(A,B){if(!z[B]||!z[B].isEphoxDWrapper){z[B]=v(A)}}for(var x in y){if(y.hasOwnProperty(x)){r(y[x],x)}}};i.mixinFunctionStyle=function(y,w){var z=w.prototype;function v(A){return i(function(){var B=i.$A(arguments);return A.apply(y,[this].concat(B))})}function r(A,B){if(!z[B]||!z[B].isEphoxDWrapper){z[B]=v(A)}}for(var x in y){if(y.hasOwnProperty(x)){r(y[x],x)}}};i.mixinFunctionStyle2=function(x,v){var r=function(y){return function(){var z=i.$A(arguments);return x[y].apply(x,[v].concat(z))}};for(var w in x){if(i.Funk.hasOwnProperty(w)){v[w]=r(w)}}};var a=function(r){return function(w){var v=i.$A(arguments,1);return i(function(){var y=i.$A(arguments);var x=r(v,y);return w.apply(this,x)})}};i.Funk={curry:a(i.Curriers.curry),satay:a(i.Curriers.satay),thaiCurry:a(i.Curriers.thai),stirFry:a(i.Curriers.stirFry),partial:a(i.Curriers.partial)};i.Funk._=i.Funk.curry;i.Funk.on=function(v,r){return i(function(){return v.apply(r,arguments)})};i.Funk.times=function(v,r){i(r).times(v)};i.Funk.unless=function(v,r){if(!r){return v()}};i.Funk.onlyIf=function(v,r){if(r){return v()}};i.Funk.chain=function(w,v){var r=i.$A(arguments);if(r.length===0){return i.identity}if(r.length===1){return i(function(y){return w(y)})}if(r.length===2){return i(function(y){return v(w(y))})}return i.Funk.chain.apply(i.Funk.chain,[i.Funk.chain(w,v)].concat(r.slice(2)))};i.Funk.create=function(v){var r=function(){return v.apply(this,arguments)};i.mixinFunctionStyle2(i.Funk,r);i.flag(r);return r};i.Funk.flip=function(r){return function(w,v){return i(r(v,w))}};i.Funk.once=function(v){var r=false;return function(){if(!r){r=true;return v.apply(this,arguments)}}};i.Funk.thenCallback=function(r){return function(v){r.apply(this,[]);v&&v()}};i.Funk.thenCallbackWithResult=function(r){return function(w){var v=r.apply(this,[]);w&&w(v)}};i.factories["function"]=i.Funk;i.chain=i.Funk.chain;i.runChain=function(r){var v=i.$A(arguments);return i.chain.apply(i.chain,v.slice(1))(r)};i.typeOf=function(r){var v=typeof r;if(r===null){return"null"}if(v==="object"&&Array.prototype.isPrototypeOf(r)){return"array"}return v};i.error=i(function(r){throw i.global.TypeError?new TypeError(r):r});i.noReturn=function(r){return function(){r.apply(this,arguments)}};i.noOp=function(){};i.noop=i.noOp;i.passThrough=i(function(r){return r.apply(this,arguments)});i.Guitar={};var e=i(function(r,v){if(i.typeOf(v)!=="string"){return undefined}return v.substring(0,1)[r]()+v.substring(1)});i.Guitar.capitalize=e.curry("toUpperCase");i.Guitar.uncapitalize=e.curry("toLowerCase");i.invoke=i(function(r,v,w){return w[r].apply(w,v)});i.invoke1=i(function(v,r,w){return i.invoke(v,[r],w)});i.invoke0=i(function(r,v){return i.invoke(r,[],v)});var p=function(x){if(i.typeOf(x)==="string"){return p([x])}if(x.length===0){return i.Optional.none()}var w=i.typeOf(x[0])==="object";var v=w?x[0]:i.global;var r=w?x.slice(1):x;var y=r.join(".");return{pathname:y,parent:v}};var m=function(y){var x=y.pathname.split(".");var w=y.parent;for(var r=0;r<x.length;r++){var v=w[x[r]];if(v){w=v}else{return i.Optional.none()}}return i.Optional.some(w)};i.resolve=i(function(v,r){return i.resolveOpt([r||i.global].concat([v])).someOr(undefined)});i.resolveOpt=i(function(r){var v=p(r);return m(v)});i.resolveOrDie=i(function(v,r){var x=p(v);var w=r||"Could not find: "+x.pathname;return m(x).someOrDie(w)});i.never=i(function(){return false});i.always=i(function(){return true});i.identity=i(function(r){return r});i.fieldEquals=i(function(w,v,r){return r[w]===v});i.isNull=i(function(r){return r===null});i.isUndefined=i(function(r){return r===undefined});i.isNullOrUndefined=i(function(r){return r===null||r===undefined});i.isTruthy=i(function(r){return !!r});i.isFalsy=i(function(r){return !r});var q=function(r){return i(new Function(["a","b"],"return a "+r+" b;"))};i.eq=q("===");i.neq=q("!==");i.add=q("+");i.subtract=q("-");i.multiply=q("*");i.divide=q("/");i.gt=q(">");i.gte=q(">=");i.lt=q("<");i.lte=q("<=");i.prefix=i.add;i.suffix=i(function(v,r){return r+v});i.ifUndefined=function(r,v){return(r===undefined)?v:r};i.set=i(function(w,r){this[w]=r}).curry;i.get=i(function(r){return this[r]}).curry;i.lookup=i(function(r,v){return v[r]});i.getConstant=i.identity.curry;i.augment=i(function(v,r){i(r).each(function(w,y){v[y]=w})});var o=function(r,v){return v};var n=function(r,v){var w=i.typeOf(r)==="object"&&i.typeOf(v)==="object";return w?i.deepMerge(r,v):v};function c(r){return function(){var z=i.$A(arguments);if(z.length==0){i.error("Can't merge zero objects")}var w={};for(var y=0;y<z.length;y++){var v=z[y];for(var x in v){if(v.hasOwnProperty(x)){w[x]=r(w[x],v[x])}}}return w}}i.merge=c(o);i.deepMerge=c(n);i.tabulate=function(z){var v={};for(var x=0;x<z.length;x++){var r=z[x];for(var w in r){if(r.hasOwnProperty(w)){var y=r[w];if(!v.hasOwnProperty(w)){v[w]=[]}v[w][x]=y}}}return v};i.unTabulate=function(w){var v=[];for(var y in w){if(w.hasOwnProperty(y)){var r=w[y];for(var x=0;x<r.length;x++){var z=r[x];v[x]=v[x]||{};v[x][y]=z}}}return v};i.deepMap=i(function(y,x){var w={object:function(){var A={};for(var z in y){if(y.hasOwnProperty(z)){A[z]=i.deepMap(y[z],x)}}return A},array:function(){var A=[];for(var z=0;z<y.length;z++){A[z]=i.deepMap(y[z],x)}return A}};var v=i.typeOf(y);var r=w[v]||x;return r(y)});i.deepClone=i.deepMap.partial(undefined,i.identity);i.wrapMethods=function(v){for(var r in v){if(v.hasOwnProperty(r)&&typeof v[r]==="function"){v[r]=i(v[r])}}};i.Enumerable={};var g=i.Enumerable;g.sink=i(function(w,v){var r=v||w.getSinkType();return r.create()});var b=i(function(z,A,y,v){var x=g.sink(A,v);var w=i(z).curry(x,y);A.each(w);return x});g.map=b.curry(function(y,z,v,w){y.add(z(v,w),w)});g.filter=b.curry(function(y,z,v,w){if(z(v,w)){y.add(v,w)}});g.find=function(w,r){try{g.each(w,function(y,z){if(r(y,z)){throw {key:z,value:y}}})}catch(v){if(typeof v==="object"&&v.hasOwnProperty("key")&&v.hasOwnProperty("value")){return v}throw v}};var j={};j.doReduce=function(y,w,z,x){if(z.length==1){return z[0]}var v=i.Array[y](z);var r=i.Array[w](z);return x(v,j.doReduce(y,w,r,x))};j.makeReducer=i(function(r,y,v,x,w){var z=x.toArray();if(z.length==0){i.error(r+" of empty collection with no initial value")}return j.doReduce(y,v,z,w)}).curry;g.reduce=j.makeReducer("reduce","head","tail");g.reduceRight=j.makeReducer("reduceRight","toe","torso");g.each=i(function(v,r){v.some(i.noReturn(r))});g.forEach=g.each;g.keys=i(function(v){var r=function(w,y){return y};return v.map(r,i.List)});g.values=i(function(r){return r.map(i.identity,i.List)});g.toArray=i(function(r){return g.values(r).toArray()});g.contains=i(function(w,r){var v=i.eq.curry(r);return w.some(v)});g.size=i(function(x){var w=0;var v=function(){w++};g.each(x,v);return w});g.delimit=i(function(w,r){if(w.size()===0){return""}r=r||",";var v=function(y,x){return y+r+x};return g.reduce(w,v)});g.filterByMethod=i(function(w,v,r){return w.filter(function(y){return r(y[v]())})});g.filterByMethodEq=i(function(w,r,v){return g.filterByMethod(w,r,i.eq.curry(v))});var k=function(r){return i(function(v){return Array.prototype.slice.call(v,r)})};i.Array={head:i(function(r){return r[0]}),toe:i(function(r){return r[r.length-1]}),torso:i(function(r){return Array.prototype.slice.call(r,0,r.length-1)}),tail:k(1),clone:k(),prepend:i(function(v,r){return[r].concat(v)}),append:i(function(v,r){return v.concat([r])}),appendArray:i(function(v,r){return v.concat(r)}),prependArray:i(function(v,r){return r.concat(v)}),add:i(function(v,r){v.push(r)}),some:i(function(x,w,v){for(var r=0;r<x.length;r++){if(w.apply(v,[x[r],r,x])){return true}}return false}),each:i(function(x,w,v){for(var r=0;r<x.length;r++){w.apply(v,[x[r],r,x])}}),map:i(function(z,y,w){var x=[];for(var v=0;v<z.length;v++){x[v]=y.apply(w,[z[v],v,z])}return x}),create:i(function(){return[]}),indexOf:i(function(w,v){for(var r=0;r<w.length;r++){if(w[r]===v){return r}}return -1}),sort:i(function(w,r){var v=i.Array.clone(w);v.sort(r);return v}),unital:i(function(r){return[r]}),boxIfNotArray:i(function(r){return i.typeOf(r)==="array"?r:[r]}),flatten:i(function(x){var w=[];for(var v=0;v<x.length;v++){w=w.concat(x[v])}return w}),intersperse:i(function(y,v){var x=[];for(var w=0;w<y.length;w++){x.push(y[w]);if(w<y.length-1){x.push(v)}}return x}),values:k()};i.Array.splitByPredicate=(function(){var r={"true":function(v,w){v.push(w)},"false":function(v,w){if(w.length>0){v.push(w)}}};return i(function(B,w,v){var x=i.Optional.fromUndefined(v).someOr(true);var z=r[String(x)];var y=[];var A=[];i.Array.each(B,function(C){if(w(C)){z(y,A);A=[]}else{A.push(C)}});z(y,A);return y})})();i.Array.contains=function(w,v,r){return i.Array.some(w,i.eq._(v),r)};i.Array.keys=function(r){return i.Array.map(r,function(v,w){return w})};i.Array.repeat=function(v,r){return i(1,r).map(i.getConstant(v)).toArray()};i.Array.merge=function(){var w=i.$A(arguments);var y=[];var z=0;for(var x=w.length-1;x>=0;x--){var v=w[x];for(;z<v.length;z++){y.push(v[z])}}return y};(function(){var r=i(function(w,z,y,v){if(z.length>=y){return i.$A(z)}var x=i.Array.repeat(v,y-z.length);return w(z,x)});i.Array.padRight=r._(i.Array.appendArray);i.Array.padLeft=r._(i.Array.prependArray)})();i.Array.index=i(function(v,x){var w={};i.Array.each(x,function(r){var y=i.typeOf(r);if(y!=="object"){i.error("D.Array.index: elements of array must be objects. Was: "+y)}if(!r.hasOwnProperty(v)){i.error("D.Array.index: one of the elements was missing the key property.")}var A=r[v];var z=i.typeOf(A);if(z!=="string"){i.error("D.Array.index: the value of the key property for one of the elements was not a string. Was: "+z)}w[A]=r});return w});i.Array.indexAndMap=i(function(r,w,v){return i.Object.map(i.Array.index(r,w),v)});i.Array.mapKeyValues=i(function(x,w){var v={};i.Array.each(x,function(r,y,A){var z=w(r,y,A);if(i.typeOf(z)!=="object"){i.error("D.Array.mapToKeyValues: return value was not an object")}if(!z.hasOwnProperty("key")){i.error("D.Array.mapToKeyValues: return value did not have 'key' property")}if(!z.hasOwnProperty("value")){i.error("D.Array.mapToKeyValues: return value did not have 'value' property")}if(i.typeOf(z.key)!=="string"){i.error("D.Array.mapToKeyValues: return value's key was not a string")}v[z.key]=z.value});return v});i.Array.mapToObject=i(function(x,w){var v={};i.Array.each(x,function(r,y,z){v[r]=w(r,y,z)});return v});i.Array.forEach=i.Array.each;i.Array.toArray=i.Array.clone;i.Array.getSinkType=i.getConstant(i.Array);i.List={};i.List.create=function(v){v=v||[];var w=v.slice();var r=i.lookup.thaiCurry(w);r.get=function(x){return w[x]};r.getSinkType=function(){return i.List};r.toArray=function(){return w.slice()};r.toObject=function(){var x={};r.each(function(y,z){x[String(z)]=y});return x};r.add=function(y){w.push(y)};r.some=function(y,x){return i.Array.some(w,function(z,A){return y.apply(x,[z,A,r])},r)};r.indexOf=i.Array.indexOf.curry(w);r.size=function(){return w.length};i.mixin(i.Enumerable,r);i.flag(r);return r};i.factories.array=i.List;i.ConsList=i(function(r){return i.ConsList.nil().consArray(r||[])});i.ConsList.create=i.ConsList;i.ConsList.consArray=i(function(r,w){for(var v=w.length-1;v>=0;v--){r=r.cons(w[v])}return r});i.ConsList.cons=i(function(r,v){var w={};w.cons=i.ConsList.cons.curry(w);w.head=i.getConstant(v);w.tail=i.getConstant(r);w.size=i.getConstant(r.size()+1);w.toString=i.getConstant(v+" : "+r.toString());w.consArray=i.ConsList.consArray.curry(w);w.isEmpty=i.getConstant(false);w.fold=i(function(y,A){var z=y;var x=w;while(!x.isEmpty()){z=A(z,x.head());x=x.tail()}return z});w.foldRight=i(function(x,y){return y(r.foldRight(x,y),v)});w.toArray=i(function(){var x=[];while(!w.isEmpty()){x.push(w.head());w=w.tail()}return x});w.filter=i(function(x){return w.foldRight(i.ConsList.nil(),function(z,y){return x(y)?z.cons(y):z})});return w});i.ConsList.nil=i(function(){var r={};r.cons=i.ConsList.cons.curry(r);r.head=i.error.curry("head called on D.ConsList.nil");r.tail=i.error.curry("tail called on D.ConsList.nil");r.size=i.getConstant(0);r.toString=i.getConstant("[] - D.ConsList");r.consArray=i.ConsList.consArray.curry(r);r.toArray=i(function(){return[]});r.isEmpty=i.getConstant(true);r.fold=i(function(v,w){return v});r.foldRight=r.fold;r.filter=i.ConsList.nil;return r});i.Object={};i.Object.some=i(function(x,w,v){v=v||x;for(var r in x){if(x.hasOwnProperty(r)){if(w(x[r],r,v)){return true}}}return false});i.Object.each=i(function(v,r){i.Object.some(v,i.noReturn(r))});i.Object.forEach=i.Object.each;i.Object.map=i(function(z,y,w){var x={};w=w||z;for(var v in z){if(z.hasOwnProperty(v)){x[v]=y(z[v],v,w)}}return x});function s(v,r){return v===r?0:v>r?1:-1}i.Object.fieldComparator=i(function(r){return function(w,v){var y=w[r];var x=v[r];return s(y,x)}});i.Object.fieldOrGetterComparator=i(function(r){return function(w,v){var y=i.evalFieldOrGetter(w,r);var x=i.evalFieldOrGetter(v,r);return s(y,x)}});i.Object.filter=i(function(z,w){var v={};for(var y in z){if(z.hasOwnProperty(y)){var r=z[y];if(w(r,y,z)){v[y]=r}}}return v});i.Object.narrow=i(function(r,w){var v=i(w).contains;return i.Object.filter(r,function(y,z){return v(z)})});i.Object.flip=i(function(v){var w={};i.Object.each(v,function(r,y){if(w.hasOwnProperty(r)){i.error("Object was not 1:1 - duplicate value found: "+r)}w[r]=y});return w});i.Hash={};i.Hash.create=function(r){r=r||{};var w=i.cloneObject(r);var v=i.lookup.thaiCurry(w);v.getSinkType=function(){return i.Hash};v.toObject=function(){return i.cloneObject(w)};v.add=function(y,A){var z=i.typeOf(A);if(z!=="string"){i.error("D.Hash only allows string keys. Key type was: "+z)}w[A]=y};v.get=function(x){return w[x]};v.remove=function(x){delete w[x]};v.put=function(y,x){v.add(x,y)};v.some=i.Object.some.partial(w,undefined,v);v.containsKey=function(y){return w.hasOwnProperty(y)};v.toParallelArrays=function(){var x=v.keys().toArray();var y=v.values().toArray();return{keys:x,values:y}};v.toArray=i(function(){var y=[];for(var x in w){if(w.hasOwnProperty(x)){y.push(w[x])}}return y});i.mixin(i.Enumerable,v);i.flag(v);return v};i.Hash.fromParallelArrays=function(r,v){var x=i.Hash.create();function w(y,z){x.add(v[z],y)}i(r).each(w);return x};i.factories.object=i.Hash;i.Range={};i.Range.create=function(w,r){if(typeof r!=="number"){r=w;w=1}var v={};v.getSinkType=function(){return i.List};v.some=function(z){for(var y=w;y<=r;y++){if(z(y,y-w)){return true}}return false};i.mixin(i.Enumerable,v);v.times=v.each;v.toList=function(){return v.map(i.identity)};v.toArray=function(){return v.toList().toArray()};v.size=function(){return Math.max(0,r-w+1)};i.flag(v);return v};i.factories.number=i.Range;i.invasiveMode=function(){i.isInvasiveMode=true;i.mixinToPrototype(i.Array,Array);i.mixinToPrototype(i.Enumerable,Array);i.mixinFunctionStyle(i.Funk,Function)};function h(r){return"get"+i.Guitar.capitalize(r)}function f(v){var r="get".length;var w=v.substring(r);return i.Guitar.uncapitalize(w)}i.getterize=i(function(y){var x={};for(var w in y){if(y.hasOwnProperty(w)){var v=h(w);x[v]=i.getConstant(y[w])}}return x});i.ungetterize=i(function(y){var x={};for(var w in y){if(y.hasOwnProperty(w)){var v=f(w);x[v]=y[w]()}}return x});i.evalFieldOrGetter=i(function(v,w){var r=h(w);return v.hasOwnProperty(r)?v[r]():v[w]});i.simpleFactory=i(function(){var r=i.$A(arguments);return i(function(){var v=i.$A(arguments);return i.Hash.fromParallelArrays(r,v).toObject()})});i.keyValue=i.simpleFactory("key","value");(function(){var w={};w.some=function(y){var z=i.getConstant(y);var A=function(B){B(y)};return{isSome:i.always,isNone:i.never,someOr:z,someOrDie:z,fold:function(B,C){return B(y)},map:function(B){return w.some(B(y))},bind:function(B){return B(y)},join:z,toNull:z,someOrNull:z,someOrUndefined:z,toString:function(){return"D.Optional.some("+y+")"},each:A,forEach:A}};var r={};var v=i.getConstant(r);r.isSome=i.never;r.isNone=i.always;r.someOr=i.identity;r.someOrDie=function(y){i.error(y||"someOrDie called on D.Optional.none")};r.fold=function(y,z){return z()};r.map=v;r.bind=v;r.join=v;r.toNull=i.getConstant(null);r.someOrNull=i.getConstant(null);r.someOrUndefined=i.getConstant(undefined);r.toString=i.getConstant("D.Optional.none()");r.each=i.noOp;r.forEach=r.each;w.none=v;var x=i(function(z,y){return z(y)?r:w.some(y)})._;w.fromNull=x(i.isNull);w.fromUndefined=x(i.isUndefined);w.fromNullOrUndefined=x(i.isNullOrUndefined);w.fromFalsy=x(i.isFalsy);w.getProperty=function(y,z){return w.fromUndefined(y[z])};w.ifMatches=i(function(y,z){return z(y)?w.some(y):w.none()});w.yoda=i(function(z){try{return w.some(z())}catch(y){return r}});i.Optional=w})();(function(v,r){v.noConflict=function(){var w=v.global;w.TheDLibrary=r.oldD;return v}})(TheDLibrary.D,TheDLibrary);i.method=i(function(v,r){return i(function(){return v[r].apply(v,arguments)})});i.getPropertyOr=function(w,r,v){return w.hasOwnProperty(r)?w[r]:v};i.isType=i(function(v,r){return i.typeOf(r)===v});i.isTypeOneOf=i(function(v,r){return i.Array.contains(v,i.typeOf(r))});i.asTypeOpt=i(function(v,r){return i.Optional.ifMatches(r,i.isType._(v))});i.asTypeOneOfOpt=i(function(v,r){return i.Optional.ifMatches(r,i.isTypeOneOf._(v))});i.asFunctionOpt=i.asTypeOpt._("function");i.asStringOpt=i.asTypeOpt._("string");i.asObjectOpt=i.asTypeOpt._("object");i.asArrayOpt=i.asTypeOpt._("array");i.asNumberOpt=i.asTypeOpt._("number");i.asNullOpt=i.asTypeOpt._("null");i.asUndefinedOpt=i.asTypeOpt._("undefined");i.asBooleanOpt=i.asTypeOpt._("boolean");i.resolveFunctionOpt=function(r){var v=function(w){return i.resolveOpt(w).bind(i.asFunctionOpt)};return i.asTypeOneOfOpt(["string","array"],r).fold(v,i.asFunctionOpt._(r))};i.resolveFunction=function(r){return i.resolveFunctionOpt(r).someOrUndefined()}})(TheDLibrary.D);
Ephox.core.module.define("Ephox.CallbackGlobaliser",[],function(a,c,b){a.install=function(f){var i="callback_";var g=f+".callbackRefs";var h=b.resolve(f);var e=0;var k=function(){var n=e;e++;return n};var d=function(){return i+k()};var m=function(n){delete h.callbackRefs[n]};var l=b(function(p,q){var o=b.resolveFunctionOpt(q).someOrDie("invalid function: "+q);var n=d();h.callbackRefs[n]=function(){p(n);o.apply(null,arguments)};return g+"."+n});var j=function(n){m(n.substring(n.lastIndexOf(".")+1))};h.callbackRefs={};h.register=l._(m);h.registerPermanent=l._(b.noOp);h.unregister=j}},[TheDLibrary.D]);
function EditLiveJava(name, width, height) {
	this.params = {};
	this.overwrittenSubmit = false;
	this.width = width;
	this.height = height;
	this.name = name;
	this.borderStyle = "";
	this.autoSubmit = true;
	this.extraJars = [];
	this.pluginUrls = [];
	this.pluginText = [];
	this.pluginBases = [];
	this.classNames = "";
	this.preload = false;
	this.forceUseTextArea = false;
	this.setFocusOnLoad(false); // default to false for normal editing
	this.started = false;
	this.textAreaRows = 17;
	this.textAreaCols = 55;
	this.cookie = false;

	this.state = EditLiveJava.EditorStates.create();

	this.preloadInstanceLoaded = false;

	EditLiveJava.registerInstance(this);
}
(function() {
	var V = Ephox.Violin;

	EditLiveJava.StringUtils = {

		delimit : function(myArray, delimiter) {
			return Array.prototype.join.call(myArray, delimiter);
		},

		stripTag: function(string, originalDiv, tag) {
			var tagIndex = string.indexOf('<' + tag + '>');
			if (tagIndex != -1) {
				var lowerCase = string.toLowerCase();
				tagIndex = lowerCase.indexOf('>', tagIndex) + '>'.length;
				return Ephox.Violin.trim(string.substring(tagIndex, lowerCase.indexOf("</" + tag + '>', tagIndex)));
			} else {
				return string;
			}
		},

		// FIX Move - this is a file path manipulation, not general string manipulation.
		removeDotSlashes : function(sDir) {
			var ret = sDir.replace(/^(\.\/)+/, "");
			return ret.replace(/\/(\.\/)+/g, "/");
		},

		// FIX Move. This is to do with CSS, not strings.
		toCSSLength : function(size) {
			if (isNaN(Number(size))) {
				return size;
			} else {
				return size + "px";
			}
		},

		ensureTrailingSlash : function(input) {
			return V.ensureTrailing(input, "/");
		}
	};
})();
EditLiveJava.URLUtils = {

	/**
	 * This function is a regular combineURL but to make life easier it uses
	 * window.location.href as the absolute URL so we can use things like
	 * window.location.host instead of writing those functions somewhere else.
	 */
	combineDownloadURL : function(sDirectory) {
		var sDir = EditLiveJava.URLUtils.combineDownloadURLBase (sDirectory, window.location);
		return EditLiveJava.StringUtils.removeDotSlashes(sDir);
	},

	/**
	 * It's important that window.location is passed in - we pass in a fake one
	 * in unit tests. Please do not refer directly to window.location within
	 * this function.
	 */
	combineDownloadURLBase : function(sDirectory, windowLocation) {
		if (Ephox.Violin.contains(sDirectory, " ")) {
			sDirectory = encodeURI(sDirectory);
		}

		var relURL = EditLiveJava.StringUtils.removeDotSlashes(sDirectory);

		// every other reference in this file assumes downloadDirectory has no
		// trailing "/". Rather than try to fix everywhere else, we'll just
		// rip out the trailing "/" if it is there.

		if (relURL.charAt(relURL.length - 1) == "/" && relURL != "/") {
			relURL = relURL.substr(0, relURL.length - 1);
		}

		// if relURL is absolute, forget about combining
		if (relURL.indexOf("://") !== -1) {
			return relURL;
		}

		// we only want the path of the URL.
		var absURL = EditLiveJava.URLUtils.removeFilename(windowLocation.href);

		// Safari gives us un-encoded URLs with spaces in it, but chokes if we
		// try to load an applet with spaces in the path.
		if (Ephox.Violin.contains(absURL, " ")) {
			// ok, it's got a space in it - probably hasn't been URI-encoded.
			// Let's encode it.
			absURL = encodeURI(absURL);
		}

		// remove trailing slash from absURL
		if (absURL.charAt(absURL.length - 1) == "/") {
			absURL = absURL.substr(0, absURL.length - 1);
		}

		// do the combining work
		var curChar = relURL.charAt(0);
		if (curChar === '/') {
			// relative to hostname
			return windowLocation.protocol + "//" + windowLocation.host + relURL;
		} else if (curChar === ".") {
			// relative to absolute path
			var sOldURL;
			// cycle through relURL ripping directories off the absURL as we
			// go up
			while(relURL.substr(0,3) == "../") {
				sOldURL = absURL;
				absURL = absURL.substring(0, absURL.lastIndexOf('/'));
				relURL = relURL.substr(relURL.indexOf('/') + 1);
				// if the final two chars are "//" then the relative
				// URL goes back too many folders, undo the previous rip
				if (absURL.charAt(absURL.lastIndexOf('/') - 1) == ':') {
					absURL = sOldURL;
				}
			}
			return absURL + "/" + relURL;
		} else {
			// is a subdir of the current dir
			return absURL + "/" + relURL;
		}
	},

	/** get the main path of the URL, minus the xx.htm etc */
	removeFilename : function(sURL) {
		var lastSlash = sURL.lastIndexOf('/');
		if (sURL.lastIndexOf('.') > lastSlash) {
			return sURL.substring(0, lastSlash + 1);
		} else {
			return sURL;
		}
	}
};

// FIX 31445 Add translations and a resolution mechanism
EditLiveJava.i18n = {
	messages : {
		DefaultCrashAction: {
			message1: "Oh no! EditLive! has experienced an issue and has closed.",
			message2: "Please select an option to continue:",
			optionNew: "Open a blank document",
			optionRevert: "Revert back to originally-opened content",
			optionAutosavePrompt: "View list of autosaved documents (if available)",
			optionAutosaveLatest: "Revert to most recent autosave (if available)"
		}
	}
};
this.Ephox = this.Ephox || {};
(function() {
	EditLiveJava.D = TheDLibrary.D.noConflict();
	
	EditLiveJava.CallbackManager = {};
	Ephox.CallbackGlobaliser.install("EditLiveJava.CallbackManager");
})();
(function() {

	// A "passive" state machine. It stores the state and validates transitions, but the actions are managed externally.

	// transitions e.g.
	// { "a" : ["b", "c"]
	//   "b" : []
	// }
	var create = function(transitions, initialState) {

		var cur = initialState;

		var getCurrent = function() {
			return cur;
		};

		var canChange = function(newState) {
			var t = transitions[cur];
			return t && D.Array.contains(t, newState);
		};

		var changeOrNoOp = function(newState) {
			var c = canChange(newState);
			if (c) {
				//noinspection ReuseOfLocalVariableJS
				cur = newState;
			}
			return c;
		};

		var change = function(newState) {
			if (!change(newState)) {
				throw "Invalid state change: [" + cur + "] -> [" + newState + "]";
			}
		};

		var changeWithHandlerOrNoOp = function(newState, f) {
			if (changeOrNoOp(newState)) {
				f();
			}
		};

		var changeWithHandler = function(newState, f) {
			if (change(newState)) {
				f();
			}
		};

		return {
			getCurrent: getCurrent,
			canChange: canChange,
			change: change,
			changeOrNoOp: changeOrNoOp,
			changeWithHandler: changeWithHandler,
			changeWithHandlerOrNoOp: changeWithHandlerOrNoOp
		};
	};

	EditLiveJava.StateMachine = {
		create: create
	};
})();
(function() {
	// Wraps a StateMachine, adding metadata information for each state

	var D = EditLiveJava.D;

	var states = {
		"closed" : ["opening"],
		"opening": ["open", "crashed"],
		"open"   : ["closing"],
		"crashed": ["opening"]
	};

	var makeProp = function() {
		return {};
	};

	var props = {
		"closed" : makeProp(),
		"opening": makeProp(),
		"open"   : makeProp(),
		"crashed": makeProp()
	};

	var create = function() {
		var sm = EditLiveJava.StateMachine.create(states, "closed");

		var curStateProps = function() {
			return props[sm.getCurrent()];
		};

		return D.merge(sm, {
			curStateProps: curStateProps
		});
	};

	EditLiveJava.EditorStates = {
		create: create
	};
})();
(function() {

    var StringUtils = EditLiveJava.StringUtils;
    var URLUtils = EditLiveJava.URLUtils;
	var delimit = StringUtils.delimit;
	var D = EditLiveJava.D;

    var setParamFn = function(propertyName) {
        return function(x) {
            this.params[propertyName] = x;
        }
    };

    var runCustomActionFn = function(actionName) {
        return function(actionValue) {
            this.runCustomAction(actionName, actionValue);
        };
    };

    var prototype = {

        // instance methods - do not add data fields here

        /** @deprecated */
        setUseWebDAV : D.noOp,

        /** @deprecated */
        setUseMathML : D.noOp,

        getAppletName : function() {
            return this.name + "_elj";
        },

        getApplet : function() {
            return EditLiveJava.getAppletWithName(this.getAppletName());
        },

        runCustomAction : function(action, value) {
            var that = this;
            var callback = function() {
                that.doCustomAction(action, value);
            };
            EditLiveJava.doSetTimeout(callback, 10);
        },

        doCustomAction : function(action, value) {
            var appletName = this.getAppletName();
            if (EditLiveJava.useLiveConnect && EditLiveJava.supportsLiveConnect(appletName)) {
                var applet = this.getApplet();
                if (applet) {
                    applet.performCustomAction("customaction:" + action + ":" + value);
                }
            } else {
                var params = {
                    "CustomAction" : "customaction:" + action + ":" + value,
                    "CustomActionTarget" : appletName,
                    "CustomActionPageID" : EditLiveJava.pageID
                };
                this.runPostApplet(params);
            }
        },

        getParam : function(name) {
            return D.getPropertyOr(this.params, name, "");
        },

        addCombinedParameter : function(paramName, pluginValues) {
            this.addParam(paramName, pluginValues.join("|"));
        },

        /** Adds an applet parameter.
         *  @return true if parameter did not already exist
         */
        addParam : function(name, value) {
            var found = this.params.hasOwnProperty(name);
            this.params[name] = value;
            return !found;
        },

        addParamOrRaiseCustomAction : function(value, paramName, customActionName) {
            if (this.started) {
                this.runCustomAction(customActionName, value);
            } else {
                this.addParam(paramName, value);
            }
        },

        getHiddenFields : function() {
            return [this.name, this.name + "_styles"];
        },

		getHiddenFieldsHtml : function() {
			var s = "";
			D.Array.each(this.getHiddenFields(), function(x) {
				s += Ephox.Violin.supplant('<input name="${x}" id="${x}" type="hidden" />', {x: x});
			});
			return s;
		},

		getHiddenFieldsHtmlIfRequired : function() {
			return (!this.useTextArea() && this.autoSubmit) ? this.getHiddenFieldsHtml() : "";
		},

        getOnInitComplete : function() {
            return this.getParam("onInitComplete");
        },

        getOnInitCompleteParams : function() {
            return this.getParam("onInitCompleteParams").split("|");
        },

        // Load-time API methods

        addJar : function(jarUrl, className) {
            this.extraJars[this.extraJars.length] = URLUtils.combineDownloadURL(jarUrl);
            this.classNames += className + " ";
        },

        addPlugin : function(pluginUrl) {
            this.pluginUrls[this.pluginUrls.length] = pluginUrl;
        },

        addPluginAsText : function(pluginText, pluginBaseUrl) {
            this.pluginText[this.pluginText.length] = pluginText;
            if (pluginBaseUrl === undefined) {
                pluginBaseUrl = "%"; // We use % to indicate that no URL was specified since it cannot ever appear by itself in a URL.
            }
            this.pluginBases[this.pluginBases.length] = pluginBaseUrl;
        },

        focus : function() {
            var applet = this.getApplet();
            if (applet) {
                applet.focus();
            }
        },

        getAppletWrapper : function() {
            return document.getElementById(this.name + "_appletWrapper");
        },

        getVersion : D.getConstant('7.6.0.73'),

        setAutoSubmit : function(val) {
            this.autoSubmit = val;
        },

        setBaseURL : setParamFn("EphoxBaseURL"),

        setBody : function(src) {
            this.addParamOrRaiseCustomAction(src, "Body", "setbody");
        },

        setBorderStyle : function(style) {
            this.borderStyle = style;
        },

        setCookie : function(cookie_) {
            if (this.started) {
                return false;
            }
            if (cookie_ !== "") {
                this.cookie = true;

                var docCookie = document.cookie;
                if (cookie_ != docCookie && docCookie.length > 0) {
                    cookie_ = docCookie + ";" + cookie_;
                }
                this.addParam("Cookie", cookie_);
            }
        },

        setCommentTemplate : setParamFn("commentTemplate"),

        setCrashAction : function(text, f) {
            var ref = EditLiveJava.CallbackManager.registerPermanent(f);
            this.addParam("crashActionFunction", ref);
			this.addParam("crashActionText", text);
        },

        setDirection : function(direction) {
            this.addParamOrRaiseCustomAction(direction, "Direction", "setdirection");
        },

        setDocument : function(src) {
            this.addParamOrRaiseCustomAction(src, "Document", "setdocument");
        },

        setFocusOnLoad       : setParamFn("focusOnLoad"),
        setStartupMode       : setParamFn("startupMode"),
        setHead              : setParamFn("Head"),
        setHideButtonIconURL : setParamFn("hideButtonIconURL"),
        setHideButtonText    : setParamFn("hideButtonText"),
        setHttpLayerManager  : setParamFn("HttpLayer"),
        setLocale            : setParamFn("setLocale"),

        setOnInitComplete : function(callback /* , callbackArguments... */) {
            if (!this.started) {
                this.addParam("onInitComplete", callback);
                this.addCombinedParameter("onInitCompleteParams", Array.prototype.splice.call(arguments, 1, arguments.length));
            }
        },

        setPluginDirectory : function(sDir) {
            sDir = URLUtils.combineDownloadURL(sDir);
            sDir = StringUtils.ensureTrailingSlash(sDir);
            this.addParam("pluginDir", sDir);
        },

        setPreload : function(callback /* , callbackArguments... */) {
            if (!this.started) {
                this.setOnInitComplete.apply(this, arguments);
                this.addParam("hideDialogs", true);
                this.preload = true;
            }
        },

        setOutputCharset          : setParamFn("outputCharset"),
        setPreserveInputStructure : setParamFn("setPreserveInputStructure"),
        setReadOnly               : setParamFn("setReadOnly"),
        setReturnBodyOnly         : setParamFn("setReturnBodyOnly"),
        setStyles                 : setParamFn("Styles"),
        setShowButtonIconURL      : setParamFn("showButtonIconURL"),
        setShowButtonText         : setParamFn("showButtonText"),

        setTextareaRows : function(iRows) {
            this.textAreaRows = iRows;
        },

        setTextareaCols : function(iCols) {
            this.textAreaCols = iCols;
        },

        setUsername : setParamFn("setUsername"),

        setUseTextArea : function(useText) {
            this.forceUseTextArea = useText;
        },

        setXML : setParamFn("setXML"),

        setXMLURL : function(strXMLURL) {
            if (Ephox.Violin.contains(strXMLURL, " ")) {
                strXMLURL = encodeURI(strXMLURL);
            }
            this.addParam("setXMLURL", strXMLURL);
        },

        useTextArea : function() {
            return this.forceUseTextArea || !EditLiveJava.platform.isSupported(EditLiveJava.supportedPlatforms);
        },

        // Run-time API methods
        GetBody : function() {
            this.runCustomAction("getbody", delimit(arguments, "##ephox##"));
        },

        GetBookmarkList       : runCustomActionFn("listbookmarks"),
        GetCharCount          : runCustomActionFn("getcharcount"),
        GetCurrentDocumentURL : runCustomActionFn("getcurrentfile"),

        GetDocument : function() {
            this.runCustomAction("getdocument", delimit(arguments, "##ephox##"));
        },

        GetHyperlinkAtCursor : runCustomActionFn("gethyperlinkatcursor"),
        GetSelectedText      : runCustomActionFn("getselectedtext"),
        GetStyles            : runCustomActionFn("getstyles"),
        GetWordAtCursor      : runCustomActionFn("getwordatcursor"),
        GetWordCount         : runCustomActionFn("getwordcount"),
        InsertHTMLAtCursor   : runCustomActionFn("inserthtmlatcursor"),

        InsertHyperlinkAtCursor : function() {
            if (arguments.length == 1) {
                this.runCustomAction("inserthyperlinkatcursor", arguments[0]);
            } else {
                // FIX is this just Array.prototype.join?
                var i = 1;
                var sHyperlinkString = arguments[0];
                for (i = 1; i < arguments.length; i++) {
                    sHyperlinkString += "##ephox##";
                    sHyperlinkString += arguments[i];
                }
                this.runCustomAction("inserthyperlinkatcursor", sHyperlinkString);
            }
        },

        IsDirty : runCustomActionFn("isdirty"),

        PostDocument : function () {
            this.runCustomAction("postdocument", delimit(arguments, "##ephox##"));
        },

        RaiseEvent : runCustomActionFn("raiseevent"),

        ScrollTo : function() {
            this.runCustomAction("scrollto", delimit(arguments, ":"));
        },

        SetProperties : runCustomActionFn("setproperties"),
        UploadFiles   : runCustomActionFn("uploadImages")
    };

    // method aliases
    prototype.SetBody              = prototype.setBody;
    prototype.SetDocument          = prototype.setDocument;
    prototype.UploadImages         = prototype.UploadFiles;
    prototype.setUseTextarea       = prototype.setUseTextArea;
    prototype.setConfigurationFile = prototype.setXMLURL;
    prototype.setConfigurationText = prototype.setXML;
    
    EditLiveJava.prototype = prototype;

})();
EditLiveJava.prototype.runOnInitComplete = function() {
	var callback = this.getOnInitComplete();
	var params = this.getOnInitCompleteParams();

	if (callback && window[callback]) {
		EditLiveJava.doSetTimeout(function() {
			window[callback].apply(window, params);
		}, 20);
	}
};
(function() {

	var D = EditLiveJava.D;

	EditLiveJava.prototype.setBackgroundMode = function(mode, userCallback) {
		EditLiveJava.BackgroundModeHandler.setMode(this, mode, userCallback);
	};

	EditLiveJava.BackgroundModeHandler = {

		setMode : function(elj, mode, userCallback) {
			if (mode == elj.backgroundMode) return;
			elj.backgroundMode = mode;
			var f = mode
				? "changeModeTrue"
				: "changeModeFalse";
			this[f](elj, userCallback);
		},

		changeModeTrue : function(elj, userCallback) {
			if (this.isOldIE()) {
				this.changeModeTrueFallback(elj, userCallback);
			} else {
				this.changeModeTrueNormalBrowser(elj, userCallback);
			}
		},

		changeModeTrueFallback : function(elj, userCallback) {
			elj.getAppletWrapper().style.border = "1px dotted #888888";
			this.shrink(elj);
			this.runUserCallback(userCallback, true);
		},

		changeModeTrueNormalBrowser : function(elj, userCallback) {
			var callbackRef = this.createCallbackRef(userCallback);
			var args = ["setBackgroundMode", "EditLiveJava.BackgroundModeHandler.callback", elj.name, callbackRef];
			var argString = args.join("|");
			elj.RaiseEvent(argString);
		},

		createCallbackRef : function(userCallback) {
			if (userCallback) return EditLiveJava.CallbackManager.register(userCallback);
			return undefined;
		},

		changeModeFalse : function(elj, callback) {
			this.expand(elj);
			if (this.isOldIE()) {
				this.changeModeFalseFallback(elj);
			} else {
				this.changeModeFalseNormal(elj);
			}
			elj.focus();
			this.runUserCallback(callback, false);
		},

		changeModeFalseNormal : function (elj) {
			elj.getAppletWrapper().style.backgroundImage = "none";
		},

		changeModeFalseFallback : function (elj) {
			elj.getAppletWrapper().style.border = "0";
		},

		shrink : function(elj) {
			this.size(elj, "2px", "2px");
		},

		expand : function(elj) {
			this.size(elj, elj.width + "", elj.height + "");
		},

		size : function(elj, width, height) {
			var applet = elj.getApplet();
			applet.width = width;
			applet.height = height;
		},

		sizeWrapper : function(elj, width, height) {
			var appletWrapperStyle = elj.getAppletWrapper().style;
			appletWrapperStyle.width = width;
			appletWrapperStyle.height = height;
		},

		callback : function(eljInstanceName, base64Data, width, height, userCallback) {
			var elj = EditLiveJava.findInstance(eljInstanceName);
			try {
				this.shrink(elj);
				this.sizeWrapper(elj, width + "px", height + "px");
				elj.getAppletWrapper().style.backgroundImage = "url(data:image/png;base64," + base64Data + ")";
				this.runUserCallback(userCallback, true);
			} catch (e) {
				this.changeModeTrueFallback(elj, userCallback);
			}
		},

		runUserCallback : function(userCallback, mode) {
			// with an undefined callback, java-land may pass the string "undefined" back to us
			if (userCallback && userCallback !== "undefined") {
				D.resolveFunctionOpt(userCallback).someOr(D.noOp)(mode);
			}
		},

		isOldIE : function () {
			return EditLiveJava.browser.isIE() && EditLiveJava.browser.version.major < 8;
		}
	};

})();
EditLiveJava.instances = [];
EditLiveJava.registerInstance = function(newInstance) {
	EditLiveJava.instances.push(newInstance);
};

EditLiveJava.deRegisterInstance = function(instance) {
	for (var i = 0; i < EditLiveJava.instances.length; i++) {
		if (EditLiveJava.instances[i] == instance) {
			EditLiveJava.instances.splice(i, 1);
		}
	}
};

EditLiveJava.findInstance = function(name) {
	for (var i = 0; i < EditLiveJava.instances.length; i++) {
		if (EditLiveJava.instances[i].name === name) {
			return EditLiveJava.instances[i];
		}
	}
};
(function(){

	EditLiveJava.initAutoSubmit = function(name) {
		if(!EditLiveJava.autoSubmitHandlerAttached && EditLiveJava.platform.isSupported(EditLiveJava.supportedPlatforms)) {
			EditLiveJava.autoSubmitHandlerAttached = true;

			var thisForm = EditLiveJava.DOM.getFormWithElementNamed(name);
			if (thisForm) {
				EditLiveJava.originalOnSubmit = thisForm.onsubmit;
				thisForm.onsubmit = EditLiveJava.autoSubmitFormHandler;
			}
		}
	};

	EditLiveJava.submit = function(appletName) {
		appletName = String(appletName); // convert to js string

		setTimeout(function() {
			EditLiveJava.doSubmit(appletName);
		}, 100);
	};

	function submitFormBizarroStyle(form) {
		// FIX: This is needed to support buttons named submit that aren't submit buttons.
		// Need to find a better way.

		var submitIsObject = false;
		var submitIsArray = false;
		if (EditLiveJava.browser.isFirefox() || EditLiveJava.browser.isSafari()) {
			submitIsObject = ((typeof form.submit) == "object");
			submitIsArray = form.submit.length > 0;
		} else {
			submitIsObject = ((form.submit.id == 'submit') || (form.submit.name == 'submit'));
			submitIsArray = typeof(form.submit.length) != "undefined";
		}

		if (submitIsArray) {
			form.onsubmit = null;
			form.submit[0].click();
		} else if (submitIsObject) {
			form.onsubmit = null;
			form.submit.click();
		} else {
			form.submit();
		}
	}

	EditLiveJava.doSubmit = function(appletName) {
		var name = Ephox.Violin.removeTrailing(appletName, "_elj");
		// FIX: surely there is a better way to get the form.
		var form = EditLiveJava.DOM.getFormWithElementNamed(name);

		if (form) {
			var originalOnSubmitExistsAndCancelled = EditLiveJava.originalOnSubmit && EditLiveJava.originalOnSubmit.apply(form) === false;
			if (!originalOnSubmitExistsAndCancelled) {
				if (typeof form.submit === "function") {
					form.submit();
				} else {
					submitFormBizarroStyle(form);
				}

				EditLiveJava.autoSubmitInProgress = false;
			}
		} else {
			throw("Unable to find form for autosubmit");
		}
	};

	EditLiveJava.autoSubmitFormHandler = function() {

		// check if an EditLive! applet exists
		var applet = null;
		var appletName = null;

		if (EditLiveJava.instances.length > 0) {
			// get the applet name from the first registered instance on the page -
			// we only need an arbitrary ELJApplet from the page - it will get all
			// applets on the page to dump content
			appletName = EditLiveJava.instances[0].name + "_elj";
			applet = EditLiveJava.getAppletWithName(appletName);
		}

		// applet does not exist in the page. The user may be using Express Edit
		if (!applet) {
			if (!EditLiveJava.originalOnSubmit) {
				return true;
			} else {
				return EditLiveJava.originalOnSubmit.apply(this);
			}
		} else {
			if (EditLiveJava.autoSubmitInProgress){
				return false;
			}
			EditLiveJava.autoSubmitInProgress = true;

			if (EditLiveJava.useLiveConnect) {
				if (EditLiveJava.supportsLiveConnect(appletName)) {
					applet.processSubmit(EditLiveJava.pageID);
					return false;
				}
			}
			var params = {
				"GetContent" : "true",
				"CustomActionPageID" : EditLiveJava.pageID
			};
			EditLiveJava.instances[0].runPostApplet(params);
			return false;
		}
	};
})();
(function() {

	var D = EditLiveJava.D;

	EditLiveJava.FocusManager = {

		focus : function(element) {
			if (EditLiveJava.DOM.isEljApplet(element)) {
				element.setFocusToApplet();
			} else if (element.focus) {
				element.focus();
			}
		},

		/** Sets focus to the specified element */
		focusElement : function(id) {
			var element = document.getElementById(id);
			if (element) {
				EditLiveJava.FocusManager.focus(element);
			}
		},

		/**
		 * Sets focus to next/prev element.
		 *
		 * @param appletName
		 *			name of EditLive applet dom element
		 * @param direction
		 *			"forwards" for forwards navigation, "backwards" for backwards
		 *			navigation
		 */
		transferFocus : function(appletName, direction) {
			if (appletName && appletName !== "") {
				var applet = document.getElementById(appletName);
				if (applet) {
					var element = this.findNextFocusableElement(applet, direction);
					if (element) {
						EditLiveJava.FocusManager.focus(element);
					}
				}
			}
		},

		iterators : {

			/** forwards iterator used for horizontal traversal of the tree */
			forwards : function(array) {
				this._array = array;
				this._nextPosition = 0;

				this.hasNext = function() {
					return this._nextPosition < this._array.length;
				};

				this.next = function() {
					return this._array[this._nextPosition++];
				};
			},

			/** backwards iterator used for horizontal traversal of the tree */
			backwards : function(array) {
				this._array = array;
				this._nextPosition = this._array.length - 1;

				this.hasNext = function() {
					return this._nextPosition >= 0;
				};

				this.next = function() {
					return this._array[this._nextPosition--];
				};
			}
		},

		/**
		 * Finds the next focusable element in the tree. Search algorithm: 1. Starts
		 * at element and traverses its siblings and their descendants. 2. If no
		 * match is found, traverses up the tree and repeats.
		 *
		 * Search is exclusive - i.e. the starting element will not be returned.
		 *
		 * @param element
		 *			element to start with
		 * @param direction
		 *			horizonatal direction of search. true = forwards, false =
		 *			backwards
		 * @return next focusable element, or null if none are found
		 */
		findNextFocusableElement : function(element, direction) {

			while (element.parentNode != document) {

				var foundElement = false;
				var iterator = new this.iterators[direction](element.parentNode.childNodes);
				while (iterator.hasNext()) {
					var child = iterator.next();
					if (child == element) {
						foundElement = true;
					} else if (foundElement) {
						var focusable = this.findFirstFocusableElementInTree(child, direction);
						if (focusable) {
							return focusable;
						}
					}
				}
				element = element.parentNode;
			}
			return null;
		},

		/**
		 * Performs a recursive depth-first search, returning the first focusable
		 * element. Search is inclusive - if element is focusable, it is returned.
		 *
		 * @param element
		 *			starting element
		 * @param direction
		 *			horizontal traversal direction. true = forwards, false =
		 *			backwards
		 * @return first focusable element. Null if element is null (should not
		 *		 happen) or if no focusable element is found.
		 */
		findFirstFocusableElementInTree : function(element, direction) {
			if (!element) {
				return null;
			}
			if (this.isFocusable(element)) {
				return element;
			}
			var iterator = new this.iterators[direction](element.childNodes);
			while (iterator.hasNext()) {
				var found = this.findFirstFocusableElementInTree(iterator.next(), direction);
				if (found) {
					return found;
				}
			}
			return null;
		},

		isFocusable : function(element) {

			try {

				if (EditLiveJava.DOM.isEljApplet(element)) {
					// editlive applets are focusable
					return true;
				}

				var tagName = element.tagName;
				var tabIndex = element.tabIndex;
				var id = element.id;

				var type = element.type;

				// Note: we skip over file form fields in Mozilla because of Mozilla
				// bug https://bugzilla.mozilla.org/show_bug.cgi?id=453377
				return type != "hidden" && tabIndex != undefined && tabIndex != -1 && id != "eLAuxDiv" && element.className !== "eLTransferFocusHelperElement" && element.focus &&
					(this.isFocusableTag(tagName) || this.isFocusableDiv(element, tagName)) && this.elementIsVisible(element) && !(type === "file" && EditLiveJava.browser.isFirefox());
			} catch (err) {
				return false;
			}
		},

		focusableTags : ["A", "BUTTON", "CAPTION", "RADIO", "SELECT", "TEXTAREA", "INPUT"],

		isFocusableTag : function(candidate) {
			return D.Array.contains(this.focusableTags, candidate);
		},

		isFocusableDiv : function(element, tagName) {
			return tagName == "DIV" && element.isEphoxEditableSection;
		},

		elementIsVisible : function(element) {
			return element == document.body || (this.elementHasVisibleStyles(element) && this.elementIsVisible(element.parentNode));
		},

		elementHasVisibleStyles : function(element) {
			var display = "";
			var visibility = "";
			if (element.style) {
				display = element.style.display;
				visibility = element.style.visibility;
			}
			return display !== "none" && visibility !== "hidden";
		}
	};

})();
(function() {

	var D = EditLiveJava.D;

	var DOM = {

		appendChildren : function(element, children) {
			D.Array.each(children, function(x) {
				element.appendChild(x);
			});
		},

		// ... because Array.prototype.slice.call doesn't work on node lists in IE8
		cloneNodeList : function(elements) {
			var result = [];
			for (var i = 0; i < elements.length; i++) {
				result.push(elements[i]);
			}
			return result;
		},

		moveChildren : function(destDiv, sourceDiv) {
			var c = DOM.cloneNodeList(sourceDiv.childNodes);
			D.Array.each(c, function(x) {
				destDiv.appendChild(x);
			});
		},

		findFormOrBodyForElement : function(element) {
			var node = element.parentNode;
			while (node && node.tagName.toUpperCase() != "FORM" && node.tagName.toUpperCase() != "BODY") {
				node = node.parentNode;
			}
			return node;
		},

		removeIfExists : function(id) {
			var element = document.getElementById(id);
			if (element) {
				element.parentNode.removeChild(element);
			}
		},

		/**
		 * Remove element and set innerHTML blank. Useful for removing elements that
		 * contain applets - helps avoid memory leaks.
		 */
		completelyRemove : D(function(id) {
			var element = document.getElementById(id);
			if (element) {
				element.parentNode.removeChild(element);
				element.innerHTML = ""; 
			}
		}),

		setDivOnFocus : function(div, newFocusFunction) {
			// older versions of safari didn't fire an onfocus when div.focus was
			// called, plus the div didn't receive focus manually
			// but we still fire .focus from certain places
			if (EditLiveJava.browser.isSafari() && EditLiveJava.browser.version.major < 4) {
				div.focus = newFocusFunction;
			} else {
				div.onfocus = newFocusFunction;
			}
		},

		getDivOnFocus : function(div) {
			if (EditLiveJava.browser.isSafari() && EditLiveJava.browser.version.major < 4) {
				return div.focus;
			} else {
				return div.onfocus;
			}
		},

		forEachFormElement : function(functionToApply, form) {
			D.Array.each(form.elements, function(element) {
				var tagName = element.tagName.toUpperCase();
				if (tagName != "OBJECT" && tagName != "APPLET" && tagName != "EMBED" && tagName != "NOEMBED") {
					functionToApply(element);
				}
			});
		},

		/**
		 * Higher-order function which call a specified function on all form
		 * elements in all forms in the document. Keep in mind that object tags are
		 * is in the form.elements in IE, but not in Firefox. As such, we omit
		 * object/applet/embed/noembed from this check.
		 */
		forEachFormElementInAllForms : function(f) {
			D.Array.each(document.forms, function(currentForm) {
				DOM.forEachFormElement(f, currentForm);
			});
		},

		/**
		 * Observe an event. Supports multiple event handlers. Uses addEventListener
		 * on supported browsers, attachEvent on others (IE). IMPORTANT: Anything
		 * relying on this must be rigorously tested cross-browser. Based on code
		 * from prototype.js
		 *
		 * @param {Element}
				*			element
		 * @param {String}
				*			name name of event to attach to
		 * @param {Function}
				*			handler
		 * @param {Boolean}
				*			mode false='capture' mode, true='bubble' mode. NOTE: mode does
		 *			not affect browsers using attachEvent (IE)
		 * @return the wrapper function actually added as the event handler
		 */
		observe: function(element, name, handler, mode) {
			if (mode === undefined) {
				mode = false;
			}

			var wrapper = function(event) {
				// augment event object to resolve cross-browser differences
				if (!event.target) {
					event.target = event.srcElement; // this will be IE
				}
				handler.apply(element, arguments);
			};

			if (element.addEventListener) {
				element.addEventListener(name, wrapper, mode);
			} else {
				element.attachEvent("on" + name, wrapper);
			}
			DOM.observerCache.push({element : element, name : name, wrapper : wrapper});

			return wrapper;
		},

		stopObserving : function(element, name, wrapper, mode) {
			if (element.addEventListener) {
				element.removeEventListener(name, wrapper, mode);
			} else {
				element.detachEvent("on" + name, wrapper);
			}
		},

		/**
		 * Gain focus after a timeout. Use this to regain focus after losing it from
		 * a CloseActiveEditableSection.
		 */
		focus : function(element) {
			try {
				element.focus();

				setTimeout(function() {
					if (element) {
						try {
							window.focus(); // IE needs this
							element.focus();

						} catch(error) {
							// ignore - most likely that the element has been
							// removed from the DOM in IE
						}
					}
				}, 100);
			} catch (error) {
				// ignore - most likely that the element has been removed from the
				// DOM in IE
			}
		},

		// cache of events, so we can nuke them onunload in IE
		observerCache : [],

		isEljApplet: function(element) {
			var id = element.id;
			var tagName = element.tagName;
			return (!!id && Ephox.Violin.endsWith(id, "_elj") && (tagName == "APPLET" || tagName == "OBJECT" || tagName == "EMBED"));
		},

		replaceNode : function(existingNode, newNode) {
			existingNode.parentNode.insertBefore(newNode, existingNode);
			existingNode.parentNode.removeChild(existingNode);
		},

		writeToDocument : function(htmlString) {
			document.write(htmlString);
		},

		getFormWithElementNamed : function(name) {
			for (var formsIndex = 0; formsIndex < document.forms.length; formsIndex++) {
				var curForm = document.forms[formsIndex];
				for (var elementsIndex = 0; elementsIndex < curForm.elements.length; elementsIndex++) {
					var curElement = curForm.elements[elementsIndex];
					if (curElement.name == name) {
						return curForm;
					}
				}
			}
			return null;
		},

		/**
		 * CloseOnFocusLost's timeouts sometimes get us into a state where accessing
		 * any member of document causes an "unknown error" in IE. This function
		 * detects that condition.
		 */
		isDocumentValid : function() {
			try {
				var x = document.body;
				return true;
			} catch (e) {
				return false;
			}
		},

		ephoxStyleSheet : null,
		ephoxStyleSheetText : "",

		/**
		 * Adds a stylesheet to the document.
		 *
		 * @param styles
		 *			CSS to add
		 * @param id
		 *			used to generate the id of the style tag, if required
		 */
		appendStyleTag : function(styles, id) {
			var styleEl;
			if (document.createStyleSheet) {
				// ideal method: add the styles to a single ephox-created document
				// stylesheet
				if (!DOM.ephoxStyleSheet) {
					DOM.ephoxStyleSheet = document.createStyleSheet();
				}
				// append the section styles to the style text
				DOM.ephoxStyleSheetText += styles;
				DOM.ephoxStyleSheet.cssText = DOM.ephoxStyleSheetText;
			} else {
				// legacy method: add a style element to the head of the document
				if (document.getElementById(id + "_styleTag")) {
					styleEl = document.getElementById(id + "_styleTag");
					styleEl.parentNode.removeChild(styleEl);
				}
				styleEl = document.createElement("style");
				styleEl.setAttribute("id", id + "_styleTag");
				document.documentElement.getElementsByTagName("head")[0].appendChild(styleEl);
				var textNode = document.createTextNode(styles);
				styleEl.appendChild(textNode);
			}
		},

		setFormValue : function(sName, sValue) {
			for (var formsIndex = 0; formsIndex < document.forms.length; formsIndex++) {
				var form = document.forms[formsIndex];
				for (var elementsIndex = 0; elementsIndex < form.elements.length; elementsIndex++) {
					var element = form.elements[elementsIndex];
					if (element.name == sName) {
						element.value = sValue;
					}
				}
			}
		},

		forEachDescendant : function(div, fn) {
			var c = div.childNodes;
			for (var i = 0; i < c.length; i++) {
				var recurse = true;
				var mutator = {
					remove : function() {
						div.removeChild(c[i]);
						i--;
						recurse = false;
					},
					replace : function(nodeName, attributes, innerHTML) {
						var el = DOM.createElement(nodeName, attributes, innerHTML);
						DOM.replaceNode(c[i], el);
					}
				};

				fn(c[i], mutator);
				if (recurse) {
					DOM.forEachDescendant(c[i], fn);
				}
			}
		},

		/** dom-based filter. Returns a div element containing the filtered content. */
		filter : function(html, fn) {
			var element = document.createElement("div");
			element.innerHTML = html;
			DOM.forEachDescendant(element, fn);
			return element;
		},

		createElement : function(nodeName, attributes, innerHTML, children) {
			innerHTML = innerHTML || "";
			attributes = attributes || {};
			children = children || [];

			var el = document.createElement(nodeName);
			for (var i in attributes) if (attributes.hasOwnProperty(i)) {
				var x = attributes[i];
				if (i === "style") {
					for (var j in x) if (x.hasOwnProperty(j)) {
						el.style[j] = x[j];
					}
				} else {
					el[i] = x;
				}
			}

			el.innerHTML = innerHTML;
			DOM.appendChildren(el, children);
			return el;
		}
	};

	EditLiveJava.DOM = DOM;

	EditLiveJava.getAppletWithName = function(name) {
		return document.getElementById(name);
	};
})();
(function() {

	var D = EditLiveJava.D;

	/** Helps get/set borders on elements. */
	EditLiveJava.BorderMan = {

		/* getAllBorders and setAllBorders use 'border objects' of the format:
		{Left: {Width: x; Style: x; Height: x}, Right: {Width: x; Style: x; Height: x},
		Top: {Width: x; Style: x; Height: x}, Bottom: {Width: x; Style: x; Height: x}}
		*/

		sides : ["Top", "Bottom", "Left", "Right"],
		borderAttrs : ["Width", "Style", "Color"],

		getBorderAttr : function(element, side, attribute) {
			return element.style["border" + side + attribute];
		},

		/** side and attribute arguments must be in TitleCase e.g. setBorder(div, "Left", "Width", "3px"); */
		setBorderAttr : function(element, side, attribute, value) {
			element.style["border" + side + attribute] = value;
		},

		getBorderForSide : function(element, side) {
			var r = {};
			this.forEachAttr(function(a) {
				r[a] = this.getBorderAttr(element, side, a);
			});
			return r;
		},

		setBorderForSide : function(element, side, value) {
			this.forEachAttr(function(a) {
				this.setBorderAttr(element, side, a, value[a]);
			});
		},

		getAllBorders : function(element) {
			var r = {};
			this.forEachSide(function(s) {
				r[s] = this.getBorderForSide(element, s);
			});
			return r;
		},

		setAllBorders : function(element, value) {
			this.forEachSide(function(s) {
				this.setBorderForSide(element, s, value[s]);
			});
		},

		forEachSide : function(x, that) {
			D.Array.each(this.sides, x, that || this);
		},

		forEachAttr : function(x, that) {
			D.Array.each(this.borderAttrs, x, that || this);
		}
	};

})();
(function() {

	var D = EditLiveJava.D;

	// Internet Explorer needs to remove event handlers on page unload
	// in order to avoid memory leaks. Based on prototype js library.
	if (window.attachEvent) {
		window.attachEvent("onunload", function() {
			D.Array.each(EditLiveJava.DOM.observerCache, function(arrayItem) {
				arrayItem.element.detachEvent(arrayItem.name, arrayItem.wrapper);
			});
		});
	}
})();

EditLiveJava.prototype.detectLocale = function() {

	var specifiedLocale = this.getParam("setLocale");

	var browserLanguage;
	if (specifiedLocale !== "") {
		browserLanguage = specifiedLocale;
	} else if (navigator.userLanguage) {
		browserLanguage = navigator.userLanguage;
	} else {
		browserLanguage = navigator.language;
	}

	var detectedLanguage = "";
	var languages = browserLanguage.split(',');
	for (var i = 0; i < languages.length && detectedLanguage === ""; i++) {
		detectedLanguage = this.getSupportedLocale(languages[i]);
	}

	if (detectedLanguage !== "") {
		this.setLocale(detectedLanguage);
	}

	return detectedLanguage;
};

EditLiveJava.prototype.getSupportedLocale = function(browserLanguage) {
	browserLanguage = this.convertToJavaLocale(browserLanguage);

	return this.parseCountryCode(browserLanguage);
};

EditLiveJava.prototype.convertToJavaLocale = function(browserLanguage) {
	browserLanguage = browserLanguage.toLowerCase().replace('-', '_');
	var scoreIndex = browserLanguage.indexOf(";");
	if (scoreIndex > 0) {
		browserLanguage = browserLanguage.substring(0, scoreIndex);
	}
	return Ephox.Violin.trim(browserLanguage);
};

EditLiveJava.prototype.parseCountryCode = function(browserLanguage) {

	// "en" isn't in the list because english strings are built into the applet jar
	if (EditLiveJava.isEnglish(browserLanguage)) {
		return browserLanguage;
	}

	if (browserLanguage == "zh_hk") {
		// Use traditional chinese
		browserLanguage = "zh_tw";
	} else if (browserLanguage == "iw") {
		// Java returns "IW" for hebrew
		browserLanguage = "he";
	} else if (browserLanguage == "no" || browserLanguage == "nn" || browserLanguage == "nn_no") {
		browserLanguage = "nb";
	}

	var languageList = [
		"ar",    // arabic
		"ca",    // catalan
		"cs",    // czech
		"da",    // danish
		"de",    // german
		"el",    // greek
		"es",    // spanish
		"fa",    // farsi
		"fi",    // finnish
		"fr",    // french
		"he",    // hebrew
		"hr",    // croatian
		"hu",    // hungarian
		"it",    // italian
		"ja",    // japanese
		"ko",    // korean
		"nl",    // dutch
		"nb",    // norwegian bokmål
		"pl",    // polish
		"pt",    // brazilian portuguese (aka pt_br)
		"pt_pt", // european portuguese
		"ro",    // romanian
		"ru",    // russian
		"sl",    // slovenian
		"sk",    // slovak
		"sv",    // swedish
		"th",    // thai
		"tr",    // turkish
		"uk",    // ukrainian
		"zh",    // simplified chinese (aka zh_cn)
		"zh_tw"  // traditional chinese
	];

	// check for full country code support first
	for (var i = 0; i < languageList.length; i++) {
		if (languageList[i] == browserLanguage) {
			return languageList[i];
		}
	}

	// We don't support this specific country, try again with just the language
	// info
	browserLanguage = browserLanguage.substring(0, 2);

	for (var j = 0; j < languageList.length; j++) {
		if (languageList[j] == browserLanguage) {
			return languageList[j];
		}
	}
	return "";
};
EditLiveJava.addLanguageJar = function(jars, locale) {
	// There is no jar for english; it's built into the applet.
	if (locale && !(EditLiveJava.isEnglish(locale))) {
    	jars.push("languages/" + locale + ".jar");
    }
};

EditLiveJava.isEnglish = function(locale) {
	return Ephox.Violin.startsWithIgnoringCase(locale, "en");
};
EditLiveJava.useLiveConnect = false;
EditLiveJava.setUseLiveConnect = function(value) {
	EditLiveJava.useLiveConnect = value;
};
/** @deprecated As this is a global setting, please call EditLiveJava.setUseLiveConnect() instead. */
EditLiveJava.prototype.setUseLiveConnect = EditLiveJava.setUseLiveConnect;


EditLiveJava.pageID = new Date().getTime();
EditLiveJava.autoSubmitInProgress = false;
EditLiveJava.autoSubmitHandlerAttached = false;
EditLiveJava.debugLevel = "off";
EditLiveJava.logger = "console";
EditLiveJava.localDeployment = false;
EditLiveJava.JREDownloadURL = "";
EditLiveJava.minimumJREVersion = "";
EditLiveJava.showSystemRequirementsError = true;
EditLiveJava.errorMessageAlreadyShown = false;
EditLiveJava.loadingMessage = "Updating components and initializing...";

EditLiveJava.prototype.setMinimumJREVersion = function(val) {
	if(val == "1.6.0" || val == "1.6" || val == "6") {
		EditLiveJava.minimumJREVersion = "1.6.0";
	} else if (val == "1.4.1" || val == "1.4.2") {
		EditLiveJava.minimumJREVersion = val;
	}
};

EditLiveJava.prototype.setJREDownloadURL = function(val) {
	EditLiveJava.JREDownloadURL = val;
};

EditLiveJava.prototype.setShowSystemRequirementsError = function(val) {
	EditLiveJava.showSystemRequirementsError = val;
};

EditLiveJava.prototype.setDebugLevel = function(val) {
	EditLiveJava.debugLevel = val;
};

EditLiveJava.prototype.setLogger = function(val) {
	EditLiveJava.logger = val;
};

EditLiveJava.prototype.setLocalDeployment = function(bDeploy) {
	EditLiveJava.localDeployment = bDeploy;
};

EditLiveJava.prototype.setDownloadingMessage = function(message) {
	EditLiveJava.loadingMessage = message;
};

EditLiveJava.setDownloadDirectory = function(dir) {
	dir = EditLiveJava.URLUtils.combineDownloadURL(dir);
	dir = EditLiveJava.StringUtils.ensureTrailingSlash(dir);
	EditLiveJava.downloadDirectory = dir;
};

/** @deprecated Use EditLiveJava.setDownloadDirectory instead */
EditLiveJava.prototype.setDownloadDirectory = EditLiveJava.setDownloadDirectory;

EditLiveJava.detectDownloadDirectory = function() {
	var base = EditLiveJava.getScriptBase("editlivejava.js");
	if (base !== undefined) {
		EditLiveJava.setDownloadDirectory(base);
	}
};

/**
 * Executes the page loaded event, calls setTimeout()
 *
 * @param string
 *            containing the name of the applet
 */
EditLiveJava.sendPageLoaded = function(name) {
	setTimeout(function() { EditLiveJava.sendPageLoadedExecute(name); }, 50);
};

EditLiveJava.pageLoadedCount = 0;

/**
 * Sends the page loaded event to the specified applet, assuming it supports
 * live connect
 *
 * @param string
 *            containing the name of the applet
 */
EditLiveJava.sendPageLoadedExecute = function(name) {
	var cacheID = EditLiveJava.getCacheFieldValue(name);

	if (EditLiveJava.supportsLiveConnect(name)) {
		var applet = EditLiveJava.getAppletWithName(name);
		// only call if applet is available or applet doesn't look
		// like it is going to be available
		if (applet || EditLiveJava.pageLoadedCount >= 20) {
			applet.pageLoaded(cacheID);
		} else {
			EditLiveJava.pageLoadedCount++;
			EditLiveJava.sendPageLoaded(name);
		}
	}
};


/**
 * Return the value of the cache field, populating it if it is empty
 *
 * @param name
 *            the name of the object to get the cache ID for
 * @return the value of the field, if it exists
 */
EditLiveJava.getCacheFieldValue = function(id) {
	var element = document.getElementById(id + "_cache");
	if (element) {
		if (element.value.length === 0) {
			element.value = EditLiveJava.pageID + id;
		}
		return element.value;
	}
	return "";
};
/** @deprecated No more experimental support.  */
EditLiveJava.prototype.setExperimentalBrowserSupport = function(){};
EditLiveJava.getScriptBase = function(scriptName) {
	scriptName = scriptName.toLowerCase();
	var scriptArray = document.getElementsByTagName("script");
	if (scriptArray && scriptArray.length) {
		for (i = 0; i < scriptArray.length; i++) {
			var scriptElement = scriptArray[i];
			if (scriptElement.src && scriptElement.src.toLowerCase().indexOf(scriptName) > -1) {
				return scriptElement.src.substring(0, scriptElement.src.lastIndexOf("/") + 1);
			}
		}
	}
};
EditLiveJava.hasQuickStarted = false;
EditLiveJava.quickStart = function(downloadDir) {
	if (EditLiveJava.hasQuickStarted) {
		return;
	}
	EditLiveJava.hasQuickStarted = true;

	//FIX THIS: Java 1.6.0_19 introduced an issue where it would prompt a security error when there was a signed and an unsigned jar being loaded. 
	var classpath = [];//[EditLiveJava.downloadDirectory + "/editlivejava.jar"];

	var javaInstalled = false;
	if (EditLiveJava.os.isOSX()) {
		javaInstalled = false;
	} else if (navigator && navigator.mimeTypes && navigator.mimeTypes.length) {
		javaInstalled = navigator.mimeTypes['application/x-java-applet;version=1.4'];
	} else if (EditLiveJava.os.isWindows() && EditLiveJava.browser.isIE() && window.ActiveXObject) {
		try {
			var obj = new ActiveXObject("JavaWebStart.isInstalled");
			javaInstalled = !!obj;
		} catch (e) {
			javaInstalled = false;
		}
	}
	if (javaInstalled) {
		var kickStartCode = EditLiveJava.generateAppletTag(1, 1, "kickstart", classpath, "QuickStartApplet", {});
		EditLiveJava.DOM.writeToDocument(kickStartCode);
	}
	return javaInstalled;
};

/** @deprecated - use EditLiveJava.quickStart instead */
var ephoxQuickStart = EditLiveJava.quickStart;
(function() {

	var D = EditLiveJava.D;

	/**
	 * @param {Boolean} preserveContent
	 * @param {Boolean} insertAuxDiv
	 * @param {Boolean} insertFocusGrabberIfNeeded defaults to true if not specified
	 */
	EditLiveJava.prototype.getAppletHTML = function(preserveContent, insertAuxDiv, insertFocusGrabberIfNeeded) {
		return this.getAppletOrTextAreaHtml(preserveContent, insertAuxDiv, insertFocusGrabberIfNeeded, this.useTextArea());
	};

	EditLiveJava.prototype.getAppletOrTextAreaHtml = function(preserveContent, insertAuxDiv, insertFocusGrabberIfNeeded, useTextArea) {
		if (this.getParam("setXMLURL") === "" && this.getParam("setXML") === "") {
			this.setConfigurationFile(EditLiveJava.downloadDirectory + "sample_eljconfig.xml");
		}

		if (insertFocusGrabberIfNeeded === undefined) {
			insertFocusGrabberIfNeeded = true;
		}

		if (!this.cookie) {
			this.setCookie(document.cookie);
		}

		var appletClass = EditLiveJava.determineAppletClass();

		this.addParam("BeanListenerClasses", this.classNames);

		// Add the plugin URLs to the parameter list
		this.addCombinedParameter("PluginUrls", this.pluginUrls);
		// Add the plugin configs that were added as text.
		this.addCombinedParameter("PluginText", this.pluginText);
		// Add the base URLs for plugins added as text.
		this.addCombinedParameter("PluginTextBaseUrls", this.pluginBases);

		var classpath = this.getClasspath().concat(this.extraJars);
		var appletName = this.name + "_elj";

		if (((EditLiveJava.os.isWindows() && EditLiveJava.browser.isIE()) || EditLiveJava.supportsLiveConnect(appletName)) && preserveContent) {
			// Attach our window.onload function for this instance
			var currentWindowOnload = window.onload;
			window.onload = function() {
				if (currentWindowOnload) {
					currentWindowOnload.apply(window);
				}
				EditLiveJava.sendPageLoaded(appletName);
			};
		} else {
			this.addParam("pageLoaded", true);
		}

		if (this.getParam("setXMLURL") === "" && this.getParam("setXML") === "") {
			this.setConfigurationFile(EditLiveJava.downloadDirectory + "sample_eljconfig.xml");
		}

		var appletTag = "";

		var isSupported = EditLiveJava.platform.isSupported(EditLiveJava.supportedPlatforms);

		if (!isSupported && !this.preload && EditLiveJava.showSystemRequirementsError && !EditLiveJava.errorMessageAlreadyShown) {
			appletTag += "<p id='EditLiveTextAreaFallbackMessage'>This system does not meet the minimum requirements to run EditLive!. Now using a textarea instead.</p>";
			EditLiveJava.errorMessageAlreadyShown = false;
		}

		if (EditLiveJava.os.isOSX() && EditLiveJava.browser.isChrome()) {
			this.setUseLiveConnect(true);
		}

		if (useTextArea) {
			appletTag += EditLiveJava.getTextArea(this.name, this.params, this.textAreaRows, this.textAreaCols);
			this.runOnInitComplete();
		} else {
			appletTag += EditLiveJava.generateAppletTag(this.width, this.height, appletName, classpath, appletClass, this.params);
		}

		return EditLiveJava.getEditorLayout(appletName, appletTag, this.borderStyle, this.width, this.height, insertAuxDiv, insertFocusGrabberIfNeeded, this.useTextArea());
	}

	function linux(classpath, codeParams, basicParams, params, globalParams, name) {
		var s = '<embed';
		s += ' type="application/x-java-applet;version=1.4"';
		s += ' cache_archive_ex="' + classpath + '"';
		s += EditLiveJava.generateAttributeString(codeParams);
		s += ' cache_archive="' + classpath + '"';
		s += ' archive="' + classpath + '"';
		s += ' cache_option="Plugin"';
		s += EditLiveJava.generateAttributeString(basicParams);
		s += ' scriptable="true" ';
		s += ' mayscript="true" ';
		s += ' UserAgent="' + escape(navigator.userAgent) + '"';
		s += ' DebugLevel="' + EditLiveJava.debugLevel + '"';
		s += ' Logger="' + EditLiveJava.logger + '"';
		s += ' PageID="' + EditLiveJava.pageID + '"';
		s += EditLiveJava.generateAttributeString(params);
		s += EditLiveJava.generateAttributeString(globalParams);
		s += ' pluginspage="https://java.sun.com/products/plugin/index.html#download"';// Java plug-in install instructions for Netscape
		s += '>';
		s += '<noembed id="' + name + '_noembed"></noembed>';
		s += '</embed>';
		s += EditLiveJava.getCacheField(name);
		return s;
	}

	function mac(classpath, codeParams, basicParams, params, globalParams, name) {
		var str = '<applet';
		str += ' cache_archive="' + classpath + '"';
		str += ' cache_option="Plugin"';
		str += ' archive="' + classpath + '"';
		str += ' cache_archive_ex="' + classpath + '"';
		str += EditLiveJava.generateAttributeString(codeParams);
		str += EditLiveJava.generateAttributeString(basicParams);
		str += ' mayscript="true">';
		str += '<param name="cache_archive_ex" value="' + classpath + '"></param>';
		str += EditLiveJava.generateParamTags(params);
		str += EditLiveJava.generateParamTags(globalParams);
		str += '<param name="UserAgent" value="' + escape(navigator.userAgent) + '"></param>';
		str += '<param name="DebugLevel" value="' + EditLiveJava.debugLevel + '"></param>';
		str += '<param name="Logger" value="' + EditLiveJava.logger + '"></param>';
		str += '<param name="progressbar" value="true"></param>';
		str += '<param name="boxmessage" value="' + EditLiveJava.loadingMessage + '"></param>';
		str += '<param name="PageID" value="' + EditLiveJava.pageID + '"></param>';
		str += '</applet>';
		str += EditLiveJava.getCacheField(name);
		return str;
	}

	function resolveMinimumJavaVersion(v) {
		return v === "1.4.2" ? "1.4.2" : "1.6";
	}

	function getLocalJreDownloadUrl(base, minimumJREVersion) {
		return base + '#Version=' + resolveMinimumJavaVersion(minimumJREVersion);
	}

	var getRemoteJreDownloadUrl = function(minVersion) {
		// download list is at http://www.oracle.com/technetwork/java/javase/autodownload-140472.html
		var base = "http://java.sun.com/update/";
		var ext = minVersion === "1.4.2"
			? "1.4.2/jinstall-1_4_2_19-windows-i586.cab"
			: "1.6.0/jinstall-6u25-windows-i586.cab";
		return base + ext;
	};

	EditLiveJava.getWindowsAJreDownloadUrl = function(localDeployment, jreDownloadUrl, minJreVersion) {
		return localDeployment
			? getLocalJreDownloadUrl(jreDownloadUrl, minJreVersion)
			: getRemoteJreDownloadUrl(minJreVersion);
	};

	function windowsA(classpath, codeParams, basicParams, params, globalParams, name, applet, browser) {
		var str = '<object';
		if (EditLiveJava.minimumJREVersion == "1.6.0") {
			str += ' classid="clsid:CAFEEFAC-0016-0000-FFFF-ABCDEFFEDCBA"';
		} else {
			str += ' classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"';
		}
		str += EditLiveJava.generateAttributeString(basicParams);
		str += EditLiveJava.generateTabIndexAttributes();

		var cb = EditLiveJava.getWindowsAJreDownloadUrl(EditLiveJava.localDeployment, EditLiveJava.JREDownloadURL, EditLiveJava.minimumJREVersion);

		str += Ephox.Violin.supplant(' codebase="${url}"', {url: cb});

		str += '>';


		// Standard PARAM elements
		str += '<param name="code" value="' + applet + '"></param>';
		if (EditLiveJava.minimumJREVersion == "1.4.2"){
			str += '<param name="type" value="application/x-java-applet;version=1.4.2"></param>';
		} else {
			str += '<param name="type" value="application/x-java-applet;version=1.6.0"></param>';
		}
		str += '<param name="archive" value="' + classpath + '" ></param>';
		str += '<param name="codebase" value="' + EditLiveJava.downloadDirectory + '" ></param>';
		str += '<param name="cache_option" value="Plugin" ></param>';
		str += '<param name="cache_archive" value="' + classpath + '" ></param>';
		str += '<param name="cache_archive_ex" value="' + classpath + '" ></param>';
		str += '<param name="name" value="' + name + '" ></param>';
		if(browser.isOpera()) {
			str += '<param name="scriptable" value="true"></param>';
		} else {
			str += '<param name="scriptable" value="false"></param>';
		}
		str += '<param name="mayscript" value="true"></param>';
		str += '<param name="progressbar" value="true"></param>';
		str += '<param name="boxmessage" value="' + EditLiveJava.loadingMessage + '"></param>';
		str += '<param name="UserAgent" value="' + escape(navigator.userAgent) +'"></param>';
		str += '<param name="DebugLevel" value="' + EditLiveJava.debugLevel + '"></param>';
		str += '<param name="Logger" value="' + EditLiveJava.logger + '"></param>';
		str += '<param name="PageID" value="' + EditLiveJava.pageID + '"></param>';

		str += EditLiveJava.generateParamTags(params);
		str += EditLiveJava.generateParamTags(globalParams);

		str += '</object>';
		str += EditLiveJava.getCacheField(name);
		return str;
	}

	function windowsB(classpath, codeParams, basicParams, params, globalParams, name, applet) {
		function applicationAttribute(v) {
			return {type: "application/x-java-applet;version=" + resolveMinimumJavaVersion(v)};
		}

		var str = '<embed';
		str += EditLiveJava.generateAttributeString(applicationAttribute(EditLiveJava.minimumJREVersion));
		str += EditLiveJava.generateAttributeString(codeParams);
		str += ' cache_archive_ex="' + classpath + '"';
		str += ' cache_archive="' + classpath + '"';
		str += ' archive="' + classpath + '"';
		str += ' cache_option="Plugin"';
		str += ' scriptable="true" ';
		str += ' mayscript="true" ';
		str += ' UserAgent="' + escape(navigator.userAgent) +'"';
		str += ' DebugLevel="' + EditLiveJava.debugLevel + '"';
		str += ' Logger="' + EditLiveJava.logger + '"';
		str += ' PageID="' + EditLiveJava.pageID + '" ';
		str += EditLiveJava.generateAttributeString(basicParams);
		str += EditLiveJava.generateTabIndexAttributes();
		str += EditLiveJava.generateAttributeString(params);
		str += EditLiveJava.generateAttributeString(globalParams);
		str += ' pluginspage="' + EditLiveJava.downloadDirectory + 'plugin-install.html"';
		str += ' />';
		str += '<noembed id="' + name + '_noembed"></noembed>';
		str += EditLiveJava.getCacheField(name);
		return str;
	}

	EditLiveJava.generateAppletTag = function(width, height, name, classpathArray, applet, params) {
		var classpath = classpathArray.join(",");
		var nameWithoutELJSuffix = Ephox.Violin.removeTrailing(name, "_elj");

		// Set the JRE download URL if it hasn't already been set.
		if (EditLiveJava.JREDownloadURL === "") {
			EditLiveJava.JREDownloadURL = EditLiveJava.downloadDirectory + "j2re-1_4_2_05-windows-i586-p.exe";
		}

		var basicParams = {width : width, height : height, name : name, id : name};
		var codeParams = {code : applet, codebase : EditLiveJava.downloadDirectory};

		var globalParams = {
			downloadDir:    EditLiveJava.downloadDirectory,
			java_arguments: "-Djnlp.packEnabled=true"
		};

		var browser = EditLiveJava.browser;
		var os = EditLiveJava.os;

		if (os.isWindows()) {
			function isOpera105() {
				var winOpera105 = {
					Windows: {
						"Opera" : {
							minimum: {
								major : 10,
								minor : 5
							}
						}
					}
				};
				//FIX: This call means "is Opera 10.5 or above supported, but is being used as if it means: "is the current browser Opera 10.5 or above"
				return EditLiveJava.platform.isSupported(winOpera105);
			}

			if (browser.isIE() || (browser.isOpera() && !isOpera105())) {
				return windowsA(classpath, codeParams, basicParams, params, globalParams, name, applet, browser);

			} else if (browser.isFirefox() || browser.isSafari() || browser.isChrome() || isOpera105()) {
				return windowsB(classpath, codeParams, basicParams, params, globalParams, name, applet);
			}

		} else if (os.isOSX()) {
			return mac(classpath, codeParams, basicParams, params, globalParams, name);

		} else if (os.isLinux()) {
			return linux(classpath, codeParams, basicParams, params, globalParams, name);

		} else {
			return '';
		}
	};

	/**
	 * add a "hidden" input tag that passes focus to the applet when it gets focus
	 *
	 * @param {String}
	 *            id of applet to divert focus to
	 * @param {Boolean}
	 *            addPTag wrap the focus grabber in a p tag
	 */
	EditLiveJava.addFocusGrabber = function(appletName, addPTag) {

		var html = "";
		if (addPTag) {
			html += "<p style='bottom:0;right:0;height:0;line-height:1px;margin:0;padding:0;border:0;color:transparent;background:transparent;position:absolute;'>";
		}
		html += '<input type="text" class="eLTransferFocusHelperElement" ';
		html += 'style="width:1px;height:1px;border:0;margin:0;padding:0;color:transparent;background-color:transparent;" tabindex="0" ';
		html += 'onfocus="this.blur();EditLiveJava.FocusManager.focusElement(\'' + appletName + '\');" id="' + appletName + '_focusGrabber" />';

		if (addPTag) {
			html += "</p>";
		}
		return html;
	};

	EditLiveJava.getEditorLayout = function(appletName, appletTag, borderStyle, width, height, insertAuxDiv, insertFocusGrabberIfNeeded, usingTextArea) {
		// set default to true;
		if (insertAuxDiv === undefined) {
			insertAuxDiv = true;
		}

		var wrappedAppletTag = "";
		if (usingTextArea) {
			wrappedAppletTag = EditLiveJava.wrapTextArea(appletTag, borderStyle, width, height);
		} else {
			wrappedAppletTag = EditLiveJava.wrapApplet(appletName, appletTag, EditLiveJava.StringUtils.toCSSLength(height), EditLiveJava.StringUtils.toCSSLength(width), insertAuxDiv);
		}

		var str = wrappedAppletTag;
		if (insertFocusGrabberIfNeeded && appletTag.toLowerCase().indexOf("editlivejava") >= 0)  {
			str += EditLiveJava.addFocusGrabber(appletName, true);
		}

		return str;
	};

	EditLiveJava.wrapTextArea = function(appletTag, borderStyle, width, height) {
		var str = '<div style="width: ' +
			EditLiveJava.StringUtils.toCSSLength(width) +
			'; height: ' + EditLiveJava.StringUtils.toCSSLength(height) + '; ' + borderStyle + '">';
		str += appletTag;
		str += '</div>';
		var auxDiv = EditLiveJava.getAuxDivHTMLIfMissing();
		if (auxDiv) {
			str += auxDiv;
		}
		return str;
	};

	EditLiveJava.wrapApplet = function(appletName, appletTag, height, width, insertAuxDiv) {
		var name = Ephox.Violin.removeTrailing(appletName, "_elj");

		var auxDiv = "";
		if (insertAuxDiv) {
			auxDiv = EditLiveJava.getAuxDivHTMLIfMissing();
		}

		return "<div style='overflow:hidden;font-size:0;line-height:0;margin:0;padding:0;'" + " id='" + name + "_appletWrapper'>"
			+ appletTag
			+ "</div>"
			+ auxDiv;
	};

	EditLiveJava.determineAppletClass = D.getConstant("com.ephox.editlive.applets.EditLiveJava");

	EditLiveJava.generateParamTags = function(params) {
		var str = "";
		for (var key in params) {
			if (params.hasOwnProperty(key)) {
				var value = params[key] + "";

				value = Ephox.Violin.htmlEncodeDoubleQuotes(value);

				str += '<param name="' + key + '" value="' + value + '"></param>';
			}
		}
		return str;
	};

	EditLiveJava.generateAttributeString = function(params) {
		var str = "";
		for (var key in params) {
			if (params.hasOwnProperty(key)) {
				var value = params[key] + "";

				value = Ephox.Violin.htmlEncodeDoubleQuotes(value);

				str += ' ' + key + '="' + value + '"';
			}
		}
		return str;
	};

	EditLiveJava.generateTabIndexAttributes = function() {
		return ' tabindex="-1" ';
	};

	EditLiveJava.getTextArea = function(name, params, rows, cols) {
		var str = '<textarea name="' + name + '" id="' + name + '" rows="' + rows + '" cols="' + cols + '">';

		var addContent = function(source) {
			str += unescape(source.replace(/\+/gi, "%20"));
		};

		if (params.hasOwnProperty("Document")) {
			addContent(params.Document);
		} else if (params.hasOwnProperty("Body")) {
			addContent(params.Body);
		}

		str += '</textarea>';
		return str;
	};

	/**
	 * Create a field to use for the cache ID, and return it as a string
	 *
	 * @param name
	 *            the name of the object this is a cache for
	 * @return a string containing the cache field
	 */
	EditLiveJava.getCacheField = function(name) {
		return '<input type="hidden" id="' + name + '_cache" tabindex="-1"/>';
	};

	EditLiveJava.getAuxDivHTMLIfMissing = function() {
		var auxDivID = "eLAuxDiv";
		if (!document.getElementById(auxDivID)) {
			return EditLiveJava.createAuxDiv(auxDivID);
		}
		return "";
	};

	EditLiveJava.createAuxDiv = function(id) {
		return '<span id="' + id + '" style="' +
			'position:absolute;' +
			'right:0;' +
			'bottom:0;' +
			'color:transparent;' +
			'background-color:transparent;' +
			'width:1px;' +
			'height:0px;' +
			'display: inline;' +
			'line-height:0;' +
			'font-size:0;"></span>';
	};

	EditLiveJava.prototype.getClasspath = function() {
		var locale = this.detectLocale();
		var jars = [];
		EditLiveJava.addLanguageJar(jars, locale);
		jars.push("editlivejava.jar");
		return jars;
	};

	EditLiveJava.prototype.getHiddenFieldString = function() {
		return '<input name="' + this.name + '" id="' + this.name + '" type="hidden">';
	};

})();

EditLiveJava.copyProperties = function(sourceObject, targetObject, attributeNames) {
	for (var i = 0; i < attributeNames.length; i++) {
		var curProperty = attributeNames[i];
		targetObject[curProperty] = sourceObject[curProperty];
	}
};
EditLiveJava.print = function(html) {
	var newWin = window.open("", "", "toolbar=no,resizable=yes");
	// newWin may be null if a popup blocker blocks it
	if (newWin) {
		newWin.document.open();
		newWin.document.write('<html><head><title>Print Preview</title></head><frameset rows="60, *"><frame name="Print"><frame name="content"></frameset></html>');
		newWin.document.close();
		newWin.Print.document.open();
		newWin.Print.document.write('<html><body><form><input type="button" value="Print" onclick="parent[\'content\'].focus();parent[\'content\'].print();"><input type="button" value="Close" onclick="parent.close();"></form></body></html>');
		newWin.Print.document.close();
		newWin.content.document.open();
		newWin.content.document.write(html);
		newWin.content.document.close();
	}
};
EditLiveJava.prototype.runPostApplet = function(params) {

	var auxDiv = document.getElementById("eLAuxDiv");
	if (auxDiv) {

		// name is blank so the post applet isn't included with form submission
		var name = '';
		var appletClass = 'com.ephox.editlive.java2.POSTApplet.class';
		var width = 1;
		var height = 1;

		var classpath = this.getClasspath();

		var appletTag = EditLiveJava.generateAppletTag(width, height, name, classpath, appletClass, params);

		auxDiv.innerHTML = "";
		auxDiv.innerHTML = appletTag;
	}
};

EditLiveJava.prototype.checkExpressEdit = function() {
	return this.expressEdit && this.expressEdit != "false" && this.loadExpressEditor();
};
EditLiveJava.supportsLiveConnect = function(name) {
	if (EditLiveJava.browser.isOpera()) {
		result = false;
	}
	if (EditLiveJava.os.isWindows() && EditLiveJava.browser.isIE()) {
		var applet = EditLiveJava.getAppletWithName(name);
		if (applet) {
			return EditLiveJava.hasAppletEverBeenVisible(applet, name);
		} else {
			return false;
		}
	}
    // Mozilla (and Safari) based browsers are our only other supported
	// browsers
	return true;
};

/**
 * Detects if a block is visible by checking itself and all its parent elements
 * for display set to none.
 *
 * This function will only work for IE (and is only called when using IE), as
 * the currentStyle is an IE only property. If you need to do this outside of
 * IE, try using window.getComputedStyle function
 *
 * On other browsers it always returns true.
 */
EditLiveJava.appletVisible = [];
EditLiveJava.hasAppletEverBeenVisible = function(element, name) {
	// if we have ever been Visible (using the state), return true now.
	if (EditLiveJava.appletVisible[name]) {
		return true;
	}
	while (element) {
		if (element.currentStyle.display == "none") {
			// set the state to remember the result
			EditLiveJava.appletVisible[name] = false;
			return false;
		}
		element = element.parentElement;
	}
	EditLiveJava.appletVisible[name] = true;
	// set the state and return true.
	return true;
};
(function() {

	var D = EditLiveJava.D;

	var doShowInElement = function(elj, container, preserveContent_) {
		var preserveContent = D.ifUndefined(preserveContent_, false);

		function getElement() {
			var t = typeof container;
			if (t === "string") return document.getElementById(container);
			if (t === "object" && t !== null) return container;
			throw "Invalid parameter for showInElement";
		}

		var element = getElement();
		if (!element) throw "Element not found for showInElement";

		element.innerHTML = elj.getAppletHTML(preserveContent) + elj.getHiddenFieldsHtmlIfRequired();
		if (elj.autoSubmit) {
			EditLiveJava.initAutoSubmit(elj.name);
		}

		elj.started = true;
	};

	var doShow = function(elj, preserveContent) {
		var id = elj.name + "_editLiveUniverse";
		var html = Ephox.Violin.supplant("<div style='padding: 0;margin: 0;overflow: hidden;' id='${id}'></div>", {id: id});
		EditLiveJava.DOM.writeToDocument(html);
		doShowInElement(elj, id, preserveContent);
	};

	EditLiveJava.prototype.show = function(preserveContent) {
		if (!this.checkExpressEdit()) {
			doShow(this, preserveContent);
		}
	};

	EditLiveJava.prototype.showInElement = function(container) {
		doShowInElement(this, container, undefined);
	};

	EditLiveJava.prototype.showAsButton = function(popout) {
		this.expressEdit = false;
		this.addParam("showAsButton", "true");
		this.addParam("popout", popout);
		this.show();
	};

})();
// wrapped so we can stub out
EditLiveJava.doSetTimeout = function(fn, time) {
	setTimeout(fn, time);
};
this.EditLiveJava = this.EditLiveJava || {};

(function() {

	EditLiveJava.supportedPlatforms = {
		Windows : {"Firefox" : {minimum: {major : 3, minor : 0}}, "Safari" : true, "Opera" : true, "IE" : true, "Chrome" : true},
		OSX : {"Firefox" : true, "Safari" : true, "Opera" : true, "Chrome": true},
		Linux : {"Firefox" : true, "Opera" : true, "Chrome" : true}
	};

	EditLiveJava.platform = Ephox.platformDetection.detect();
	EditLiveJava.browser = EditLiveJava.platform.browser;
	EditLiveJava.os = EditLiveJava.platform.os;
})();
EditLiveJava.detectDownloadDirectory();
(function() {

	var V = Ephox.Violin;
	var messages = EditLiveJava.i18n.messages.DefaultCrashAction;
	var DOM = EditLiveJava.DOM;
	var el = DOM.createElement;

	var row = function(text, onClick) {

		var button = el("a", {style: {fontSize: "12pt"}, href: "#"}, "(icon)");
		DOM.observe(button, "click", onClick);

		var label = el("span", {}, text);

		return el("tr", {}, "", [
			el("td", {}, "", [button]),
			el("td", {style:"font-size:12pt;"}, "", [label])
		]);
	};

	var createCrashScreen = function() {

		var dummyOnClick = function() {
			alert("item clicked");
		};

		return el("div", {}, "", [
			el("p", {style: {fontSize: "14pt"}}, messages.message1),
			el("p", {style: {fontSize: "12pt"}}, messages.message2),
			el("table", {}, "", [
				row(messages.optionNew, dummyOnClick),
				row(messages.optionRevert, dummyOnClick),
				row(messages.optionAutosavePrompt, dummyOnClick),
				row(messages.optionAutosaveLatest, dummyOnClick)
			])
		]);
	};

	EditLiveJava.DefaultCrashAction = function(appletName) {
		if (typeof appletName != "string") throw "appletName was not a string";
		var wrapperDivId = Ephox.Violin.removeTrailing(appletName, "_elj") + "_appletWrapper";
		var wrapperDiv = document.getElementById(wrapperDivId);
		if (wrapperDiv) {
			wrapperDiv.innerHTML = "";
			var s = createCrashScreen();
			wrapperDiv.appendChild(s);
		}
	};
})();
EditLiveJava.QueueWhileLoadingProcessor = (function() {
	/*
	Given a "processor", a QueueWhileLoadingProcessor accepts requests for tasks that the processor can process.
	A "processor" comprises three functions: open, close, process.

	Upon the first request, the processor is opened and the task queued.
	When the processor completes opening, it flushes the queue and processes those that were queued. It then closes.

	We don't keep it open, as this impacts the closing of jvms for ELJ applet.

	During loading or processing, tasks are queued.
	*/

	return {
		/**
		 * processor = {open, close, args} functions.
		 *  'open' arg is asynchronous. function(callback){ ... }
		 *  'close' and 'process' args are synchronous
		 */
		create: function(processor) {
			var newQueue = EditLiveJava.D.List.create;

			var queue = newQueue();
			var status = "closed";

			var openIfClosed = function() {
				if (status === "closed") {
					status = "opening";
					processor.open(processQueue);
				}
			};

			var enqueue = function(x) {
				queue.add(x);
				openIfClosed();
			};

			var processQueue = function processQueue() {
				if (queue.size() > 0 && status !== "processing") {
					status = "processing";
					var toProcess = queue;
					queue = newQueue();

					// setTimeout to prevent stack blowout
					setTimeout(function() {
						toProcess.each(processor.process);
						processor.close();
						status = "closed";
						processQueue();
					}, 1);
				}
			};

			return {
				enqueue: enqueue
			};
		}
	};
})();

