From: Subject: =?Windows-1252?Q?El_blog_de_Jorge_Mestre_=BB_=93La_tierra_es_plana=94_e?= =?Windows-1252?Q?n_espa=F1ol?= Date: Tue, 24 Jan 2006 13:31:44 +0100 MIME-Version: 1.0 Content-Type: multipart/related; type="text/html"; boundary="----=_NextPart_000_00C5_01C620EA.84C9EDA0" X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2900.2180 This is a multi-part message in MIME format. ------=_NextPart_000_00C5_01C620EA.84C9EDA0 Content-Type: text/html; charset="utf-8" Content-Transfer-Encoding: quoted-printable Content-Location: http://www.jorgemestre.com/?p=23 =EF=BB=BF El blog de Jorge Mestre =C2=BB = =E2=80=9CLa tierra es plana=E2=80=9D en espa=C3=B1ol

El=20 blog de Jorge Mestre

Todo lo que a mi me gusta, a un clic.

=E2=80=9CLa = tierra es plana=E2=80=9D en=20 espa=C3=B1ol

Jue 12 Ene = 2006
Categoria: Varios , Pol=C3=ADtica=20 internacional -  
Despu=C3=A9s de varios a=C3=B1os sin traducirse ninguna = obra al espa=C3=B1ol del=20 periodista Thomas L. Friedman, desde este mes de enero = ya est=C3=A1=20 a la venta su obra =E2=80=9CLa tierra es plana=E2=80=9D (The = world is flat) una=20 aut=C3=A9ntica delicia de libro que ofrece las claves de la = globalizaci=C3=B3n actual. Si=20 para comprar el =C3=BAltimo de Harry Potter se montaron colas y colas, = es una pena=20 que en este caso no lo conocieran ni en la librer=C3=ADa donde yo lo he = adquirido. No=20 dir=C3=A9 el nombre porque me temo que me habr=C3=ADa pasado = tambi=C3=A9n en cualquier otra.=20 Friedman suele escribir los mi=C3=A9rcoles en el NYT y ha hecho = de su libro=20 un aut=C3=A9ntico bestseller en EE UU.  =20

Deja tu comentario

Name (requerido)

Website

=20 =

Archived Entry

  • Post Date :=20
  • Jueves, Ene 12th, 2006 at 5:35 pm=20
  • Category :=20
  • Varios and Pol=C3=ADtica=20 internacional=20
  • Do More :=20
  • You can leave a=20 response, or trackback= from=20 your own site.

=C2=A9 Jorge = Mestre. Todos=20 los derechos reservados. | Dise=C3=B1o por Mauro=20 Sotelo.

------=_NextPart_000_00C5_01C620EA.84C9EDA0 Content-Type: image/gif Content-Transfer-Encoding: base64 Content-Location: http://www.jorgemestre.com/wp-content/images/tierraplana.gif R0lGODlhYACTAOYAAFdJN5WHcE+YwQx2tqmqp3llR+Tl4Xd4dggJCxV7t+nq5bi4tYaHhIlzVcnV 2GdoZ5iZlyooJCeEuqelnunm3rXL1GdWPNvd2Yi1zGqlxkdISEM5KjOKvDYxKDY3N8HCvVZXV+Lj 4JK6zuHi3ajF0m1cQtna1bO0sOzt6NTb2qOTeNHSzcC4qHWryDEtJiQjH8nKxtTV0LykdKqTZ8au e/Lz7pSUkczNyebo46ONZ5qEXeLj3klAMuLi3N7g28TFwObk3YBrTP///7Sec/Hq36ibhIdxT7GZ boVvUY96V+Pk3/fs4Ih7Z+Pk4Pr79eDi3UWTwKKKYOXm4+Tj3ezn3ltTR0w/Lpu+z3RgQdfY08bH w8/Qy7OsnvT18L2+uXtxYX+Afr7Q1l5OOo6PjJ+gnSAfHB5/uUFCQs/Mwff48u/w6qDA0K6vrDyO vlyexE5PT15gXhUWGG9wbzIzM1FEMiAhIi8wMCssLX+wyuPj4QNytDw9PZeMej9AP+Dh3eDh3CH5 BAAAAAAALAAAAABgAJMAAAf/gH+Cg4SFhoeIiYqLjI2Oj5CRkpOUlZaXmJmam5ydnp+goaKjpKWm pyM7OyOHqqyEqrGxI6k7f7Wyq3+5r4K4uoW1vaNKrMWgSgoKw4LJKL1KzZs4Cx4eYAqECtUeD1Ks OxcgHnvl5R4MB3N9NwTk5nvdUnDve2cgZDgGD/V9IBAGbKEgY+1AtkwKCCBA8AAFIRRyFsb5gOOP EhN1Fmpc+ADEQhgQNmrso8CDyIVg1PQ5iUDOMgVvFtaJYQChQoYOm5mwgyAOggMOe1wYA+ZAGQRz GIA54TEOyIVyyECAYIPNjj0I6jBg8OBomRUaEJQBw0BOxokoYJxFACHnJQVs/6C6TdjTpwcftv4o qBEjI4gaatTEdBoSAZmDUhT4wGpHSg0ncBayiRkhxOOIhtOMqYvgzTJMcDm6RRHZDmYCB/9IgXHU 8wiYPZ/GqXMnQh05DhnHCLHiTE8vlFeEiBETAQEUYc9EnljxLQGfDQUZWPECARwY0FOvzvgGx+vB N0LG8bkQTu6e1iL41CAlbJz0Pvfg+OBz6cIDakDfxC0IhQ3JQoRVxxY1qaZWZ8vgAF5hYHxwwgla 1LQSeT2BsAVyPUnUGQw1HNDTD2qYdFdelSTkkxxOoKBGDYM9AMZKCIyR03YIjoBDWGWEtxABQtQA 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 GAgAOw== ------=_NextPart_000_00C5_01C620EA.84C9EDA0 Content-Type: text/css; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Location: http://www.jorgemestre.com/wp-content/themes/connections/style.css BODY { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 0.9em; BACKGROUND: = #666666; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #000000; LINE-HEIGHT: = 1.3em; PADDING-TOP: 0px; FONT-FAMILY: 'Trebuchet MS',Georgia, Times, = Times New Roman, sans-serif; TEXT-ALIGN: center } A { FONT-WEIGHT: bold; COLOR: #000; TEXT-DECORATION: none } A:visited { COLOR: #8a3207 } A:hover { COLOR: #990000; TEXT-DECORATION: none } INPUT { BORDER-RIGHT: #a1a59a 1px solid; BORDER-TOP: #a1a59a 1px solid; = BACKGROUND: #fff; BORDER-LEFT: #a1a59a 1px solid; BORDER-BOTTOM: #a1a59a = 1px solid } TEXTAREA { BORDER-RIGHT: #a1a59a 1px solid; BORDER-TOP: #a1a59a 1px solid; = BACKGROUND: #fff; BORDER-LEFT: #a1a59a 1px solid; BORDER-BOTTOM: #a1a59a = 1px solid } #rap { PADDING-RIGHT: 8px; PADDING-LEFT: 8px; FONT-SIZE: 0.9em; BACKGROUND: = url(img/rap.jpg) #fff repeat-y center 50%; PADDING-BOTTOM: 0px; MARGIN: = 0px auto; WIDTH: 760px; PADDING-TOP: 0px; FONT-FAMILY: Trebuchet = MS,Georgia, Arial, serif; TEXT-ALIGN: left } #header { BORDER-RIGHT: #a1a5ba 0px solid; PADDING-RIGHT: 0px; BORDER-TOP: = #a1a5ba 0px solid; PADDING-LEFT: 0px; BACKGROUND: url(img/top.jpg) #fff = no-repeat 50% top; PADDING-BOTTOM: 0px; MARGIN: 0px; BORDER-LEFT: = #a1a5ba 0px solid; WIDTH: 760px; PADDING-TOP: 50px; BORDER-BOTTOM: = #a1a5ba 0px solid; HEIGHT: 133px } #main { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px = auto; WIDTH: 740px; PADDING-TOP: 0px; BACKGROUND-COLOR: #eeebeb } #content { PADDING-RIGHT: 5px; DISPLAY: inline; PADDING-LEFT: 5px; FLOAT: left; = PADDING-BOTTOM: 5px; MARGIN: 0px; OVERFLOW: hidden; WIDTH: 510px; = PADDING-TOP: 5px } #sidebar { PADDING-RIGHT: 8px; DISPLAY: inline; PADDING-LEFT: 8px; FONT-SIZE: 1em; = FLOAT: right; PADDING-BOTTOM: 10px; MARGIN: 0px; WIDTH: 186px; COLOR: = #000; PADDING-TOP: 0px; BACKGROUND-COLOR: #e2dfb2 } A IMG { BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: = none; BORDER-BOTTOM-STYLE: none } ACRONYM { BORDER-BOTTOM: #a1a59a 1px solid } abbr { BORDER-BOTTOM: #a1a59a 1px solid } ACRONYM { CURSOR: help; LETTER-SPACING: 0.07em } abbr { CURSOR: help; LETTER-SPACING: 0.07em } SPAN.caps { CURSOR: help; LETTER-SPACING: 0.07em } CODE { FONT-SIZE: 1em; FONT-STYLE: italic } BLOCKQUOTE { PADDING-RIGHT: 0px; PADDING-LEFT: 45px; BACKGROUND: = url(img/blockquote.gif) no-repeat left top; PADDING-BOTTOM: 0px; MARGIN: = 15px 30px 0px 45px; PADDING-TOP: 0px; FONT-STYLE: italic } CITE { FONT-SIZE: 0.9em; FONT-STYLE: normal } H3 { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 1.3em; = PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 0px } P { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: 0px = 0px 1em; LINE-HEIGHT: 1.5em; PADDING-TOP: 0px } H1 { FONT-WEIGHT: normal; FONT-FAMILY: lucida, Verdana, sans-serif } H2 { FONT-WEIGHT: normal; FONT-FAMILY: lucida, Verdana, sans-serif } H3 { FONT-WEIGHT: normal; FONT-FAMILY: lucida, Verdana, sans-serif } H4 { FONT-WEIGHT: normal; FONT-FAMILY: lucida, Verdana, sans-serif } #header H1 { PADDING-RIGHT: 20px; PADDING-LEFT: 0px; FONT-SIZE: 1.6em; = PADDING-BOTTOM: 0px; MARGIN: 0px; PADDING-TOP: 10px; TEXT-ALIGN: right } #header H1 A { COLOR: #f7f3ed; TEXT-DECORATION: none } #header H1 A:hover { COLOR: #b5c09d } #header #desc { PADDING-RIGHT: 20px; PADDING-LEFT: 0px; FONT-WEIGHT: normal; FONT-SIZE: = 1em; PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #b5c09d; PADDING-TOP: 0px; = FONT-STYLE: italic; TEXT-ALIGN: right } #sidebar H2 { BORDER-RIGHT: #8b8f85 0px solid; PADDING-RIGHT: 2px; BORDER-TOP: = #8b8f85 0px solid; PADDING-LEFT: 2px; FONT-WEIGHT: bold; FONT-SIZE: = 13px; PADDING-BOTTOM: 2px; MARGIN: 10px 0px 0px; BORDER-LEFT: #8b8f85 = 0px solid; COLOR: #333; PADDING-TOP: 2px; BORDER-BOTTOM: #8b8f85 0px = solid; FONT-FAMILY: Helvetica, sans-serif; HEIGHT: 22px; TEXT-ALIGN: = center } #sidebar UL { BORDER-RIGHT: #666666 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: = #666666 1px solid; PADDING-LEFT: 5px; FONT-SIZE: 0.9em; BACKGROUND: = #929d91; PADDING-BOTTOM: 5px; MARGIN: 0px; BORDER-LEFT: #666666 1px = solid; PADDING-TOP: 5px; BORDER-BOTTOM: #666666 1px solid; = LIST-STYLE-TYPE: none } #pagenav { LIST-STYLE-TYPE: none } #sidebar UL LI { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; PADDING-BOTTOM: 0px; MARGIN: = 0.1em 0px 0px; PADDING-TOP: 0px } #sidebar UL LI A { COLOR: #000000; BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; = BORDER-LEFT-STYLE: none; TEXT-DECORATION: none; BORDER-BOTTOM-STYLE: = none } #sidebar UL LI A:link { COLOR: #000000 } #sidebar UL LI A:visited { COLOR: #333333 } #sidebar UL LI A:hover { COLOR: #990000 } #sidebar UL LI A:active { COLOR: #990000 } #sidebar UL UL { PADDING-RIGHT: 5px; PADDING-LEFT: 5px; FONT-SIZE: 1em; BACKGROUND: none = transparent scroll repeat 0% 0%; PADDING-BOTTOM: 5px; MARGIN: 0px; = BORDER-TOP-STYLE: none; PADDING-TOP: 5px; BORDER-RIGHT-STYLE: none; = BORDER-LEFT-STYLE: none; LIST-STYLE-TYPE: none; BORDER-BOTTOM-STYLE: = none } #sidebar UL UL LI { PADDING-RIGHT: 0px; PADDING-LEFT: 10px; BACKGROUND: = url(img/subcat_bullet.gif) no-repeat left 50%; PADDING-BOTTOM: 0px; = MARGIN: 0px 0px 0px 10px; PADDING-TOP: 0px } #content UL { PADDING-LEFT: 45px; MARGIN-LEFT: 0px; LIST-STYLE-TYPE: none } #content UL LI { PADDING-LEFT: 1.5em; BACKGROUND: url(img/bullet.gif) no-repeat 0px 7px } .post { PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: = 0px 0px 30px; PADDING-TOP: 10px } .page { PADDING-RIGHT: 10px; PADDING-LEFT: 10px; PADDING-BOTTOM: 10px; MARGIN: = 0px 0px 30px; PADDING-TOP: 10px } .page { MARGIN: 25px -5px 0px 27px } .post-info { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 0.85em; = PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #333; PADDING-TOP: 0px; = FONT-FAMILY: verdana, Arial, Sans-Serif } .page-info { PADDING-RIGHT: 0px; PADDING-LEFT: 0px; FONT-SIZE: 0.85em; = PADDING-BOTTOM: 0px; MARGIN: 0px; COLOR: #333; PADDING-TOP: 0px; = FONT-FAMILY: verdana, Arial, Sans-Serif } .page-info { TEXT-ALIGN: center } .post-info A { FONT-WEIGHT: bold; COLOR: #990000; BORDER-TOP-STYLE: none; = BORDER-RIGHT-STYLE: none; BORDER-LEFT-STYLE: none; TEXT-DECORATION: = none; BORDER-BOTTOM-STYLE: none } .post-info A:hover { COLOR: #000 } .post-content { PADDING-RIGHT: 0px; BORDER-TOP: #bbc4a3 1px solid; PADDING-LEFT: 0px; = FONT-SIZE: 12px; PADDING-BOTTOM: 10px; MARGIN: 3px 0px; PADDING-TOP: = 10px; FONT-FAMILY: Georgia, Verdana, Arial, serif } .page-content { PADDING-RIGHT: 0px; BORDER-TOP: #bbc4a3 1px solid; PADDING-LEFT: 0px; = FONT-SIZE: 12px; PADDING-BOTTOM: 10px; MARGIN: 3px 0px; PADDING-TOP: = 10px; FONT-FAMILY: Georgia, Verdana, Arial, serif } .post-content A { FONT-WEIGHT: normal; COLOR: #6699cc; BORDER-BOTTOM: #6699cc 1px dotted } .post-content A:visited { FONT-WEIGHT: normal; COLOR: #6699cc; BORDER-BOTTOM: #6699cc 1px dotted } .post-content A:active { FONT-WEIGHT: normal; COLOR: #6699cc; BORDER-BOTTOM: #6699cc 1px dotted } .post-content A:hover { COLOR: #990000; BORDER-BOTTOM: #990000 1px dotted } .post-title { FONT-WEIGHT: normal; FONT-SIZE: 16px; MARGIN: 0px; FONT-FAMILY: Arial, = Serif } .page-title { FONT-WEIGHT: normal; FONT-SIZE: 16px; MARGIN: 0px; FONT-FAMILY: Arial, = Serif } .page-title { FONT-WEIGHT: normal; FONT-SIZE: 1.7em } #content .page-title A { COLOR: #000; TEXT-DECORATION: none } .post-title A:link { COLOR: #000; TEXT-DECORATION: none } .post-title A:visited { COLOR: #000; TEXT-DECORATION: none } .post-title A:hover { COLOR: #000; TEXT-DECORATION: none } .post-title A:active { COLOR: #000; TEXT-DECORATION: none } .post-date { PADDING-RIGHT: 3px; PADDING-LEFT: 3px; FONT-SIZE: 10px; PADDING-BOTTOM: = 8px; MARGIN: 3px 10px 0px 0px; COLOR: #333333; PADDING-TOP: 8px; = FONT-FAMILY: Verdana, Arial, Helvetica, sans-serif; TEXT-ALIGN: left } .post-footer { PADDING-TOP: 20px } #footer { CLEAR: both; PADDING-RIGHT: 0px; BORDER-TOP: #bbc4a3 1px solid; = PADDING-LEFT: 0px; FONT-SIZE: 0.8em; PADDING-BOTTOM: 7px; MARGIN: 0px = auto; WIDTH: 740px; COLOR: #999; PADDING-TOP: 7px; TEXT-ALIGN: center } #footer A { COLOR: #7a7636; BORDER-TOP-STYLE: none; BORDER-RIGHT-STYLE: none; = BORDER-LEFT-STYLE: none; BORDER-BOTTOM-STYLE: none } .commentlist { FONT-WEIGHT: normal; FONT-SIZE: 1em } #commentform { MARGIN: 0px 0px 0px 40px } #commentform TEXTAREA { WIDTH: 80% } #commentform P { MARGIN: 0px 0px 1em } #comments { MARGIN: 3em 0px 1em 40px; FONT: 0.9em verdana, helvetica, sans-serif; = TEXT-TRANSFORM: uppercase; COLOR: #676e04 } #respond { MARGIN: 3em 0px 1em 40px; FONT: 0.9em verdana, helvetica, sans-serif; = TEXT-TRANSFORM: uppercase; COLOR: #676e04 } .commentlist LI { BORDER-RIGHT: #e1d6c6 1px solid; PADDING-RIGHT: 10px; BORDER-TOP: = #e1d6c6 1px solid; PADDING-LEFT: 10px; BACKGROUND: = url(img/comments_bottom.jpg) #f3f6ed repeat-x 50% bottom; = PADDING-BOTTOM: 20px; MARGIN: 5px 0px; BORDER-LEFT: #e1d6c6 1px solid; = PADDING-TOP: 10px; BORDER-BOTTOM: #e1d6c6 1px solid } .commentlist .alt { =09 } #topnav { CLEAR: both; BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 1px; = BORDER-TOP: #000 1px solid; PADDING-LEFT: 10px; FONT-WEIGHT: normal; = FONT-SIZE: 10px; FILTER: progid:DXImageTransform.Microsoft.Alpha( = Opacity=3D85); PADDING-BOTTOM: 1px; MARGIN: 50px 0px 0px 20px; = BORDER-LEFT: #000 1px solid; WIDTH: 360px; PADDING-TOP: 1px; = BORDER-BOTTOM: #000 1px solid; FONT-FAMILY: Verdana, Arial, Sans-Serif; = LIST-STYLE-TYPE: none; BACKGROUND-COLOR: #006666; TEXT-ALIGN: left } #topnav LI { PADDING-RIGHT: 0px; DISPLAY: inline; PADDING-LEFT: 0px; PADDING-BOTTOM: = 0px; MARGIN: 0px; PADDING-TOP: 0px; LIST-STYLE-TYPE: none } #topnav LI A:link { FONT-WEIGHT: normal; COLOR: #f7f3ed; TEXT-DECORATION: none } #topnav LI A:visited { FONT-WEIGHT: normal; COLOR: #f7f3ed; TEXT-DECORATION: none } #topnav LI A:hover { COLOR: #bbc4a3 } #topnav LI A:active { COLOR: #bbc4a3 } ------=_NextPart_000_00C5_01C620EA.84C9EDA0 Content-Type: application/octet-stream Content-Transfer-Encoding: quoted-printable Content-Location: http://www.jorgemestre.com/wp-content/plugins/livecalendar/xmlhttprequest.js /* Cross-Browser XMLHttpRequest v1.1 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D Emulate Gecko 'XMLHttpRequest()' functionality in IE and Opera. Opera = requires the Sun Java Runtime Environment . by Andrew Gregory http://www.scss.com.au/family/andrew/webdesign/xmlhttprequest/ This work is licensed under the Creative Commons Attribution License. To = view a copy of this license, visit http://creativecommons.org/licenses/by/1.0/ = or send a letter to Creative Commons, 559 Nathan Abbott Way, Stanford, = California 94305, USA. Not Supported in Opera ---------------------- * user/password authentication * responseXML data member Not Fully Supported in Opera ---------------------------- * async requests * abort() * getAllResponseHeaders(), getAllResponseHeader(header) */ // IE support if (window.ActiveXObject && !window.XMLHttpRequest) { window.XMLHttpRequest =3D function() { return new = ActiveXObject((navigator.userAgent.toLowerCase().indexOf('msie 5') !=3D = -1) ? 'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP'); }; } // Gecko support /* ;-) */ // Opera support if (window.opera && !window.XMLHttpRequest) { window.XMLHttpRequest =3D function() { this.readyState =3D 0; // = 0=3Duninitialized,1=3Dloading,2=3Dloaded,3=3Dinteractive,4=3Dcomplete this.status =3D 0; // HTTP status codes this.statusText =3D ''; this._headers =3D []; this._aborted =3D false; this._async =3D true; this.abort =3D function() { this._aborted =3D true; }; this.getAllResponseHeaders =3D function() { return this.getAllResponseHeader('*'); }; this.getAllResponseHeader =3D function(header) { var ret =3D ''; for (var i =3D 0; i < this._headers.length; i++) { if (header =3D=3D '*' || this._headers[i].h =3D=3D header) { ret +=3D this._headers[i].h + ': ' + this._headers[i].v + = '\n'; } } return ret; }; this.setRequestHeader =3D function(header, value) { this._headers[this._headers.length] =3D {h:header, v:value}; }; this.open =3D function(method, url, async, user, password) { this.method =3D method; this.url =3D url; this._async =3D true; this._aborted =3D false; if (arguments.length >=3D 3) { this._async =3D async; } if (arguments.length > 3) { // user/password support requires a custom Authenticator class opera.postError('XMLHttpRequest.open() - user/password not = supported'); } this._headers =3D []; this.readyState =3D 1; if (this.onreadystatechange) { this.onreadystatechange(); } }; this.send =3D function(data) { if (!navigator.javaEnabled()) { alert("XMLHttpRequest.send() - Java must be installed and = enabled."); return; } if (this._async) { setTimeout(this._sendasync, 0, this, data); // this is not really asynchronous and won't execute until the = current // execution context ends } else { this._sendsync(data); } } this._sendasync =3D function(req, data) { if (!req._aborted) { req._sendsync(data); } }; this._sendsync =3D function(data) { this.readyState =3D 2; if (this.onreadystatechange) { this.onreadystatechange(); } // open connection var url =3D new java.net.URL(new = java.net.URL(window.location.href), this.url); var conn =3D url.openConnection(); for (var i =3D 0; i < this._headers.length; i++) { conn.setRequestProperty(this._headers[i].h, this._headers[i].v); } this._headers =3D []; if (this.method =3D=3D 'POST') { // POST data conn.setDoOutput(true); var wr =3D new = java.io.OutputStreamWriter(conn.getOutputStream()); wr.write(data); wr.flush(); wr.close(); } // read response headers // NOTE: the getHeaderField() methods always return nulls for me = :( var gotContentEncoding =3D false; var gotContentLength =3D false; var gotContentType =3D false; var gotDate =3D false; var gotExpiration =3D false; var gotLastModified =3D false; for (var i =3D 0; ; i++) { var hdrName =3D conn.getHeaderFieldKey(i); var hdrValue =3D conn.getHeaderField(i); if (hdrName =3D=3D null && hdrValue =3D=3D null) { break; } if (hdrName !=3D null) { this._headers[this._headers.length] =3D {h:hdrName, = v:hdrValue}; switch (hdrName.toLowerCase()) { case 'content-encoding': gotContentEncoding =3D true; break; case 'content-length' : gotContentLength =3D true; break; case 'content-type' : gotContentType =3D true; break; case 'date' : gotDate =3D true; break; case 'expires' : gotExpiration =3D true; break; case 'last-modified' : gotLastModified =3D true; break; } } } // try to fill in any missing header information var val; val =3D conn.getContentEncoding(); if (val !=3D null && !gotContentEncoding) = this._headers[this._headers.length] =3D {h:'Content-encoding', v:val}; val =3D conn.getContentLength(); if (val !=3D -1 && !gotContentLength) = this._headers[this._headers.length] =3D {h:'Content-length', v:val}; val =3D conn.getContentType(); if (val !=3D null && !gotContentType) = this._headers[this._headers.length] =3D {h:'Content-type', v:val}; val =3D conn.getDate(); if (val !=3D 0 && !gotDate) this._headers[this._headers.length] = =3D {h:'Date', v:(new Date(val)).toUTCString()}; val =3D conn.getExpiration(); if (val !=3D 0 && !gotExpiration) = this._headers[this._headers.length] =3D {h:'Expires', v:(new = Date(val)).toUTCString()}; val =3D conn.getLastModified(); if (val !=3D 0 && !gotLastModified) = this._headers[this._headers.length] =3D {h:'Last-modified', v:(new = Date(val)).toUTCString()}; // read response data var reqdata =3D ''; var stream =3D conn.getInputStream(); if (stream) { var reader =3D new java.io.BufferedReader(new = java.io.InputStreamReader(stream)); var line; while ((line =3D reader.readLine()) !=3D null) { if (this.readyState =3D=3D 2) { this.readyState =3D 3; if (this.onreadystatechange) { this.onreadystatechange(); } } reqdata +=3D line + '\n'; } reader.close(); this.status =3D 200; this.statusText =3D 'OK'; this.responseText =3D reqdata; this.readyState =3D 4; if (this.onreadystatechange) { this.onreadystatechange(); } if (this.onload) { this.onload(); } } else { // error this.status =3D 404; this.statusText =3D 'Not Found'; this.responseText =3D ''; this.readyState =3D 4; if (this.onreadystatechange) { this.onreadystatechange(); } if (this.onerror) { this.onerror(); } } }; }; } // ActiveXObject emulation if (!window.ActiveXObject && window.XMLHttpRequest) { window.ActiveXObject =3D function(type) { switch (type.toLowerCase()) { case 'microsoft.xmlhttp': case 'msxml2.xmlhttp': return new XMLHttpRequest(); } return null; }; } ------=_NextPart_000_00C5_01C620EA.84C9EDA0 Content-Type: application/octet-stream Content-Transfer-Encoding: quoted-printable Content-Location: http://www.jorgemestre.com/wp-content/plugins/livecalendar/kcalendarscript.php var week_begins =3D 1; var thismonth =3D 01; var thisyear =3D 2006; var firstpost =3D ''; var min_year =3D 2005; var min_month =3D 11; var permastruct =3D '/?m=3D%year%%monthnum%%day%'; var m_permastruct=3D '/?m=3D%year%%monthnum%'; var has_fp =3D false; var dateDay =3D new Array('Domingo', 'Lunes', 'Martes', = 'Miércoles', 'Jueves', 'Viernes', 'Sábado'); var dateDayShort =3D new Array('D', 'L', 'M', 'X', 'J', 'V', 'S'); var dateDayAbbr =3D new Array('Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', = 'Sab'); var dateMon =3D new Array('Enero', 'Febrero', 'Marzo', 'Abril', = 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', = 'Noviembre', 'Diciembre'); var dateMonShort =3D new Array('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', = 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic'); var archives =3D 'Archivos:'; var viewpostsfor_=3D 'Ver todas las entradas para %1$s %2$s'; var siteurl =3D 'http://www.jorgemestre.com'; function viewpostsfor(year,month) { return = viewpostsfor_.replace("%1\$s",dateMon[month]).replace("%2\$s",year); =20 } var unixmonth =3D new Date(thisyear,thismonth-1,1); unixmonth.setYear(thisyear); // to be sure it's a 4 digit value. var entries_cache=3Dnew Array(); var tocall; function addEvent(el,ev,fn){ if(el.attachEvent)el.attachEvent('on'+ev,fn); else if(el.addEventListener)el.addEventListener(ev,fn,false); } if(typeof window.XMLHttpRequest!=3D"undefined") { if(navigator.userAgent.indexOf('KHTML')>0){ setTimeout('kcalendar_refresh()',2000); }else{ addEvent(window,'load',kcalendar_refresh); } } function kcalendar_build(year,month,day){ var today=3Dnew Date; shownDate=3Dnew Date(year,month,day); cal=3Ddocument.createElement('table'); cal.id=3D"wp-calendar"; // caption caption=3Ddocument.createElement('caption'); = caption.appendChild(document.createTextNode(dateMon[shownDate.getMonth()]= +' '+shownDate.getFullYear())); cal.appendChild(caption); caption.id=3D"wp-calendar_caption"; =20 // draw day headers // "var wd" value sets weekday display style; currently set to = dateDayAbbr (Sun) // swap commenting on "var wd" entries for weekday displays of either = dateDayShort (S) or dateDay (Sunday) cal_head =3D document.createElement('THEAD'); cal.appendChild(cal_head);=20 cal_row=3Dcal_head.insertRow(0); cal_row.id=3D"calendar_daysRow"; for(i=3D0;i<7;i++){ cal_cell =3D document.createElement('TH'); cal_row.appendChild(cal_cell); var wd =3D dateDayShort[(i+week_begins)%7]; // var wd =3D dateDayAbbr[(i+week_begins)%7]; // var wd =3D dateDay[(i+week_begins)%7]; cal_cell.appendChild(document.createTextNode(wd)); cal_cell.abbr =3Dwd; cal_cell.title=3Dwd; cal_cell.scope=3D"col"; } =20 // draw navigation row month cal_foot =3D document.createElement('TFOOT'); cal.appendChild(cal_foot); cal_row=3Dcal_foot.insertRow(0); cal_cell=3Dcal_row.insertCell(0); link_year=3DshownDate.getFullYear(); link_month=3DshownDate.getMonth()-1; if(link_month=3D=3D-1){link_month=3D11;link_year--;} =20 // print prev. month nav if we have a post from back then... if(link_year > min_year || (link_year =3D=3D min_year && link_month+1 = >=3D min_month)) { link=3Ddocument.createElement('a'); link.appendChild(document.createTextNode(String.fromCharCode(171)+" = " + dateMonShort[link_month])); = link.href=3D"javascript:kcalendar_refresh("+link_year+","+(link_month+1)+= ");"; link.title =3D viewpostsfor(link_year,link_month) cal_cell.appendChild(link); } else { cal_cell.className=3D'pad'; } cal_cell.colSpan=3D3; cal_cell.abbr=3DdateMonShort[link_month]; cal_cell.id=3D"prev" cal_cell=3Dcal_row.insertCell(1); cal_cell.className=3D"pad"; spinner =3D document.createElement("IMG"); spinner.id=3D"calendar_spin"; spinner.src =3D siteurl + "/wp-content/plugins/livecalendar/wait.gif"; cal_cell.appendChild(spinner); cal_cell=3Dcal_row.insertCell(2); cal_cell.colSpan=3D3; cal_cell.className=3D"pad"; link_year=3DshownDate.getFullYear(); link_month=3DshownDate.getMonth()+1; if(link_month=3D=3D12){link_month=3D0;link_year++;} if(link_year min_year || (link_year =3D=3D min_year && link_month = >=3D min_month)){ link=3Ddocument.createElement('a'); link.appendChild(document.createTextNode(String.fromCharCode(171)+" = " + [link_year])); = link.href=3D"javascript:kcalendar_refresh("+link_year+","+(link_month+1)+= ");"; link.title =3D viewpostsfor(link_year,link_month) cal_cell.appendChild(link); } else { cal_cell.className =3D 'pad' } cal_cell.colSpan=3D3; cal_cell.abbr=3D[link_year]; cal_cell.id=3D"prev" cal_cell=3Dcal_row.insertCell(1); cal_cell.className=3D"pad"; cal_cell=3Dcal_row.insertCell(2); cal_cell.colSpan=3D3; cal_cell.className=3D"pad"; link_year=3DshownDate.getFullYear()+1; link_month=3DshownDate.getMonth(); if(link_year1)cellDate-=3D7; // draw rest of month = days_in_last_month=3Dkcalendar_daysInMonth(shownDate.getFullYear(),shownD= ate.getMonth()-1); for(i=3D0;i<6;i++){ cal_row=3Dcal_body.insertRow(i); for(j=3D0;j<7;j++){ cal_cell=3Dcal_row.insertCell(j); class_to_show=3D''; if(cellDate<1){ class_to_show=3D'pad'; num_to_show=3D'';//days_in_last_month+cellDate; }else = if(cellDate>kcalendar_daysInMonth(shownDate.getFullYear(),shownDate.getMo= nth())){ class_to_show=3D'pad'; = num_to_show=3D'';//cellDate-kcalendar_daysInMonth(shownDate.getFullYear()= ,shownDate.getMonth()); }else{ num_to_show=3DcellDate; class_to_show=3D''; if(shownDate.getFullYear()=3D=3Dtoday.getFullYear() && = shownDate.getMonth()=3D=3Dtoday.getMonth() && = cellDate=3D=3Dtoday.getDate()){ cal_cell.id=3D'today'; class_to_show=3D''; } } cal_cell.appendChild(document.createTextNode(num_to_show)); cal_cell.className=3Dclass_to_show; if(cal_cell.id !=3D 'today') { = cal_cell.id=3D"kcalendar_"+shownDate.getFullYear()+"_"+(shownDate.getMont= h()+1)+"_"+cellDate; } cellDate++; } } =20 = tocall=3D'kcalendar_'+(shownDate.getFullYear())+"_"+(shownDate.getMonth()= ); return cal; } function kcalendar_create_links(arr){ if(arr.length =3D=3D 0) return; for(i=3D0;i1){ split=3Dsplit[0].split(/-/); text=3Del.childNodes[0]; el2=3Ddocument.createElement('a'); el2.title=3D archives+' '+dateMon[split[1]-1]+ ' ' +split[0]; el2.appendChild(text); el2.href =3D siteurl + m_permastruct; el2.href =3D el2.href.replace(/%year%/,split[0]); el2.href =3D el2.href.replace(/%monthnum%/,split[1]); // create fancy tooltips if the plugin is enabled... if( has_fp =3D=3D true ) FancyTooltips.autoCreation(); el.appendChild(el2); } } function kcalendar_daysInMonth(year,month){ if(month<0){month+=3D12;year--} if(month=3D=3D3||month=3D=3D5||month=3D=3D8||month=3D=3D10)return 30; if(month!=3D1)return 31; if(!(year%4))return 29; return 28; } function kcalendar_refresh(year,month){ if(isNaN(year)){ year=3Dunixmonth.getFullYear(); month=3Dunixmonth.getMonth(); } else { month--; } if(month<0 ){month+=3D12;year--} if(month>11){month-=3D12;year++} el=3Ddocument.getElementById('calendar'); if(!el) { el2=3Ddocument.getElementById('wp-calendar'); if(el2){ el=3Ddocument.createElement('div'); el.id=3D'calendar'; el3=3Del2.parentNode; el3.insertBefore(el,el2); el3.removeChild(el2); el.appendChild(el2); } } if(!el) return; els=3Del.childNodes; for(i=3Del.childNodes.length-1;i>-1;i--)el.removeChild(els[i]); cal=3Dkcalendar_build(year,month,1); el.appendChild(cal); // get any applicable links for the dates if(entries_cache[tocall]){ kcalendar_create_links(entries_cache[tocall]); el=3Ddocument.getElementById('calendar_spin'); if(el) el.parentNode.removeChild(el); }else{ var req =3D new XMLHttpRequest(); if (req) { req.onreadystatechange=3Dfunction(){ if(req.readyState=3D=3D4&&req.status=3D=3D200) { entries_cache[tocall]=3D(req.responseText)? req.responseText.split(/\n/): []; kcalendar_create_links(entries_cache[tocall]); el=3Ddocument.getElementById('calendar_spin'); if(el) el.parentNode.removeChild(el); } }; req.open('GET', siteurl + = '/wp-content/plugins/livecalendar/kcalendar.php?year=3D'+shownDate.getFul= lYear()+'&month=3D'+(shownDate.getMonth()+1)); if(navigator.userAgent.indexOf('KHTML')=3D=3D-1)req.send(null); else req.send(); } } } ------=_NextPart_000_00C5_01C620EA.84C9EDA0 Content-Type: application/octet-stream Content-Transfer-Encoding: quoted-printable Content-Location: http://www.jorgemestre.com/wp-content/plugins/xinha4wp/xinha_core/htmlarea.js =0A= = /*--------------------------------------:noTabs=3Dtrue:tabSize=3D2:indent= Size=3D2:--=0A= -- Xinha (is not htmlArea) - http://xinha.gogo.co.nz/=0A= --=0A= -- Use of Xinha is granted by the terms of the htmlArea License = (based on=0A= -- BSD license) please read license.txt in this package for = details.=0A= --=0A= -- Xinha was originally based on work by Mihai Bazon which is:=0A= -- Copyright (c) 2003-2004 dynarch.com.=0A= -- Copyright (c) 2002-2003 interactivetools.com, inc.=0A= -- This copyright notice MUST stay intact for use.=0A= --=0A= -- Developers - Coding Style:=0A= -- For the sake of not committing needlessly conflicting changes,=0A= --=0A= -- * New code to be indented with 2 spaces ("soft tab").=0A= -- * New code preferably uses BSD-Style Bracing=0A= -- if(foo)=0A= -- {=0A= -- bar();=0A= -- }=0A= -- * Don't change brace styles unless you're working on the non = BSD-Style=0A= -- area (so we don't get spurious changes in line numbering).=0A= -- * Don't change indentation unless you're working on the badly = indented=0A= -- area (so we don't get spurious changes of large blocks of = code).=0A= -- * Jedit is the recommended editor, a comment of this format = should be=0A= -- included in the top 10 lines of the file (see the embedded = edit mode)=0A= --=0A= -- $HeadURL: http://svn.xinha.python-hosting.com/trunk/htmlarea.js $=0A= -- $LastChangedDate: 2005-09-14 19:13:33 +1200 (Wed, 14 Sep 2005) $=0A= -- $LastChangedRevision: 316 $=0A= -- $LastChangedBy: niko $=0A= = -------------------------------------------------------------------------= -*/=0A= =0A= HTMLArea.version =3D=0A= {=0A= 'Release' : 'Trunk',=0A= 'Head' : '$HeadURL: = http://svn.xinha.python-hosting.com/trunk/htmlarea.js = $'.replace(/^[^:]*: (.*) \$$/, '$1'),=0A= 'Date' : '$LastChangedDate: 2005-09-14 19:13:33 +1200 (Wed, 14 = Sep 2005) $'.replace(/^[^:]*: ([0-9-]*) ([0-9:]*) ([+0-9]*) \((.*)\) = \$/, '$4 $2 $3'),=0A= 'Revision' : '$LastChangedRevision: 316 $'.replace(/^[^:]*: (.*) = \$$/, '$1'),=0A= 'RevisionBy': '$LastChangedBy: niko $'.replace(/^[^:]*: (.*) \$$/, = '$1')=0A= }=0A= =0A= if (typeof _editor_url =3D=3D "string") {=0A= // Leave exactly one backslash at the end of _editor_url=0A= _editor_url =3D _editor_url.replace(/\x2f*$/, '/');=0A= } else {=0A= alert("WARNING: _editor_url is not set! You should set this variable = to the editor files path; it should preferably be an absolute path, like = in '/htmlarea/', but it can be relative if you prefer. Further we will = try to load the editor files correctly but we'll probably fail.");=0A= _editor_url =3D '';=0A= }=0A= =0A= // make sure we have a language=0A= if (typeof _editor_lang =3D=3D "string") {=0A= _editor_lang =3D _editor_lang.toLowerCase();=0A= } else {=0A= _editor_lang =3D "en";=0A= }=0A= =0A= // skin stylesheet to load=0A= if (!(typeof _editor_skin =3D=3D "string")) {=0A= _editor_skin =3D "";=0A= }=0A= =0A= var __htmlareas =3D [ ];=0A= =0A= // browser identification=0A= HTMLArea.agt =3D navigator.userAgent.toLowerCase();=0A= HTMLArea.is_ie =3D ((HTMLArea.agt.indexOf("msie") !=3D -1) && = (HTMLArea.agt.indexOf("opera") =3D=3D -1));=0A= HTMLArea.is_opera =3D (HTMLArea.agt.indexOf("opera") !=3D -1);=0A= HTMLArea.is_mac =3D (HTMLArea.agt.indexOf("mac") !=3D -1);=0A= HTMLArea.is_mac_ie =3D (HTMLArea.is_ie && HTMLArea.is_mac);=0A= HTMLArea.is_win_ie =3D (HTMLArea.is_ie && !HTMLArea.is_mac);=0A= HTMLArea.is_gecko =3D (navigator.product =3D=3D "Gecko");=0A= =0A= // Creates a new HTMLArea object. Tries to replace the textarea with = the given=0A= // ID with it.=0A= function HTMLArea(textarea, config)=0A= {=0A= if(!textarea) throw("Tried to create HTMLArea without textarea = specified.");=0A= =0A= if (HTMLArea.checkSupportedBrowser()) {=0A= if (typeof config =3D=3D "undefined") {=0A= this.config =3D new HTMLArea.Config();=0A= } else {=0A= this.config =3D config;=0A= }=0A= this._htmlArea =3D null;=0A= =0A= if(typeof textarea !=3D 'object')=0A= {=0A= textarea =3D HTMLArea.getElementById('textarea', textarea);=0A= }=0A= this._textArea =3D textarea;=0A= =0A= // Before we modify anything, get the initial textarea size=0A= this._initial_ta_size =3D=0A= {=0A= w: textarea.style.width ? textarea.style.width : = (textarea.offsetWidth + 'px'),=0A= h: textarea.style.height ? textarea.style.height : = (textarea.offsetHeight + 'px')=0A= }=0A= =0A= this._editMode =3D "wysiwyg";=0A= this.plugins =3D {};=0A= this._timerToolbar =3D null;=0A= this._timerUndo =3D null;=0A= this._undoQueue =3D new Array(this.config.undoSteps);=0A= this._undoPos =3D -1;=0A= this._customUndo =3D true;=0A= this._mdoc =3D document; // cache the document, we need it in plugins=0A= this.doctype =3D '';=0A= this.__htmlarea_id_num =3D __htmlareas.length;=0A= __htmlareas[this.__htmlarea_id_num] =3D this;=0A= =0A= this._notifyListeners =3D { };=0A= =0A= // Panels=0A= var panels =3D this._panels =3D=0A= {=0A= right:=0A= {=0A= on: true,=0A= container: document.createElement('td'),=0A= panels: [ ]=0A= },=0A= left:=0A= {=0A= on: true,=0A= container: document.createElement('td'),=0A= panels: [ ]=0A= },=0A= top:=0A= {=0A= on: true,=0A= container: document.createElement('td'),=0A= panels: [ ]=0A= },=0A= bottom:=0A= {=0A= on: true,=0A= container: document.createElement('td'),=0A= panels: [ ]=0A= }=0A= };=0A= =0A= for(var i in panels)=0A= {=0A= panels[i].div =3D panels[i].container; // legacy=0A= panels[i].container.className =3D 'panels ' + i;=0A= HTMLArea.freeLater(panels[i], 'container');=0A= HTMLArea.freeLater(panels[i], 'div'); =0A= }=0A= HTMLArea.freeLater(this, '_textArea');=0A= }=0A= };=0A= =0A= HTMLArea.onload =3D function(){};=0A= HTMLArea.init =3D function() {=0A= HTMLArea.onload();=0A= };=0A= =0A= =0A= // cache some regexps=0A= HTMLArea.RE_tagName =3D /(<\/|<)\s*([^ \t\n>]+)/ig;=0A= HTMLArea.RE_doctype =3D /()\n?/i;=0A= HTMLArea.RE_head =3D /((.|\n)*?)<\/head>/i;=0A= HTMLArea.RE_body =3D /]*>((.|\n|\r|\t)*?)<\/body>/i;=0A= HTMLArea.RE_Specials =3D /([\/\^$*+?.()|{}[\]])/g;=0A= HTMLArea.RE_email =3D = /[a-z0-9_]{3,}@[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,})+/i;=0A= HTMLArea.RE_url =3D = /(https?:\/\/)?(([a-z0-9_]+:[a-z0-9_]+@)?[a-z0-9_-]{2,}(\.[a-z0-9_-]{2,})= {2,}(:[0-9]+)?(\/\S+)*)/i;=0A= =0A= HTMLArea.Config =3D function () {=0A= var cfg =3D this;=0A= this.version =3D HTMLArea.version.Revision;=0A= =0A= // Width and Height=0A= // you may set these as follows=0A= // width =3D 'auto' -- the width of the original textarea will = be used=0A= // width =3D 'toolbar' -- the width of the toolbar will be used=0A= // width =3D '' -- use any css measurement, eg width =3D = '75%'=0A= //=0A= // height =3D 'auto' -- the height of the original textarea=0A= // height =3D '' -- any css measurement, eg height =3D = '480px'=0A= this.width =3D "auto";=0A= this.height =3D "auto";=0A= =0A= // the next parameter specifies whether the toolbar should be included=0A= // in the size above, or are extra to it. If false then it's = recommended=0A= // to have explicit pixel sizes above (or on your textarea and have = auto above)=0A= this.sizeIncludesBars =3D true;=0A= =0A= // the next parameter specifies whether the panels should be included=0A= // in the size above, or are extra to it. If false then it's = recommended=0A= // to have explicit pixel sizes above (or on your textarea and have = auto above)=0A= this.sizeIncludesPanels =3D true;=0A= =0A= // each of the panels has a dimension, for the left/right it's the = width=0A= // for the top/bottom it's the height.=0A= //=0A= // WARNING: PANEL DIMENSIONS MUST BE SPECIFIED AS PIXEL WIDTHS=0A= this.panel_dimensions =3D=0A= {=0A= left: '200px', // Width=0A= right: '200px',=0A= top: '100px', // Height=0A= bottom: '100px'=0A= }=0A= =0A= // enable creation of a status bar?=0A= this.statusBar =3D true;=0A= =0A= // intercept ^V and use the HTMLArea paste command=0A= // If false, then passes ^V through to browser editor widget=0A= this.htmlareaPaste =3D false;=0A= =0A= this.mozParaHandler =3D 'best'; // set to 'built-in', 'dirty' or 'best'=0A= // built-in: will (may) use 'br' instead = of 'p' tags=0A= // dirty : will use p and work good = enough for the majority of cases,=0A= // best : works the best, but it's = about 12kb worth of javascript=0A= // and will probably be slower than = 'dirty'. This is the "EnterParagraphs"=0A= // plugin from "hipikat", rolled in to = be part of the core code=0A= =0A= // maximum size of the undo queue=0A= this.undoSteps =3D 20;=0A= =0A= // the time interval at which undo samples are taken=0A= this.undoTimeout =3D 500; // 1/2 sec.=0A= =0A= // if true then HTMLArea will retrieve the full HTML, starting with the=0A= // tag.=0A= this.fullPage =3D false;=0A= =0A= // style included in the iframe document=0A= this.pageStyle =3D "";=0A= =0A= // external stylesheets to load (REFERENCE THESE ABSOLUTELY)=0A= this.pageStyleSheets =3D [ ];=0A= =0A= // specify a base href for relative links=0A= this.baseHref =3D null;=0A= =0A= // we can strip the base href out of relative links to leave them = relative, reason for this=0A= // especially if you don't specify a baseHref is that mozilla at = least (& IE ?) will prefix=0A= // the baseHref to any relative links to make them absolute, which = isn't what you want most the time.=0A= this.stripBaseHref =3D true;=0A= =0A= // and we can strip the url of the editor page from named links (eg ...)=0A= // reason for this is that mozilla at least (and IE ?) prefixes = location.href to any=0A= // that don't have a url prefixing them=0A= this.stripSelfNamedAnchors =3D true;=0A= =0A= // sometimes high-ascii in links can cause problems for servers = (basically they don't recognise them)=0A= // so you can use this flag to ensure that all characters other than = the normal ascii set (actually=0A= // only ! through ~) are escaped in URLs to % codes=0A= this.only7BitPrintablesInURLs =3D true;=0A= =0A= // if you are putting the HTML written in Xinha into an email you = might want it to be 7-bit=0A= // characters only. This config option (off by default) will convert = all characters consuming=0A= // more than 7bits into UNICODE decimal entity references (actually = it will convert anything=0A= // below (chr 20) except cr, lf and tab and above (~, = chr 7E))=0A= this.sevenBitClean =3D false;=0A= =0A= // sometimes we want to be able to replace some string in the html = comng in and going out=0A= // so that in the editor we use the "internal" string, and outside = and in the source view=0A= // we use the "external" string this is useful for say making = special codes for=0A= // your absolute links, your external string might be some special = code, say "{server_url}"=0A= // an you say that the internal represenattion of that should be = http://your.server/=0A= this.specialReplacements =3D { }; // { 'external_string' : = 'internal_string' }=0A= =0A= // set to true if you want Word code to be cleaned upon Paste=0A= this.killWordOnPaste =3D true;=0A= =0A= // enable the 'Target' field in the Make Link dialog=0A= this.makeLinkShowsTarget =3D true;=0A= =0A= // CharSet of the iframe, default is the charset of the document=0A= this.charSet =3D HTMLArea.is_gecko ? document.characterSet : = document.charset;=0A= =0A= // URL-s=0A= this.imgURL =3D "images/";=0A= this.popupURL =3D "popups/";=0A= this.helpURL =3D _editor_url + "reference.html";=0A= =0A= // remove tags (these have to be a regexp, or null if this = functionality is not desired)=0A= this.htmlRemoveTags =3D null;=0A= =0A= // Turning this on will turn all "linebreak" and "separator" items in = your toolbar into soft-breaks,=0A= // this means that if the items between that item and the next = linebreak/separator can=0A= // fit on the same line as that which came before then they will, = otherwise they will=0A= // float down to the next line.=0A= =0A= // If you put a linebreak and separator next to each other, only the = separator will=0A= // take effect, this allows you to have one toolbar that works for = both flowToolbars =3D true and false=0A= // infact the toolbar below has been designed in this way, if = flowToolbars is false then it will=0A= // create explictly two lines (plus any others made by plugins) = breaking at justifyleft, however if=0A= // flowToolbars is false and your window is narrow enough then it will = create more than one line=0A= // even neater, if you resize the window the toolbars will reflow. = Niiiice.=0A= =0A= this.flowToolbars =3D true;=0A= =0A= /** CUSTOMIZING THE TOOLBAR=0A= * -------------------------=0A= *=0A= * It is recommended that you customize the toolbar contents in an=0A= * external file (i.e. the one calling HTMLArea) and leave this one=0A= * unchanged. That's because when we (InteractiveTools.com) release a=0A= * new official version, it's less likely that you will have problems=0A= * upgrading HTMLArea.=0A= */=0A= this.toolbar =3D=0A= [=0A= ["popupeditor"],=0A= = ["separator","formatblock","fontname","fontsize","bold","italic","underli= ne","strikethrough"],=0A= ["separator","forecolor","hilitecolor","textindicator"],=0A= ["separator","subscript","superscript"],=0A= = ["linebreak","separator","justifyleft","justifycenter","justifyright","ju= stifyfull"],=0A= = ["separator","insertorderedlist","insertunorderedlist","outdent","indent"= ],=0A= = ["separator","inserthorizontalrule","createlink","insertimage","inserttab= le"],=0A= ["separator","undo","redo","selectall"], (HTMLArea.is_gecko ? [] : = ["cut","copy","paste","overwrite","saveas"]),=0A= = ["separator","killword","removeformat","toggleborders","lefttoright", = "righttoleft","separator","htmlmode","about"]=0A= ];=0A= =0A= =0A= this.fontname =3D {=0A= "— font —": '',=0A= "Arial": 'arial,helvetica,sans-serif',=0A= "Courier New": 'courier new,courier,monospace',=0A= "Georgia": 'georgia,times new roman,times,serif',=0A= "Tahoma": 'tahoma,arial,helvetica,sans-serif',=0A= "Times New Roman": 'times new roman,times,serif',=0A= "Verdana": 'verdana,arial,helvetica,sans-serif',=0A= "impact": 'impact',=0A= "WingDings": 'wingdings'=0A= };=0A= =0A= this.fontsize =3D {=0A= "— size —" : "",=0A= "1 (8 pt)" : "1",=0A= "2 (10 pt)": "2",=0A= "3 (12 pt)": "3",=0A= "4 (14 pt)": "4",=0A= "5 (18 pt)": "5",=0A= "6 (24 pt)": "6",=0A= "7 (36 pt)": "7"=0A= };=0A= =0A= this.formatblock =3D {=0A= "— format —" : "",=0A= "Heading 1": "h1",=0A= "Heading 2": "h2",=0A= "Heading 3": "h3",=0A= "Heading 4": "h4",=0A= "Heading 5": "h5",=0A= "Heading 6": "h6",=0A= "Normal" : "p",=0A= "Address" : "address",=0A= "Formatted": "pre"=0A= };=0A= =0A= this.customSelects =3D {};=0A= =0A= function cut_copy_paste(e, cmd, obj) {=0A= e.execCommand(cmd);=0A= };=0A= =0A= this.debug =3D true;=0A= =0A= this.URIs =3D {=0A= "blank": "popups/blank.html",=0A= "link": "link.html",=0A= "insert_image": "insert_image.html",=0A= "insert_table": "insert_table.html",=0A= "select_color": "select_color.html",=0A= "about": "about.html"=0A= };=0A= =0A= =0A= // ADDING CUSTOM BUTTONS: please read below!=0A= // format of the btnList elements is "ID: [ ToolTip, Icon, Enabled in = text mode?, ACTION ]"=0A= // - ID: unique ID for the button. If the button calls = document.execCommand=0A= // it's wise to give it the same name as the called command.=0A= // - ACTION: function that gets called when the button is clicked.=0A= // it has the following prototype:=0A= // function(editor, buttonName)=0A= // - editor is the HTMLArea object that triggered the call=0A= // - buttonName is the ID of the clicked button=0A= // These 2 parameters makes it possible for you to use = the same=0A= // handler for more HTMLArea objects or for more = different buttons.=0A= // - ToolTip: tooltip, will be translated below=0A= // - Icon: path to an icon image file for the button=0A= // OR; you can use an 18x18 block of a larger image by = supllying an array=0A= // that has three elemtents, the first is the larger image, = the second is the column=0A= // the third is the row. The ros and columns numbering = starts at 0 but there is=0A= // a header row and header column which have numbering to = make life easier.=0A= // See images/buttons_main.gif to see how it's done.=0A= // - Enabled in text mode: if false the button gets disabled for = text-only mode; otherwise enabled all the time.=0A= this.btnList =3D {=0A= bold: [ "Bold", HTMLArea._lc({key: 'button_bold', string: = ["ed_buttons_main.gif",3,2]}, 'HTMLArea'), false, function(e) = {e.execCommand("bold");} ],=0A= italic: [ "Italic", HTMLArea._lc({key: 'button_italic', = string: ["ed_buttons_main.gif",2,2]}, 'HTMLArea'), false, function(e) = {e.execCommand("italic");} ],=0A= underline: [ "Underline", HTMLArea._lc({key: 'button_underline', = string: ["ed_buttons_main.gif",2,0]}, 'HTMLArea'), false, function(e) = {e.execCommand("underline");} ],=0A= strikethrough: [ "Strikethrough", HTMLArea._lc({key: = 'button_strikethrough', string: ["ed_buttons_main.gif",3,0]}, = 'HTMLArea'), false, function(e) {e.execCommand("strikethrough");} ],=0A= subscript: [ "Subscript", HTMLArea._lc({key: 'button_subscript', = string: ["ed_buttons_main.gif",3,1]}, 'HTMLArea'), false, function(e) = {e.execCommand("subscript");} ],=0A= superscript: [ "Superscript", HTMLArea._lc({key: = 'button_superscript', string: ["ed_buttons_main.gif",2,1]}, 'HTMLArea'), = false, function(e) {e.execCommand("superscript");} ],=0A= =0A= justifyleft: [ "Justify Left", ["ed_buttons_main.gif",0,0], false, = function(e) {e.execCommand("justifyleft");} ],=0A= justifycenter: [ "Justify Center", ["ed_buttons_main.gif",1,1], = false, function(e){e.execCommand("justifycenter");}],=0A= justifyright: [ "Justify Right", ["ed_buttons_main.gif",1,0], false, = function(e) {e.execCommand("justifyright");} ],=0A= justifyfull: [ "Justify Full", ["ed_buttons_main.gif",0,1], false, = function(e) {e.execCommand("justifyfull");} ],=0A= =0A= =0A= orderedlist: [ "Ordered List", ["ed_buttons_main.gif",0,3], false, = function(e) {e.execCommand("insertorderedlist");} ],=0A= unorderedlist: [ "Bulleted List", ["ed_buttons_main.gif",1,3], = false, function(e) {e.execCommand("insertunorderedlist");} ],=0A= insertorderedlist: [ "Ordered List", ["ed_buttons_main.gif",0,3], = false, function(e) {e.execCommand("insertorderedlist");} ],=0A= insertunorderedlist: [ "Bulleted List", ["ed_buttons_main.gif",1,3], = false, function(e) {e.execCommand("insertunorderedlist");} ],=0A= =0A= outdent: [ "Decrease Indent", ["ed_buttons_main.gif",1,2], false, = function(e) {e.execCommand("outdent");} ],=0A= indent: [ "Increase Indent",["ed_buttons_main.gif",0,2], false, = function(e) {e.execCommand("indent");} ],=0A= forecolor: [ "Font Color", ["ed_buttons_main.gif",3,3], false, = function(e) {e.execCommand("forecolor");} ],=0A= hilitecolor: [ "Background Color", ["ed_buttons_main.gif",2,3], = false, function(e) {e.execCommand("hilitecolor");} ],=0A= =0A= undo: [ "Undoes your last action", ["ed_buttons_main.gif",4,2], = false, function(e) {e.execCommand("undo");} ],=0A= redo: [ "Redoes your last action", ["ed_buttons_main.gif",5,2], = false, function(e) {e.execCommand("redo");} ],=0A= cut: [ "Cut selection", ["ed_buttons_main.gif",5,0], false, = cut_copy_paste ],=0A= copy: [ "Copy selection", ["ed_buttons_main.gif",4,0], false, = cut_copy_paste ],=0A= paste: [ "Paste from clipboard", ["ed_buttons_main.gif",4,1], false, = cut_copy_paste ],=0A= selectall: [ "Select all", "ed_selectall.gif", false, function(e) = {e.execCommand("selectall");} ],=0A= =0A= =0A= inserthorizontalrule: [ "Horizontal Rule", = ["ed_buttons_main.gif",6,0], false, function(e) = {e.execCommand("inserthorizontalrule");} ],=0A= createlink: [ "Insert Web Link", ["ed_buttons_main.gif",6,1], false, = function(e) {e._createLink();} ],=0A= insertimage: [ "Insert/Modify Image", ["ed_buttons_main.gif",6,3], = false, function(e) {e.execCommand("insertimage");} ],=0A= inserttable: [ "Insert Table", ["ed_buttons_main.gif",6,2], false, = function(e) {e.execCommand("inserttable");} ],=0A= =0A= =0A= htmlmode: [ "Toggle HTML Source", ["ed_buttons_main.gif",7,0], true, = function(e) {e.execCommand("htmlmode");} ],=0A= toggleborders: [ "Toggle Borders", ["ed_buttons_main.gif",7,2], = false, function(e) { e._toggleBorders() } ],=0A= print: [ "Print document", ["ed_buttons_main.gif",8,1], = false, function(e) {e._iframe.contentWindow.print();} ],=0A= saveas: [ "Save as", "ed_saveas.gif", false, function(e) = {e.execCommand("saveas",false,"noname.htm");} ],=0A= about: [ "About this editor", ["ed_buttons_main.gif",8,2], true, = function(e) {e.execCommand("about");} ],=0A= showhelp: [ "Help using editor", ["ed_buttons_main.gif",9,2], true, = function(e) {e.execCommand("showhelp");} ],=0A= =0A= splitblock: [ "Split Block", "ed_splitblock.gif", false, = function(e) {e._splitBlock();} ],=0A= lefttoright: [ "Direction left to right", = ["ed_buttons_main.gif",0,4], false, function(e) = {e.execCommand("lefttoright");} ],=0A= righttoleft: [ "Direction right to left", = ["ed_buttons_main.gif",1,4], false, function(e) = {e.execCommand("righttoleft");} ],=0A= overwrite: [ "Insert/Overwrite", "ed_overwrite.gif", false, = function(e) {e.execCommand("overwrite");} ],=0A= =0A= wordclean: [ "MS Word Cleaner", ["ed_buttons_main.gif",5,3], = false, function(e) {e._wordClean();} ],=0A= clearfonts: [ "Clear Inline Font Specifications", = ["ed_buttons_main.gif",5,4], false, function(e) {e._clearFonts();} ],=0A= removeformat: [ "Remove formatting", ["ed_buttons_main.gif",4,4], = false, function(e) {e.execCommand("removeformat");} ],=0A= killword: [ "Clear MSOffice tags", ["ed_buttons_main.gif",4,3], = false, function(e) {e.execCommand("killword");} ]=0A= =0A= };=0A= /* ADDING CUSTOM BUTTONS=0A= * ---------------------=0A= *=0A= * It is recommended that you add the custom buttons in an external=0A= * file and leave this one unchanged. That's because when we=0A= * (InteractiveTools.com) release a new official version, it's less=0A= * likely that you will have problems upgrading HTMLArea.=0A= *=0A= * Example on how to add a custom button when you construct the = HTMLArea:=0A= *=0A= * var editor =3D new HTMLArea("your_text_area_id");=0A= * var cfg =3D editor.config; // this is the default configuration=0A= * cfg.btnList["my-hilite"] =3D=0A= * [ function(editor) { editor.surroundHTML('', ''); }, // action=0A= * "Highlight selection", // tooltip=0A= * "my_hilite.gif", // image=0A= * false // disabled in text mode=0A= * ];=0A= * cfg.toolbar.push(["linebreak", "my-hilite"]); // add the new = button to the toolbar=0A= *=0A= * An alternate (also more convenient and recommended) way to=0A= * accomplish this is to use the registerButton function below.=0A= */=0A= // initialize tooltips from the I18N module and generate correct image = path=0A= for (var i in this.btnList) {=0A= var btn =3D this.btnList[i];=0A= if(typeof btn[1] !=3D 'string')=0A= {=0A= btn[1][0] =3D _editor_url + this.imgURL + btn[1][0];=0A= }=0A= else=0A= {=0A= btn[1] =3D _editor_url + this.imgURL + btn[1];=0A= }=0A= btn[0] =3D HTMLArea._lc(btn[0]); //initialize tooltip=0A= }=0A= =0A= };=0A= =0A= /** Helper function: register a new button with the configuration. It = can be=0A= * called with all 5 arguments, or with only one (first one). When = called with=0A= * only one argument it must be an object with the following properties: = id,=0A= * tooltip, image, textMode, action. Examples:=0A= *=0A= * 1. config.registerButton("my-hilite", "Hilite text", "my-hilite.gif", = false, function(editor) {...});=0A= * 2. config.registerButton({=0A= * id : "my-hilite", // the ID of your button=0A= * tooltip : "Hilite text", // the tooltip=0A= * image : "my-hilite.gif", // image to be displayed in the = toolbar=0A= * textMode : false, // disabled in text mode=0A= * action : function(editor) { // called when the button is = clicked=0A= * editor.surroundHTML('', = '');=0A= * },=0A= * context : "p" // will be disabled if outside a =

element=0A= * });=0A= */=0A= HTMLArea.Config.prototype.registerButton =3D function(id, tooltip, = image, textMode, action, context) {=0A= var the_id;=0A= if (typeof id =3D=3D "string") {=0A= the_id =3D id;=0A= } else if (typeof id =3D=3D "object") {=0A= the_id =3D id.id;=0A= } else {=0A= alert("ERROR [HTMLArea.Config::registerButton]:\ninvalid arguments");=0A= return false;=0A= }=0A= // check for existing id=0A= if (typeof this.customSelects[the_id] !=3D "undefined") {=0A= // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown = with the same ID already exists.");=0A= }=0A= if (typeof this.btnList[the_id] !=3D "undefined") {=0A= // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button = with the same ID already exists.");=0A= }=0A= switch (typeof id) {=0A= case "string": this.btnList[id] =3D [ tooltip, image, textMode, = action, context ]; break;=0A= case "object": this.btnList[id.id] =3D [ id.tooltip, id.image, = id.textMode, id.action, id.context ]; break;=0A= }=0A= };=0A= =0A= HTMLArea.prototype.registerPanel =3D function(side, object)=0A= {=0A= if(!side) side =3D 'right';=0A= var panel =3D this.addPanel(side);=0A= if(object)=0A= {=0A= object.drawPanelIn(panel);=0A= }=0A= }=0A= =0A= /** The following helper function registers a dropdown box with the = editor=0A= * configuration. You still have to add it to the toolbar, same as with = the=0A= * buttons. Call it like this:=0A= *=0A= * FIXME: add example=0A= */=0A= HTMLArea.Config.prototype.registerDropdown =3D function(object) {=0A= // check for existing id=0A= if (typeof this.customSelects[object.id] !=3D "undefined") {=0A= // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA dropdown = with the same ID already exists.");=0A= }=0A= if (typeof this.btnList[object.id] !=3D "undefined") {=0A= // alert("WARNING [HTMLArea.Config::registerDropdown]:\nA button = with the same ID already exists.");=0A= }=0A= this.customSelects[object.id] =3D object;=0A= };=0A= =0A= /** Call this function to remove some buttons/drop-down boxes from the = toolbar.=0A= * Pass as the only parameter a string containing button/drop-down names=0A= * delimited by spaces. Note that the string should also begin with a = space=0A= * and end with a space. Example:=0A= *=0A= * config.hideSomeButtons(" fontname fontsize textindicator ");=0A= *=0A= * It's useful because it's easier to remove stuff from the defaul = toolbar than=0A= * create a brand new toolbar ;-)=0A= */=0A= HTMLArea.Config.prototype.hideSomeButtons =3D function(remove) {=0A= var toolbar =3D this.toolbar;=0A= for (var i =3D toolbar.length; --i >=3D 0;) {=0A= var line =3D toolbar[i];=0A= for (var j =3D line.length; --j >=3D 0; ) {=0A= if (remove.indexOf(" " + line[j] + " ") >=3D 0) {=0A= var len =3D 1;=0A= if (/separator|space/.test(line[j + 1])) {=0A= len =3D 2;=0A= }=0A= line.splice(j, len);=0A= }=0A= }=0A= }=0A= };=0A= =0A= /** Helper Function: add buttons/drop-downs boxes with title or = separator to the toolbar=0A= * if the buttons/drop-downs boxes doesn't allready exists.=0A= * id: button or selectbox (as array with separator or title)=0A= * where: button or selectbox (as array if the first is not found take = the second and so on)=0A= * position:=0A= * -1 =3D insert button (id) one position before the button (where)=0A= * 0 =3D replace button (where) by button (id)=0A= * +1 =3D insert button (id) one position after button (where)=0A= *=0A= * cfg.addToolbarElement(["T[title]", "button_id", "separator"] , = ["first_id","second_id"], -1);=0A= */=0A= =0A= HTMLArea.Config.prototype.addToolbarElement =3D function(id, where, = position) {=0A= var toolbar =3D this.toolbar;=0A= var a, i, j, o, sid;=0A= var idIsArray =3D false;=0A= var whereIsArray =3D false;=0A= var whereLength =3D 0;=0A= var whereJ =3D 0;=0A= var whereI =3D 0;=0A= var exists =3D false;=0A= var found =3D false;=0A= // check if id and where are arrys=0A= if ((id && typeof id =3D=3D "object") && (id.constructor =3D=3D = Array)) {=0A= idIsArray =3D true;=0A= }=0A= if ((where && typeof where =3D=3D "object") && (where.constructor = =3D=3D Array)) {=0A= whereIsArray =3D true;=0A= whereLength =3D where.length;=0A= }=0A= =0A= if (idIsArray) { //find the button/select box in input array=0A= for (i =3D 0; i < id.length; ++i) {=0A= if ((id[i] !=3D "separator") && (id[i].indexOf("T[") !=3D 0)) {=0A= sid =3D id[i];=0A= }=0A= }=0A= } else {=0A= sid =3D id;=0A= }=0A= =0A= for (var i =3D 0; !exists && !found && i < toolbar.length; ++i) {=0A= a =3D toolbar[i]=0A= for (j =3D 0; !found && j < a.length; ++j) {=0A= if (a[i] =3D=3D sid) { // check if button/select box exists=0A= exists =3D true;=0A= break;=0A= }=0A= if (whereIsArray) {=0A= for (o =3D 0; o < whereLength; ++o) {=0A= if(a[j] =3D=3D where[o]) {=0A= if (o =3D=3D 0) {=0A= found =3D true;=0A= j--;=0A= break;=0A= } else {=0A= whereI =3D i;=0A= whereJ =3D j;=0A= whereLength =3D o;=0A= }=0A= }=0A= }=0A= } else {=0A= if (a[j] =3D=3D where) { // find the position to insert=0A= found =3D true;=0A= break;=0A= }=0A= }=0A= }=0A= }=0A= =0A= if (!exists) {=0A= if (!found && whereIsArray) { //if check found any other as the = first button=0A= if (where.length !=3D whereLength) {=0A= j =3D whereJ;=0A= a =3D toolbar[whereI];=0A= found =3D true;=0A= }=0A= }=0A= if (found) {=0A= if (position =3D=3D 0) { // replace the found button=0A= if (idIsArray) {=0A= a[j] =3D id[id.length-1];=0A= for (i =3D id.length-1; --i >=3D 0;) {=0A= a.splice(j, 0, id[i]);=0A= }=0A= } else {=0A= a[j] =3D id;=0A= }=0A= } else { // insert before/after the found button=0A= if (position < 0) {=0A= j =3D j + position + 1; //correct position before=0A= } else if (position > 0) {=0A= j =3D j + position; //correct posion after=0A= }=0A= if (idIsArray) {=0A= for (i =3D id.length; --i >=3D 0;) {=0A= a.splice(j, 0, id[i]);=0A= }=0A= } else {=0A= a.splice(j, 0, id);=0A= }=0A= }=0A= } else { // no button found=0A= toolbar[0].splice(0, 0, "separator");=0A= if (idIsArray) {=0A= for (i =3D id.length; --i >=3D 0;) {=0A= toolbar[0].splice(0, 0, id[i]);=0A= }=0A= } else {=0A= toolbar[0].splice(0, 0, id);=0A= }=0A= }=0A= }=0A= }=0A= =0A= /** Helper function: replace all TEXTAREA-s in the document with = HTMLArea-s. */=0A= HTMLArea.replaceAll =3D function(config) {=0A= var tas =3D document.getElementsByTagName("textarea");=0A= for (var i =3D tas.length; i > 0; (new HTMLArea(tas[--i], = config)).generate());=0A= };=0A= =0A= /** Helper function: replaces the TEXTAREA with the given ID with = HTMLArea. */=0A= HTMLArea.replace =3D function(id, config)=0A= {=0A= var ta =3D HTMLArea.getElementById("textarea", id);=0A= return ta ? (new HTMLArea(ta, config)).generate() : null;;=0A= };=0A= =0A= // Creates the toolbar and appends it to the _htmlarea=0A= HTMLArea.prototype._createToolbar =3D function () {=0A= var editor =3D this; // to access this in nested functions=0A= =0A= var toolbar =3D document.createElement("div");=0A= // ._toolbar is for legacy, ._toolBar is better thanks.=0A= this._toolBar =3D this._toolbar =3D toolbar;=0A= toolbar.className =3D "toolbar";=0A= toolbar.unselectable =3D "1";=0A= =0A= HTMLArea.freeLater(this, '_toolBar');=0A= HTMLArea.freeLater(this, '_toolbar');=0A= =0A= var tb_row =3D null;=0A= var tb_objects =3D new Object();=0A= this._toolbarObjects =3D tb_objects;=0A= =0A= this._createToolbar1(editor, toolbar, tb_objects);=0A= this._htmlArea.appendChild(toolbar); =0A= =0A= return toolbar;=0A= }=0A= =0A= =0A= HTMLArea.prototype._setConfig =3D function(config) {=0A= this.config =3D config;=0A= }=0A= =0A= HTMLArea.prototype._addToolbar =3D function() {=0A= this._createToolbar1(this, this._toolbar, this._toolbarObjects);=0A= }=0A= =0A= // separate from previous createToolBar to allow dynamic change of = toolbar=0A= HTMLArea.prototype._createToolbar1 =3D function (editor, toolbar, = tb_objects) {=0A= =0A= // This shouldn't be necessary, but IE seems to float outside of the = container=0A= // when we float toolbar sections, so we have to clear:both here as = well=0A= // as at the end (which we do have to do).=0A= if(editor.config.flowToolbars)=0A= {=0A= var brk =3D document.createElement('div');=0A= brk.style.height =3D=0A= brk.style.width =3D=0A= brk.style.lineHeight =3D=0A= brk.style.fontSize =3D '1px';=0A= brk.style.clear =3D 'both';=0A= toolbar.appendChild(brk);=0A= }=0A= =0A= // creates a new line in the toolbar=0A= function newLine() {=0A= if(typeof tb_row !=3D 'undefined' && tb_row.childNodes.length =3D=3D = 0) return;=0A= =0A= var table =3D document.createElement("table");=0A= table.border =3D "0px";=0A= table.cellSpacing =3D "0px";=0A= table.cellPadding =3D "0px";=0A= if(editor.config.flowToolbars)=0A= {=0A= if(HTMLArea.is_ie)=0A= {=0A= table.style.styleFloat =3D "left";=0A= }=0A= else=0A= {=0A= table.style.cssFloat =3D "left";=0A= }=0A= }=0A= =0A= toolbar.appendChild(table);=0A= // TBODY is required for IE, otherwise you don't see anything=0A= // in the TABLE.=0A= var tb_body =3D document.createElement("tbody");=0A= table.appendChild(tb_body);=0A= tb_row =3D document.createElement("tr");=0A= tb_body.appendChild(tb_row);=0A= =0A= table.className =3D 'toolbarRow'; // meh, kinda.=0A= }; // END of function: newLine=0A= =0A= // init first line=0A= newLine();=0A= =0A= // updates the state of a toolbar element. This function is member of=0A= // a toolbar element object (unnamed objects created by createButton or=0A= // createSelect functions below).=0A= function setButtonStatus(id, newval) {=0A= var oldval =3D this[id];=0A= var el =3D this.element;=0A= if (oldval !=3D newval) {=0A= switch (id) {=0A= case "enabled":=0A= if (newval) {=0A= HTMLArea._removeClass(el, "buttonDisabled");=0A= el.disabled =3D false;=0A= } else {=0A= HTMLArea._addClass(el, "buttonDisabled");=0A= el.disabled =3D true;=0A= }=0A= break;=0A= case "active":=0A= if (newval) {=0A= HTMLArea._addClass(el, "buttonPressed");=0A= } else {=0A= HTMLArea._removeClass(el, "buttonPressed");=0A= }=0A= break;=0A= }=0A= this[id] =3D newval;=0A= }=0A= }; // END of function: setButtonStatus=0A= =0A= // this function will handle creation of combo boxes. Receives as=0A= // parameter the name of a button as defined in the toolBar config.=0A= // This function is called from createButton, above, if the given "txt"=0A= // doesn't match a button.=0A= function createSelect(txt) {=0A= var options =3D null;=0A= var el =3D null;=0A= var cmd =3D null;=0A= var customSelects =3D editor.config.customSelects;=0A= var context =3D null;=0A= var tooltip =3D "";=0A= switch (txt) {=0A= case "fontsize":=0A= case "fontname":=0A= case "formatblock":=0A= // the following line retrieves the correct=0A= // configuration option because the variable name=0A= // inside the Config object is named the same as the=0A= // button/select in the toolbar. For instance, if txt=0A= // =3D=3D "formatblock" we retrieve config.formatblock (or=0A= // a different way to write it in JS is=0A= // config["formatblock"].=0A= options =3D editor.config[txt];=0A= cmd =3D txt;=0A= break;=0A= default:=0A= // try to fetch it from the list of registered selects=0A= cmd =3D txt;=0A= var dropdown =3D customSelects[cmd];=0A= if (typeof dropdown !=3D "undefined") {=0A= options =3D dropdown.options;=0A= context =3D dropdown.context;=0A= if (typeof dropdown.tooltip !=3D "undefined") {=0A= tooltip =3D dropdown.tooltip;=0A= }=0A= } else {=0A= alert("ERROR [createSelect]:\nCan't find the requested dropdown = definition");=0A= }=0A= break;=0A= }=0A= if (options) {=0A= el =3D document.createElement("select");=0A= el.title =3D tooltip;=0A= var obj =3D {=0A= name : txt, // field name=0A= element : el, // the UI element (SELECT)=0A= enabled : true, // is it enabled?=0A= text : false, // enabled in text mode?=0A= cmd : cmd, // command ID=0A= state : setButtonStatus, // for changing state=0A= context : context=0A= };=0A= =0A= HTMLArea.freeLater(obj);=0A= =0A= tb_objects[txt] =3D obj;=0A= =0A= for (var i in options) {=0A= var op =3D document.createElement("option");=0A= op.innerHTML =3D HTMLArea._lc(i);=0A= op.value =3D options[i];=0A= el.appendChild(op);=0A= }=0A= HTMLArea._addEvent(el, "change", function () {=0A= editor._comboSelected(el, txt);=0A= });=0A= }=0A= return el;=0A= }; // END of function: createSelect=0A= =0A= // appends a new button to toolbar=0A= function createButton(txt) {=0A= // the element that will be created=0A= var el =3D null;=0A= var btn =3D null;=0A= switch (txt) {=0A= case "separator":=0A= if(editor.config.flowToolbars) newLine();=0A= el =3D document.createElement("div");=0A= el.className =3D "separator";=0A= break;=0A= case "space":=0A= el =3D document.createElement("div");=0A= el.className =3D "space";=0A= break;=0A= case "linebreak":=0A= newLine();=0A= return false;=0A= case "textindicator":=0A= el =3D document.createElement("div");=0A= el.appendChild(document.createTextNode("A"));=0A= el.className =3D "indicator";=0A= el.title =3D HTMLArea._lc("Current style");=0A= var obj =3D {=0A= name : txt, // the button name (i.e. 'bold')=0A= element : el, // the UI element (DIV)=0A= enabled : true, // is it enabled?=0A= active : false, // is it pressed?=0A= text : false, // enabled in text mode?=0A= cmd : "textindicator", // the command ID=0A= state : setButtonStatus // for changing state=0A= };=0A= =0A= HTMLArea.freeLater(obj);=0A= =0A= tb_objects[txt] =3D obj;=0A= break;=0A= default:=0A= btn =3D editor.config.btnList[txt];=0A= }=0A= if (!el && btn) {=0A= el =3D document.createElement("a");=0A= el.style.display =3D 'block';=0A= el.href =3D 'javascript:void(0)';=0A= el.style.textDecoration =3D 'none';=0A= el.title =3D btn[0];=0A= el.className =3D "button";=0A= // let's just pretend we have a button object, and=0A= // assign all the needed information to it.=0A= var obj =3D {=0A= name : txt, // the button name (i.e. 'bold')=0A= element : el, // the UI element (DIV)=0A= enabled : true, // is it enabled?=0A= active : false, // is it pressed?=0A= text : btn[2], // enabled in text mode?=0A= cmd : btn[3], // the command ID=0A= state : setButtonStatus, // for changing state=0A= context : btn[4] || null // enabled in a certain context?=0A= };=0A= =0A= HTMLArea.freeLater(obj);=0A= =0A= tb_objects[txt] =3D obj;=0A= // handlers to emulate nice flat toolbar buttons=0A= HTMLArea._addEvent(el, "mouseout", function () {=0A= if (obj.enabled) with (HTMLArea) {=0A= //_removeClass(el, "buttonHover");=0A= _removeClass(el, "buttonActive");=0A= (obj.active) && _addClass(el, "buttonPressed");=0A= }=0A= });=0A= =0A= HTMLArea._addEvent(el, "mousedown", function (ev) {=0A= if (obj.enabled) with (HTMLArea) {=0A= _addClass(el, "buttonActive");=0A= _removeClass(el, "buttonPressed");=0A= _stopEvent(is_ie ? window.event : ev);=0A= }=0A= });=0A= // when clicked, do the following:=0A= HTMLArea._addEvent(el, "click", function (ev) {=0A= if (obj.enabled) with (HTMLArea) {=0A= _removeClass(el, "buttonActive");=0A= //_removeClass(el, "buttonHover");=0A= if(HTMLArea.is_gecko)=0A= {=0A= editor.activateEditor();=0A= }=0A= obj.cmd(editor, obj.name, obj);=0A= _stopEvent(is_ie ? window.event : ev);=0A= }=0A= });=0A= =0A= var i_contain =3D HTMLArea.makeBtnImg(btn[1]);=0A= var img =3D i_contain.firstChild;=0A= el.appendChild(i_contain);=0A= =0A= obj.imgel =3D img; =0A= obj.swapImage =3D function(newimg)=0A= {=0A= if(typeof newimg !=3D 'string')=0A= {=0A= img.src =3D newimg[0];=0A= img.style.position =3D 'relative';=0A= img.style.top =3D newimg[2] ? ('-' + (18 * (newimg[2] + 1)) + = 'px') : '-18px';=0A= img.style.left =3D newimg[1] ? ('-' + (18 * (newimg[1] + 1)) + = 'px') : '-18px';=0A= }=0A= else=0A= {=0A= obj.imgel.src =3D newimg;=0A= img.style.top =3D '0px';=0A= img.style.left =3D '0px';=0A= }=0A= }=0A= =0A= } else if (!el) {=0A= el =3D createSelect(txt);=0A= }=0A= =0A= return el;=0A= };=0A= =0A= var first =3D true;=0A= for (var i =3D 0; i < this.config.toolbar.length; ++i) {=0A= if (!first) {=0A= // createButton("linebreak");=0A= } else {=0A= first =3D false;=0A= }=0A= if(this.config.toolbar[i] =3D=3D null) this.config.toolbar[i] =3D = ['separator'];=0A= var group =3D this.config.toolbar[i];=0A= =0A= for (var j =3D 0; j < group.length; ++j)=0A= {=0A= var code =3D group[j];=0A= if (/^([IT])\[(.*?)\]/.test(code))=0A= {=0A= // special case, create text label=0A= var l7ed =3D RegExp.$1 =3D=3D "I"; // localized?=0A= var label =3D RegExp.$2;=0A= if (l7ed) {=0A= label =3D HTMLArea._lc(label);=0A= }=0A= var tb_cell =3D document.createElement("td");=0A= tb_row.appendChild(tb_cell);=0A= tb_cell.className =3D "label";=0A= tb_cell.innerHTML =3D label;=0A= }=0A= else if(typeof code !=3D 'function')=0A= {=0A= var tb_element =3D createButton(code);=0A= =0A= if (tb_element)=0A= {=0A= var tb_cell =3D document.createElement("td");=0A= tb_cell.className =3D 'toolbarElement';=0A= tb_row.appendChild(tb_cell);=0A= tb_cell.appendChild(tb_element);=0A= }=0A= else if (tb_element =3D=3D null)=0A= {=0A= alert("FIXME: Unknown toolbar item: " + code);=0A= }=0A= }=0A= }=0A= }=0A= =0A= if(editor.config.flowToolbars)=0A= {=0A= var brk =3D document.createElement('div');=0A= brk.style.height =3D=0A= brk.style.width =3D=0A= brk.style.lineHeight =3D=0A= brk.style.fontSize =3D '1px';=0A= brk.style.clear =3D 'both';=0A= toolbar.appendChild(brk);=0A= }=0A= =0A= return toolbar;=0A= };=0A= =0A= use_clone_img =3D false;=0A= HTMLArea.makeBtnImg =3D function(imgDef, doc)=0A= {=0A= if(!doc) doc =3D document;=0A= =0A= if(!doc._htmlareaImgCache)=0A= {=0A= doc._htmlareaImgCache =3D { };=0A= HTMLArea.freeLater(doc._htmlareaImgCache);=0A= }=0A= =0A= var i_contain =3D null;=0A= if(HTMLArea.is_ie && ((!doc.compatMode) || (doc.compatMode && = doc.compatMode =3D=3D "BackCompat")))=0A= {=0A= i_contain =3D doc.createElement('span');=0A= }=0A= else=0A= {=0A= i_contain =3D doc.createElement('div');=0A= i_contain.style.position =3D 'relative';=0A= }=0A= =0A= i_contain.style.overflow =3D 'hidden';=0A= i_contain.style.width =3D "18px";=0A= i_contain.style.height =3D "18px";=0A= i_contain.className =3D 'buttonImageContainer';=0A= =0A= var img =3D null;=0A= if(typeof imgDef =3D=3D 'string')=0A= {=0A= if(doc._htmlareaImgCache[imgDef])=0A= {=0A= img =3D doc._htmlareaImgCache[imgDef].cloneNode();=0A= }=0A= else=0A= {=0A= img =3D doc.createElement("img");=0A= img.src =3D imgDef;=0A= img.style.width =3D "18px";=0A= img.style.height =3D "18px";=0A= if(use_clone_img)=0A= doc._htmlareaImgCache[imgDef] =3D img.cloneNode();=0A= }=0A= }=0A= else=0A= {=0A= if(doc._htmlareaImgCache[imgDef[0]])=0A= {=0A= img =3D doc._htmlareaImgCache[imgDef[0]].cloneNode();=0A= }=0A= else=0A= {=0A= img =3D doc.createElement("img");=0A= img.src =3D imgDef[0];=0A= img.style.position =3D 'relative';=0A= if(use_clone_img)=0A= doc._htmlareaImgCache[imgDef[0]] =3D img.cloneNode();=0A= }=0A= img.style.top =3D imgDef[2] ? ('-' + (18 * (imgDef[2] + 1)) + 'px') = : '-18px';=0A= img.style.left =3D imgDef[1] ? ('-' + (18 * (imgDef[1] + 1)) + 'px') = : '-18px';=0A= }=0A= i_contain.appendChild(img);=0A= return i_contain;=0A= }=0A= =0A= HTMLArea.prototype._createStatusBar =3D function() {=0A= var statusbar =3D document.createElement("div");=0A= statusbar.className =3D "statusBar";=0A= this._statusBar =3D statusbar;=0A= HTMLArea.freeLater(this, '_statusBar');=0A= =0A= // statusbar.appendChild(document.createTextNode(HTMLArea._lc("Path") = + ": "));=0A= // creates a holder for the path view=0A= div =3D document.createElement("span");=0A= div.className =3D "statusBarTree";=0A= div.innerHTML =3D HTMLArea._lc("Path") + ": ";=0A= this._statusBarTree =3D div;=0A= HTMLArea.freeLater(this, '_statusBarTree');=0A= this._statusBar.appendChild(div);=0A= =0A= div =3D document.createElement("span");=0A= div.innerHTML =3D HTMLArea._lc("You are in TEXT MODE. Use the [<>] = button to switch back to WYSIWYG.");=0A= div.style.display =3D "none";=0A= this._statusBarTextMode =3D div;=0A= HTMLArea.freeLater(this, '_statusBarTextMode');=0A= this._statusBar.appendChild(div);=0A= =0A= if (!this.config.statusBar)=0A= {=0A= // disable it...=0A= statusbar.style.display =3D "none";=0A= }=0A= =0A= return statusbar;=0A= };=0A= =0A= // Creates the HTMLArea object and replaces the textarea with it.=0A= HTMLArea.prototype.generate =3D function ()=0A= {=0A= var editor =3D this; // we'll need "this" in some nested functions=0A= =0A= if(typeof Dialog =3D=3D 'undefined')=0A= {=0A= HTMLArea._loadback=0A= (_editor_url + 'dialog.js', function() { editor.generate(); } );=0A= return false;=0A= }=0A= =0A= if(typeof HTMLArea.Dialog =3D=3D 'undefined')=0A= {=0A= HTMLArea._loadback=0A= (_editor_url + 'inline-dialog.js', function() { editor.generate(); = } );=0A= return false;=0A= }=0A= =0A= if(typeof PopupWin =3D=3D 'undefined')=0A= {=0A= HTMLArea._loadback=0A= (_editor_url + 'popupwin.js', function() { editor.generate(); } );=0A= return false;=0A= }=0A= =0A= if(_editor_skin !=3D "") {=0A= var found=3Dfalse;=0A= var head =3D document.getElementsByTagName("head")[0];=0A= var links =3D document.getElementsByTagName("link");=0A= for(var i =3D 0; i=3D 0;) {=0A= for (var j =3D toolbar[i].length; --j >=3D 0; ) {=0A= if (toolbar[i][j]=3D=3D"popupeditor") {=0A= if(typeof FullScreen =3D=3D "undefined") {=0A= HTMLArea.loadPlugin("FullScreen", function() { = editor.generate(); } );=0A= return false;=0A= }=0A= editor.registerPlugin('FullScreen');=0A= }=0A= }=0A= }=0A= =0A= // If this is gecko, set up the paragraph handling now=0A= if(HTMLArea.is_gecko)=0A= {=0A= switch(editor.config.mozParaHandler)=0A= {=0A= case 'best':=0A= {=0A= if(typeof EnterParagraphs =3D=3D 'undefined')=0A= {=0A= HTMLArea.loadPlugin("EnterParagraphs", function() { = editor.generate(); } );=0A= return false;=0A= }=0A= editor.registerPlugin('EnterParagraphs');=0A= }=0A= break;=0A= =0A= case 'dirty' :=0A= case 'built-in':=0A= default :=0A= {=0A= // See _editorEvent=0A= }=0A= break;=0A= }=0A= }=0A= =0A= // create the editor framework, yah, table layout I know, but much = easier=0A= // to get it working correctly this way, sorry about that, patches = welcome.=0A= =0A= this._framework =3D=0A= {=0A= 'table' :document.createElement('table'),=0A= 'tbody' :document.createElement('tbody'), // IE will not show = the table if it doesn't have a tbody!=0A= 'tb_row' :document.createElement('tr'),=0A= 'tb_cell' :document.createElement('td'), // Toolbar=0A= =0A= 'tp_row' :document.createElement('tr'),=0A= 'tp_cell' :this._panels.top.container, // top panel=0A= =0A= 'ler_row' :document.createElement('tr'),=0A= 'lp_cell' :this._panels.left.container, // left panel=0A= 'ed_cell' :document.createElement('td'), // editor=0A= 'rp_cell' :this._panels.right.container, // right panel=0A= =0A= 'bp_row' :document.createElement('tr'),=0A= 'bp_cell' :this._panels.bottom.container,// bottom panel=0A= =0A= 'sb_row' :document.createElement('tr'),=0A= 'sb_cell' :document.createElement('td') // status bar=0A= =0A= }=0A= =0A= HTMLArea.freeLater(this._framework);=0A= =0A= var fw =3D this._framework;=0A= fw.table.border=3D"0";=0A= fw.table.cellPadding=3D"0";=0A= fw.table.cellSpacing=3D"0";=0A= =0A= fw.tb_row.style.verticalAlign =3D 'top';=0A= fw.tp_row.style.verticalAlign =3D 'top';=0A= fw.ler_row.style.verticalAlign=3D 'top';=0A= fw.bp_row.style.verticalAlign =3D 'top';=0A= fw.sb_row.style.verticalAlign =3D 'top';=0A= fw.ed_cell.style.position =3D 'relative';=0A= =0A= // Put the cells in the rows set col & rowspans=0A= // note that I've set all these so that all panels are showing=0A= // but they will be redone in sizeEditor() depending on which=0A= // panels are shown. It's just here to clarify how the thing=0A= // is put togethor.=0A= fw.tb_row.appendChild(fw.tb_cell); fw.tb_cell.colSpan =3D 3;=0A= =0A= fw.tp_row.appendChild(fw.tp_cell); fw.tp_cell.colSpan =3D 3;=0A= =0A= fw.ler_row.appendChild(fw.lp_cell);=0A= fw.ler_row.appendChild(fw.ed_cell);=0A= fw.ler_row.appendChild(fw.rp_cell);=0A= =0A= fw.bp_row.appendChild(fw.bp_cell); fw.bp_cell.colSpan =3D 3;=0A= =0A= fw.sb_row.appendChild(fw.sb_cell); fw.sb_cell.colSpan =3D 3;=0A= =0A= // Put the rows in the table body=0A= fw.tbody.appendChild(fw.tb_row); // Toolbar=0A= fw.tbody.appendChild(fw.tp_row); // Left, Top, Right panels=0A= fw.tbody.appendChild(fw.ler_row); // Editor/Textarea=0A= fw.tbody.appendChild(fw.bp_row); // Bottom panel=0A= fw.tbody.appendChild(fw.sb_row); // Statusbar=0A= =0A= // and body in the table=0A= fw.table.appendChild(fw.tbody);=0A= =0A= var htmlarea =3D this._framework.table;=0A= this._htmlArea =3D htmlarea;=0A= HTMLArea.freeLater(this, '_htmlArea');=0A= htmlarea.className =3D "htmlarea";=0A= =0A= // create the toolbar and put in the area=0A= var toolbar =3D this._createToolbar();=0A= this._framework.tb_cell.appendChild(toolbar);=0A= =0A= // create the IFRAME & add to container=0A= var iframe =3D document.createElement("iframe");=0A= iframe.src =3D _editor_url + editor.config.URIs["blank"];=0A= this._framework.ed_cell.appendChild(iframe);=0A= this._iframe =3D iframe;=0A= this._iframe.className =3D 'xinha_iframe';=0A= HTMLArea.freeLater(this, '_iframe');=0A= =0A= // creates & appends the status bar=0A= var statusbar =3D this._createStatusBar();=0A= this._framework.sb_cell.appendChild(statusbar);=0A= =0A= // insert Xinha before the textarea.=0A= var textarea =3D this._textArea;=0A= textarea.parentNode.insertBefore(htmlarea, textarea);=0A= textarea.className =3D 'xinha_textarea';=0A= =0A= // extract the textarea and insert it into the htmlarea=0A= HTMLArea.removeFromParent(textarea);=0A= this._framework.ed_cell.appendChild(textarea);=0A= =0A= =0A= // Set up event listeners for saving the iframe content to the textarea=0A= if (textarea.form)=0A= {=0A= // onsubmit get the HTMLArea content and update original textarea.=0A= HTMLArea.prependDom0Event=0A= (=0A= this._textArea.form,=0A= 'submit',=0A= function() {editor._textArea.value =3D = editor.outwardHtml(editor.getHTML()); return true;}=0A= );=0A= =0A= var initialTAContent =3D textarea.value;=0A= =0A= // onreset revert the HTMLArea content to the textarea content=0A= HTMLArea.prependDom0Event=0A= (=0A= this._textArea.form,=0A= 'reset',=0A= function() { editor.setHTML(editor.inwardHtml(initialTAContent)); = editor.updateToolbar(); return true; }=0A= );=0A= }=0A= =0A= // add a handler for the "back/forward" case -- on body.unload we save=0A= // the HTML content into the original textarea.=0A= HTMLArea.prependDom0Event(window, 'unload', function() {textarea.value = =3D editor.outwardHtml(editor.getHTML()); return true; });=0A= =0A= // Hide textarea=0A= textarea.style.display =3D "none";=0A= =0A= // Initalize size=0A= editor.initSize();=0A= =0A= // Add an event to initialize the iframe once loaded.=0A= editor._iframeLoadDone =3D false;=0A= HTMLArea._addEvent=0A= (=0A= this._iframe,=0A= 'load',=0A= function(e)=0A= {=0A= if(! editor._iframeLoadDone)=0A= {=0A= editor._iframeLoadDone =3D true;=0A= editor.initIframe();=0A= }=0A= return true;=0A= }=0A= );=0A= =0A= };=0A= =0A= =0A= /**=0A= * Size the editor according to the INITIAL sizing information.=0A= * config.width=0A= * The width may be set via three ways=0A= * auto =3D the width is inherited from the original textarea=0A= * toolbar =3D the width is set to be the same size as the toolbar=0A= * =3D the width is an explicit size (any CSS = measurement, eg 100em should be fine)=0A= *=0A= * config.height=0A= * auto =3D the height is inherited from the original textarea=0A= * =3D an explicit size measurement (again, CSS = measurements)=0A= *=0A= * config.sizeIncludesBars=0A= * true =3D the tool & status bars will appear inside the width = & height confines=0A= * false =3D the tool & status bars will appear outside the width = & height confines=0A= *=0A= */=0A= =0A= HTMLArea.prototype.initSize =3D function()=0A= {=0A= var editor =3D this;=0A= =0A= var width =3D null;=0A= var height =3D null;=0A= switch(this.config.width)=0A= {=0A= case 'auto':=0A= {=0A= width =3D this._initial_ta_size.w;=0A= }=0A= break;=0A= =0A= case 'toolbar':=0A= {=0A= width =3D this._toolBar.offsetWidth;=0A= }=0A= break;=0A= =0A= default :=0A= {=0A= width =3D this.config.width;=0A= }=0A= break;=0A= }=0A= =0A= switch(this.config.height)=0A= {=0A= case 'auto':=0A= {=0A= height =3D this._initial_ta_size.h;=0A= }=0A= break;=0A= =0A= default :=0A= {=0A= height =3D this.config.height;=0A= }=0A= break;=0A= }=0A= =0A= this.sizeEditor(width, height, this.config.sizeIncludesBars, = this.config.sizeIncludesPanels);=0A= =0A= HTMLArea.addDom0Event(window, 'resize', function(e) { = editor.sizeEditor(); });=0A= =0A= this.notifyOn('panel_change',function(){editor.sizeEditor();});=0A= }=0A= =0A= /**=0A= * Size the editor to a specific size, or just refresh the size (when = window resizes for example)=0A= * @param width optional width (CSS specification)=0A= * @param height optional height (CSS specification)=0A= * @param includingBars optional boolean to indicate if the size = should include or exclude tool & status bars=0A= */=0A= =0A= HTMLArea.prototype.sizeEditor =3D function(width, height, = includingBars, includingPanels)=0A= {=0A= =0A= // We need to set the iframe & textarea to 100% height so that the = htmlarea=0A= // isn't "pushed out" when we get it's height, so we can change them = later.=0A= this._iframe.style.height =3D '100%';=0A= this._textArea.style.height =3D '100%';=0A= this._iframe.style.width =3D '';=0A= this._textArea.style.width =3D '';=0A= =0A= if(includingBars !=3D null) this._htmlArea.sizeIncludesToolbars = =3D includingBars;=0A= if(includingPanels !=3D null) this._htmlArea.sizeIncludesPanels = =3D includingPanels;=0A= =0A= if(width !=3D null)=0A= {=0A= this._htmlArea.style.width =3D width;=0A= if(!this._htmlArea.sizeIncludesPanels)=0A= {=0A= // Need to add some for l & r panels=0A= var panel =3D this._panels.right;=0A= if(panel.on && panel.panels.length && = HTMLArea.hasDisplayedChildren(panel.div))=0A= {=0A= this._htmlArea.style.width =3D this._htmlArea.offsetWidth + = parseInt(this.config.panel_dimensions.right);=0A= }=0A= =0A= var panel =3D this._panels.left;=0A= if(panel.on && panel.panels.length && = HTMLArea.hasDisplayedChildren(panel.div))=0A= {=0A= this._htmlArea.style.width =3D this._htmlArea.offsetWidth + = parseInt(this.config.panel_dimensions.left);=0A= }=0A= }=0A= }=0A= =0A= if(height !=3D null)=0A= {=0A= this._htmlArea.style.height =3D height;=0A= if(!this._htmlArea.sizeIncludesToolbars)=0A= {=0A= // Need to add some for toolbars=0A= this._htmlArea.style.height =3D = this._htmlArea.offsetHeight + this._toolbar.offsetHeight + = this._statusBar.offsetHeight;=0A= }=0A= =0A= if(!this._htmlArea.sizeIncludesPanels)=0A= {=0A= // Need to add some for l & r panels=0A= var panel =3D this._panels.top;=0A= if(panel.on && panel.panels.length && = HTMLArea.hasDisplayedChildren(panel.div))=0A= {=0A= this._htmlArea.style.height =3D this._htmlArea.offsetHeight + = parseInt(this.config.panel_dimensions.top);=0A= }=0A= =0A= var panel =3D this._panels.bottom;=0A= if(panel.on && panel.panels.length && = HTMLArea.hasDisplayedChildren(panel.div))=0A= {=0A= this._htmlArea.style.height =3D this._htmlArea.offsetHeight + = parseInt(this.config.panel_dimensions.bottom);=0A= }=0A= }=0A= }=0A= =0A= // At this point we have this._htmlArea.style.width & = this._htmlArea.style.height=0A= // which are the size for the OUTER editor area, including toolbars = and panels=0A= // now we size the INNER area and position stuff in the right places.=0A= width =3D this._htmlArea.offsetWidth;=0A= height =3D this._htmlArea.offsetHeight;=0A= =0A= // Set colspan for toolbar, and statusbar, rowspan for left & right = panels, and insert panels to be displayed=0A= // into thier rows=0A= var panels =3D this._panels;=0A= var editor =3D this;=0A= var col_span =3D 1;=0A= =0A= function panel_is_alive(pan)=0A= {=0A= if(panels[pan].on && panels[pan].panels.length && = HTMLArea.hasDisplayedChildren(panels[pan].container))=0A= {=0A= panels[pan].container.style.display =3D '';=0A= return true;=0A= }=0A= =0A= // Otherwise make sure it's been removed from the framework=0A= else=0A= {=0A= panels[pan].container.style.display=3D'none';=0A= return false;=0A= }=0A= }=0A= =0A= if(panel_is_alive('left'))=0A= {=0A= col_span +=3D 1; =0A= }=0A= =0A= if(panel_is_alive('top'))=0A= {=0A= // NOP=0A= }=0A= =0A= if(panel_is_alive('right'))=0A= {=0A= col_span +=3D 1;=0A= }=0A= =0A= if(panel_is_alive('bottom'))=0A= {=0A= // NOP=0A= }=0A= =0A= this._framework.tb_cell.colSpan =3D col_span;=0A= this._framework.tp_cell.colSpan =3D col_span;=0A= this._framework.bp_cell.colSpan =3D col_span;=0A= this._framework.sb_cell.colSpan =3D col_span;=0A= =0A= // Put in the panel rows, top panel goes above editor row=0A= if(!this._framework.tp_row.childNodes.length)=0A= {=0A= HTMLArea.removeFromParent(this._framework.tp_row);=0A= }=0A= else=0A= {=0A= if(!HTMLArea.hasParentNode(this._framework.tp_row))=0A= {=0A= this._framework.tbody.insertBefore(this._framework.tp_row, = this._framework.ler_row);=0A= }=0A= }=0A= =0A= // bp goes after the editor=0A= if(!this._framework.bp_row.childNodes.length)=0A= {=0A= HTMLArea.removeFromParent(this._framework.bp_row);=0A= }=0A= else=0A= {=0A= if(!HTMLArea.hasParentNode(this._framework.bp_row))=0A= {=0A= this._framework.tbody.insertBefore(this._framework.bp_row, = this._framework.ler_row.nextSibling);=0A= }=0A= }=0A= =0A= // finally if the statusbar is on, insert it=0A= if(!this.config.statusBar)=0A= {=0A= HTMLArea.removeFromParent(this._framework.sb_row);=0A= }=0A= else=0A= {=0A= if(!HTMLArea.hasParentNode(this._framework.sb_row))=0A= {=0A= this._framework.table.appendChild(this._framework.sb_row);=0A= }=0A= }=0A= =0A= // Size and set colspans, link up the framework=0A= this._framework.lp_cell.style.width =3D = this.config.panel_dimensions.left;=0A= this._framework.rp_cell.style.width =3D = this.config.panel_dimensions.right;=0A= this._framework.tp_cell.style.height =3D = this.config.panel_dimensions.top;=0A= this._framework.bp_cell.style.height =3D = this.config.panel_dimensions.bottom;=0A= this._framework.tb_cell.style.height =3D this._toolBar.offsetHeight = + 'px';=0A= this._framework.sb_cell.style.height =3D = this._statusBar.offsetHeight + 'px';=0A= =0A= var edcellheight =3D height - this._toolBar.offsetHeight - = this._statusBar.offsetHeight;=0A= if(panel_is_alive('top')) edcellheight -=3D = parseInt(this.config.panel_dimensions.top);=0A= if(panel_is_alive('bottom')) edcellheight -=3D = parseInt(this.config.panel_dimensions.bottom);;=0A= this._iframe.style.height =3D edcellheight + 'px';=0A= =0A= var edcellwidth =3D width;=0A= if(panel_is_alive('left')) edcellwidth -=3D = parseInt(this.config.panel_dimensions.left);=0A= if(panel_is_alive('right')) edcellwidth -=3D = parseInt(this.config.panel_dimensions.right);=0A= this._iframe.style.width =3D edcellwidth + 'px';=0A= =0A= this._textArea.style.height =3D this._iframe.style.height;=0A= this._textArea.style.width =3D this._iframe.style.width;=0A= =0A= this.notifyOf('resize', {width:this._htmlArea.offsetWidth, = height:this._htmlArea.offsetHeight});=0A= }=0A= =0A= HTMLArea.prototype.addPanel =3D function(side)=0A= {=0A= var div =3D document.createElement('div');=0A= div.side =3D side;=0A= if(side =3D=3D 'left' || side =3D=3D 'right')=0A= {=0A= div.style.width =3D this.config.panel_dimensions[side];=0A= }=0A= HTMLArea.addClasses(div, 'panel');=0A= this._panels[side].panels.push(div);=0A= this._panels[side].div.appendChild(div);=0A= =0A= this.notifyOf('panel_change', {'action':'add','panel':div});=0A= =0A= return div;=0A= }=0A= =0A= HTMLArea.prototype.removePanel =3D function(panel)=0A= {=0A= this._panels[panel.side].div.removeChild(panel);=0A= var clean =3D [ ];=0A= for(var i =3D 0; i < this._panels[panel.side].panels.length; i++)=0A= {=0A= if(this._panels[panel.side].panels[i] !=3D panel)=0A= {=0A= clean.push(this._panels[panel.side].panels[i]);=0A= }=0A= }=0A= this._panels[panel.side].panels =3D clean;=0A= this.notifyOf('panel_change', {'action':'remove','panel':panel});=0A= }=0A= =0A= HTMLArea.prototype.hidePanel =3D function(panel)=0A= {=0A= if(panel)=0A= {=0A= panel.style.display =3D 'none';=0A= this.notifyOf('panel_change', {'action':'hide','panel':panel});=0A= }=0A= }=0A= =0A= HTMLArea.prototype.showPanel =3D function(panel)=0A= {=0A= if(panel)=0A= {=0A= panel.style.display =3D '';=0A= this.notifyOf('panel_change', {'action':'show','panel':panel});=0A= }=0A= }=0A= =0A= HTMLArea.prototype.hidePanels =3D function(sides)=0A= {=0A= if(typeof sides =3D=3D 'undefined')=0A= {=0A= sides =3D ['left','right','top','bottom'];=0A= }=0A= =0A= var reShow =3D [];=0A= for(var i =3D 0; i < sides.length;i++)=0A= {=0A= if(this._panels[sides[i]].on)=0A= {=0A= reShow.push(sides[i]);=0A= this._panels[sides[i]].on =3D false;=0A= }=0A= }=0A= this.notifyOf('panel_change', {'action':'multi_hide','sides':sides});=0A= }=0A= =0A= HTMLArea.prototype.showPanels =3D function(sides)=0A= {=0A= if(typeof sides =3D=3D 'undefined')=0A= {=0A= sides =3D ['left','right','top','bottom'];=0A= }=0A= =0A= var reHide =3D [];=0A= for(var i =3D 0; i < sides.length;i++)=0A= {=0A= if(!this._panels[sides[i]].on)=0A= {=0A= reHide.push(sides[i]);=0A= this._panels[sides[i]].on =3D true;=0A= }=0A= }=0A= this.notifyOf('panel_change', {'action':'multi_show','sides':sides});=0A= }=0A= =0A= HTMLArea.objectProperties =3D function(obj)=0A= {=0A= var props =3D [ ];=0A= for(var x in obj)=0A= {=0A= props[props.length] =3D x;=0A= }=0A= return props;=0A= }=0A= =0A= /*=0A= * EDITOR ACTIVATION NOTES:=0A= * when a page has multiple Xinha editors, ONLY ONE should be = activated at any time (this is mostly to=0A= * work around a bug in Mozilla, but also makes some sense). No = editor should be activated or focused=0A= * automatically until at least one editor has been activated through = user action (by mouse-clicking in=0A= * the editor).=0A= */=0A= =0A= HTMLArea.prototype.editorIsActivated =3D function() {=0A= try {=0A= if (HTMLArea.is_gecko) return (this._doc.designMode =3D=3D 'on');=0A= else return (this._doc.body.contentEditable);=0A= } catch (e)=0A= {=0A= return false;=0A= }=0A= }=0A= =0A= HTMLArea._someEditorHasBeenActivated =3D false;=0A= HTMLArea._currentlyActiveEditor =3D false;=0A= HTMLArea.prototype.activateEditor =3D function()=0A= {=0A= // We only want ONE editor at a time to be active=0A= if(HTMLArea._currentlyActiveEditor)=0A= {=0A= if(HTMLArea._currentlyActiveEditor =3D=3D this) return true;=0A= HTMLArea._currentlyActiveEditor.deactivateEditor();=0A= }=0A= =0A= if (HTMLArea.is_gecko && this._doc.designMode !=3D 'on')=0A= {=0A= try=0A= {=0A= // cannot set design mode if no display=0A= if (this._iframe.style.display =3D=3D 'none')=0A= {=0A= this._iframe.style.display =3D '';=0A= this._doc.designMode =3D 'on';=0A= this._iframe.style.display =3D 'none';=0A= }=0A= else=0A= {=0A= this._doc.designMode =3D 'on';=0A= }=0A= } catch (e) {}=0A= }=0A= else if(!HTMLArea.is_gecko && this._doc.body.contentEditable !=3D = true)=0A= {=0A= this._doc.body.contentEditable =3D true;=0A= }=0A= =0A= // We need to know that at least one editor on the page has been = activated=0A= // this is because we will not focus any editor until an editor has = been activated=0A= HTMLArea._someEditorHasBeenActivated =3D true;=0A= HTMLArea._currentlyActiveEditor =3D this;=0A= =0A= var editor =3D this;=0A= this.enableToolbar();=0A= }=0A= =0A= HTMLArea.prototype.deactivateEditor =3D function()=0A= {=0A= // If the editor isn't active then the user shouldn't use the toolbar=0A= this.disableToolbar();=0A= =0A= if (HTMLArea.is_gecko && this._doc.designMode !=3D 'off')=0A= {=0A= try {this._doc.designMode =3D 'off';} catch (e) {}=0A= }=0A= else if(!HTMLArea.is_gecko && this._doc.body.contentEditable !=3D = false)=0A= {=0A= this._doc.body.contentEditable =3D false;=0A= }=0A= =0A= if(HTMLArea._currentlyActiveEditor !=3D this)=0A= {=0A= // We just deactivated an editor that wasn't marked as the = currentlyActiveEditor=0A= =0A= return; // I think this should really be an error, there shouldn't = be a situation where=0A= // an editor is deactivated without first being activated. = but it probably won't=0A= // hurt anything.=0A= }=0A= =0A= HTMLArea._currentlyActiveEditor =3D false;=0A= }=0A= =0A= HTMLArea.prototype.initIframe =3D function()=0A= {=0A= this.disableToolbar();=0A= var doc =3D null;=0A= var editor =3D this;=0A= try=0A= {=0A= if (editor._iframe.contentDocument)=0A= {=0A= this._doc =3D editor._iframe.contentDocument; =0A= }=0A= else=0A= {=0A= this._doc =3D editor._iframe.contentWindow.document;=0A= }=0A= doc =3D this._doc; =0A= if (!doc) { // try later=0A= if (HTMLArea.is_gecko) {=0A= setTimeout(function() { editor.initIframe()}, 50);=0A= return false;=0A= } else {=0A= alert("ERROR: IFRAME can't be initialized.");=0A= }=0A= }=0A= }=0A= catch(e)=0A= { // try later=0A= setTimeout(function() { editor.initIframe()}, 50);=0A= }=0A= =0A= HTMLArea.freeLater(this, '_doc');=0A= =0A= doc.open();=0A= if (!editor.config.fullPage) {=0A= var html =3D "\n";=0A= html +=3D "\n";=0A= html +=3D "\n";=0A= if(typeof editor.config.baseHref !=3D 'undefined' && = editor.config.baseHref !=3D null)=0A= {=0A= html +=3D "\n";=0A= }=0A= html +=3D "\n";=0A= html +=3D "\n";=0A= =0A= if(editor.config.pageStyle)=0A= {=0A= html +=3D "";=0A= }=0A= =0A= if(typeof editor.config.pageStyleSheets !=3D=3D 'undefined')=0A= {=0A= for(style_i =3D 0; style_i < = editor.config.pageStyleSheets.length; style_i++)=0A= {=0A= if(editor.config.pageStyleSheets[style_i].length > 0)=0A= html +=3D "";=0A= //html +=3D "\n";=0A= }=0A= }=0A= html +=3D "\n";=0A= html +=3D "\n";=0A= html +=3D editor.inwardHtml(editor._textArea.value);=0A= html +=3D "\n";=0A= html +=3D "";=0A= } else {=0A= var html =3D editor.inwardHtml(editor._textArea.value);=0A= if (html.match(HTMLArea.RE_doctype)) {=0A= editor.setDoctype(RegExp.$1);=0A= html =3D html.replace(HTMLArea.RE_doctype, "");=0A= }=0A= }=0A= doc.write(html);=0A= doc.close();=0A= =0A= // if we have multiple editors some bug in Mozilla makes some lose = editing ability=0A= HTMLArea._addEvents=0A= (=0A= doc,=0A= ["mousedown"],=0A= function() { editor.activateEditor(); return true; }=0A= );=0A= =0A= =0A= // intercept some events; for updating the toolbar & keyboard = handlers=0A= HTMLArea._addEvents=0A= (doc, ["keydown", "keypress", "mousedown", "mouseup", "drag"],=0A= function (event) {=0A= return editor._editorEvent(HTMLArea.is_ie ? = editor._iframe.contentWindow.event : event);=0A= });=0A= =0A= // check if any plugins have registered refresh handlers=0A= for (var i in editor.plugins) {=0A= var plugin =3D editor.plugins[i].instance;=0A= HTMLArea.refreshPlugin(plugin);=0A= }=0A= =0A= // specific editor initialization=0A= if(typeof editor._onGenerate =3D=3D "function") {=0A= editor._onGenerate();=0A= }=0A= }=0A= =0A= // Switches editor mode; parameter can be "textmode" or "wysiwyg". If no=0A= // parameter was passed this function toggles between modes.=0A= HTMLArea.prototype.setMode =3D function(mode) {=0A= if (typeof mode =3D=3D "undefined") {=0A= mode =3D ((this._editMode =3D=3D "textmode") ? "wysiwyg" : = "textmode");=0A= }=0A= switch (mode) {=0A= case "textmode":=0A= {=0A= var html =3D this.outwardHtml(this.getHTML());=0A= this.setHTML(html);=0A= =0A= // Hide the iframe=0A= this.deactivateEditor();=0A= this._iframe.style.display =3D 'none';=0A= this._textArea.style.display =3D '';=0A= =0A= if (this.config.statusBar)=0A= {=0A= this._statusBarTree.style.display =3D "none";=0A= this._statusBarTextMode.style.display =3D "";=0A= }=0A= =0A= this.notifyOf('modechange', {'mode':'text'});=0A= break;=0A= }=0A= =0A= case "wysiwyg":=0A= {=0A= var html =3D this.inwardHtml(this.getHTML());=0A= this.deactivateEditor();=0A= this.setHTML(html);=0A= this._iframe.style.display =3D '';=0A= this._textArea.style.display =3D "none";=0A= this.activateEditor();=0A= if (this.config.statusBar)=0A= {=0A= this._statusBarTree.style.display =3D "";=0A= this._statusBarTextMode.style.display =3D "none";=0A= }=0A= =0A= this.notifyOf('modechange', {'mode':'wysiwyg'});=0A= break;=0A= }=0A= =0A= default:=0A= {=0A= alert("Mode <" + mode + "> not defined!");=0A= return false;=0A= }=0A= }=0A= this._editMode =3D mode;=0A= =0A= for (var i in this.plugins) {=0A= var plugin =3D this.plugins[i].instance;=0A= if (typeof plugin.onMode =3D=3D "function") plugin.onMode(mode);=0A= }=0A= };=0A= =0A= HTMLArea.prototype.setFullHTML =3D function(html) {=0A= var save_multiline =3D RegExp.multiline;=0A= RegExp.multiline =3D true;=0A= if (html.match(HTMLArea.RE_doctype)) {=0A= this.setDoctype(RegExp.$1);=0A= html =3D html.replace(HTMLArea.RE_doctype, "");=0A= }=0A= RegExp.multiline =3D save_multiline;=0A= if (!HTMLArea.is_ie) {=0A= if (html.match(HTMLArea.RE_head))=0A= this._doc.getElementsByTagName("head")[0].innerHTML =3D RegExp.$1;=0A= if (html.match(HTMLArea.RE_body))=0A= this._doc.getElementsByTagName("body")[0].innerHTML =3D RegExp.$1;=0A= } else {=0A= var reac =3D this.editorIsActivated();=0A= if(reac) this.deactivateEditor();=0A= var html_re =3D /((.|\n)*?)<\/html>/i;=0A= html =3D html.replace(html_re, "$1");=0A= this._doc.open();=0A= this._doc.write(html);=0A= this._doc.close();=0A= if(reac) this.activateEditor();=0A= return true;=0A= }=0A= };=0A= =0A= /***************************************************=0A= * Category: PLUGINS=0A= ***************************************************/=0A= =0A= // Create the specified plugin and register it with this HTMLArea=0A= // return the plugin created to allow refresh when necessary=0A= HTMLArea.prototype.registerPlugin =3D function() {=0A= var plugin =3D arguments[0];=0A= =0A= // We can only register plugins that have been succesfully loaded=0A= if=0A= (=0A= plugin =3D=3D null=0A= || typeof plugin =3D=3D 'undefined'=0A= || (typeof plugin =3D=3D 'string' && eval('typeof ' + plugin) =3D=3D = 'undefined')=0A= ) return false;=0A= =0A= var args =3D [];=0A= for (var i =3D 1; i < arguments.length; ++i)=0A= args.push(arguments[i]);=0A= return this.registerPlugin2(plugin, args);=0A= };=0A= =0A= // this is the variant of the function above where the plugin arguments = are=0A= // already packed in an array. Externally, it should be only used in the=0A= // full-screen editor code, in order to initialize plugins with the same=0A= // parameters as in the opener window.=0A= HTMLArea.prototype.registerPlugin2 =3D function(plugin, args) {=0A= if (typeof plugin =3D=3D "string")=0A= plugin =3D eval(plugin);=0A= if (typeof plugin =3D=3D "undefined") {=0A= /* FIXME: This should never happen. But why does it do? */=0A= return false;=0A= }=0A= var obj =3D new plugin(this, args);=0A= if (obj) {=0A= var clone =3D {};=0A= var info =3D plugin._pluginInfo;=0A= for (var i in info)=0A= clone[i] =3D info[i];=0A= clone.instance =3D obj;=0A= clone.args =3D args;=0A= this.plugins[plugin._pluginInfo.name] =3D clone;=0A= return obj;=0A= } else=0A= alert("Can't register plugin " + plugin.toString() + ".");=0A= };=0A= =0A= // static function that loads the required plugin and lang file, based = on the=0A= // language loaded already for HTMLArea. You better make sure that the = plugin=0A= // _has_ that language, otherwise shit might happen ;-)=0A= HTMLArea.getPluginDir =3D function(pluginName) {=0A= return _editor_url + "plugins/" + pluginName;=0A= };=0A= =0A= HTMLArea.loadPlugin =3D function(pluginName, callback) {=0A= // Might already be loaded=0A= if(eval('typeof ' + pluginName) !=3D 'undefined')=0A= {=0A= if(callback)=0A= {=0A= callback(pluginName);=0A= }=0A= return true;=0A= }=0A= =0A= var dir =3D this.getPluginDir(pluginName);=0A= var plugin =3D pluginName.replace(/([a-z])([A-Z])([a-z])/g,=0A= function (str, l1, l2, l3) {=0A= return l1 + "-" + l2.toLowerCase() + l3;=0A= }).toLowerCase() + ".js";=0A= var plugin_file =3D dir + "/" + plugin;=0A= =0A= if(callback)=0A= {=0A= HTMLArea._loadback(plugin_file, function() { callback(pluginName); = });=0A= }=0A= else=0A= {=0A= document.write("");=0A= }=0A= return false;=0A= };=0A= =0A= HTMLArea._pluginLoadStatus =3D { };=0A= HTMLArea.loadPlugins =3D function(plugins, callbackIfNotReady)=0A= {=0A= // Rip the ones that are loaded and look for ones that have failed=0A= var retVal =3D true;=0A= var nuPlugins =3D HTMLArea.cloneObject(plugins);=0A= while(nuPlugins.length)=0A= {=0A= var p =3D nuPlugins.pop();=0A= if(typeof HTMLArea._pluginLoadStatus[p] =3D=3D 'undefined')=0A= {=0A= // Load it=0A= HTMLArea._pluginLoadStatus[p] =3D 'loading';=0A= HTMLArea.loadPlugin(p,=0A= function(plugin)=0A= {=0A= if(eval('typeof ' + plugin) !=3D 'undefined')=0A= {=0A= HTMLArea._pluginLoadStatus[plugin] =3D 'ready';=0A= }=0A= else=0A= {=0A= // Actually, this won't happen, because if the script fails=0A= // it will throw an exception preventing the callback from=0A= // running. This will leave it always in the "loading" = state=0A= // unfortunatly that means we can't fail plugins gracefully=0A= // by just skipping them.=0A= HTMLArea._pluginLoadStatus[plugin] =3D 'failed';=0A= }=0A= }=0A= );=0A= retVal =3D false;=0A= }=0A= else=0A= {=0A= switch(HTMLArea._pluginLoadStatus[p])=0A= {=0A= case 'failed':=0A= case 'ready' :=0A= break;=0A= =0A= case 'loading':=0A= default :=0A= retVal =3D false;=0A= break;=0A= }=0A= }=0A= }=0A= =0A= if(retVal) return true; // All done, just return=0A= =0A= // Waiting on plugins to load, return false now and come back a bit = later=0A= // if we have to callback=0A= if(callbackIfNotReady)=0A= {=0A= setTimeout(function() { if(HTMLArea.loadPlugins(plugins, = callbackIfNotReady)) callbackIfNotReady(); }, 150);=0A= }=0A= return retVal;=0A= }=0A= =0A= // refresh plugin by calling onGenerate or onGenerateOnce method.=0A= HTMLArea.refreshPlugin =3D function(plugin) {=0A= if (typeof plugin.onGenerate =3D=3D "function")=0A= plugin.onGenerate();=0A= if (typeof plugin.onGenerateOnce =3D=3D "function") {=0A= plugin.onGenerateOnce();=0A= plugin.onGenerateOnce =3D null;=0A= }=0A= };=0A= =0A= HTMLArea.loadStyle =3D function(style, plugin) {=0A= var url =3D _editor_url || '';=0A= if (typeof plugin !=3D "undefined") {=0A= url +=3D "plugins/" + plugin + "/";=0A= }=0A= url +=3D style;=0A= if (/^\//.test(style))=0A= url =3D style;=0A= var head =3D document.getElementsByTagName("head")[0];=0A= var link =3D document.createElement("link");=0A= link.rel =3D "stylesheet";=0A= link.href =3D url;=0A= head.appendChild(link);=0A= //document.write("");=0A= };=0A= HTMLArea.loadStyle(typeof _editor_css =3D=3D "string" ? _editor_css : = "htmlarea.css");=0A= =0A= /***************************************************=0A= * Category: EDITOR UTILITIES=0A= ***************************************************/=0A= =0A= HTMLArea.prototype.debugTree =3D function() {=0A= var ta =3D document.createElement("textarea");=0A= ta.style.width =3D "100%";=0A= ta.style.height =3D "20em";=0A= ta.value =3D "";=0A= function debug(indent, str) {=0A= for (; --indent >=3D 0;)=0A= ta.value +=3D " ";=0A= ta.value +=3D str + "\n";=0A= };=0A= function _dt(root, level) {=0A= var tag =3D root.tagName.toLowerCase(), i;=0A= var ns =3D HTMLArea.is_ie ? root.scopeName : root.prefix;=0A= debug(level, "- " + tag + " [" + ns + "]");=0A= for (i =3D root.firstChild; i; i =3D i.nextSibling)=0A= if (i.nodeType =3D=3D 1)=0A= _dt(i, level + 2);=0A= };=0A= _dt(this._doc.body, 0);=0A= document.body.appendChild(ta);=0A= };=0A= =0A= HTMLArea.getInnerText =3D function(el) {=0A= var txt =3D '', i;=0A= for (i =3D el.firstChild; i; i =3D i.nextSibling) {=0A= if (i.nodeType =3D=3D 3)=0A= txt +=3D i.data;=0A= else if (i.nodeType =3D=3D 1)=0A= txt +=3D HTMLArea.getInnerText(i);=0A= }=0A= return txt;=0A= };=0A= =0A= HTMLArea.prototype._wordClean =3D function() {=0A= var=0A= editor =3D this,=0A= stats =3D {=0A= empty_tags : 0,=0A= mso_class : 0,=0A= mso_style : 0,=0A= mso_xmlel : 0,=0A= orig_len : this._doc.body.innerHTML.length,=0A= T : (new Date()).getTime()=0A= },=0A= stats_txt =3D {=0A= empty_tags : "Empty tags removed: ",=0A= mso_class : "MSO class names removed: ",=0A= mso_style : "MSO inline style removed: ",=0A= mso_xmlel : "MSO XML elements stripped: "=0A= };=0A= function showStats() {=0A= var txt =3D "HTMLArea word cleaner stats: \n\n";=0A= for (var i in stats)=0A= if (stats_txt[i])=0A= txt +=3D stats_txt[i] + stats[i] + "\n";=0A= txt +=3D "\nInitial document length: " + stats.orig_len + "\n";=0A= txt +=3D "Final document length: " + = editor._doc.body.innerHTML.length + "\n";=0A= txt +=3D "Clean-up took " + (((new Date()).getTime() - stats.T) / = 1000) + " seconds";=0A= alert(txt);=0A= };=0A= function clearClass(node) {=0A= var newc =3D node.className.replace(/(^|\s)mso.*?(\s|$)/ig, ' ');=0A= if (newc !=3D node.className) {=0A= node.className =3D newc;=0A= if (!/\S/.test(node.className)) {=0A= node.removeAttribute("className");=0A= ++stats.mso_class;=0A= }=0A= }=0A= };=0A= function clearStyle(node) {=0A= var declarations =3D node.style.cssText.split(/\s*;\s*/);=0A= for (var i =3D declarations.length; --i >=3D 0;)=0A= if (/^mso|^tab-stops/i.test(declarations[i]) ||=0A= /^margin\s*:\s*0..\s+0..\s+0../i.test(declarations[i])) {=0A= ++stats.mso_style;=0A= declarations.splice(i, 1);=0A= }=0A= node.style.cssText =3D declarations.join("; ");=0A= };=0A= function stripTag(el) {=0A= if (HTMLArea.is_ie)=0A= el.outerHTML =3D HTMLArea.htmlEncode(el.innerText);=0A= else {=0A= var txt =3D document.createTextNode(HTMLArea.getInnerText(el));=0A= el.parentNode.insertBefore(txt, el);=0A= HTMLArea.removeFromParent(el);=0A= }=0A= ++stats.mso_xmlel;=0A= };=0A= function checkEmpty(el) {=0A= if (/^(a|span|b|strong|i|em|font)$/i.test(el.tagName) &&=0A= !el.firstChild) {=0A= HTMLArea.removeFromParent(el);=0A= ++stats.empty_tags;=0A= }=0A= };=0A= function parseTree(root) {=0A= var tag =3D root.tagName.toLowerCase(), i, next;=0A= if ((HTMLArea.is_ie && root.scopeName !=3D 'HTML') || = (!HTMLArea.is_ie && /:/.test(tag))) {=0A= stripTag(root);=0A= return false;=0A= } else {=0A= clearClass(root);=0A= clearStyle(root);=0A= for (i =3D root.firstChild; i; i =3D next) {=0A= next =3D i.nextSibling;=0A= if (i.nodeType =3D=3D 1 && parseTree(i))=0A= checkEmpty(i);=0A= }=0A= }=0A= return true;=0A= };=0A= parseTree(this._doc.body);=0A= // showStats();=0A= // this.debugTree();=0A= // this.setHTML(this.getHTML());=0A= // this.setHTML(this.getInnerHTML());=0A= // this.forceRedraw();=0A= this.updateToolbar();=0A= };=0A= =0A= HTMLArea.prototype._clearFonts =3D function() {=0A= var D =3D this.getInnerHTML();=0A= =0A= if(confirm('Would you like to clear font typefaces?'))=0A= {=0A= D =3D D.replace(/face=3D"[^"]*"/gi, '');=0A= D =3D D.replace(/font-family:[^;}"']+;?/gi, '');=0A= }=0A= =0A= if(confirm('Would you like to clear font sizes?'))=0A= {=0A= D =3D D.replace(/size=3D"[^"]*"/gi, '');=0A= D =3D D.replace(/font-size:[^;}"']+;?/gi, '');=0A= }=0A= =0A= if(confirm('Would you like to clear font colours?'))=0A= {=0A= D =3D D.replace(/color=3D"[^"]*"/gi, '');=0A= D =3D D.replace(/([^-])color:[^;}"']+;?/gi, '$1');=0A= }=0A= =0A= D =3D D.replace(/(style|class)=3D"\s*"/gi, '');=0A= D =3D D.replace(/<(font|span)\s*>/gi, '');=0A= this.setHTML(D);=0A= this.updateToolbar();=0A= }=0A= =0A= HTMLArea.prototype._splitBlock =3D function()=0A= {=0A= this._doc.execCommand('formatblock', false, '

');=0A= }=0A= =0A= HTMLArea.prototype.forceRedraw =3D function() {=0A= this._doc.body.style.visibility =3D "hidden";=0A= this._doc.body.style.visibility =3D "visible";=0A= // this._doc.body.innerHTML =3D this.getInnerHTML();=0A= };=0A= =0A= // focuses the iframe window. returns a reference to the editor = document.=0A= HTMLArea.prototype.focusEditor =3D function() {=0A= switch (this._editMode) {=0A= // notice the try { ... } catch block to avoid some rare = exceptions in FireFox=0A= // (perhaps also in other Gecko browsers). Manual focus by user is = required in=0A= // case of an error. Somebody has an idea?=0A= case "wysiwyg" :=0A= try=0A= {=0A= // We don't want to focus the field unless at least one field = has been activated.=0A= if(HTMLArea._someEditorHasBeenActivated)=0A= {=0A= this.activateEditor(); // Ensure *this* editor is activated=0A= this._iframe.contentWindow.focus(); // and focus it=0A= }=0A= } catch (e) {} break;=0A= case "textmode": try { this._textArea.focus() } catch (e) {} break;=0A= default : alert("ERROR: mode " + this._editMode + " is not = defined");=0A= }=0A= return this._doc;=0A= };=0A= =0A= // takes a snapshot of the current text (for undo)=0A= HTMLArea.prototype._undoTakeSnapshot =3D function() {=0A= ++this._undoPos;=0A= if (this._undoPos >=3D this.config.undoSteps) {=0A= // remove the first element=0A= this._undoQueue.shift();=0A= --this._undoPos;=0A= }=0A= // use the fasted method (getInnerHTML);=0A= var take =3D true;=0A= var txt =3D this.getInnerHTML();=0A= if (this._undoPos > 0)=0A= take =3D (this._undoQueue[this._undoPos - 1] !=3D txt);=0A= if (take) {=0A= this._undoQueue[this._undoPos] =3D txt;=0A= } else {=0A= this._undoPos--;=0A= }=0A= };=0A= =0A= HTMLArea.prototype.undo =3D function() {=0A= if (this._undoPos > 0) {=0A= var txt =3D this._undoQueue[--this._undoPos];=0A= if (txt) this.setHTML(txt);=0A= else ++this._undoPos;=0A= }=0A= };=0A= =0A= HTMLArea.prototype.redo =3D function() {=0A= if (this._undoPos < this._undoQueue.length - 1) {=0A= var txt =3D this._undoQueue[++this._undoPos];=0A= if (txt) this.setHTML(txt);=0A= else --this._undoPos;=0A= }=0A= };=0A= =0A= HTMLArea.prototype.disableToolbar =3D function(except)=0A= {=0A= if(this._timerToolbar) clearTimeout(this._timerToolbar);=0A= if(typeof except =3D=3D 'undefined')=0A= {=0A= except =3D [ ];=0A= }=0A= else if(typeof except !=3D 'object')=0A= {=0A= except =3D [except];=0A= }=0A= =0A= for (var i in this._toolbarObjects)=0A= {=0A= var btn =3D this._toolbarObjects[i];=0A= if(except.contains(i))=0A= {=0A= continue;=0A= }=0A= btn.state("enabled", false);=0A= }=0A= }=0A= =0A= HTMLArea.prototype.enableToolbar =3D function()=0A= {=0A= this.updateToolbar();=0A= }=0A= =0A= if(!Array.prototype.contains)=0A= {=0A= Array.prototype.contains =3D function(needle)=0A= {=0A= var haystack =3D this;=0A= for(var i =3D 0; i < haystack.length; i++)=0A= {=0A= if(needle =3D=3D haystack[i]) return true;=0A= }=0A= =0A= return false;=0A= }=0A= }=0A= =0A= if(!Array.prototype.indexOf)=0A= {=0A= Array.prototype.indexOf =3D function(needle)=0A= {=0A= var haystack =3D this;=0A= for(var i =3D 0; i < haystack.length; i++)=0A= {=0A= if(needle =3D=3D haystack[i]) return i;=0A= }=0A= =0A= return null;=0A= }=0A= }=0A= =0A= =0A= // updates enabled/disable/active state of the toolbar elements=0A= HTMLArea.prototype.updateToolbar =3D function(noStatus) {=0A= var doc =3D this._doc;=0A= var text =3D (this._editMode =3D=3D "textmode");=0A= var ancestors =3D null;=0A= if (!text) {=0A= ancestors =3D this.getAllAncestors();=0A= if (this.config.statusBar && !noStatus) {=0A= this._statusBarTree.innerHTML =3D HTMLArea._lc("Path") + ": "; // = clear=0A= for (var i =3D ancestors.length; --i >=3D 0;) {=0A= var el =3D ancestors[i];=0A= if (!el) {=0A= // hell knows why we get here; this=0A= // could be a classic example of why=0A= // it's good to check for conditions=0A= // that are impossible to happen ;-)=0A= continue;=0A= }=0A= var a =3D document.createElement("a");=0A= a.href =3D "javascript:void(0)";=0A= a.el =3D el;=0A= a.editor =3D this;=0A= HTMLArea.addDom0Event(a, 'click', function() {=0A= this.blur();=0A= this.editor.selectNodeContents(this.el);=0A= this.editor.updateToolbar(true);=0A= return false;=0A= });=0A= HTMLArea.addDom0Event(a, 'contextmenu', function() {=0A= // TODO: add context menu here=0A= this.blur();=0A= var info =3D "Inline style:\n\n";=0A= info +=3D this.el.style.cssText.split(/;\s*/).join(";\n");=0A= alert(info);=0A= return false;=0A= });=0A= var txt =3D el.tagName.toLowerCase();=0A= a.title =3D el.style.cssText;=0A= if (el.id) {=0A= txt +=3D "#" + el.id;=0A= }=0A= if (el.className) {=0A= txt +=3D "." + el.className;=0A= }=0A= a.appendChild(document.createTextNode(txt));=0A= this._statusBarTree.appendChild(a);=0A= if (i !=3D 0) {=0A= = this._statusBarTree.appendChild(document.createTextNode(String.fromCharCo= de(0xbb)));=0A= }=0A= }=0A= }=0A= }=0A= =0A= for (var i in this._toolbarObjects) {=0A= var btn =3D this._toolbarObjects[i];=0A= var cmd =3D i;=0A= var inContext =3D true;=0A= if (btn.context && !text) {=0A= inContext =3D false;=0A= var context =3D btn.context;=0A= var attrs =3D [];=0A= if (/(.*)\[(.*?)\]/.test(context)) {=0A= context =3D RegExp.$1;=0A= attrs =3D RegExp.$2.split(",");=0A= }=0A= context =3D context.toLowerCase();=0A= var match =3D (context =3D=3D "*");=0A= for (var k =3D 0; k < ancestors.length; ++k) {=0A= if (!ancestors[k]) {=0A= // the impossible really happens.=0A= continue;=0A= }=0A= if (match || (ancestors[k].tagName.toLowerCase() =3D=3D = context)) {=0A= inContext =3D true;=0A= for (var ka =3D 0; ka < attrs.length; ++ka) {=0A= if (!eval("ancestors[k]." + attrs[ka])) {=0A= inContext =3D false;=0A= break;=0A= }=0A= }=0A= if (inContext) {=0A= break;=0A= }=0A= }=0A= }=0A= }=0A= btn.state("enabled", (!text || btn.text) && inContext);=0A= if (typeof cmd =3D=3D "function") {=0A= continue;=0A= }=0A= // look-it-up in the custom dropdown boxes=0A= var dropdown =3D this.config.customSelects[cmd];=0A= if ((!text || btn.text) && (typeof dropdown !=3D "undefined")) {=0A= dropdown.refresh(this);=0A= continue;=0A= }=0A= switch (cmd)=0A= {=0A= case "fontname":=0A= case "fontsize":=0A= {=0A= if (!text) try {=0A= var value =3D ("" + doc.queryCommandValue(cmd)).toLowerCase();=0A= if (!value) {=0A= btn.element.selectedIndex =3D 0;=0A= break;=0A= }=0A= =0A= // HACK -- retrieve the config option for this=0A= // combo box. We rely on the fact that the=0A= // variable in config has the same name as=0A= // button name in the toolbar.=0A= var options =3D this.config[cmd];=0A= var k =3D 0;=0A= for (var j in options)=0A= {=0A= // FIXME: the following line is scary.=0A= if ((j.toLowerCase() =3D=3D value) || (options[j].substr(0, = value.length).toLowerCase() =3D=3D value))=0A= {=0A= btn.element.selectedIndex =3D k;=0A= throw "ok";=0A= }=0A= ++k;=0A= }=0A= btn.element.selectedIndex =3D 0;=0A= } catch(e) {};=0A= }=0A= break;=0A= =0A= // It's better to search for the format block by tag name from the=0A= // current selection upwards, because IE has a tendancy to return=0A= // things like 'heading 1' for 'h1', which breaks things if you = want=0A= // to call your heading blocks 'header 1'. Stupid MS.=0A= case "formatblock" :=0A= {=0A= var blocks =3D [ ];=0A= for(var i in this.config['formatblock'])=0A= {=0A= blocks[blocks.length] =3D this.config['formatblock'][i];=0A= }=0A= =0A= var deepestAncestor =3D = this._getFirstAncestor(this._getSelection(), blocks);=0A= if(deepestAncestor)=0A= {=0A= for(var x=3D 0; x < blocks.length; x++)=0A= {=0A= if(blocks[x].toLowerCase() =3D=3D = deepestAncestor.tagName.toLowerCase())=0A= {=0A= btn.element.selectedIndex =3D x;=0A= }=0A= }=0A= }=0A= else=0A= {=0A= btn.element.selectedIndex =3D 0;=0A= }=0A= }=0A= break;=0A= =0A= case "textindicator":=0A= if (!text) {=0A= try {with (btn.element.style) {=0A= backgroundColor =3D HTMLArea._makeColor(=0A= doc.queryCommandValue(HTMLArea.is_ie ? "backcolor" : = "hilitecolor"));=0A= if (/transparent/i.test(backgroundColor)) {=0A= // Mozilla=0A= backgroundColor =3D = HTMLArea._makeColor(doc.queryCommandValue("backcolor"));=0A= }=0A= color =3D = HTMLArea._makeColor(doc.queryCommandValue("forecolor"));=0A= fontFamily =3D doc.queryCommandValue("fontname");=0A= fontWeight =3D doc.queryCommandState("bold") ? "bold" : = "normal";=0A= fontStyle =3D doc.queryCommandState("italic") ? "italic" : = "normal";=0A= }} catch (e) {=0A= // alert(e + "\n\n" + cmd);=0A= }=0A= }=0A= break;=0A= case "htmlmode": btn.state("active", text); break;=0A= case "lefttoright":=0A= case "righttoleft":=0A= var el =3D this.getParentElement();=0A= while (el && !HTMLArea.isBlockElement(el))=0A= el =3D el.parentNode;=0A= if (el)=0A= btn.state("active", (el.style.direction =3D=3D ((cmd =3D=3D = "righttoleft") ? "rtl" : "ltr")));=0A= break;=0A= default:=0A= cmd =3D cmd.replace(/(un)?orderedlist/i, "insert$1orderedlist");=0A= try {=0A= btn.state("active", (!text && doc.queryCommandState(cmd)));=0A= } catch (e) {}=0A= }=0A= }=0A= // take undo snapshots=0A= if (this._customUndo && !this._timerUndo) {=0A= this._undoTakeSnapshot();=0A= var editor =3D this;=0A= this._timerUndo =3D setTimeout(function() {=0A= editor._timerUndo =3D null;=0A= }, this.config.undoTimeout);=0A= }=0A= =0A= // Insert a space in certain locations, this is just to make editing a = little=0A= // easier (to "get out of" tags), it's not essential.=0A= // TODO: Make this work for IE?=0A= // TODO: Perhaps should use a plain space character, I'm not sure.=0A= // OK, I've disabled this temporarily, to be honest, I can't rightly = remember what the=0A= // original problem was I was trying to solve with it. I think = perhaps that EnterParagraphs=0A= // might solve the problem, whatever the hell it was. I'm going = senile, I'm sure.=0A= if(0 && HTMLArea.is_gecko)=0A= {=0A= var s =3D this._getSelection();=0A= // If the last character in the last text node of the parent tag=0A= // and the parent tag is not a block tag=0A= if(s && s.isCollapsed && s.anchorNode=0A= && s.anchorNode.parentNode.tagName.toLowerCase() !=3D 'body'=0A= && s.anchorNode.nodeType =3D=3D 3 && s.anchorOffset =3D=3D = s.anchorNode.length=0A= && !=0A= ( s.anchorNode.parentNode.nextSibling=0A= && s.anchorNode.parentNode.nextSibling.nodeType =3D=3D 3=0A= )=0A= && !HTMLArea.isBlockElement(s.anchorNode.parentNode)=0A= )=0A= {=0A= // Insert hair-width-space after the close tag if there isn't = another text node on the other side=0A= // It could also work with zero-width-space (\u200B) but I don't = like it so much.=0A= // Perhaps this won't work well in various character sets and we = should use plain space (20)?=0A= try=0A= {=0A= s.anchorNode.parentNode.parentNode.insertBefore=0A= (this._doc.createTextNode('\t'), = s.anchorNode.parentNode.nextSibling);=0A= }=0A= catch(e)=0A= {=0A= // Disregard=0A= }=0A= }=0A= }=0A= =0A= // check if any plugins have registered refresh handlers=0A= for (var i in this.plugins) {=0A= var plugin =3D this.plugins[i].instance;=0A= if (typeof plugin.onUpdateToolbar =3D=3D "function")=0A= plugin.onUpdateToolbar();=0A= }=0A= =0A= =0A= }=0A= =0A= /** Returns a node after which we can insert other nodes, in the current=0A= * selection. The selection is removed. It splits a text node, if = needed.=0A= */=0A= HTMLArea.prototype.insertNodeAtSelection =3D function(toBeInserted) {=0A= if (!HTMLArea.is_ie) {=0A= var sel =3D this._getSelection();=0A= var range =3D this._createRange(sel);=0A= // remove the current selection=0A= sel.removeAllRanges();=0A= range.deleteContents();=0A= var node =3D range.startContainer;=0A= var pos =3D range.startOffset;=0A= switch (node.nodeType) {=0A= case 3: // Node.TEXT_NODE=0A= // we have to split it at the caret position.=0A= if (toBeInserted.nodeType =3D=3D 3) {=0A= // do optimized insertion=0A= node.insertData(pos, toBeInserted.data);=0A= range =3D this._createRange();=0A= range.setEnd(node, pos + toBeInserted.length);=0A= range.setStart(node, pos + toBeInserted.length);=0A= sel.addRange(range);=0A= } else {=0A= node =3D node.splitText(pos);=0A= var selnode =3D toBeInserted;=0A= if (toBeInserted.nodeType =3D=3D 11 /* = Node.DOCUMENT_FRAGMENT_NODE */) {=0A= selnode =3D selnode.firstChild;=0A= }=0A= node.parentNode.insertBefore(toBeInserted, node);=0A= this.selectNodeContents(selnode);=0A= this.updateToolbar();=0A= }=0A= break;=0A= case 1: // Node.ELEMENT_NODE=0A= var selnode =3D toBeInserted;=0A= if (toBeInserted.nodeType =3D=3D 11 /* Node.DOCUMENT_FRAGMENT_NODE = */) {=0A= selnode =3D selnode.firstChild;=0A= }=0A= node.insertBefore(toBeInserted, node.childNodes[pos]);=0A= this.selectNodeContents(selnode);=0A= this.updateToolbar();=0A= break;=0A= }=0A= } else {=0A= return null; // this function not yet used for IE =0A= }=0A= };=0A= =0A= // Returns the deepest node that contains both endpoints of the = selection.=0A= HTMLArea.prototype.getParentElement =3D function(sel) {=0A= if(typeof sel =3D=3D 'undefined')=0A= {=0A= sel =3D this._getSelection();=0A= }=0A= var range =3D this._createRange(sel);=0A= if (HTMLArea.is_ie) {=0A= switch (sel.type) {=0A= case "Text":=0A= case "None":=0A= // It seems that even for selection of type "None",=0A= // there _is_ a parent element and it's value is not=0A= // only correct, but very important to us. MSIE is=0A= // certainly the buggiest browser in the world and I=0A= // wonder, God, how can Earth stand it?=0A= return range.parentElement();=0A= case "Control":=0A= return range.item(0);=0A= default:=0A= return this._doc.body;=0A= }=0A= } else try {=0A= var p =3D range.commonAncestorContainer;=0A= if (!range.collapsed && range.startContainer =3D=3D = range.endContainer &&=0A= range.startOffset - range.endOffset <=3D 1 && = range.startContainer.hasChildNodes())=0A= p =3D range.startContainer.childNodes[range.startOffset];=0A= /*=0A= alert(range.startContainer + ":" + range.startOffset + "\n" +=0A= range.endContainer + ":" + range.endOffset);=0A= */=0A= while (p.nodeType =3D=3D 3) {=0A= p =3D p.parentNode;=0A= }=0A= return p;=0A= } catch (e) {=0A= return null;=0A= }=0A= };=0A= =0A= // Returns an array with all the ancestor nodes of the selection.=0A= HTMLArea.prototype.getAllAncestors =3D function() {=0A= var p =3D this.getParentElement();=0A= var a =3D [];=0A= while (p && (p.nodeType =3D=3D 1) && (p.tagName.toLowerCase() !=3D = 'body')) {=0A= a.push(p);=0A= p =3D p.parentNode;=0A= }=0A= a.push(this._doc.body);=0A= return a;=0A= };=0A= =0A= // Returns the deepest ancestor of the selection that is of the current = type=0A= HTMLArea.prototype._getFirstAncestor =3D function(sel, types)=0A= {=0A= var prnt =3D this._activeElement(sel);=0A= if(prnt =3D=3D null)=0A= {=0A= try=0A= {=0A= prnt =3D (HTMLArea.is_ie ? this._createRange(sel).parentElement() = : this._createRange(sel).commonAncestorContainer);=0A= }=0A= catch(e)=0A= {=0A= return null;=0A= }=0A= }=0A= =0A= if(typeof types =3D=3D 'string')=0A= {=0A= types =3D [types];=0A= }=0A= =0A= while(prnt)=0A= {=0A= if(prnt.nodeType =3D=3D 1)=0A= {=0A= if(types =3D=3D null) return prnt;=0A= if(types.contains(prnt.tagName.toLowerCase()))=0A= {=0A= =0A= return prnt;=0A= }=0A= if(prnt.tagName.toLowerCase() =3D=3D 'body') break;=0A= if(prnt.tagName.toLowerCase() =3D=3D 'table') break;=0A= }=0A= prnt =3D prnt.parentNode;=0A= }=0A= =0A= return null;=0A= }=0A= =0A= /**=0A= * Returns the selected element, if any. That is,=0A= * the element that you have last selected in the "path"=0A= * at the bottom of the editor, or a "control" (eg image)=0A= *=0A= * @returns null | element=0A= */=0A= HTMLArea.prototype._activeElement =3D function(sel)=0A= {=0A= if(sel =3D=3D null) return null;=0A= if(this._selectionEmpty(sel)) return null;=0A= =0A= if(HTMLArea.is_ie)=0A= {=0A= if(sel.type.toLowerCase() =3D=3D "control")=0A= {=0A= return sel.createRange().item(0);=0A= }=0A= else=0A= {=0A= =0A= // If it's not a control, then we need to see if=0A= // the selection is the _entire_ text of a parent node=0A= // (this happens when a node is clicked in the tree)=0A= var range =3D sel.createRange();=0A= var p_elm =3D this.getParentElement(sel);=0A= if(p_elm.innerHTML =3D=3D range.htmlText)=0A= {=0A= return p_elm;=0A= }=0A= /*=0A= if(p_elm)=0A= {=0A= var p_rng =3D this._doc.body.createTextRange();=0A= p_rng.moveToElementText(p_elm);=0A= if(p_rng.isEqual(range))=0A= {=0A= return p_elm;=0A= }=0A= }=0A= =0A= if(range.parentElement())=0A= {=0A= var prnt_range =3D this._doc.body.createTextRange();=0A= prnt_range.moveToElementText(range.parentElement());=0A= if(prnt_range.isEqual(range))=0A= {=0A= return range.parentElement();=0A= }=0A= }=0A= */=0A= return null;=0A= }=0A= }=0A= else=0A= {=0A= // For Mozilla we just see if the selection is not collapsed = (something is selected)=0A= // and that the anchor (start of selection) is an element. This = might not be totally=0A= // correct, we possibly should do a simlar check to IE?=0A= if(! sel.isCollapsed)=0A= {=0A= if(sel.anchorNode.childNodes.length > sel.anchorOffset && = sel.anchorNode.childNodes[sel.anchorOffset].nodeType =3D=3D 1)=0A= {=0A= return sel.anchorNode.childNodes[sel.anchorOffset];=0A= }=0A= else if(sel.anchorNode.nodeType =3D=3D 1)=0A= {=0A= return sel.anchorNode;=0A= }=0A= else=0A= {=0A= return sel.anchorNode.parentNode;=0A= }=0A= }=0A= return null;=0A= }=0A= }=0A= =0A= =0A= HTMLArea.prototype._selectionEmpty =3D function(sel)=0A= {=0A= if(!sel) return true;=0A= =0A= if(HTMLArea.is_ie)=0A= {=0A= return this._createRange(sel).htmlText =3D=3D '';=0A= }=0A= else if(typeof sel.isCollapsed !=3D 'undefined')=0A= {=0A= return sel.isCollapsed;=0A= }=0A= =0A= return true;=0A= }=0A= =0A= HTMLArea.prototype._getAncestorBlock =3D function(sel)=0A= {=0A= // Scan upwards to find a block level element that we can change or = apply to=0A= var prnt =3D (HTMLArea.is_ie ? this._createRange(sel).parentElement : = this._createRange(sel).commonAncestorContainer);=0A= =0A= while(prnt && (prnt.nodeType =3D=3D 1))=0A= {=0A= switch(prnt.tagName.toLowerCase())=0A= {=0A= case 'div' :=0A= case 'p' :=0A= case 'address' :=0A= case 'blockquote' :=0A= case 'center' :=0A= case 'del' :=0A= case 'ins' :=0A= case 'pre' :=0A= case 'h1' :=0A= case 'h2' :=0A= case 'h3' :=0A= case 'h4' :=0A= case 'h5' :=0A= case 'h6' :=0A= case 'h7' :=0A= // Block Element=0A= return prnt;=0A= =0A= case 'body' :=0A= case 'noframes' :=0A= case 'dd' :=0A= case 'li' :=0A= case 'th' :=0A= case 'td' :=0A= case 'noscript' :=0A= // Halting element (stop searching)=0A= return null;=0A= =0A= default :=0A= // Keep lookin=0A= break;=0A= }=0A= }=0A= =0A= return null;=0A= }=0A= =0A= HTMLArea.prototype._createImplicitBlock =3D function(type)=0A= {=0A= // expand it until we reach a block element in either direction=0A= // then wrap the selection in a block and return=0A= var sel =3D this._getSelection();=0A= if(HTMLArea.is_ie)=0A= {=0A= sel.empty();=0A= }=0A= else=0A= {=0A= sel.collapseToStart();=0A= }=0A= =0A= var rng =3D this._createRange(sel);=0A= =0A= // Expand UP=0A= =0A= // Expand DN=0A= }=0A= =0A= HTMLArea.prototype._formatBlock =3D function(block_format)=0A= {=0A= var ancestors =3D this.getAllAncestors();=0A= var apply_to =3D null;=0A= =0A= // Block format can be a tag followed with class defs=0A= // eg div.blue.left=0A= var target_tag =3D null;=0A= var target_classNames =3D [ ];=0A= =0A= if(block_format.indexOf('.') >=3D 0)=0A= {=0A= target_tag =3D block_format.substr(0, = block_format.indexOf('.')).toLowerCase();;=0A= =0A= target_classNames =3D block_format.substr(block_format.indexOf('.'), = block_format.length - block_format.indexOf('.')).replace(/\./g, = '').replace(/^\s*/, '').replace(/\s*$/, '').split(' ');=0A= }=0A= else=0A= {=0A= target_tag =3D block_format.toLowerCase();=0A= }=0A= =0A= var sel =3D this._getSelection();=0A= var rng =3D this._createRange(sel);=0A= var apply_to =3D null;=0A= =0A= if(HTMLArea.is_gecko)=0A= {=0A= if(sel.isCollapsed)=0A= {=0A= // With no selection we want to apply to the whole contents of the = ancestor block=0A= apply_to =3D this._getAncestorBlock(sel);=0A= if(apply_to =3D=3D null)=0A= {=0A= // If there wasn't an ancestor, make one.=0A= apply_to =3D this._createImplicitBlock(sel, target_tag);=0A= }=0A= }=0A= else=0A= {=0A= // With a selection it's more tricky=0A= switch(target_tag)=0A= {=0A= =0A= case 'h1' :=0A= case 'h2' :=0A= case 'h3' :=0A= case 'h4' :=0A= case 'h5' :=0A= case 'h6' :=0A= case 'h7' :=0A= apply_to =3D [ ];=0A= var search_tags =3D ['h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'h7'];=0A= for(var y =3D 0; y < search_tags.length; y++)=0A= {=0A= var headers =3D = this._doc.getElementsByTagName(search_tag[y]);=0A= for(var x =3D 0; x < headers.length; x++)=0A= {=0A= if(sel.containsNode(headers[x]))=0A= {=0A= apply_to[apply_to.length] =3D headers[x];=0A= }=0A= }=0A= }=0A= if(apply_to.length > 0) break;=0A= // If there wern't any in the selection drop through=0A= case 'div' :=0A= apply_to =3D this._doc.createElement(target_tag);=0A= apply_to.appendChild(rng.extractContents());=0A= rng.insertNode(apply_to);=0A= break;=0A= =0A= case 'p' :=0A= case 'center' :=0A= case 'pre' :=0A= case 'ins' :=0A= case 'del' :=0A= case 'blockquote' :=0A= case 'address' :=0A= apply_to =3D [ ];=0A= var paras =3D this._doc.getElementsByTagName(target_tag);=0A= for(var x =3D 0; x < paras.length; x++)=0A= {=0A= if(sel.containsNode(paras[x]))=0A= {=0A= apply_to[apply_to.length] =3D paras[x];=0A= }=0A= }=0A= =0A= if(apply_to.length =3D=3D 0)=0A= {=0A= sel.collapseToStart();=0A= return this._formatBlock(block_format);=0A= }=0A= break;=0A= }=0A= }=0A= }=0A= =0A= }=0A= =0A= // Selects the contents inside the given node=0A= HTMLArea.prototype.selectNodeContents =3D function(node, pos) {=0A= this.focusEditor();=0A= this.forceRedraw();=0A= var range;=0A= var collapsed =3D typeof pos =3D=3D "undefined" ? true : false;=0A= if (HTMLArea.is_ie) {=0A= // Tables and Images get selected as "objects" rather than the text = contents=0A= if(collapsed && node.tagName && = node.tagName.toLowerCase().match(/table|img|input|select|textarea/))=0A= {=0A= range =3D this._doc.body.createControlRange();=0A= range.add(node);=0A= }=0A= else=0A= {=0A= range =3D this._doc.body.createTextRange();=0A= range.moveToElementText(node);=0A= //(collapsed) && range.collapse(pos);=0A= }=0A= range.select();=0A= } else {=0A= var sel =3D this._getSelection();=0A= range =3D this._doc.createRange();=0A= // Tables and Images get selected as "objects" rather than the text = contents=0A= if(collapsed && node.tagName && = node.tagName.toLowerCase().match(/table|img|input|textarea|select/))=0A= {=0A= range.selectNode(node);=0A= }=0A= else=0A= {=0A= range.selectNodeContents(node);=0A= //(collapsed) && range.collapse(pos);=0A= }=0A= sel.removeAllRanges();=0A= sel.addRange(range);=0A= }=0A= };=0A= =0A= /** Call this function to insert HTML code at the current position. It = deletes=0A= * the selection, if any.=0A= */=0A= HTMLArea.prototype.insertHTML =3D function(html) {=0A= var sel =3D this._getSelection();=0A= var range =3D this._createRange(sel);=0A= if (HTMLArea.is_ie) {=0A= range.pasteHTML(html);=0A= } else {=0A= // construct a new document fragment with the given HTML=0A= var fragment =3D this._doc.createDocumentFragment();=0A= var div =3D this._doc.createElement("div");=0A= div.innerHTML =3D html;=0A= while (div.firstChild) {=0A= // the following call also removes the node from div=0A= fragment.appendChild(div.firstChild);=0A= }=0A= // this also removes the selection=0A= var node =3D this.insertNodeAtSelection(fragment);=0A= }=0A= };=0A= =0A= /**=0A= * Call this function to surround the existing HTML code in the = selection with=0A= * your tags. FIXME: buggy! This function will be deprecated "soon".=0A= */=0A= HTMLArea.prototype.surroundHTML =3D function(startTag, endTag) {=0A= var html =3D this.getSelectedHTML();=0A= // the following also deletes the selection=0A= this.insertHTML(startTag + html + endTag);=0A= };=0A= =0A= /// Retrieve the selected block=0A= HTMLArea.prototype.getSelectedHTML =3D function() {=0A= var sel =3D this._getSelection();=0A= var range =3D this._createRange(sel);=0A= var existing =3D null;=0A= if (HTMLArea.is_ie) {=0A= existing =3D range.htmlText;=0A= } else {=0A= existing =3D HTMLArea.getHTML(range.cloneContents(), false, this);=0A= }=0A= return existing;=0A= };=0A= =0A= /// Return true if we have some selection=0A= HTMLArea.prototype.hasSelectedText =3D function() {=0A= // FIXME: come _on_ mishoo, you can do better than this ;-)=0A= return this.getSelectedHTML() !=3D '';=0A= };=0A= =0A= HTMLArea.prototype._createLink =3D function(link) {=0A= var editor =3D this;=0A= var outparam =3D null;=0A= if (typeof link =3D=3D "undefined") {=0A= link =3D this.getParentElement();=0A= if (link) {=0A= if (/^img$/i.test(link.tagName))=0A= link =3D link.parentNode;=0A= if (!/^a$/i.test(link.tagName))=0A= link =3D null;=0A= }=0A= }=0A= if (!link) {=0A= var sel =3D editor._getSelection();=0A= var range =3D editor._createRange(sel);=0A= var compare =3D 0;=0A= if (HTMLArea.is_ie) {=0A= if(sel.type =3D=3D "Control")=0A= {=0A= compare =3D range.length;=0A= }=0A= else=0A= {=0A= compare =3D range.compareEndPoints("StartToEnd", range);=0A= }=0A= } else {=0A= compare =3D range.compareBoundaryPoints(range.START_TO_END, range);=0A= }=0A= if (compare =3D=3D 0) {=0A= alert(HTMLArea._lc("You need to select some text before creating a = link"));=0A= return;=0A= }=0A= outparam =3D {=0A= f_href : '',=0A= f_title : '',=0A= f_target : '',=0A= f_usetarget : editor.config.makeLinkShowsTarget=0A= };=0A= } else=0A= outparam =3D {=0A= f_href : HTMLArea.is_ie ? editor.stripBaseURL(link.href) : = link.getAttribute("href"),=0A= f_title : link.title,=0A= f_target : link.target,=0A= f_usetarget : editor.config.makeLinkShowsTarget=0A= };=0A= this._popupDialog(editor.config.URIs["link"], function(param) {=0A= if (!param)=0A= return false;=0A= var a =3D link;=0A= if (!a) try {=0A= editor._doc.execCommand("createlink", false, param.f_href);=0A= a =3D editor.getParentElement();=0A= var sel =3D editor._getSelection();=0A= var range =3D editor._createRange(sel);=0A= if (!HTMLArea.is_ie) {=0A= a =3D range.startContainer;=0A= if (!/^a$/i.test(a.tagName)) {=0A= a =3D a.nextSibling;=0A= if (a =3D=3D null)=0A= a =3D range.startContainer.parentNode;=0A= }=0A= }=0A= } catch(e) {}=0A= else {=0A= var href =3D param.f_href.trim();=0A= editor.selectNodeContents(a);=0A= if (href =3D=3D "") {=0A= editor._doc.execCommand("unlink", false, null);=0A= editor.updateToolbar();=0A= return false;=0A= }=0A= else {=0A= a.href =3D href;=0A= }=0A= }=0A= if (!(a && /^a$/i.test(a.tagName)))=0A= return false;=0A= a.target =3D param.f_target.trim();=0A= a.title =3D param.f_title.trim();=0A= editor.selectNodeContents(a);=0A= editor.updateToolbar();=0A= }, outparam);=0A= };=0A= =0A= // Called when the user clicks on "InsertImage" button. If an image is = already=0A= // there, it will just modify it's properties.=0A= HTMLArea.prototype._insertImage =3D function(image) {=0A= var editor =3D this; // for nested functions=0A= var outparam =3D null;=0A= if (typeof image =3D=3D "undefined") {=0A= image =3D this.getParentElement();=0A= if (image && !/^img$/i.test(image.tagName))=0A= image =3D null;=0A= }=0A= if (image) outparam =3D {=0A= f_base : editor.config.baseHref,=0A= f_url : HTMLArea.is_ie ? editor.stripBaseURL(image.src) : = image.getAttribute("src"),=0A= f_alt : image.alt,=0A= f_border : image.border,=0A= f_align : image.align,=0A= f_vert : image.vspace,=0A= f_horiz : image.hspace=0A= };=0A= this._popupDialog(editor.config.URIs["insert_image"], function(param) {=0A= if (!param) { // user must have pressed Cancel=0A= return false;=0A= }=0A= var img =3D image;=0A= if (!img) {=0A= var sel =3D editor._getSelection();=0A= var range =3D editor._createRange(sel);=0A= editor._doc.execCommand("insertimage", false, param.f_url);=0A= if (HTMLArea.is_ie) {=0A= img =3D range.parentElement();=0A= // wonder if this works...=0A= if (img.tagName.toLowerCase() !=3D "img") {=0A= img =3D img.previousSibling;=0A= }=0A= } else {=0A= img =3D range.startContainer.previousSibling;=0A= if (!img.tagName) {=0A= // if the cursor is at the beginning of the document=0A= img =3D range.startContainer.firstChild;=0A= }=0A= }=0A= } else {=0A= img.src =3D param.f_url;=0A= }=0A= =0A= for (var field in param) {=0A= var value =3D param[field];=0A= switch (field) {=0A= case "f_alt" : img.alt =3D value; break;=0A= case "f_border" : img.border =3D parseInt(value || "0"); break;=0A= case "f_align" : img.align =3D value; break;=0A= case "f_vert" : img.vspace =3D parseInt(value || "0"); break;=0A= case "f_horiz" : img.hspace =3D parseInt(value || "0"); break;=0A= }=0A= }=0A= }, outparam);=0A= };=0A= =0A= // Called when the user clicks the Insert Table button=0A= HTMLArea.prototype._insertTable =3D function() {=0A= var sel =3D this._getSelection();=0A= var range =3D this._createRange(sel);=0A= var editor =3D this; // for nested functions=0A= this._popupDialog(editor.config.URIs["insert_table"], function(param) {=0A= if (!param) { // user must have pressed Cancel=0A= return false;=0A= }=0A= var doc =3D editor._doc;=0A= // create the table element=0A= var table =3D doc.createElement("table");=0A= // assign the given arguments=0A= =0A= for (var field in param) {=0A= var value =3D param[field];=0A= if (!value) {=0A= continue;=0A= }=0A= switch (field) {=0A= case "f_width" : table.style.width =3D value + = param["f_unit"]; break;=0A= case "f_align" : table.align =3D value; break;=0A= case "f_border" : table.border =3D parseInt(value); break;=0A= case "f_spacing" : table.cellSpacing =3D parseInt(value); = break;=0A= case "f_padding" : table.cellPadding =3D parseInt(value); = break;=0A= }=0A= }=0A= var cellwidth =3D 0;=0A= if (param.f_fixed)=0A= cellwidth =3D Math.floor(100 / parseInt(param.f_cols));=0A= var tbody =3D doc.createElement("tbody");=0A= table.appendChild(tbody);=0A= for (var i =3D 0; i < param["f_rows"]; ++i) {=0A= var tr =3D doc.createElement("tr");=0A= tbody.appendChild(tr);=0A= for (var j =3D 0; j < param["f_cols"]; ++j) {=0A= var td =3D doc.createElement("td");=0A= if (cellwidth)=0A= td.style.width =3D cellwidth + "%";=0A= tr.appendChild(td);=0A= // Mozilla likes to see something inside the cell.=0A= (HTMLArea.is_gecko) && td.appendChild(doc.createElement("br"));=0A= }=0A= }=0A= if (HTMLArea.is_ie) {=0A= range.pasteHTML(table.outerHTML);=0A= } else {=0A= // insert the table=0A= editor.insertNodeAtSelection(table);=0A= }=0A= return true;=0A= }, null);=0A= };=0A= =0A= /***************************************************=0A= * Category: EVENT HANDLERS=0A= ***************************************************/=0A= =0A= // el is reference to the SELECT object=0A= // txt is the name of the select field, as in config.toolbar=0A= HTMLArea.prototype._comboSelected =3D function(el, txt) {=0A= this.focusEditor();=0A= var value =3D el.options[el.selectedIndex].value;=0A= switch (txt) {=0A= case "fontname":=0A= case "fontsize": this.execCommand(txt, false, value); break;=0A= case "formatblock":=0A= // (HTMLArea.is_ie) && (value =3D "<" + value + ">");=0A= value =3D "<" + value + ">"=0A= this.execCommand(txt, false, value);=0A= break;=0A= default:=0A= // try to look it up in the registered dropdowns=0A= var dropdown =3D this.config.customSelects[txt];=0A= if (typeof dropdown !=3D "undefined") {=0A= dropdown.action(this);=0A= } else {=0A= alert("FIXME: combo box " + txt + " not implemented");=0A= }=0A= }=0A= };=0A= =0A= // the execCommand function (intercepts some commands and replaces them = with=0A= // our own implementation)=0A= HTMLArea.prototype.execCommand =3D function(cmdID, UI, param) {=0A= var editor =3D this; // for nested functions=0A= this.focusEditor();=0A= cmdID =3D cmdID.toLowerCase();=0A= if (HTMLArea.is_gecko) try { this._doc.execCommand('useCSS', false, = true); } catch (e) {}; //switch useCSS off (true=3Doff)=0A= switch (cmdID) {=0A= case "htmlmode" : this.setMode(); break;=0A= case "hilitecolor":=0A= (HTMLArea.is_ie) && (cmdID =3D "backcolor");=0A= if (HTMLArea.is_gecko) try { editor._doc.execCommand('useCSS', = false, false); } catch (e) {};//switch on useCSS (mozilla bug #279330)=0A= case "forecolor":=0A= this._popupDialog(editor.config.URIs["select_color"], = function(color) {=0A= if (color) { // selection not canceled=0A= editor._doc.execCommand(cmdID, false, "#" + color);=0A= }=0A= }, HTMLArea._colorToRgb(this._doc.queryCommandValue(cmdID)));=0A= break;=0A= case "createlink":=0A= this._createLink();=0A= break;=0A= case "undo":=0A= case "redo":=0A= if (this._customUndo)=0A= this[cmdID]();=0A= else=0A= this._doc.execCommand(cmdID, UI, param);=0A= break;=0A= case "inserttable": this._insertTable(); break;=0A= case "insertimage": this._insertImage(); break;=0A= case "about" : this._popupDialog(editor.config.URIs["about"], = null, this); break;=0A= case "showhelp" : window.open(this.config.helpURL, "ha_help"); = break;=0A= =0A= case "killword": this._wordClean(); break;=0A= =0A= case "cut":=0A= case "copy":=0A= case "paste":=0A= try {=0A= this._doc.execCommand(cmdID, UI, param);=0A= if (this.config.killWordOnPaste)=0A= this._wordClean();=0A= } catch (e) {=0A= if (HTMLArea.is_gecko) {=0A= alert(HTMLArea._lc("The Paste button does not work in Mozilla = based web browsers (technical security reasons). Press CTRL-V on your = keyboard to paste directly."));=0A= }=0A= }=0A= break;=0A= case "lefttoright":=0A= case "righttoleft":=0A= var dir =3D (cmdID =3D=3D "righttoleft") ? "rtl" : "ltr";=0A= var el =3D this.getParentElement();=0A= while (el && !HTMLArea.isBlockElement(el))=0A= el =3D el.parentNode;=0A= if (el) {=0A= if (el.style.direction =3D=3D dir)=0A= el.style.direction =3D "";=0A= else=0A= el.style.direction =3D dir;=0A= }=0A= break;=0A= default: try { this._doc.execCommand(cmdID, UI, param); }=0A= catch(e) { if (this.config.debug) { alert(e + "\n\nby execCommand(" = + cmdID + ");"); } }=0A= }=0A= =0A= this.updateToolbar();=0A= return false;=0A= };=0A= =0A= /** A generic event handler for things that happen in the IFRAME's = document.=0A= * This function also handles key bindings. */=0A= HTMLArea.prototype._editorEvent =3D function(ev) {=0A= var editor =3D this;=0A= var keyEvent =3D (HTMLArea.is_ie && ev.type =3D=3D "keydown") || = (!HTMLArea.is_ie && ev.type =3D=3D "keypress");=0A= =0A= //call events of textarea=0A= if(typeof editor._textArea['on'+ev.type] =3D=3D "function") {=0A= editor._textArea['on'+ev.type]();=0A= }=0A= =0A= if(HTMLArea.is_gecko && keyEvent && ev.ctrlKey && this._unLink && = this._unlinkOnUndo)=0A= {=0A= if(String.fromCharCode(ev.charCode).toLowerCase() =3D=3D 'z')=0A= {=0A= HTMLArea._stopEvent(ev);=0A= this._unLink();=0A= editor.updateToolbar();=0A= return;=0A= }=0A= }=0A= =0A= if (keyEvent)=0A= {=0A= for (var i in editor.plugins)=0A= {=0A= var plugin =3D editor.plugins[i].instance;=0A= if (typeof plugin.onKeyPress =3D=3D "function")=0A= if (plugin.onKeyPress(ev))=0A= return false;=0A= }=0A= }=0A= =0A= if (keyEvent && ev.ctrlKey && !ev.altKey)=0A= {=0A= var sel =3D null;=0A= var range =3D null;=0A= var key =3D String.fromCharCode(HTMLArea.is_ie ? ev.keyCode : = ev.charCode).toLowerCase();=0A= var cmd =3D null;=0A= var value =3D null;=0A= switch (key) {=0A= case 'a':=0A= if (!HTMLArea.is_ie) {=0A= // KEY select all=0A= sel =3D this._getSelection();=0A= sel.removeAllRanges();=0A= range =3D this._createRange();=0A= range.selectNodeContents(this._doc.body);=0A= sel.addRange(range);=0A= HTMLArea._stopEvent(ev);=0A= }=0A= break;=0A= =0A= // simple key commands follow=0A= =0A= case 'b': cmd =3D "bold"; break;=0A= case 'i': cmd =3D "italic"; break;=0A= case 'u': cmd =3D "underline"; break;=0A= case 's': cmd =3D "strikethrough"; break;=0A= case 'l': cmd =3D "justifyleft"; break;=0A= case 'e': cmd =3D "justifycenter"; break;=0A= case 'r': cmd =3D "justifyright"; break;=0A= case 'j': cmd =3D "justifyfull"; break;=0A= case 'z': cmd =3D "undo"; break;=0A= case 'y': cmd =3D "redo"; break;=0A= case 'v': if (HTMLArea.is_ie || editor.config.htmlareaPaste) { = cmd =3D "paste"; } break;=0A= case 'n': cmd =3D "formatblock"; value =3D HTMLArea.is_ie ? = "

" : "p"; break;=0A= =0A= case '0': cmd =3D "killword"; break;=0A= =0A= // headings=0A= case '1':=0A= case '2':=0A= case '3':=0A= case '4':=0A= case '5':=0A= case '6':=0A= cmd =3D "formatblock";=0A= value =3D "h" + key;=0A= if (HTMLArea.is_ie)=0A= value =3D "<" + value + ">";=0A= break;=0A= }=0A= if (cmd) {=0A= // execute simple command=0A= this.execCommand(cmd, false, value);=0A= HTMLArea._stopEvent(ev);=0A= }=0A= }=0A= else if (keyEvent)=0A= {=0A= =0A= // IE's textRange and selection object is woefully inadequate,=0A= // which means this fancy stuff is gecko only sorry :-|=0A= // Die Bill, Die. (IE supports it somewhat nativly though)=0A= if(HTMLArea.is_gecko)=0A= {=0A= var s =3D editor._getSelection()=0A= var autoWrap =3D function (textNode, tag)=0A= {=0A= var rightText =3D textNode.nextSibling;=0A= if(typeof tag =3D=3D 'string') tag =3D = editor._doc.createElement(tag);=0A= var a =3D textNode.parentNode.insertBefore(tag, rightText);=0A= HTMLArea.removeFromParent(textNode);=0A= a.appendChild(textNode);=0A= rightText.data =3D ' ' + rightText.data;=0A= =0A= if(HTMLArea.is_ie)=0A= {=0A= var r =3D editor._createRange(s);=0A= s.moveToElementText(rightText);=0A= s.move('character', 1);=0A= }=0A= else=0A= {=0A= s.collapse(rightText, 1);=0A= }=0A= HTMLArea._stopEvent(ev);=0A= =0A= editor._unLink =3D function()=0A= {=0A= var t =3D a.firstChild;=0A= a.removeChild(t);=0A= a.parentNode.insertBefore(t, a);=0A= HTMLArea.removeFromParent(a);=0A= editor._unLink =3D null;=0A= editor._unlinkOnUndo =3D false;=0A= }=0A= editor._unlinkOnUndo =3D true;=0A= =0A= return a;=0A= }=0A= =0A= switch(ev.which)=0A= {=0A= // Space, see if the text just typed looks like a URL, or email = address=0A= // and link it appropriatly=0A= case 32:=0A= {=0A= if(s && s.isCollapsed && s.anchorNode.nodeType =3D=3D 3 && = s.anchorNode.data.length > 3 && s.anchorNode.data.indexOf('.') >=3D 0)=0A= {=0A= var midStart =3D = s.anchorNode.data.substring(0,s.anchorOffset).search(/\S{4,}$/);=0A= if(midStart =3D=3D -1) break;=0A= =0A= if(this._getFirstAncestor(s, 'a'))=0A= {=0A= break; // already in an anchor=0A= }=0A= =0A= var matchData =3D = s.anchorNode.data.substring(0,s.anchorOffset).replace(/^.*?(\S*)$/, = '$1');=0A= =0A= var m =3D matchData.match(HTMLArea.RE_email);=0A= if(m)=0A= {=0A= var leftText =3D s.anchorNode;=0A= var rightText =3D leftText.splitText(s.anchorOffset);=0A= var midText =3D leftText.splitText(midStart);=0A= =0A= autoWrap(midText, 'a').href =3D 'mailto:' + m[0];=0A= break;=0A= }=0A= =0A= var m =3D matchData.match(HTMLArea.RE_url);=0A= if(m)=0A= {=0A= var leftText =3D s.anchorNode;=0A= var rightText =3D leftText.splitText(s.anchorOffset);=0A= var midText =3D leftText.splitText(midStart);=0A= autoWrap(midText, 'a').href =3D (m[1] ? m[1] : 'http://') = + m[2];=0A= break;=0A= }=0A= }=0A= =0A= }=0A= break;=0A= =0A= default :=0A= {=0A= if(ev.keyCode =3D=3D 27 || (this._unlinkOnUndo && ev.ctrlKey = && ev.which =3D=3D 122) )=0A= {=0A= if(this._unLink)=0A= {=0A= this._unLink();=0A= HTMLArea._stopEvent(ev);=0A= }=0A= break;=0A= }=0A= else if(ev.which || ev.keyCode =3D=3D 8 || ev.keyCode =3D=3D = 46)=0A= {=0A= this._unlinkOnUndo =3D false;=0A= =0A= if(s.anchorNode && s.anchorNode.nodeType =3D=3D 3)=0A= {=0A= // See if we might be changing a link=0A= var a =3D this._getFirstAncestor(s, 'a');=0A= if(!a) break; // not an anchor=0A= if(!a._updateAnchTimeout)=0A= {=0A= if( s.anchorNode.data.match(HTMLArea.RE_email)=0A= && (a.href.match('mailto:' + = s.anchorNode.data.trim()))=0A= )=0A= {=0A= var textNode =3D s.anchorNode;=0A= var fn =3D function()=0A= {=0A= a.href =3D 'mailto:' + textNode.data.trim();=0A= a._updateAnchTimeout =3D setTimeout(fn, 250);=0A= }=0A= a._updateAnchTimeout =3D setTimeout(fn, 250);=0A= break;=0A= }=0A= =0A= var m =3D s.anchorNode.data.match(HTMLArea.RE_url);=0A= if(m && a.href.match(s.anchorNode.data.trim()) )=0A= {=0A= var textNode =3D s.anchorNode;=0A= var fn =3D function()=0A= {=0A= var m =3D textNode.data.match(HTMLArea.RE_url);=0A= a.href =3D (m[1] ? m[1] : 'http://') + m[2];=0A= a._updateAnchTimeout =3D setTimeout(fn, 250);=0A= }=0A= a._updateAnchTimeout =3D setTimeout(fn, 250);=0A= }=0A= }=0A= }=0A= =0A= }=0A= }=0A= break;=0A= }=0A= }=0A= =0A= // other keys here=0A= switch (ev.keyCode)=0A= {=0A= case 13: // KEY enter=0A= if (HTMLArea.is_gecko && !ev.shiftKey && = this.config.mozParaHandler =3D=3D 'dirty' )=0A= {=0A= this.dom_checkInsertP();=0A= HTMLArea._stopEvent(ev);=0A= }=0A= break;=0A= case 8: // KEY backspace=0A= case 46: // KEY delete=0A= if (HTMLArea.is_gecko && !ev.shiftKey) {=0A= if (this.dom_checkBackspace())=0A= HTMLArea._stopEvent(ev);=0A= } else if (HTMLArea.is_ie) {=0A= if (this.ie_checkBackspace())=0A= HTMLArea._stopEvent(ev);=0A= }=0A= break;=0A= }=0A= }=0A= =0A= // update the toolbar state after some time=0A= if (editor._timerToolbar) {=0A= clearTimeout(editor._timerToolbar);=0A= }=0A= editor._timerToolbar =3D setTimeout(function() {=0A= editor.updateToolbar();=0A= editor._timerToolbar =3D null;=0A= }, 250);=0A= };=0A= =0A= HTMLArea.prototype.convertNode =3D function(el, newTagName) {=0A= var newel =3D this._doc.createElement(newTagName);=0A= while (el.firstChild)=0A= newel.appendChild(el.firstChild);=0A= return newel;=0A= };=0A= =0A= HTMLArea.prototype.ie_checkBackspace =3D function() {=0A= var sel =3D this._getSelection();=0A= if(HTMLArea.is_ie && sel.type =3D=3D 'Control')=0A= {=0A= var elm =3D this._activeElement(sel);=0A= HTMLArea.removeFromParent(elm);=0A= return true;=0A= }=0A= =0A= // This bit of code preseves links when you backspace over the=0A= // endpoint of the link in IE. Without it, if you have something like=0A= // link_here |=0A= // where | is the cursor, and backspace over the last e, then the link=0A= // will de-link, which is a bit tedious=0A= var range =3D this._createRange(sel);=0A= var r2 =3D range.duplicate();=0A= r2.moveStart("character", -1);=0A= var a =3D r2.parentElement();=0A= if (a !=3D range.parentElement() &&=0A= /^a$/i.test(a.tagName)) {=0A= r2.collapse(true);=0A= r2.moveEnd("character", 1);=0A= r2.pasteHTML('');=0A= r2.select();=0A= return true;=0A= }=0A= };=0A= =0A= HTMLArea.prototype.dom_checkBackspace =3D function() {=0A= var self =3D this;=0A= setTimeout(function() {=0A= var sel =3D self._getSelection();=0A= var range =3D self._createRange(sel);=0A= var SC =3D range.startContainer;=0A= var SO =3D range.startOffset;=0A= var EC =3D range.endContainer;=0A= var EO =3D range.endOffset;=0A= var newr =3D SC.nextSibling;=0A= if (SC.nodeType =3D=3D 3)=0A= SC =3D SC.parentNode;=0A= if (!/\S/.test(SC.tagName)) {=0A= var p =3D document.createElement("p");=0A= while (SC.firstChild)=0A= p.appendChild(SC.firstChild);=0A= SC.parentNode.insertBefore(p, SC);=0A= HTMLArea.removeFromParent(SC);=0A= var r =3D range.cloneRange();=0A= r.setStartBefore(newr);=0A= r.setEndAfter(newr);=0A= r.extractContents();=0A= sel.removeAllRanges();=0A= sel.addRange(r);=0A= }=0A= }, 10);=0A= };=0A= =0A= /** The idea here is=0A= * 1. See if we are in a block element=0A= * 2. If we are not, then wrap the current "block" of text into a = paragraph=0A= * 3. Now that we have a block element, select all the text between the = insertion point=0A= * and just AFTER the end of the block=0A= * eg

The quick |brown fox jumped over the lazy dog.

|=0A= * ---------------------------------------=0A= * 4. Extract that from the document, making=0A= *

The quick

=0A= * and a document fragment with=0A= *

brown fox jumped over the lazy dog.

=0A= * 5. Reinsert it just after the block element=0A= *

The quick

brown fox jumped over the lazy dog.

=0A= *=0A= * Along the way, allow inserting blank paragraphs, which will look like =


=0A= */=0A= =0A= HTMLArea.prototype.dom_checkInsertP =3D function() {=0A= =0A= // Get the insertion point, we'll scrub any highlighted text the user = wants rid of while we are there.=0A= var sel =3D this._getSelection();=0A= var range =3D this._createRange(sel);=0A= if (!range.collapsed)=0A= {=0A= range.deleteContents();=0A= }=0A= this.deactivateEditor();=0A= //sel.removeAllRanges();=0A= //sel.addRange(range);=0A= =0A= var SC =3D range.startContainer;=0A= var SO =3D range.startOffset;=0A= var EC =3D range.endContainer;=0A= var EO =3D range.endOffset;=0A= =0A= // If the insertion point is character 0 of the=0A= // document, then insert a space character that we will wrap into a = paragraph=0A= // in a bit.=0A= if (SC =3D=3D EC && SC =3D=3D body && !SO && !EO)=0A= {=0A= p =3D this._doc.createTextNode(" ");=0A= body.insertBefore(p, body.firstChild);=0A= range.selectNodeContents(p);=0A= SC =3D range.startContainer;=0A= SO =3D range.startOffset;=0A= EC =3D range.endContainer;=0A= EO =3D range.endOffset;=0A= }=0A= =0A= // See if we are in a block element, if so, great.=0A= var p =3D this.getAllAncestors();=0A= =0A= var block =3D null;=0A= var body =3D this._doc.body;=0A= for (var i =3D 0; i < p.length; ++i)=0A= {=0A= if(HTMLArea.isParaContainer(p[i]))=0A= {=0A= break;=0A= }=0A= else if (HTMLArea.isBlockElement(p[i]) && = !/body|html/i.test(p[i].tagName))=0A= {=0A= block =3D p[i];=0A= break;=0A= }=0A= }=0A= =0A= // If not in a block element, we'll have to turn some stuff into a = paragraph=0A= if (!block)=0A= {=0A= // We want to wrap as much stuff as possible into the paragraph in = both directions=0A= // from the insertion point. We start with the start container and = walk back up to the=0A= // node just before any of the paragraph containers.=0A= var wrap =3D range.startContainer;=0A= while(wrap.parentNode && !HTMLArea.isParaContainer(wrap.parentNode))=0A= {=0A= wrap =3D wrap.parentNode;=0A= }=0A= var start =3D wrap;=0A= var end =3D wrap;=0A= =0A= // Now we walk up the sibling list until we hit the top of the = document=0A= // or an element that we shouldn't put in a p (eg other p, div, ul, = ol, table)=0A= while(start.previousSibling)=0A= {=0A= if(start.previousSibling.tagName)=0A= {=0A= if(!HTMLArea.isBlockElement(start.previousSibling))=0A= {=0A= start =3D start.previousSibling;=0A= }=0A= else=0A= {=0A= break;=0A= }=0A= }=0A= else=0A= {=0A= start =3D start.previousSibling;=0A= }=0A= }=0A= =0A= // Same down the list=0A= while(end.nextSibling)=0A= {=0A= if(end.nextSibling.tagName)=0A= {=0A= if(!HTMLArea.isBlockElement(end.nextSibling))=0A= {=0A= end =3D end.nextSibling;=0A= }=0A= else=0A= {=0A= break;=0A= }=0A= }=0A= else=0A= {=0A= end =3D end.nextSibling;=0A= }=0A= }=0A= =0A= // Select the entire block=0A= range.setStartBefore(start);=0A= range.setEndAfter(end);=0A= =0A= // Make it a paragraph=0A= range.surroundContents(this._doc.createElement('p'));=0A= =0A= // Which becomes the block element=0A= block =3D range.startContainer.firstChild;=0A= =0A= // And finally reset the insertion point to where it was originally=0A= range.setStart(SC, SO);=0A= }=0A= =0A= // The start point is the insertion point, so just move the end point = to immediatly=0A= // after the block=0A= range.setEndAfter(block);=0A= =0A= // Extract the range, to split the block=0A= // If we just did range.extractContents() then Mozilla does wierd stuff=0A= // with selections, but if we clone, then remove the original range = and extract=0A= // the clone, it's quite happy.=0A= var r2 =3D range.cloneRange();=0A= sel.removeRange(range);=0A= var df =3D r2.extractContents();=0A= =0A= if(df.childNodes.length =3D=3D 0)=0A= {=0A= df.appendChild(this._doc.createElement('p'));=0A= df.firstChild.appendChild(this._doc.createElement('br'));=0A= }=0A= =0A= if(df.childNodes.length > 1)=0A= {=0A= var nb =3D this._doc.createElement('p');=0A= while(df.firstChild)=0A= {=0A= var s =3D df.firstChild;=0A= df.removeChild(s);=0A= nb.appendChild(s);=0A= }=0A= df.appendChild(nb);=0A= }=0A= =0A= // If the original block is empty, put a nsbp in it.=0A= if (!/\S/.test(block.innerHTML))=0A= block.innerHTML =3D " ";=0A= =0A= p =3D df.firstChild;=0A= if (!/\S/.test(p.innerHTML))=0A= p.innerHTML =3D "
";=0A= =0A= // If the new block is empty and it's a heading, make it a paragraph=0A= // note, the new block is empty when you are hitting enter at the end = of the existing block=0A= if (/^\s*\s*$/.test(p.innerHTML) && = /^h[1-6]$/i.test(p.tagName))=0A= {=0A= df.appendChild(this.convertNode(p, "p"));=0A= df.removeChild(p);=0A= }=0A= =0A= var newblock =3D block.parentNode.insertBefore(df.firstChild, = block.nextSibling);=0A= =0A= // Select the range (to set the insertion)=0A= // collapse to the start of the new block=0A= // (remember the block might be


, so if we collapsed to = the end the
would be noticable)=0A= =0A= //range.selectNode(newblock.firstChild);=0A= //range.collapse(true);=0A= =0A= this.activateEditor();=0A= =0A= var sel =3D this._getSelection();=0A= sel.removeAllRanges();=0A= sel.collapse(newblock,0);=0A= =0A= // scroll into view=0A= this.scrollToElement(newblock);=0A= =0A= //this.forceRedraw();=0A= =0A= };=0A= =0A= HTMLArea.prototype.scrollToElement =3D function(e)=0A= {=0A= if(HTMLArea.is_gecko)=0A= {=0A= var top =3D 0;=0A= var left =3D 0;=0A= while(e)=0A= {=0A= top +=3D e.offsetTop;=0A= left +=3D e.offsetLeft;=0A= if(e.offsetParent && e.offsetParent.tagName.toLowerCase() !=3D = 'body')=0A= {=0A= e =3D e.offsetParent;=0A= }=0A= else=0A= {=0A= e =3D null;=0A= }=0A= }=0A= this._iframe.contentWindow.scrollTo(left, top);=0A= }=0A= }=0A= =0A= // retrieve the HTML=0A= HTMLArea.prototype.getHTML =3D function() {=0A= var html =3D '';=0A= switch (this._editMode) {=0A= case "wysiwyg" :=0A= {=0A= if (!this.config.fullPage)=0A= html =3D HTMLArea.getHTML(this._doc.body, false, this);=0A= else=0A= html =3D this.doctype + "\n" + = HTMLArea.getHTML(this._doc.documentElement, true, this);=0A= break;=0A= }=0A= case "textmode" :=0A= {=0A= html =3D this._textArea.value;=0A= break;=0A= }=0A= default :=0A= {=0A= alert("Mode <" + mode + "> not defined!");=0A= return false;=0A= }=0A= }=0A= return html;=0A= };=0A= =0A= HTMLArea.prototype.outwardHtml =3D function(html)=0A= {=0A= html =3D html.replace(/<(\/?)b(\s|>|\/)/ig, "<$1strong$2");=0A= html =3D html.replace(/<(\/?)i(\s|>|\/)/ig, "<$1em$2");=0A= html =3D html.replace(/<(\/?)strike(\s|>|\/)/ig, "<$1del$2");=0A= =0A= // replace window.open to that any clicks won't open a popup in = designMode=0A= html =3D html.replace("onclick=3D\"try{if(document.designMode = && document.designMode =3D=3D 'on') return false;}catch(e){} = window.open(", "onclick=3D\"window.open(");=0A= =0A= // Figure out what our server name is, and how it's referenced=0A= var serverBase =3D location.href.replace(/(https?:\/\/[^\/]*)\/.*/, = '$1') + '/';=0A= =0A= // IE puts this in can't figure out why=0A= html =3D html.replace(/https?:\/\/null\//g, serverBase);=0A= =0A= // Make semi-absolute links to be truely absolute=0A= // we do this just to standardize so that special replacements knows = what=0A= // to expect=0A= html =3D html.replace(/((href|src|background)=3D[\'\"])\/+/ig, '$1' + = serverBase);=0A= =0A= html =3D this.outwardSpecialReplacements(html);=0A= =0A= html =3D this.fixRelativeLinks(html);=0A= =0A= if(this.config.sevenBitClean)=0A= {=0A= html =3D html.replace(/[^ -~\r\n\t]/g, function(c){ return = '&#'+c.charCodeAt(0)+';';});=0A= }=0A= =0A= // ticket:56, the "greesemonkey" plugin for Firefox adds this junk,=0A= // so we strip it out. Original submitter gave a plugin, but that's=0A= // a bit much just for this IMHO - james=0A= if(HTMLArea.is_gecko)=0A= {=0A= html =3D = html.replace(/[\s]*<\/= script>/ig, '');=0A= }=0A= =0A= return html;=0A= }=0A= =0A= HTMLArea.prototype.inwardHtml =3D function(html)=0A= {=0A= // Midas uses b and i instead of strong and em, um, hello,=0A= // mozilla, this is the 21st century calling!=0A= if (HTMLArea.is_gecko) {=0A= html =3D html.replace(/<(\/?)strong(\s|>|\/)/ig, "<$1b$2");=0A= html =3D html.replace(/<(\/?)em(\s|>|\/)/ig, "<$1i$2");=0A= html =3D html.replace(/<(\/?)strike(\s|>|\/)/ig, "<$1del$2");=0A= }=0A= =0A= // replace window.open to that any clicks won't open a popup in = designMode=0A= html =3D html.replace("onclick=3D\"window.open(", = "onclick=3D\"try{if(document.designMode && document.designMode = =3D=3D 'on') return false;}catch(e){} window.open(");=0A= =0A= html =3D this.inwardSpecialReplacements(html);=0A= =0A= // For IE's sake, make any URLs that are semi-absolute (=3D"/....") to = be=0A= // truely absolute=0A= var nullRE =3D new RegExp('((href|src|background)=3D[\'"])/+', 'gi');=0A= html =3D html.replace(nullRE, '$1' + = location.href.replace(/(https?:\/\/[^\/]*)\/.*/, '$1') + '/');=0A= =0A= html =3D this.fixRelativeLinks(html);=0A= return html;=0A= }=0A= =0A= HTMLArea.prototype.outwardSpecialReplacements =3D function(html)=0A= {=0A= for(var i in this.config.specialReplacements)=0A= {=0A= var from =3D this.config.specialReplacements[i];=0A= var to =3D i;=0A= // alert('out : ' + from + '=3D>' + to);=0A= var reg =3D new RegExp(from.replace(HTMLArea.RE_Specials, '\\$1'), = 'g');=0A= html =3D html.replace(reg, to.replace(/\$/g, '$$$$'));=0A= //html =3D html.replace(from, to);=0A= }=0A= return html;=0A= }=0A= =0A= HTMLArea.prototype.inwardSpecialReplacements =3D function(html)=0A= {=0A= // alert("inward");=0A= for(var i in this.config.specialReplacements)=0A= {=0A= var from =3D i;=0A= var to =3D this.config.specialReplacements[i];=0A= // alert('in : ' + from + '=3D>' + to);=0A= //=0A= // html =3D html.replace(reg, to);=0A= // html =3D html.replace(from, to);=0A= var reg =3D new RegExp(from.replace(HTMLArea.RE_Specials, '\\$1'), = 'g');=0A= html =3D html.replace(reg, to.replace(/\$/g, '$$$$')); // IE uses = doubled dollar signs to escape backrefs, also beware that IE also = implements $& $_ and $' like perl.=0A= }=0A= return html;=0A= }=0A= =0A= =0A= HTMLArea.prototype.fixRelativeLinks =3D function(html)=0A= {=0A= =0A= if(typeof this.config.stripSelfNamedAnchors !=3D 'undefined' && = this.config.stripSelfNamedAnchors)=0A= {=0A= var stripRe =3D new = RegExp(document.location.href.replace(HTMLArea.RE_Specials, '\\$1') + = '(#[^\'" ]*)', 'g');=0A= html =3D html.replace(stripRe, '$1');=0A= }=0A= =0A= =0A= if(typeof this.config.stripBaseHref !=3D 'undefined' && = this.config.stripBaseHref)=0A= {=0A= var baseRe =3D null=0A= if(typeof this.config.baseHref !=3D 'undefined' && = this.config.baseHref !=3D null)=0A= {=0A= baseRe =3D new = RegExp(this.config.baseHref.replace(HTMLArea.RE_Specials, '\\$1'), 'g');=0A= }=0A= else=0A= {=0A= baseRe =3D new = RegExp(document.location.href.replace(/([^\/]*\/?)$/, = '').replace(HTMLArea.RE_Specials, '\\$1'), 'g');=0A= }=0A= =0A= html =3D html.replace(baseRe, '');=0A= }=0A= =0A= if(HTMLArea.is_ie)=0A= {=0A= // This is now done in inward & outward=0A= // Don't know why but IE is doing this (putting http://null/ on = links?!=0A= // alert(html);=0A= // var nullRE =3D new RegExp('https?:\/\/null\/', 'g');=0A= // html =3D html.replace(nullRE, = location.href.replace(/(https?:\/\/[^\/]*\/).*/, '$1'));=0A= // alert(html);=0A= }=0A= =0A= return html;=0A= }=0A= =0A= // retrieve the HTML (fastest version, but uses innerHTML)=0A= HTMLArea.prototype.getInnerHTML =3D function() {=0A= if(!this._doc.body) return '';=0A= switch (this._editMode) {=0A= case "wysiwyg" :=0A= if (!this.config.fullPage)=0A= // return this._doc.body.innerHTML;=0A= html =3D this._doc.body.innerHTML;=0A= else=0A= html =3D this.doctype + "\n" + = this._doc.documentElement.innerHTML;=0A= break;=0A= case "textmode" :=0A= html =3D this._textArea.value;=0A= break;=0A= default :=0A= alert("Mode <" + mode + "> not defined!");=0A= return false;=0A= }=0A= =0A= return html;=0A= };=0A= =0A= // completely change the HTML inside=0A= HTMLArea.prototype.setHTML =3D function(html) {=0A= if (!this.config.fullPage)=0A= {=0A= this._doc.body.innerHTML =3D html;=0A= }=0A= else=0A= {=0A= this.setFullHTML(html);=0A= }=0A= this._textArea.value =3D html;=0A= };=0A= =0A= // sets the given doctype (useful when config.fullPage is true)=0A= HTMLArea.prototype.setDoctype =3D function(doctype) {=0A= this.doctype =3D doctype;=0A= };=0A= =0A= /***************************************************=0A= * Category: UTILITY FUNCTIONS=0A= ***************************************************/=0A= =0A= // variable used to pass the object to the popup editor window.=0A= HTMLArea._object =3D null;=0A= =0A= // function that returns a clone of the given object=0A= HTMLArea.cloneObject =3D function(obj) {=0A= if (!obj) return null;=0A= var newObj =3D new Object;=0A= =0A= // check for array objects=0A= if (obj.constructor.toString().indexOf("function Array(") !=3D -1) {=0A= newObj =3D obj.constructor();=0A= }=0A= =0A= // check for function objects (as usual, IE is fucked up)=0A= if (obj.constructor.toString().indexOf("function Function(") =3D=3D 1) = {=0A= newObj =3D obj; // just copy reference to it=0A= } else for (var n in obj) {=0A= var node =3D obj[n];=0A= if (typeof node =3D=3D 'object') { newObj[n] =3D = HTMLArea.cloneObject(node); }=0A= else { newObj[n] =3D node; }=0A= }=0A= =0A= return newObj;=0A= };=0A= =0A= // FIXME!!! this should return false for IE < 5.5=0A= HTMLArea.checkSupportedBrowser =3D function() {=0A= if (HTMLArea.is_gecko) {=0A= if (navigator.productSub < 20021201) {=0A= alert("You need at least Mozilla-1.3 Alpha.\n" +=0A= "Sorry, your Gecko is not supported.");=0A= return false;=0A= }=0A= if (navigator.productSub < 20030210) {=0A= alert("Mozilla < 1.3 Beta is not supported!\n" +=0A= "I'll try, though, but it might not work.");=0A= }=0A= }=0A= return HTMLArea.is_gecko || HTMLArea.is_ie;=0A= };=0A= =0A= // selection & ranges=0A= =0A= // returns the current selection object=0A= HTMLArea.prototype._getSelection =3D function() {=0A= if (HTMLArea.is_ie) {=0A= return this._doc.selection;=0A= } else {=0A= return this._iframe.contentWindow.getSelection();=0A= }=0A= };=0A= =0A= // returns a range for the current selection=0A= HTMLArea.prototype._createRange =3D function(sel) {=0A= if (HTMLArea.is_ie) {=0A= return sel.createRange();=0A= } else {=0A= this.activateEditor();=0A= if (typeof sel !=3D "undefined") {=0A= try {=0A= return sel.getRangeAt(0);=0A= } catch(e) {=0A= return this._doc.createRange();=0A= }=0A= } else {=0A= return this._doc.createRange();=0A= }=0A= }=0A= };=0A= =0A= // event handling=0A= =0A= /** Event Flushing=0A= * To try and work around memory leaks in the rather broken=0A= * garbage collector in IE, HTMLArea.flushEvents can be called=0A= * onunload, it will remove any event listeners (that were added=0A= * through _addEvent(s)) and clear any DOM-0 events.=0A= */=0A= HTMLArea._eventFlushers =3D [ ];=0A= HTMLArea.flushEvents =3D function()=0A= {=0A= var x =3D 0;=0A= var e =3D null;=0A= while(e =3D HTMLArea._eventFlushers.pop())=0A= {=0A= if(e.length =3D=3D 3)=0A= {=0A= HTMLArea._removeEvent(e[0], e[1], e[2]);=0A= x++;=0A= }=0A= else if (e.length =3D=3D 2)=0A= {=0A= e[0]['on' + e[1]] =3D null;=0A= e[0]._xinha_dom0Events[e[1]] =3D null;=0A= x++;=0A= }=0A= }=0A= =0A= /* =0A= // This code is very agressive, and incredibly slow in IE, so I've = disabled it.=0A= =0A= if(document.all)=0A= {=0A= for(var i =3D 0; i < document.all.length; i++)=0A= {=0A= for(var j in document.all[i])=0A= {=0A= if(/^on/.test(j) && typeof document.all[i][j] =3D=3D = 'function')=0A= {=0A= document.all[i][j] =3D null;=0A= x++;=0A= }=0A= }=0A= }=0A= }=0A= */=0A= =0A= // alert('Flushed ' + x + ' events.');=0A= }=0A= =0A= HTMLArea._addEvent =3D function(el, evname, func) {=0A= if (HTMLArea.is_ie) {=0A= el.attachEvent("on" + evname, func);=0A= } else {=0A= el.addEventListener(evname, func, true);=0A= }=0A= HTMLArea._eventFlushers.push([el, evname, func]);=0A= };=0A= =0A= HTMLArea._addEvents =3D function(el, evs, func) {=0A= for (var i =3D evs.length; --i >=3D 0;) {=0A= HTMLArea._addEvent(el, evs[i], func);=0A= }=0A= };=0A= =0A= HTMLArea._removeEvent =3D function(el, evname, func) {=0A= if (HTMLArea.is_ie) {=0A= el.detachEvent("on" + evname, func);=0A= } else {=0A= el.removeEventListener(evname, func, true);=0A= }=0A= };=0A= =0A= HTMLArea._removeEvents =3D function(el, evs, func) {=0A= for (var i =3D evs.length; --i >=3D 0;) {=0A= HTMLArea._removeEvent(el, evs[i], func);=0A= }=0A= };=0A= =0A= HTMLArea._stopEvent =3D function(ev) {=0A= if (HTMLArea.is_ie) {=0A= ev.cancelBubble =3D true;=0A= ev.returnValue =3D false;=0A= } else {=0A= ev.preventDefault();=0A= ev.stopPropagation();=0A= }=0A= };=0A= =0A= /**=0A= * Adds a standard "DOM-0" event listener to an element.=0A= * The DOM-0 events are those applied directly as attributes to=0A= * an element - eg element.onclick =3D stuff;=0A= *=0A= * By using this function instead of simply overwriting any existing=0A= * DOM-0 event by the same name on the element it will trigger as well=0A= * as the existing ones. Handlers are triggered one after the other=0A= * in the order they are added.=0A= *=0A= * Remember to return true/false from your handler, this will determine=0A= * whether subsequent handlers will be triggered (ie that the event will=0A= * continue or be canceled).=0A= *=0A= */=0A= =0A= HTMLArea.addDom0Event =3D function(el, ev, fn)=0A= {=0A= HTMLArea._prepareForDom0Events(el, ev);=0A= el._xinha_dom0Events[ev].unshift(fn);=0A= }=0A= =0A= =0A= /**=0A= * See addDom0Event, the difference is that handlers registered using=0A= * prependDom0Event will be triggered before existing DOM-0 events of the=0A= * same name on the same element.=0A= */=0A= =0A= HTMLArea.prependDom0Event =3D function(el, ev, fn)=0A= {=0A= HTMLArea._prepareForDom0Events(el, ev);=0A= el._xinha_dom0Events[ev].push(fn);=0A= }=0A= =0A= /**=0A= * Prepares an element to receive more than one DOM-0 event handler=0A= * when handlers are added via addDom0Event and prependDom0Event.=0A= */=0A= HTMLArea._prepareForDom0Events =3D function(el, ev)=0A= {=0A= // Create a structure to hold our lists of event handlers=0A= if(typeof el._xinha_dom0Events =3D=3D 'undefined')=0A= {=0A= el._xinha_dom0Events =3D { };=0A= HTMLArea.freeLater(el, '_xinha_dom0Events');=0A= }=0A= =0A= // Create a list of handlers for this event type=0A= if(typeof el._xinha_dom0Events[ev] =3D=3D 'undefined')=0A= {=0A= el._xinha_dom0Events[ev] =3D [ ];=0A= if(typeof el['on'+ev] =3D=3D 'function')=0A= {=0A= el._xinha_dom0Events[ev].push(el['on'+ev]);=0A= }=0A= =0A= // Make the actual event handler, which runs through=0A= // each of the handlers in the list and executes them=0A= // in the correct context.=0A= el['on'+ev] =3D function(event)=0A= {=0A= var a =3D el._xinha_dom0Events[ev];=0A= // call previous submit methods if they were there.=0A= var allOK =3D true;=0A= for (var i =3D a.length; --i >=3D 0;)=0A= {=0A= // We want the handler to be a member of the form, not the = array, so that "this" will work correctly=0A= el._xinha_tempEventHandler =3D a[i];=0A= if(el._xinha_tempEventHandler(event) =3D=3D false)=0A= {=0A= el._xinha_tempEventHandler =3D null;=0A= allOK =3D false;=0A= break;=0A= }=0A= el._xinha_tempEventHandler =3D null;=0A= }=0A= return allOK;=0A= }=0A= =0A= HTMLArea._eventFlushers.push([el, ev]);=0A= }=0A= }=0A= =0A= HTMLArea.prototype.notifyOn =3D function(ev, fn)=0A= {=0A= if(typeof this._notifyListeners[ev] =3D=3D 'undefined')=0A= {=0A= this._notifyListeners[ev] =3D [ ];=0A= HTMLArea.freeLater(this, '_notifyListeners');=0A= }=0A= =0A= this._notifyListeners[ev].push(fn);=0A= }=0A= =0A= HTMLArea.prototype.notifyOf =3D function(ev, args)=0A= {=0A= =0A= if(this._notifyListeners[ev])=0A= {=0A= =0A= for(var i =3D 0; i < this._notifyListeners[ev].length; i++)=0A= {=0A= this._notifyListeners[ev][i](ev, args);=0A= }=0A= }=0A= }=0A= =0A= =0A= HTMLArea._removeClass =3D function(el, className) {=0A= if (!(el && el.className)) {=0A= return;=0A= }=0A= var cls =3D el.className.split(" ");=0A= var ar =3D new Array();=0A= for (var i =3D cls.length; i > 0;) {=0A= if (cls[--i] !=3D className) {=0A= ar[ar.length] =3D cls[i];=0A= }=0A= }=0A= el.className =3D ar.join(" ");=0A= };=0A= =0A= HTMLArea._addClass =3D function(el, className) {=0A= // remove the class first, if already there=0A= HTMLArea._removeClass(el, className);=0A= el.className +=3D " " + className;=0A= };=0A= =0A= HTMLArea._hasClass =3D function(el, className) {=0A= if (!(el && el.className)) {=0A= return false;=0A= }=0A= var cls =3D el.className.split(" ");=0A= for (var i =3D cls.length; i > 0;) {=0A= if (cls[--i] =3D=3D className) {=0A= return true;=0A= }=0A= }=0A= return false;=0A= };=0A= =0A= HTMLArea._blockTags =3D " body form textarea fieldset ul ol dl li div " +=0A= "p h1 h2 h3 h4 h5 h6 quote pre table thead " +=0A= "tbody tfoot tr td th iframe address blockquote";=0A= HTMLArea.isBlockElement =3D function(el) {=0A= return el && el.nodeType =3D=3D 1 && (HTMLArea._blockTags.indexOf(" " = + el.tagName.toLowerCase() + " ") !=3D -1);=0A= };=0A= =0A= HTMLArea._paraContainerTags =3D " body td th caption fieldset div";=0A= HTMLArea.isParaContainer =3D function(el)=0A= {=0A= return el && el.nodeType =3D=3D 1 && = (HTMLArea._paraContainerTags.indexOf(" " + el.tagName.toLowerCase() + " = ") !=3D -1);=0A= }=0A= =0A= HTMLArea._closingTags =3D " head script style div span tr td tbody table = em strong b i strike code cite dfn abbr acronym font a title textarea = select form ";=0A= HTMLArea.needsClosingTag =3D function(el) {=0A= return el && el.nodeType =3D=3D 1 && (HTMLArea._closingTags.indexOf(" = " + el.tagName.toLowerCase() + " ") !=3D -1);=0A= };=0A= =0A= // performs HTML encoding of some given string=0A= HTMLArea.htmlEncode =3D function(str) {=0A= if(typeof str.replace =3D=3D 'undefined') str =3D str.toString();=0A= // we don't need regexp for that, but.. so be it for now.=0A= str =3D str.replace(/&/ig, "&");=0A= str =3D str.replace(//ig, ">");=0A= str =3D str.replace(/\xA0/g, " "); // Decimal 160, = non-breaking-space=0A= str =3D str.replace(/\x22/g, """);=0A= // \x22 means '"' -- we use hex reprezentation so that we don't disturb=0A= // JS compressors (well, at least mine fails.. ;)=0A= return str;=0A= };=0A= =0A= // Retrieves the HTML code from the given node. This is a replacement = for=0A= // getting innerHTML, using standard DOM calls.=0A= // Wrapper catch a Mozilla-Exception with non well formed html source = code=0A= HTMLArea.getHTML =3D function(root, outputRoot, editor){=0A= try{=0A= return HTMLArea.getHTMLWrapper(root,outputRoot,editor);=0A= }=0A= catch(e){=0A= alert(HTMLArea._lc('Your Document is not well formed. Check = JavaScript console for details.'));=0A= return editor._iframe.contentWindow.document.body.innerHTML;=0A= }=0A= }=0A= =0A= HTMLArea.getHTMLWrapper =3D function(root, outputRoot, editor, indent) {=0A= var html =3D "";=0A= if(!indent) indent =3D '';=0A= =0A= switch (root.nodeType) {=0A= case 10:// Node.DOCUMENT_TYPE_NODE=0A= case 6: // Node.ENTITY_NODE=0A= case 12:// Node.NOTATION_NODE=0A= // this all are for the document type, probably not necessary=0A= break;=0A= =0A= case 2: // Node.ATTRIBUTE_NODE=0A= // Never get here, this has to be handled in the ELEMENT case = because=0A= // of IE crapness requring that some attributes are grabbed = directly from=0A= // the attribute (nodeValue doesn't return correct values), see=0A= = //http://groups.google.com/groups?hl=3Den&lr=3D&ie=3DUTF-8&oe=3DUTF-8&saf= e=3Doff&selm=3D3porgu4mc4ofcoa1uqkf7u8kvv064kjjb4%404ax.com=0A= // for information=0A= break;=0A= =0A= case 4: // Node.CDATA_SECTION_NODE=0A= // Mozilla seems to convert CDATA into a comment when going into = wysiwyg mode,=0A= // don't know about IE=0A= html +=3D (HTMLArea.is_ie ? ('\n' + indent) : '') + '' ;=0A= break;=0A= =0A= case 5: // Node.ENTITY_REFERENCE_NODE=0A= html +=3D '&' + root.nodeValue + ';';=0A= break;=0A= =0A= case 7: // Node.PROCESSING_INSTRUCTION_NODE=0A= // PI's don't seem to survive going into the wysiwyg mode, (at = least in moz)=0A= // so this is purely academic=0A= html +=3D (HTMLArea.is_ie ? ('\n' + indent) : '') + '';=0A= break;=0A= =0A= =0A= case 1: // Node.ELEMENT_NODE=0A= case 11: // Node.DOCUMENT_FRAGMENT_NODE=0A= case 9: // Node.DOCUMENT_NODE=0A= {=0A= var closed;=0A= var i;=0A= var root_tag =3D (root.nodeType =3D=3D 1) ? = root.tagName.toLowerCase() : '';=0A= if (outputRoot)=0A= outputRoot =3D !(editor.config.htmlRemoveTags && = editor.config.htmlRemoveTags.test(root_tag));=0A= if (HTMLArea.is_ie && root_tag =3D=3D "head") {=0A= if (outputRoot)=0A= html +=3D (HTMLArea.is_ie ? ('\n' + indent) : '') + "";=0A= // lowercasize=0A= var save_multiline =3D RegExp.multiline;=0A= RegExp.multiline =3D true;=0A= var txt =3D root.innerHTML.replace(HTMLArea.RE_tagName, = function(str, p1, p2) {=0A= return p1 + p2.toLowerCase();=0A= });=0A= RegExp.multiline =3D save_multiline;=0A= html +=3D txt + '\n';=0A= if (outputRoot)=0A= html +=3D (HTMLArea.is_ie ? ('\n' + indent) : '') + "";=0A= break;=0A= } else if (outputRoot) {=0A= closed =3D (!(root.hasChildNodes() || = HTMLArea.needsClosingTag(root)));=0A= html +=3D (HTMLArea.is_ie && HTMLArea.isBlockElement(root) ? ('\n' = + indent) : '') + "<" + root.tagName.toLowerCase();=0A= var attrs =3D root.attributes;=0A= for (i =3D 0; i < attrs.length; ++i) {=0A= var a =3D attrs.item(i);=0A= if (!a.specified && = !(root.tagName.toLowerCase().match(/input|option/) && a.nodeName =3D=3D = 'value')) {=0A= continue;=0A= }=0A= var name =3D a.nodeName.toLowerCase();=0A= if (/_moz_editor_bogus_node/.test(name)) {=0A= html =3D "";=0A= break;=0A= }=0A= if (/(_moz)|(contenteditable)|(_msh)/.test(name)) {=0A= // avoid certain attributes=0A= continue;=0A= }=0A= var value;=0A= if (name !=3D "style") {=0A= // IE5.5 reports 25 when cellSpacing is=0A= // 1; other values might be doomed too.=0A= // For this reason we extract the=0A= // values directly from the root node.=0A= // I'm starting to HATE JavaScript=0A= // development. Browser differences=0A= // suck.=0A= //=0A= // Using Gecko the values of href and src are converted to = absolute links=0A= // unless we get them using nodeValue()=0A= if (typeof root[a.nodeName] !=3D "undefined" && name !=3D = "href" && name !=3D "src" && !/^on/.test(name)) {=0A= value =3D root[a.nodeName];=0A= } else {=0A= value =3D a.nodeValue;=0A= // IE seems not willing to return the original values - it = converts to absolute=0A= // links using a.nodeValue, a.value, a.stringValue, = root.getAttribute("href")=0A= // So we have to strip the baseurl manually :-/=0A= if (HTMLArea.is_ie && (name =3D=3D "href" || name =3D=3D = "src")) {=0A= value =3D editor.stripBaseURL(value);=0A= }=0A= =0A= // High-ascii (8bit) characters in links seem to cause = problems for some sites,=0A= // while this seems to be consistent with RFC 3986 Section = 2.4=0A= // because these are not "reserved" characters, it does seem = to=0A= // cause links to international resources not to work. See = ticket:167=0A= =0A= // IE always returns high-ascii characters un-encoded in = links even if they=0A= // were supplied as % codes (it unescapes them when we pul = the value from the link).=0A= =0A= // Hmmm, very strange if we use encodeURI here, or = encodeURIComponent in place=0A= // of escape below, then the encoding is wrong. I mean, = completely.=0A= // Nothing like it should be at all. Using escape seems to = work though.=0A= // It's in both browsers too, so either I'm doing something = wrong, or=0A= // something else is going on?=0A= =0A= if(editor.config.only7BitPrintablesInURLs && (name =3D=3D = "href" || name =3D=3D "src"))=0A= {=0A= value =3D value.replace(/([^!-~]+)/g, function(match) { = return escape(match); });=0A= }=0A= }=0A= } else { // IE fails to put style in attributes list=0A= // FIXME: cssText reported by IE is UPPERCASE=0A= value =3D root.style.cssText;=0A= }=0A= if (/^(_moz)?$/.test(value)) {=0A= // Mozilla reports some special tags=0A= // here; we don't need them.=0A= continue;=0A= }=0A= html +=3D " " + name + '=3D"' + HTMLArea.htmlEncode(value) + '"';=0A= }=0A= if (html !=3D "") {=0A= if(closed && root_tag=3D=3D"p") {=0A= //never use

as empty paragraphs won't be visible=0A= html +=3D "> 

";=0A= } else if(closed) {=0A= html +=3D " />";=0A= } else {=0A= html +=3D ">";=0A= }=0A= }=0A= }=0A= var containsBlock =3D false;=0A= for (i =3D root.firstChild; i; i =3D i.nextSibling) {=0A= if(!containsBlock && i.nodeType =3D=3D 1 && = HTMLArea.isBlockElement(i)) containsBlock =3D true;=0A= html +=3D HTMLArea.getHTMLWrapper(i, true, editor, indent + ' ');=0A= }=0A= if (outputRoot && !closed) {=0A= html +=3D (HTMLArea.is_ie && HTMLArea.isBlockElement(root) && = containsBlock ? ('\n' + indent) : '') + "";=0A= }=0A= break;=0A= }=0A= case 3: // Node.TEXT_NODE=0A= html =3D /^script|style$/i.test(root.parentNode.tagName) ? root.data = : HTMLArea.htmlEncode(root.data);=0A= break;=0A= =0A= case 8: // Node.COMMENT_NODE=0A= html =3D "";=0A= break;=0A= }=0A= return html;=0A= };=0A= =0A= /** @see getHTMLWrapper (search for "value =3D a.nodeValue;") */=0A= =0A= HTMLArea.prototype.stripBaseURL =3D function(string)=0A= {=0A= if(this.config.baseHref=3D=3Dnull || !this.config.stripBaseHref)=0A= {=0A= return(string);=0A= }=0A= var baseurl =3D this.config.baseHref;=0A= =0A= // strip host-part of URL which is added by MSIE to links relative to = server root=0A= baseurl =3D baseurl.replace(/^(https?:\/\/[^\/]+)(.*)$/, '$1');=0A= basere =3D new RegExp(baseurl);=0A= return string.replace(basere, "");=0A= };=0A= =0A= String.prototype.trim =3D function() {=0A= return this.replace(/^\s+/, '').replace(/\s+$/, '');=0A= };=0A= =0A= // creates a rgb-style color from a number=0A= HTMLArea._makeColor =3D function(v) {=0A= if (typeof v !=3D "number") {=0A= // already in rgb (hopefully); IE doesn't get here.=0A= return v;=0A= }=0A= // IE sends number; convert to rgb.=0A= var r =3D v & 0xFF;=0A= var g =3D (v >> 8) & 0xFF;=0A= var b =3D (v >> 16) & 0xFF;=0A= return "rgb(" + r + "," + g + "," + b + ")";=0A= };=0A= =0A= // returns hexadecimal color representation from a number or a rgb-style = color.=0A= HTMLArea._colorToRgb =3D function(v) {=0A= if (!v)=0A= return '';=0A= =0A= // returns the hex representation of one byte (2 digits)=0A= function hex(d) {=0A= return (d < 16) ? ("0" + d.toString(16)) : d.toString(16);=0A= };=0A= =0A= if (typeof v =3D=3D "number") {=0A= // we're talking to IE here=0A= var r =3D v & 0xFF;=0A= var g =3D (v >> 8) & 0xFF;=0A= var b =3D (v >> 16) & 0xFF;=0A= return "#" + hex(r) + hex(g) + hex(b);=0A= }=0A= =0A= if (v.substr(0, 3) =3D=3D "rgb") {=0A= // in rgb(...) form -- Mozilla=0A= var re =3D /rgb\s*\(\s*([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\s*\)/;=0A= if (v.match(re)) {=0A= var r =3D parseInt(RegExp.$1);=0A= var g =3D parseInt(RegExp.$2);=0A= var b =3D parseInt(RegExp.$3);=0A= return "#" + hex(r) + hex(g) + hex(b);=0A= }=0A= // doesn't match RE?! maybe uses percentages or float numbers=0A= // -- FIXME: not yet implemented.=0A= return null;=0A= }=0A= =0A= if (v.substr(0, 1) =3D=3D "#") {=0A= // already hex rgb (hopefully :D )=0A= return v;=0A= }=0A= =0A= // if everything else fails ;)=0A= return null;=0A= };=0A= =0A= // modal dialogs for Mozilla (for IE we're using the showModalDialog() = call).=0A= =0A= // receives an URL to the popup dialog and a function that receives one = value;=0A= // this function will get called after the dialog is closed, with the = return=0A= // value of the dialog.=0A= HTMLArea.prototype._popupDialog =3D function(url, action, init) {=0A= Dialog(this.popupURL(url), action, init);=0A= };=0A= =0A= // paths=0A= =0A= HTMLArea.prototype.imgURL =3D function(file, plugin) {=0A= if (typeof plugin =3D=3D "undefined")=0A= return _editor_url + file;=0A= else=0A= return _editor_url + "plugins/" + plugin + "/img/" + file;=0A= };=0A= =0A= HTMLArea.prototype.popupURL =3D function(file) {=0A= var url =3D "";=0A= if (file.match(/^plugin:\/\/(.*?)\/(.*)/)) {=0A= var plugin =3D RegExp.$1;=0A= var popup =3D RegExp.$2;=0A= if (!/\.html$/.test(popup))=0A= popup +=3D ".html";=0A= url =3D _editor_url + "plugins/" + plugin + "/popups/" + popup;=0A= } else if(file.match(/^\/.*?/))=0A= url =3D file;=0A= else=0A= url =3D _editor_url + this.config.popupURL + file;=0A= return url;=0A= };=0A= =0A= /**=0A= * FIX: Internet Explorer returns an item having the _name_ equal to the = given=0A= * id, even if it's not having any id. This way it can return a = different form=0A= * field even if it's not a textarea. This workarounds the problem by=0A= * specifically looking to search only elements having a certain tag = name.=0A= */=0A= HTMLArea.getElementById =3D function(tag, id) {=0A= var el, i, objs =3D document.getElementsByTagName(tag);=0A= for (i =3D objs.length; --i >=3D 0 && (el =3D objs[i]);)=0A= if (el.id =3D=3D id)=0A= return el;=0A= return null;=0A= };=0A= =0A= =0A= /** Use some CSS trickery to toggle borders on tables */=0A= =0A= HTMLArea.prototype._toggleBorders =3D function()=0A= {=0A= tables =3D this._doc.getElementsByTagName('TABLE');=0A= if(tables.length !=3D 0)=0A= {=0A= if(!this.borders)=0A= {=0A= name =3D "bordered";=0A= this.borders =3D true;=0A= }=0A= else=0A= {=0A= name =3D "";=0A= this.borders =3D false;=0A= }=0A= =0A= for (var ix=3D0;ix < tables.length;ix++)=0A= {=0A= if(this.borders)=0A= {=0A= // flashing the display forces moz to listen (JB:18-04-2005) - = #102=0A= if(HTMLArea.is_gecko)=0A= {=0A= tables[ix].style.display=3D"none";=0A= tables[ix].style.display=3D"table";=0A= }=0A= HTMLArea._addClass(tables[ix], 'htmtableborders');=0A= }=0A= else=0A= {=0A= HTMLArea._removeClass(tables[ix], 'htmtableborders');=0A= }=0A= }=0A= }=0A= return true;=0A= }=0A= =0A= =0A= HTMLArea.addClasses =3D function(el, classes)=0A= {=0A= if(el !=3D null)=0A= {=0A= var thiers =3D el.className.trim().split(' ');=0A= var ours =3D classes.split(' ');=0A= for(var x =3D 0; x < ours.length; x++)=0A= {=0A= var exists =3D false;=0A= for(var i =3D 0; exists =3D=3D false && i < thiers.length; i++)=0A= {=0A= if(thiers[i] =3D=3D ours[x])=0A= {=0A= exists =3D true;=0A= }=0A= }=0A= if(exists =3D=3D false)=0A= {=0A= thiers[thiers.length] =3D ours[x];=0A= }=0A= }=0A= el.className =3D thiers.join(' ').trim();=0A= }=0A= }=0A= =0A= HTMLArea.removeClasses =3D function(el, classes)=0A= {=0A= var existing =3D el.className.trim().split();=0A= var new_classes =3D [ ];=0A= var remove =3D classes.trim().split();=0A= =0A= for(var i =3D 0; i < existing.length; i++)=0A= {=0A= var found =3D false;=0A= for(var x =3D 0; x < remove.length && !found; x++)=0A= {=0A= if(existing[i] =3D=3D remove[x])=0A= {=0A= found =3D true;=0A= }=0A= }=0A= if(!found)=0A= {=0A= new_classes[new_classes.length] =3D existing[i];=0A= }=0A= }=0A= return new_classes.join(' ');=0A= }=0A= =0A= /** Alias these for convenience */=0A= HTMLArea.addClass =3D HTMLArea._addClass;=0A= HTMLArea.removeClass =3D HTMLArea._removeClass;=0A= HTMLArea._addClasses =3D HTMLArea.addClasses;=0A= HTMLArea._removeClasses =3D HTMLArea.removeClasses;=0A= =0A= /** Use XML HTTPRequest to post some data back to the server and do = something=0A= * with the response (asyncronously!), this is used by such things as = the tidy functions=0A= */=0A= HTMLArea._postback =3D function(url, data, handler)=0A= {=0A= var req =3D null;=0A= if(HTMLArea.is_ie)=0A= {=0A= req =3D new ActiveXObject("Microsoft.XMLHTTP");=0A= }=0A= else=0A= {=0A= req =3D new XMLHttpRequest();=0A= }=0A= =0A= var content =3D '';=0A= for(var i in data)=0A= {=0A= content +=3D (content.length ? '&' : '') + i + '=3D' + = encodeURIComponent(data[i]);=0A= }=0A= =0A= function callBack()=0A= {=0A= if(req.readyState =3D=3D 4)=0A= {=0A= if(req.status =3D=3D 200)=0A= {=0A= if(typeof handler =3D=3D 'function')=0A= handler(req.responseText, req);=0A= }=0A= else=0A= {=0A= alert('An error has occurred: ' + req.statusText);=0A= }=0A= }=0A= }=0A= =0A= req.onreadystatechange =3D callBack;=0A= =0A= req.open('POST', url, true);=0A= req.setRequestHeader=0A= (=0A= 'Content-Type',=0A= 'application/x-www-form-urlencoded; charset=3DUTF-8'=0A= );=0A= //alert(content);=0A= req.send(content);=0A= }=0A= =0A= HTMLArea._getback =3D function(url, handler)=0A= {=0A= var req =3D null;=0A= if(HTMLArea.is_ie)=0A= {=0A= req =3D new ActiveXObject("Microsoft.XMLHTTP");=0A= }=0A= else=0A= {=0A= req =3D new XMLHttpRequest();=0A= }=0A= =0A= function callBack()=0A= {=0A= if(req.readyState =3D=3D 4)=0A= {=0A= if(req.status =3D=3D 200)=0A= {=0A= handler(req.responseText, req);=0A= }=0A= else=0A= {=0A= alert('An error has occurred: ' + req.statusText);=0A= }=0A= }=0A= }=0A= =0A= req.onreadystatechange =3D callBack;=0A= req.open('GET', url, true);=0A= req.send(null);=0A= }=0A= =0A= HTMLArea._geturlcontent =3D function(url)=0A= {=0A= var req =3D null;=0A= if(HTMLArea.is_ie)=0A= {=0A= req =3D new ActiveXObject("Microsoft.XMLHTTP");=0A= }=0A= else=0A= {=0A= req =3D new XMLHttpRequest();=0A= }=0A= =0A= // Synchronous!=0A= req.open('GET', url, false);=0A= req.send(null);=0A= if(req.status =3D=3D 200)=0A= {=0A= return req.responseText;=0A= }=0A= else=0A= {=0A= return '';=0A= }=0A= =0A= }=0A= =0A= /**=0A= * Unless somebody already has, make a little function to debug things=0A= */=0A= if(typeof dump =3D=3D 'undefined')=0A= {=0A= function dump(o) {=0A= var s =3D '';=0A= for (var prop in o) {=0A= s +=3D prop + ' =3D ' + o[prop] + '\n';=0A= }=0A= =0A= x =3D window.open("", "debugger");=0A= x.document.write('
' + s + '
');=0A= }=0A= }=0A= =0A= =0A= HTMLArea.arrayContainsArray =3D function(a1, a2)=0A= {=0A= var all_found =3D true;=0A= for(var x =3D 0; x < a2.length; x++)=0A= {=0A= var found =3D false;=0A= for(var i =3D 0; i < a1.length; i++)=0A= {=0A= if(a1[i] =3D=3D a2[x])=0A= {=0A= found =3D true;=0A= break;=0A= }=0A= }=0A= if(!found)=0A= {=0A= all_found =3D false;=0A= break;=0A= }=0A= }=0A= return all_found;=0A= }=0A= =0A= HTMLArea.arrayFilter =3D function(a1, filterfn)=0A= {=0A= var new_a =3D [ ];=0A= for(var x =3D 0; x < a1.length; x++)=0A= {=0A= if(filterfn(a1[x]))=0A= new_a[new_a.length] =3D a1[x];=0A= }=0A= =0A= return new_a;=0A= }=0A= =0A= HTMLArea.uniq_count =3D 0;=0A= HTMLArea.uniq =3D function(prefix)=0A= {=0A= return prefix + HTMLArea.uniq_count++;=0A= }=0A= =0A= /** New language handling functions **/=0A= =0A= =0A= /** Load a language file.=0A= * This function should not be used directly, HTMLArea._lc will use it = when necessary.=0A= * @param context Case sensitive context name, eg 'HTMLArea', = 'TableOperations', ...=0A= */=0A= HTMLArea._loadlang =3D function(context)=0A= {=0A= if(typeof _editor_lcbackend =3D=3D "string")=0A= {=0A= //use backend=0A= var url =3D _editor_lcbackend;=0A= url =3D url.replace(/%lang%/, _editor_lang);=0A= url =3D url.replace(/%context%/, context);=0A= }=0A= else=0A= {=0A= //use internal files=0A= if(context !=3D 'HTMLArea') {=0A= var url =3D = _editor_url+"plugins/"+context+"/lang/"+_editor_lang+".js";=0A= } else {=0A= var url =3D _editor_url+"lang/"+_editor_lang+".js";=0A= }=0A= }=0A= =0A= var lang;=0A= var langData =3D HTMLArea._geturlcontent(url);=0A= if(langData !=3D "") {=0A= try {=0A= eval('lang =3D ' + langData);=0A= } catch(Error) {=0A= alert('Error reading Language-File = ('+url+'):\n'+Error.toString());=0A= lang =3D { }=0A= }=0A= } else {=0A= lang =3D { };=0A= }=0A= =0A= return lang;=0A= }=0A= =0A= /** Return a localised string.=0A= * @param string English language string=0A= * @param context Case sensitive context name, eg 'HTMLArea' = (default), 'TableOperations'...=0A= * @param replace Replace $variables in String, eg {foo: = 'replaceText'} ($foo in string will be replaced)=0A= */=0A= HTMLArea._lc =3D function(string, context, replace)=0A= {=0A= var ret;=0A= if(_editor_lang =3D=3D "en")=0A= {=0A= if(typeof string =3D=3D 'object' && string.string) {=0A= ret =3D string.string;=0A= } else {=0A= ret =3D string;=0A= }=0A= }=0A= else=0A= {=0A= if(typeof HTMLArea._lc_catalog =3D=3D 'undefined')=0A= {=0A= HTMLArea._lc_catalog =3D [ ];=0A= }=0A= =0A= if(typeof context =3D=3D 'undefined')=0A= {=0A= context =3D 'HTMLArea';=0A= }=0A= =0A= if(typeof HTMLArea._lc_catalog[context] =3D=3D 'undefined')=0A= {=0A= HTMLArea._lc_catalog[context] =3D HTMLArea._loadlang(context);=0A= }=0A= =0A= var key;=0A= if(typeof string =3D=3D 'object' && string.key)=0A= {=0A= key =3D string.key;=0A= }=0A= else=0A= {=0A= key =3D string;=0A= }=0A= =0A= if(typeof HTMLArea._lc_catalog[context][key] =3D=3D 'undefined')=0A= {=0A= if(context=3D=3D'HTMLArea')=0A= {=0A= // Indicate it's untranslated=0A= if(typeof string =3D=3D 'object' && string.string) {=0A= ret =3D string.string;=0A= } else {=0A= ret =3D string;=0A= }=0A= }=0A= else=0A= {=0A= //if string is not found and context is not HTMLArea try if it = is in HTMLArea=0A= return HTMLArea._lc(string, 'HTMLArea', replace);=0A= }=0A= }=0A= else=0A= {=0A= ret =3D HTMLArea._lc_catalog[context][key];=0A= }=0A= }=0A= =0A= if(typeof string =3D=3D 'object' && string.replace)=0A= {=0A= replace =3D string.replace;=0A= }=0A= if(typeof replace !=3D "undefined")=0A= {=0A= for(var i in replace)=0A= {=0A= ret =3D ret.replace('$'+i, replace[i]);=0A= }=0A= }=0A= =0A= return ret;=0A= }=0A= =0A= HTMLArea.hasDisplayedChildren =3D function(el)=0A= {=0A= var children =3D el.childNodes;=0A= for(var i =3D0; i < children.length;i++)=0A= {=0A= if(children[i].tagName)=0A= {=0A= if(children[i].style.display !=3D 'none')=0A= {=0A= return true;=0A= }=0A= }=0A= }=0A= return false;=0A= }=0A= =0A= =0A= HTMLArea._loadback =3D function(src, callback)=0A= {=0A= var head =3D document.getElementsByTagName("head")[0];=0A= var evt =3D HTMLArea.is_ie ? "onreadystatechange" : "onload";=0A= =0A= var script =3D document.createElement("script");=0A= script.type =3D "text/javascript";=0A= script.src =3D src;=0A= script[evt] =3D function()=0A= {=0A= if(HTMLArea.is_ie && = !/loaded|complete/.test(window.event.srcElement.readyState)) return;=0A= callback();=0A= }=0A= head.appendChild(script);=0A= };=0A= =0A= HTMLArea.collectionToArray =3D function(collection)=0A= {=0A= var array =3D [ ];=0A= for(var i =3D 0; i < collection.length; i++)=0A= {=0A= array.push(collection.item(i));=0A= }=0A= return array;=0A= }=0A= =0A= if(!Array.prototype.append)=0A= {=0A= Array.prototype.append =3D function(a)=0A= {=0A= for(var i =3D 0; i> 2;=0A= enc2 =3D ((chr1 & 3) << 4) | (chr2 >> 4);=0A= enc3 =3D ((chr2 & 15) << 2) | (chr3 >> 6);=0A= enc4 =3D chr3 & 63;=0A= =0A= if (isNaN(chr2)) {=0A= enc3 =3D enc4 =3D 64;=0A= } else if (isNaN(chr3)) {=0A= enc4 =3D 64;=0A= }=0A= =0A= output =3D output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +=0A= keyStr.charAt(enc3) + keyStr.charAt(enc4);=0A= } while (i < input.length);=0A= =0A= return output;=0A= }=0A= =0A= /** Utility function to base64_decode some arbitrary data, uses the = builtin atob() if it exists (Moz) */=0A= =0A= HTMLArea.base64_decode =3Dfunction(input)=0A= {=0A= var keyStr =3D = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=3D";=0A= var output =3D "";=0A= var chr1, chr2, chr3;=0A= var enc1, enc2, enc3, enc4;=0A= var i =3D 0;=0A= =0A= // remove all characters that are not A-Z, a-z, 0-9, +, /, or =3D=0A= input =3D input.replace(/[^A-Za-z0-9\+\/\=3D]/g, "");=0A= =0A= do {=0A= enc1 =3D keyStr.indexOf(input.charAt(i++));=0A= enc2 =3D keyStr.indexOf(input.charAt(i++));=0A= enc3 =3D keyStr.indexOf(input.charAt(i++));=0A= enc4 =3D keyStr.indexOf(input.charAt(i++));=0A= =0A= chr1 =3D (enc1 << 2) | (enc2 >> 4);=0A= chr2 =3D ((enc2 & 15) << 4) | (enc3 >> 2);=0A= chr3 =3D ((enc3 & 3) << 6) | enc4;=0A= =0A= output =3D output + String.fromCharCode(chr1);=0A= =0A= if (enc3 !=3D 64) {=0A= output =3D output + String.fromCharCode(chr2);=0A= }=0A= if (enc4 !=3D 64) {=0A= output =3D output + String.fromCharCode(chr3);=0A= }=0A= } while (i < input.length);=0A= =0A= return output;=0A= }=0A= =0A= HTMLArea.removeFromParent =3D function(el)=0A= {=0A= if(!el.parentNode) return;=0A= var pN =3D el.parentNode;=0A= pN.removeChild(el);=0A= return el;=0A= }=0A= =0A= HTMLArea.hasParentNode =3D function(el)=0A= {=0A= if(el.parentNode)=0A= {=0A= // When you remove an element from the parent in IE it makes the = parent=0A= // of the element a document fragment. Moz doesn't.=0A= if(el.parentNode.nodeType =3D=3D 11)=0A= {=0A= return false;=0A= }=0A= return true;=0A= }=0A= =0A= return false;=0A= }=0A= =0A= HTMLArea.getOuterHTML =3D function(element)=0A= {=0A= if(HTMLArea.is_ie)=0A= {=0A= return element.outerHTML;=0A= }=0A= else=0A= {=0A= return (new XMLSerializer()).serializeToString(element);=0A= }=0A= }=0A= =0A= HTMLArea.toFree =3D [ ];=0A= HTMLArea.freeLater =3D function(obj,prop)=0A= {=0A= HTMLArea.toFree.push({o:obj,p:prop});=0A= }=0A= =0A= HTMLArea.free =3D function(obj, prop)=0A= {=0A= if(obj && !prop)=0A= {=0A= for(var p in obj)=0A= {=0A= HTMLArea.free(obj, p);=0A= }=0A= }=0A= else if (obj)=0A= {=0A= obj[prop] =3D null;=0A= }=0A= }=0A= =0A= /** IE's Garbage Collector is broken very badly. We will do our best to =0A= * do it's job for it, but we can't be perfect.=0A= */=0A= =0A= HTMLArea.collectGarbageForIE =3D function() =0A= { =0A= HTMLArea.flushEvents(); =0A= for(var x =3D 0; x < HTMLArea.toFree.length; x++)=0A= {=0A= if(!HTMLArea.toFree[x].o) alert("What is " + x + ' ' + = HTMLArea.toFree[x].o);=0A= HTMLArea.free(HTMLArea.toFree[x].o, HTMLArea.toFree[x].p);=0A= }=0A= }=0A= =0A= HTMLArea.init();=0A= HTMLArea.addDom0Event(window,'unload',HTMLArea.collectGarbageForIE);=0A= ------=_NextPart_000_00C5_01C620EA.84C9EDA0--