fixing misplaced apostrophe
[koha_fer] / koha-tmpl / intranet-tmpl / prog / fr / js / tinymce / jscripts / tiny_mce / tiny_mce_src.js
1 \r
2 /* file:jscripts/tiny_mce/classes/TinyMCE_Engine.class.js */\r
3 \r
4 function TinyMCE_Engine() {\r
5         var ua;\r
6 \r
7         this.majorVersion = "2";\r
8         this.minorVersion = "1.2";\r
9         this.releaseDate = "2007-08-21";\r
10 \r
11         this.instances = [];\r
12         this.switchClassCache = [];\r
13         this.windowArgs = [];\r
14         this.loadedFiles = [];\r
15         this.pendingFiles = [];\r
16         this.loadingIndex = 0;\r
17         this.configs = [];\r
18         this.currentConfig = 0;\r
19         this.eventHandlers = [];\r
20         this.log = [];\r
21         this.undoLevels = [];\r
22         this.undoIndex = 0;\r
23         this.typingUndoIndex = -1;\r
24         this.settings = [];\r
25 \r
26         // Browser check\r
27         ua = navigator.userAgent;\r
28         this.isMSIE = (navigator.appName == "Microsoft Internet Explorer");\r
29         this.isMSIE5 = this.isMSIE && (ua.indexOf('MSIE 5') != -1);\r
30         this.isMSIE5_0 = this.isMSIE && (ua.indexOf('MSIE 5.0') != -1);\r
31         this.isMSIE7 = this.isMSIE && (ua.indexOf('MSIE 7') != -1);\r
32         this.isGecko = ua.indexOf('Gecko') != -1; // Will also be true on Safari\r
33         this.isSafari = ua.indexOf('Safari') != -1;\r
34         this.isOpera = window['opera'] && opera.buildNumber ? true : false;\r
35         this.isMac = ua.indexOf('Mac') != -1;\r
36         this.isNS7 = ua.indexOf('Netscape/7') != -1;\r
37         this.isNS71 = ua.indexOf('Netscape/7.1') != -1;\r
38         this.dialogCounter = 0;\r
39         this.plugins = [];\r
40         this.themes = [];\r
41         this.menus = [];\r
42         this.loadedPlugins = [];\r
43         this.buttonMap = [];\r
44         this.isLoaded = false;\r
45 \r
46         // Fake MSIE on Opera and if Opera fakes IE, Gecko or Safari cancel those\r
47         if (this.isOpera) {\r
48                 this.isMSIE = true;\r
49                 this.isGecko = false;\r
50                 this.isSafari =  false;\r
51         }\r
52 \r
53         this.isIE = this.isMSIE;\r
54         this.isRealIE = this.isMSIE && !this.isOpera;\r
55 \r
56         // TinyMCE editor id instance counter\r
57         this.idCounter = 0;\r
58 };\r
59 \r
60 TinyMCE_Engine.prototype = {\r
61         init : function(settings) {\r
62                 var theme, nl, baseHREF = "", i, cssPath, entities, h, p, src, elements = [], head;\r
63 \r
64                 // IE 5.0x is no longer supported since 5.5, 6.0 and 7.0 now exists. We can't support old browsers forever, sorry.\r
65                 if (this.isMSIE5_0)\r
66                         return;\r
67 \r
68                 this.settings = settings;\r
69 \r
70                 // Check if valid browser has execcommand support\r
71                 if (typeof(document.execCommand) == 'undefined')\r
72                         return;\r
73 \r
74                 // Get script base path\r
75                 if (!tinyMCE.baseURL) {\r
76                         // Search through head\r
77                         head = document.getElementsByTagName('head')[0];\r
78 \r
79                         if (head) {\r
80                                 for (i=0, nl = head.getElementsByTagName('script'); i<nl.length; i++)\r
81                                         elements.push(nl[i]);\r
82                         }\r
83 \r
84                         // Search through rest of document\r
85                         for (i=0, nl = document.getElementsByTagName('script'); i<nl.length; i++)\r
86                                 elements.push(nl[i]);\r
87 \r
88                         // If base element found, add that infront of baseURL\r
89                         nl = document.getElementsByTagName('base');\r
90                         for (i=0; i<nl.length; i++) {\r
91                                 if (nl[i].href)\r
92                                         baseHREF = nl[i].href;\r
93                         }\r
94 \r
95                         for (i=0; i<elements.length; i++) {\r
96                                 if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_dev.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1 || elements[i].src.indexOf("tiny_mce_gzip") != -1)) {\r
97                                         src = elements[i].src;\r
98 \r
99                                         tinyMCE.srcMode = (src.indexOf('_src') != -1 || src.indexOf('_dev') != -1) ? '_src' : '';\r
100                                         tinyMCE.gzipMode = src.indexOf('_gzip') != -1;\r
101                                         src = src.substring(0, src.lastIndexOf('/'));\r
102 \r
103                                         if (settings.exec_mode == "src" || settings.exec_mode == "normal")\r
104                                                 tinyMCE.srcMode = settings.exec_mode == "src" ? '_src' : '';\r
105 \r
106                                         // Force it absolute if page has a base href\r
107                                         if (baseHREF !== '' && src.indexOf('://') == -1)\r
108                                                 tinyMCE.baseURL = baseHREF + src;\r
109                                         else\r
110                                                 tinyMCE.baseURL = src;\r
111 \r
112                                         break;\r
113                                 }\r
114                         }\r
115                 }\r
116 \r
117                 // Get document base path\r
118                 this.documentBasePath = document.location.href;\r
119                 if (this.documentBasePath.indexOf('?') != -1)\r
120                         this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.indexOf('?'));\r
121                 this.documentURL = this.documentBasePath;\r
122                 this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.lastIndexOf('/'));\r
123 \r
124                 // If not HTTP absolute\r
125                 if (tinyMCE.baseURL.indexOf('://') == -1 && tinyMCE.baseURL.charAt(0) != '/') {\r
126                         // If site absolute\r
127                         tinyMCE.baseURL = this.documentBasePath + "/" + tinyMCE.baseURL;\r
128                 }\r
129 \r
130                 // Set default values on settings\r
131                 this._def("mode", "none");\r
132                 this._def("theme", "advanced");\r
133                 this._def("plugins", "", true);\r
134                 this._def("language", "en");\r
135                 this._def("docs_language", this.settings.language);\r
136                 this._def("elements", "");\r
137                 this._def("textarea_trigger", "mce_editable");\r
138                 this._def("editor_selector", "");\r
139                 this._def("editor_deselector", "mceNoEditor");\r
140                 this._def("valid_elements", "+a[id|style|rel|rev|charset|hreflang|dir|lang|tabindex|accesskey|type|name|href|target|title|class|onfocus|onblur|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup],-strong/-b[class|style],-em/-i[class|style],-strike[class|style],-u[class|style],#p[id|style|dir|class|align],-ol[class|style],-ul[class|style],-li[class|style],br,img[id|dir|lang|longdesc|usemap|style|class|src|onmouseover|onmouseout|border|alt=|title|hspace|vspace|width|height|align],-sub[style|class],-sup[style|class],-blockquote[dir|style],-table[border=0|cellspacing|cellpadding|width|height|class|align|summary|style|dir|id|lang|bgcolor|background|bordercolor],-tr[id|lang|dir|class|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor],tbody[id|class],thead[id|class],tfoot[id|class],#td[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|bgcolor|background|bordercolor|scope],-th[id|lang|dir|class|colspan|rowspan|width|height|align|valign|style|scope],caption[id|lang|dir|class|style],-div[id|dir|class|align|style],-span[style|class|align],-pre[class|align|style],address[class|align|style],-h1[id|style|dir|class|align],-h2[id|style|dir|class|align],-h3[id|style|dir|class|align],-h4[id|style|dir|class|align],-h5[id|style|dir|class|align],-h6[id|style|dir|class|align],hr[class|style],-font[face|size|style|id|class|dir|color],dd[id|class|title|style|dir|lang],dl[id|class|title|style|dir|lang],dt[id|class|title|style|dir|lang],cite[title|id|class|style|dir|lang],abbr[title|id|class|style|dir|lang],acronym[title|id|class|style|dir|lang],del[title|id|class|style|dir|lang|datetime|cite],ins[title|id|class|style|dir|lang|datetime|cite]");\r
141                 this._def("extended_valid_elements", "");\r
142                 this._def("invalid_elements", "");\r
143                 this._def("encoding", "");\r
144                 this._def("urlconverter_callback", tinyMCE.getParam("urlconvertor_callback", "TinyMCE_Engine.prototype.convertURL"));\r
145                 this._def("save_callback", "");\r
146                 this._def("force_br_newlines", false);\r
147                 this._def("force_p_newlines", true);\r
148                 this._def("add_form_submit_trigger", true);\r
149                 this._def("relative_urls", true);\r
150                 this._def("remove_script_host", true);\r
151                 this._def("focus_alert", true);\r
152                 this._def("document_base_url", this.documentURL);\r
153                 this._def("visual", true);\r
154                 this._def("visual_table_class", "mceVisualAid");\r
155                 this._def("setupcontent_callback", "");\r
156                 this._def("fix_content_duplication", true);\r
157                 this._def("custom_undo_redo", true);\r
158                 this._def("custom_undo_redo_levels", -1);\r
159                 this._def("custom_undo_redo_keyboard_shortcuts", true);\r
160                 this._def("custom_undo_redo_restore_selection", true);\r
161                 this._def("custom_undo_redo_global", false);\r
162                 this._def("verify_html", true);\r
163                 this._def("apply_source_formatting", false);\r
164                 this._def("directionality", "ltr");\r
165                 this._def("cleanup_on_startup", false);\r
166                 this._def("inline_styles", false);\r
167                 this._def("convert_newlines_to_brs", false);\r
168                 this._def("auto_reset_designmode", true);\r
169                 this._def("entities", "39,#39,160,nbsp,161,iexcl,162,cent,163,pound,164,curren,165,yen,166,brvbar,167,sect,168,uml,169,copy,170,ordf,171,laquo,172,not,173,shy,174,reg,175,macr,176,deg,177,plusmn,178,sup2,179,sup3,180,acute,181,micro,182,para,183,middot,184,cedil,185,sup1,186,ordm,187,raquo,188,frac14,189,frac12,190,frac34,191,iquest,192,Agrave,193,Aacute,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,201,Eacute,202,Ecirc,203,Euml,204,Igrave,205,Iacute,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,211,Oacute,212,Ocirc,213,Otilde,214,Ouml,215,times,216,Oslash,217,Ugrave,218,Uacute,219,Ucirc,220,Uuml,221,Yacute,222,THORN,223,szlig,224,agrave,225,aacute,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,233,eacute,234,ecirc,235,euml,236,igrave,237,iacute,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,243,oacute,244,ocirc,245,otilde,246,ouml,247,divide,248,oslash,249,ugrave,250,uacute,251,ucirc,252,uuml,253,yacute,254,thorn,255,yuml,402,fnof,913,Alpha,914,Beta,915,Gamma,916,Delta,917,Epsilon,918,Zeta,919,Eta,920,Theta,921,Iota,922,Kappa,923,Lambda,924,Mu,925,Nu,926,Xi,927,Omicron,928,Pi,929,Rho,931,Sigma,932,Tau,933,Upsilon,934,Phi,935,Chi,936,Psi,937,Omega,945,alpha,946,beta,947,gamma,948,delta,949,epsilon,950,zeta,951,eta,952,theta,953,iota,954,kappa,955,lambda,956,mu,957,nu,958,xi,959,omicron,960,pi,961,rho,962,sigmaf,963,sigma,964,tau,965,upsilon,966,phi,967,chi,968,psi,969,omega,977,thetasym,978,upsih,982,piv,8226,bull,8230,hellip,8242,prime,8243,Prime,8254,oline,8260,frasl,8472,weierp,8465,image,8476,real,8482,trade,8501,alefsym,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8704,forall,8706,part,8707,exist,8709,empty,8711,nabla,8712,isin,8713,notin,8715,ni,8719,prod,8721,sum,8722,minus,8727,lowast,8730,radic,8733,prop,8734,infin,8736,ang,8743,and,8744,or,8745,cap,8746,cup,8747,int,8756,there4,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8804,le,8805,ge,8834,sub,8835,sup,8836,nsub,8838,sube,8839,supe,8853,oplus,8855,otimes,8869,perp,8901,sdot,8968,lceil,8969,rceil,8970,lfloor,8971,rfloor,9001,lang,9002,rang,9674,loz,9824,spades,9827,clubs,9829,hearts,9830,diams,34,quot,38,amp,60,lt,62,gt,338,OElig,339,oelig,352,Scaron,353,scaron,376,Yuml,710,circ,732,tilde,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,8211,ndash,8212,mdash,8216,lsquo,8217,rsquo,8218,sbquo,8220,ldquo,8221,rdquo,8222,bdquo,8224,dagger,8225,Dagger,8240,permil,8249,lsaquo,8250,rsaquo,8364,euro", true);\r
170                 this._def("entity_encoding", "named");\r
171                 this._def("cleanup_callback", "");\r
172                 this._def("add_unload_trigger", true);\r
173                 this._def("ask", false);\r
174                 this._def("nowrap", false);\r
175                 this._def("auto_resize", false);\r
176                 this._def("auto_focus", false);\r
177                 this._def("cleanup", true);\r
178                 this._def("remove_linebreaks", true);\r
179                 this._def("button_tile_map", false);\r
180                 this._def("submit_patch", true);\r
181                 this._def("browsers", "msie,safari,gecko,opera", true);\r
182                 this._def("dialog_type", "window");\r
183                 this._def("accessibility_warnings", true);\r
184                 this._def("accessibility_focus", true);\r
185                 this._def("merge_styles_invalid_parents", "");\r
186                 this._def("force_hex_style_colors", true);\r
187                 this._def("trim_span_elements", true);\r
188                 this._def("convert_fonts_to_spans", false);\r
189                 this._def("doctype", '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">');\r
190                 this._def("font_size_classes", '');\r
191                 this._def("font_size_style_values", 'xx-small,x-small,small,medium,large,x-large,xx-large', true);\r
192                 this._def("event_elements", 'a,img', true);\r
193                 this._def("convert_urls", true);\r
194                 this._def("table_inline_editing", false);\r
195                 this._def("object_resizing", true);\r
196                 this._def("custom_shortcuts", true);\r
197                 this._def("convert_on_click", false);\r
198                 this._def("content_css", '');\r
199                 this._def("fix_list_elements", true);\r
200                 this._def("fix_table_elements", false);\r
201                 this._def("strict_loading_mode", document.contentType == 'application/xhtml+xml');\r
202                 this._def("hidden_tab_class", '');\r
203                 this._def("display_tab_class", '');\r
204                 this._def("gecko_spellcheck", false);\r
205                 this._def("hide_selects_on_submit", true);\r
206                 this._def("forced_root_block", false);\r
207                 this._def("remove_trailing_nbsp", false);\r
208                 this._def("save_on_tinymce_forms", false);\r
209 \r
210                 // Force strict loading mode to false on non Gecko browsers\r
211                 if (this.isMSIE && !this.isOpera)\r
212                         this.settings.strict_loading_mode = false;\r
213 \r
214                 // Browser check IE\r
215                 if (this.isMSIE && this.settings.browsers.indexOf('msie') == -1)\r
216                         return;\r
217 \r
218                 // Browser check Gecko\r
219                 if (this.isGecko && this.settings.browsers.indexOf('gecko') == -1)\r
220                         return;\r
221 \r
222                 // Browser check Safari\r
223                 if (this.isSafari && this.settings.browsers.indexOf('safari') == -1)\r
224                         return;\r
225 \r
226                 // Browser check Opera\r
227                 if (this.isOpera && this.settings.browsers.indexOf('opera') == -1)\r
228                         return;\r
229 \r
230                 // If not super absolute make it so\r
231                 baseHREF = tinyMCE.settings.document_base_url;\r
232                 h = document.location.href;\r
233                 p = h.indexOf('://');\r
234                 if (p > 0 && document.location.protocol != "file:") {\r
235                         p = h.indexOf('/', p + 3);\r
236                         h = h.substring(0, p);\r
237 \r
238                         if (baseHREF.indexOf('://') == -1)\r
239                                 baseHREF = h + baseHREF;\r
240 \r
241                         tinyMCE.settings.document_base_url = baseHREF;\r
242                         tinyMCE.settings.document_base_prefix = h;\r
243                 }\r
244 \r
245                 // Trim away query part\r
246                 if (baseHREF.indexOf('?') != -1)\r
247                         baseHREF = baseHREF.substring(0, baseHREF.indexOf('?'));\r
248 \r
249                 this.settings.base_href = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/";\r
250 \r
251                 theme = this.settings.theme;\r
252                 this.inlineStrict = 'A|BR|SPAN|BDO|MAP|OBJECT|IMG|TT|I|B|BIG|SMALL|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|#text|#comment';\r
253                 this.inlineTransitional = 'A|BR|SPAN|BDO|OBJECT|APPLET|IMG|MAP|IFRAME|TT|I|B|U|S|STRIKE|BIG|SMALL|FONT|BASEFONT|EM|STRONG|DFN|CODE|Q|SAMP|KBD|VAR|CITE|ABBR|ACRONYM|SUB|SUP|INPUT|SELECT|TEXTAREA|LABEL|BUTTON|#text|#comment';\r
254                 this.blockElms = 'H[1-6]|P|DIV|ADDRESS|PRE|FORM|TABLE|LI|OL|UL|TD|CAPTION|BLOCKQUOTE|CENTER|DL|DT|DD|DIR|FIELDSET|FORM|NOSCRIPT|NOFRAMES|MENU|ISINDEX|SAMP';\r
255                 this.blockRegExp = new RegExp("^(" + this.blockElms + ")$", "i");\r
256                 this.posKeyCodes = [13,45,36,35,33,34,37,38,39,40];\r
257                 this.uniqueURL = 'javascript:void(091039730);'; // Make unique URL non real URL\r
258                 this.uniqueTag = '<div id="mceTMPElement" style="display: none">TMP</div>';\r
259                 this.callbacks = ['onInit', 'getInfo', 'getEditorTemplate', 'setupContent', 'onChange', 'onPageLoad', 'handleNodeChange', 'initInstance', 'execCommand', 'getControlHTML', 'handleEvent', 'cleanup', 'removeInstance'];\r
260 \r
261                 // Theme url\r
262                 this.settings.theme_href = tinyMCE.baseURL + "/themes/" + theme;\r
263 \r
264                 if (!tinyMCE.isIE || tinyMCE.isOpera)\r
265                         this.settings.force_br_newlines = false;\r
266 \r
267                 if (tinyMCE.getParam("popups_css", false)) {\r
268                         cssPath = tinyMCE.getParam("popups_css", "");\r
269 \r
270                         // Is relative\r
271                         if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')\r
272                                 this.settings.popups_css = this.documentBasePath + "/" + cssPath;\r
273                         else\r
274                                 this.settings.popups_css = cssPath;\r
275                 } else\r
276                         this.settings.popups_css = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_popup.css";\r
277 \r
278                 if (tinyMCE.getParam("editor_css", false)) {\r
279                         cssPath = tinyMCE.getParam("editor_css", "");\r
280 \r
281                         // Is relative\r
282                         if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/')\r
283                                 this.settings.editor_css = this.documentBasePath + "/" + cssPath;\r
284                         else\r
285                                 this.settings.editor_css = cssPath;\r
286                 } else {\r
287                         if (this.settings.editor_css !== '')\r
288                                 this.settings.editor_css = tinyMCE.baseURL + "/themes/" + theme + "/css/editor_ui.css";\r
289                 }\r
290 \r
291                 // Only do this once\r
292                 if (this.configs.length == 0) {\r
293                         if (typeof(TinyMCECompressed) == "undefined") {\r
294                                 tinyMCE.addEvent(window, "DOMContentLoaded", TinyMCE_Engine.prototype.onLoad);\r
295 \r
296                                 if (tinyMCE.isRealIE) {\r
297                                         if (document.body)\r
298                                                 tinyMCE.addEvent(document.body, "readystatechange", TinyMCE_Engine.prototype.onLoad);\r
299                                         else\r
300                                                 tinyMCE.addEvent(document, "readystatechange", TinyMCE_Engine.prototype.onLoad);\r
301                                 }\r
302 \r
303                                 tinyMCE.addEvent(window, "load", TinyMCE_Engine.prototype.onLoad);\r
304                                 tinyMCE._addUnloadEvents();\r
305                         }\r
306                 }\r
307 \r
308                 this.loadScript(tinyMCE.baseURL + '/themes/' + this.settings.theme + '/editor_template' + tinyMCE.srcMode + '.js');\r
309                 this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings.language +  '.js');\r
310                 this.loadCSS(this.settings.editor_css);\r
311 \r
312                 // Add plugins\r
313                 p = tinyMCE.getParam('plugins', '', true, ',');\r
314                 if (p.length > 0) {\r
315                         for (i=0; i<p.length; i++) {\r
316                                 if (p[i].charAt(0) != '-')\r
317                                         this.loadScript(tinyMCE.baseURL + '/plugins/' + p[i] + '/editor_plugin' + tinyMCE.srcMode + '.js');\r
318                         }\r
319                 }\r
320 \r
321                 // Setup entities\r
322                 if (tinyMCE.getParam('entity_encoding') == 'named') {\r
323                         settings.cleanup_entities = [];\r
324                         entities = tinyMCE.getParam('entities', '', true, ',');\r
325                         for (i=0; i<entities.length; i+=2)\r
326                                 settings.cleanup_entities['c' + entities[i]] = entities[i+1];\r
327                 }\r
328 \r
329                 // Save away this config\r
330                 settings.index = this.configs.length;\r
331                 this.configs[this.configs.length] = settings;\r
332 \r
333                 // Start loading first one in chain\r
334                 this.loadNextScript();\r
335 \r
336                 // Force flicker free CSS backgrounds in IE\r
337                 if (this.isIE && !this.isOpera) {\r
338                         try {\r
339                                 document.execCommand('BackgroundImageCache', false, true);\r
340                         } catch (e) {\r
341                                 // Ignore\r
342                         }\r
343                 }\r
344 \r
345                 // Setup XML encoding regexps\r
346                 this.xmlEncodeRe = new RegExp('[<>&"]', 'g');\r
347         },\r
348 \r
349         _addUnloadEvents : function() {\r
350                 var st = tinyMCE.settings.add_unload_trigger;\r
351 \r
352                 if (tinyMCE.isIE) {\r
353                         if (st) {\r
354                                 tinyMCE.addEvent(window, "unload", TinyMCE_Engine.prototype.unloadHandler);\r
355                                 tinyMCE.addEvent(window.document, "beforeunload", TinyMCE_Engine.prototype.unloadHandler);\r
356                         }\r
357                 } else {\r
358                         if (st)\r
359                                 tinyMCE.addEvent(window, "unload", function () {tinyMCE.triggerSave(true, true);});\r
360                 }\r
361         },\r
362 \r
363         _def : function(key, def_val, t) {\r
364                 var v = tinyMCE.getParam(key, def_val);\r
365 \r
366                 v = t ? v.replace(/\s+/g, "") : v;\r
367 \r
368                 this.settings[key] = v;\r
369         },\r
370 \r
371         hasPlugin : function(n) {\r
372                 return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;\r
373         },\r
374 \r
375         addPlugin : function(n, p) {\r
376                 var op = this.plugins[n];\r
377 \r
378                 // Use the previous plugin object base URL used when loading external plugins\r
379                 p.baseURL = op ? op.baseURL : tinyMCE.baseURL + "/plugins/" + n;\r
380                 this.plugins[n] = p;\r
381 \r
382                 this.loadNextScript();\r
383         },\r
384 \r
385         setPluginBaseURL : function(n, u) {\r
386                 var op = this.plugins[n];\r
387 \r
388                 if (op)\r
389                         op.baseURL = u;\r
390                 else\r
391                         this.plugins[n] = {baseURL : u};\r
392         },\r
393 \r
394         loadPlugin : function(n, u) {\r
395                 u = u.indexOf('.js') != -1 ? u.substring(0, u.lastIndexOf('/')) : u;\r
396                 u = u.charAt(u.length-1) == '/' ? u.substring(0, u.length-1) : u;\r
397                 this.plugins[n] = {baseURL : u};\r
398                 this.loadScript(u + "/editor_plugin" + (tinyMCE.srcMode ? '_src' : '') + ".js");\r
399         },\r
400 \r
401         hasTheme : function(n) {\r
402                 return typeof(this.themes[n]) != "undefined" && this.themes[n] != null;\r
403         },\r
404 \r
405         addTheme : function(n, t) {\r
406                 this.themes[n] = t;\r
407 \r
408                 this.loadNextScript();\r
409         },\r
410 \r
411         addMenu : function(n, m) {\r
412                 this.menus[n] = m;\r
413         },\r
414 \r
415         hasMenu : function(n) {\r
416                 return typeof(this.plugins[n]) != "undefined" && this.plugins[n] != null;\r
417         },\r
418 \r
419         loadScript : function(url) {\r
420                 var i;\r
421 \r
422                 for (i=0; i<this.loadedFiles.length; i++) {\r
423                         if (this.loadedFiles[i] == url)\r
424                                 return;\r
425                 }\r
426 \r
427                 if (tinyMCE.settings.strict_loading_mode)\r
428                         this.pendingFiles[this.pendingFiles.length] = url;\r
429                 else\r
430                         document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></script>');\r
431 \r
432                 this.loadedFiles[this.loadedFiles.length] = url;\r
433         },\r
434 \r
435         loadNextScript : function() {\r
436                 var d = document, se;\r
437 \r
438                 if (!tinyMCE.settings.strict_loading_mode)\r
439                         return;\r
440 \r
441                 if (this.loadingIndex < this.pendingFiles.length) {\r
442                         se = d.createElementNS('http://www.w3.org/1999/xhtml', 'script');\r
443                         se.setAttribute('language', 'javascript');\r
444                         se.setAttribute('type', 'text/javascript');\r
445                         se.setAttribute('src', this.pendingFiles[this.loadingIndex++]);\r
446 \r
447                         d.getElementsByTagName("head")[0].appendChild(se);\r
448                 } else\r
449                         this.loadingIndex = -1; // Done with loading\r
450         },\r
451 \r
452         loadCSS : function(url) {\r
453                 var ar = url.replace(/\s+/, '').split(',');\r
454                 var lflen = 0, csslen = 0, skip = false;\r
455                 var x = 0, i = 0, nl, le;\r
456 \r
457                 for (x = 0,csslen = ar.length; x<csslen; x++) {\r
458                         if (ar[x] != null && ar[x] != 'null' && ar[x].length > 0) {\r
459                                 /* Make sure it doesn't exist. */\r
460                                 for (i=0, lflen=this.loadedFiles.length; i<lflen; i++) {\r
461                                         if (this.loadedFiles[i] == ar[x]) {\r
462                                                 skip = true;\r
463                                                 break;\r
464                                         }\r
465                                 }\r
466 \r
467                                 if (!skip) {\r
468                                         if (tinyMCE.settings.strict_loading_mode) {\r
469                                                 nl = document.getElementsByTagName("head");\r
470 \r
471                                                 le = document.createElement('link');\r
472                                                 le.setAttribute('href', ar[x]);\r
473                                                 le.setAttribute('rel', 'stylesheet');\r
474                                                 le.setAttribute('type', 'text/css');\r
475 \r
476                                                 nl[0].appendChild(le);                  \r
477                                         } else\r
478                                                 document.write('<link href="' + ar[x] + '" rel="stylesheet" type="text/css" />');\r
479 \r
480                                         this.loadedFiles[this.loadedFiles.length] = ar[x];\r
481                                 }\r
482                         }\r
483                 }\r
484         },\r
485 \r
486         importCSS : function(doc, css) {\r
487                 var css_ary = css.replace(/\s+/, '').split(',');\r
488                 var csslen, elm, headArr, x, css_file;\r
489 \r
490                 for (x = 0, csslen = css_ary.length; x<csslen; x++) {\r
491                         css_file = css_ary[x];\r
492 \r
493                         if (css_file != null && css_file != 'null' && css_file.length > 0) {\r
494                                 // Is relative, make absolute\r
495                                 if (css_file.indexOf('://') == -1 && css_file.charAt(0) != '/')\r
496                                         css_file = this.documentBasePath + "/" + css_file;\r
497 \r
498                                 if (typeof(doc.createStyleSheet) == "undefined") {\r
499                                         elm = doc.createElement("link");\r
500 \r
501                                         elm.rel = "stylesheet";\r
502                                         elm.href = css_file;\r
503 \r
504                                         if ((headArr = doc.getElementsByTagName("head")) != null && headArr.length > 0)\r
505                                                 headArr[0].appendChild(elm);\r
506                                 } else\r
507                                         doc.createStyleSheet(css_file);\r
508                         }\r
509                 }\r
510         },\r
511 \r
512         confirmAdd : function(e, settings) {\r
513                 var elm = tinyMCE.isIE ? event.srcElement : e.target;\r
514                 var elementId = elm.name ? elm.name : elm.id;\r
515 \r
516                 tinyMCE.settings = settings;\r
517 \r
518                 if (tinyMCE.settings.convert_on_click || (!elm.getAttribute('mce_noask') && confirm(tinyMCELang.lang_edit_confirm)))\r
519                         tinyMCE.addMCEControl(elm, elementId);\r
520 \r
521                 elm.setAttribute('mce_noask', 'true');\r
522         },\r
523 \r
524         updateContent : function(form_element_name) {\r
525                 var formElement, n, inst, doc;\r
526 \r
527                 // Find MCE instance linked to given form element and copy it's value\r
528                 formElement = document.getElementById(form_element_name);\r
529                 for (n in tinyMCE.instances) {\r
530                         inst = tinyMCE.instances[n];\r
531 \r
532                         if (!tinyMCE.isInstance(inst))\r
533                                 continue;\r
534 \r
535                         inst.switchSettings();\r
536 \r
537                         if (inst.formElement == formElement) {\r
538                                 doc = inst.getDoc();\r
539 \r
540                                 tinyMCE._setHTML(doc, inst.formElement.value);\r
541 \r
542                                 if (!tinyMCE.isIE)\r
543                                         doc.body.innerHTML = tinyMCE._cleanupHTML(inst, doc, this.settings, doc.body, inst.visualAid);\r
544                         }\r
545                 }\r
546         },\r
547 \r
548         addMCEControl : function(replace_element, form_element_name, target_document) {\r
549                 var id = "mce_editor_" + tinyMCE.idCounter++;\r
550                 var inst = new TinyMCE_Control(tinyMCE.settings);\r
551 \r
552                 inst.editorId = id;\r
553                 this.instances[id] = inst;\r
554 \r
555                 inst._onAdd(replace_element, form_element_name, target_document);\r
556         },\r
557 \r
558         removeInstance : function(ti) {\r
559                 var t = [], n, i;\r
560 \r
561                 // Remove from instances\r
562                 for (n in tinyMCE.instances) {\r
563                         i = tinyMCE.instances[n];\r
564 \r
565                         if (tinyMCE.isInstance(i) && ti != i)\r
566                                         t[n] = i;\r
567                 }\r
568 \r
569                 tinyMCE.instances = t;\r
570 \r
571                 // Remove from global undo/redo\r
572                 n = [];\r
573                 t = tinyMCE.undoLevels;\r
574 \r
575                 for (i=0; i<t.length; i++) {\r
576                         if (t[i] != ti)\r
577                                 n.push(t[i]);\r
578                 }\r
579 \r
580                 tinyMCE.undoLevels = n;\r
581                 tinyMCE.undoIndex = n.length;\r
582 \r
583                 // Dispatch remove instance call\r
584                 tinyMCE.dispatchCallback(ti, 'remove_instance_callback', 'removeInstance', ti);\r
585 \r
586                 return ti;\r
587         },\r
588 \r
589         removeMCEControl : function(editor_id) {\r
590                 var inst = tinyMCE.getInstanceById(editor_id), h, re, ot, tn, n;\r
591 \r
592                 if (inst) {\r
593                         inst.switchSettings();\r
594 \r
595                         editor_id = inst.editorId;\r
596                         h = tinyMCE.getContent(editor_id);\r
597 \r
598                         this.removeInstance(inst);\r
599 \r
600                         tinyMCE.selectedElement = null;\r
601                         tinyMCE.selectedInstance = null;\r
602 \r
603                         tinyMCE.selectedElement = null;\r
604                         tinyMCE.selectedInstance = null;\r
605 \r
606                         // Try finding an instance\r
607                         for (n in tinyMCE.instances) {\r
608                                 if (!tinyMCE.isInstance(tinyMCE.instances[n]))\r
609                                         continue;\r
610 \r
611                                 tinyMCE.selectedInstance = tinyMCE.instances[n];\r
612                                 break;\r
613                         }\r
614 \r
615                         // Remove element\r
616                         re = document.getElementById(editor_id + "_parent");\r
617                         ot = inst.oldTargetElement;\r
618                         tn = ot.nodeName.toLowerCase();\r
619 \r
620                         if (tn == "textarea" || tn == "input") {\r
621                                 re.parentNode.removeChild(re);\r
622                                 ot.style.display = "inline";\r
623                                 ot.value = h;\r
624                         } else {\r
625                                 ot.innerHTML = h;\r
626                                 ot.style.display = 'block';\r
627                                 re.parentNode.insertBefore(ot, re);\r
628                                 re.parentNode.removeChild(re);\r
629                         }\r
630                 }\r
631         },\r
632 \r
633         triggerSave : function(skip_cleanup, skip_callback) {\r
634                 var inst, n;\r
635 \r
636                 // Default to false\r
637                 if (typeof(skip_cleanup) == "undefined")\r
638                         skip_cleanup = false;\r
639 \r
640                 // Default to false\r
641                 if (typeof(skip_callback) == "undefined")\r
642                         skip_callback = false;\r
643 \r
644                 // Cleanup and set all form fields\r
645                 for (n in tinyMCE.instances) {\r
646                         inst = tinyMCE.instances[n];\r
647 \r
648                         if (!tinyMCE.isInstance(inst))\r
649                                 continue;\r
650 \r
651                         inst.triggerSave(skip_cleanup, skip_callback);\r
652                 }\r
653         },\r
654 \r
655         resetForm : function(form_index) {\r
656                 var i, inst, n, formObj = document.forms[form_index];\r
657 \r
658                 for (n in tinyMCE.instances) {\r
659                         inst = tinyMCE.instances[n];\r
660 \r
661                         if (!tinyMCE.isInstance(inst))\r
662                                 continue;\r
663 \r
664                         inst.switchSettings();\r
665 \r
666                         for (i=0; i<formObj.elements.length; i++) {\r
667                                 if (inst.formTargetElementId == formObj.elements[i].name)\r
668                                         inst.getBody().innerHTML = inst.startContent;\r
669                         }\r
670                 }\r
671         },\r
672 \r
673         execInstanceCommand : function(editor_id, command, user_interface, value, focus) {\r
674                 var inst = tinyMCE.getInstanceById(editor_id), r;\r
675 \r
676                 if (inst) {\r
677                         r = inst.selection.getRng();\r
678 \r
679                         if (typeof(focus) == "undefined")\r
680                                 focus = true;\r
681 \r
682                         // IE bug lost focus on images in absolute divs Bug #1534575\r
683                         if (focus && (!r || !r.item))\r
684                                 inst.contentWindow.focus();\r
685 \r
686                         // Reset design mode if lost\r
687                         inst.autoResetDesignMode();\r
688 \r
689                         this.selectedElement = inst.getFocusElement();\r
690                         inst.select();\r
691                         tinyMCE.execCommand(command, user_interface, value);\r
692 \r
693                         // Cancel event so it doesn't call onbeforeonunlaod\r
694                         if (tinyMCE.isIE && window.event != null)\r
695                                 tinyMCE.cancelEvent(window.event);\r
696                 }\r
697         },\r
698 \r
699         execCommand : function(command, user_interface, value) {\r
700                 var inst = tinyMCE.selectedInstance, n, pe, te;\r
701 \r
702                 // Default input\r
703                 user_interface = user_interface ? user_interface : false;\r
704                 value = value ? value : null;\r
705 \r
706                 if (inst)\r
707                         inst.switchSettings();\r
708 \r
709                 switch (command) {\r
710                         case "Undo":\r
711                                 if (this.getParam('custom_undo_redo_global')) {\r
712                                         if (this.undoIndex > 0) {\r
713                                                 tinyMCE.nextUndoRedoAction = 'Undo';\r
714                                                 inst = this.undoLevels[--this.undoIndex];\r
715                                                 inst.select();\r
716 \r
717                                                 if (!tinyMCE.nextUndoRedoInstanceId)\r
718                                                         inst.execCommand('Undo');\r
719                                         }\r
720                                 } else\r
721                                         inst.execCommand('Undo');\r
722                                 return true;\r
723 \r
724                         case "Redo":\r
725                                 if (this.getParam('custom_undo_redo_global')) {\r
726                                         if (this.undoIndex <= this.undoLevels.length - 1) {\r
727                                                 tinyMCE.nextUndoRedoAction = 'Redo';\r
728                                                 inst = this.undoLevels[this.undoIndex++];\r
729                                                 inst.select();\r
730 \r
731                                                 if (!tinyMCE.nextUndoRedoInstanceId)\r
732                                                         inst.execCommand('Redo');\r
733                                         }\r
734                                 } else\r
735                                         inst.execCommand('Redo');\r
736 \r
737                                 return true;\r
738 \r
739                         case 'mceFocus':\r
740                                 inst = tinyMCE.getInstanceById(value);\r
741 \r
742                                 if (inst)\r
743                                         inst.getWin().focus();\r
744                         return;\r
745 \r
746                         case "mceAddControl":\r
747                         case "mceAddEditor":\r
748                                 tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);\r
749                                 return;\r
750 \r
751                         case "mceAddFrameControl":\r
752                                 tinyMCE.addMCEControl(tinyMCE._getElementById(value.element, value.document), value.element, value.document);\r
753                                 return;\r
754 \r
755                         case "mceRemoveControl":\r
756                         case "mceRemoveEditor":\r
757                                 tinyMCE.removeMCEControl(value);\r
758                                 return;\r
759 \r
760                         case "mceToggleEditor":\r
761                                 inst = tinyMCE.getInstanceById(value);\r
762 \r
763                                 if (inst) {\r
764                                         pe = document.getElementById(inst.editorId + '_parent');\r
765                                         te = inst.oldTargetElement;\r
766 \r
767                                         if (typeof(inst.enabled) == 'undefined')\r
768                                                 inst.enabled = true;\r
769 \r
770                                         inst.enabled = !inst.enabled;\r
771 \r
772                                         if (!inst.enabled) {\r
773                                                 pe.style.display = 'none';\r
774 \r
775                                                 if (te.nodeName == 'TEXTAREA' || te.nodeName == 'INPUT')\r
776                                                         te.value = inst.getHTML();\r
777                                                 else\r
778                                                         te.innerHTML = inst.getHTML();\r
779 \r
780                                                 te.style.display = inst.oldTargetDisplay;\r
781                                                 tinyMCE.dispatchCallback(inst, 'hide_instance_callback', 'hideInstance', inst);\r
782                                         } else {\r
783                                                 pe.style.display = 'block';\r
784                                                 te.style.display = 'none';\r
785 \r
786                                                 if (te.nodeName == 'TEXTAREA' || te.nodeName == 'INPUT')\r
787                                                         inst.setHTML(te.value);\r
788                                                 else\r
789                                                         inst.setHTML(te.innerHTML);\r
790 \r
791                                                 inst.useCSS = false;\r
792                                                 tinyMCE.dispatchCallback(inst, 'show_instance_callback', 'showInstance', inst);\r
793                                         }\r
794                                 } else\r
795                                         tinyMCE.addMCEControl(tinyMCE._getElementById(value), value);\r
796 \r
797                                 return;\r
798 \r
799                         case "mceResetDesignMode":\r
800                                 // Resets the designmode state of the editors in Gecko\r
801                                 if (tinyMCE.isGecko) {\r
802                                         for (n in tinyMCE.instances) {\r
803                                                 if (!tinyMCE.isInstance(tinyMCE.instances[n]))\r
804                                                         continue;\r
805 \r
806                                                 try {\r
807                                                         tinyMCE.instances[n].getDoc().designMode = "off";\r
808                                                         tinyMCE.instances[n].getDoc().designMode = "on";\r
809                                                         tinyMCE.instances[n].useCSS = false;\r
810                                                 } catch (e) {\r
811                                                         // Ignore any errors\r
812                                                 }\r
813                                         }\r
814                                 }\r
815 \r
816                                 return;\r
817                 }\r
818 \r
819                 if (inst) {\r
820                         inst.execCommand(command, user_interface, value);\r
821                 } else if (tinyMCE.settings.focus_alert)\r
822                         alert(tinyMCELang.lang_focus_alert);\r
823         },\r
824 \r
825         _createIFrame : function(replace_element, doc, win) {\r
826                 var iframe, id = replace_element.getAttribute("id");\r
827                 var aw, ah;\r
828 \r
829                 if (typeof(doc) == "undefined")\r
830                         doc = document;\r
831 \r
832                 if (typeof(win) == "undefined")\r
833                         win = window;\r
834 \r
835                 iframe = doc.createElement("iframe");\r
836 \r
837                 aw = "" + tinyMCE.settings.area_width;\r
838                 ah = "" + tinyMCE.settings.area_height;\r
839 \r
840                 if (aw.indexOf('%') == -1) {\r
841                         aw = parseInt(aw);\r
842                         aw = (isNaN(aw) || aw < 0) ? 300 : aw;\r
843                         aw = aw + "px";\r
844                 }\r
845 \r
846                 if (ah.indexOf('%') == -1) {\r
847                         ah = parseInt(ah);\r
848                         ah = (isNaN(ah) || ah < 0) ? 240 : ah;\r
849                         ah = ah + "px";\r
850                 }\r
851 \r
852                 iframe.setAttribute("id", id);\r
853                 iframe.setAttribute("name", id);\r
854                 iframe.setAttribute("class", "mceEditorIframe");\r
855                 iframe.setAttribute("border", "0");\r
856                 iframe.setAttribute("frameBorder", "0");\r
857                 iframe.setAttribute("marginWidth", "0");\r
858                 iframe.setAttribute("marginHeight", "0");\r
859                 iframe.setAttribute("leftMargin", "0");\r
860                 iframe.setAttribute("topMargin", "0");\r
861                 iframe.setAttribute("width", aw);\r
862                 iframe.setAttribute("height", ah);\r
863                 iframe.setAttribute("allowtransparency", "true");\r
864                 iframe.className = 'mceEditorIframe';\r
865 \r
866                 if (tinyMCE.settings.auto_resize)\r
867                         iframe.setAttribute("scrolling", "no");\r
868 \r
869                 // Must have a src element in MSIE HTTPs breaks aswell as absoute URLs\r
870                 if (tinyMCE.isRealIE)\r
871                         iframe.setAttribute("src", this.settings.default_document);\r
872 \r
873                 iframe.style.width = aw;\r
874                 iframe.style.height = ah;\r
875 \r
876                 // Ugly hack for Gecko problem in strict mode\r
877                 if (tinyMCE.settings.strict_loading_mode)\r
878                         iframe.style.marginBottom = '-5px';\r
879 \r
880                 // MSIE 5.0 issue\r
881                 if (tinyMCE.isRealIE)\r
882                         replace_element.outerHTML = iframe.outerHTML;\r
883                 else\r
884                         replace_element.parentNode.replaceChild(iframe, replace_element);\r
885 \r
886                 if (tinyMCE.isRealIE)\r
887                         return win.frames[id];\r
888                 else\r
889                         return iframe;\r
890         },\r
891 \r
892         setupContent : function(editor_id) {\r
893                 var inst = tinyMCE.instances[editor_id], i, doc = inst.getDoc(), head = doc.getElementsByTagName('head').item(0);\r
894                 var content = inst.startContent, contentElement, body;\r
895 \r
896                 // HTML values get XML encoded in strict mode\r
897                 if (tinyMCE.settings.strict_loading_mode) {\r
898                         content = content.replace(/&lt;/g, '<');\r
899                         content = content.replace(/&gt;/g, '>');\r
900                         content = content.replace(/&quot;/g, '"');\r
901                         content = content.replace(/&amp;/g, '&');\r
902                 }\r
903 \r
904                 tinyMCE.selectedInstance = inst;\r
905                 inst.switchSettings();\r
906 \r
907                 // Not loaded correctly hit it again, Mozilla bug #997860\r
908                 if (!tinyMCE.isIE && tinyMCE.getParam("setupcontent_reload", false) && doc.title != "blank_page") {\r
909                         // This part will remove the designMode status\r
910                         // Failes first time in Firefox 1.5b2 on Mac\r
911                         try {doc.location.href = tinyMCE.baseURL + "/blank.htm";} catch (ex) {}\r
912                         window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 1000);\r
913                         return;\r
914                 }\r
915 \r
916                 // Wait for it to load\r
917                 if (!head || !doc.body) {\r
918                         window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 10);\r
919                         return;\r
920                 }\r
921 \r
922                 // Import theme specific content CSS the user specific\r
923                 tinyMCE.importCSS(inst.getDoc(), tinyMCE.baseURL + "/themes/" + inst.settings.theme + "/css/editor_content.css");\r
924                 tinyMCE.importCSS(inst.getDoc(), inst.settings.content_css);\r
925                 tinyMCE.dispatchCallback(inst, 'init_instance_callback', 'initInstance', inst);\r
926 \r
927                 // Setup keyboard shortcuts\r
928                 if (tinyMCE.getParam('custom_undo_redo_keyboard_shortcuts')) {\r
929                         inst.addShortcut('ctrl', 'z', 'lang_undo_desc', 'Undo');\r
930                         inst.addShortcut('ctrl', 'y', 'lang_redo_desc', 'Redo');\r
931                 }\r
932 \r
933                 // BlockFormat shortcuts keys\r
934                 for (i=1; i<=6; i++)\r
935                         inst.addShortcut('ctrl', '' + i, '', 'FormatBlock', false, '<h' + i + '>');\r
936 \r
937                 inst.addShortcut('ctrl', '7', '', 'FormatBlock', false, '<p>');\r
938                 inst.addShortcut('ctrl', '8', '', 'FormatBlock', false, '<div>');\r
939                 inst.addShortcut('ctrl', '9', '', 'FormatBlock', false, '<address>');\r
940 \r
941                 // Add default shortcuts for gecko\r
942                 if (tinyMCE.isGecko) {\r
943                         inst.addShortcut('ctrl', 'b', 'lang_bold_desc', 'Bold');\r
944                         inst.addShortcut('ctrl', 'i', 'lang_italic_desc', 'Italic');\r
945                         inst.addShortcut('ctrl', 'u', 'lang_underline_desc', 'Underline');\r
946                 }\r
947 \r
948                 // Setup span styles\r
949                 if (tinyMCE.getParam("convert_fonts_to_spans"))\r
950                         inst.getBody().setAttribute('id', 'mceSpanFonts');\r
951 \r
952                 if (tinyMCE.settings.nowrap)\r
953                         doc.body.style.whiteSpace = "nowrap";\r
954 \r
955                 doc.body.dir = this.settings.directionality;\r
956                 doc.editorId = editor_id;\r
957 \r
958                 // Add on document element in Mozilla\r
959                 if (!tinyMCE.isIE)\r
960                         doc.documentElement.editorId = editor_id;\r
961 \r
962                 inst.setBaseHREF(tinyMCE.settings.base_href);\r
963 \r
964                 // Replace new line characters to BRs\r
965                 if (tinyMCE.settings.convert_newlines_to_brs) {\r
966                         content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi");\r
967                         content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi");\r
968                         content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi");\r
969                 }\r
970 \r
971                 // Open closed anchors\r
972         //      content = content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');\r
973 \r
974                 // Call custom cleanup code\r
975                 content = tinyMCE.storeAwayURLs(content);\r
976                 content = tinyMCE._customCleanup(inst, "insert_to_editor", content);\r
977 \r
978                 if (tinyMCE.isIE) {\r
979                         // Ugly!!!\r
980                         window.setInterval('try{tinyMCE.getCSSClasses(tinyMCE.instances["' + editor_id + '"].getDoc(), "' + editor_id + '");}catch(e){}', 500);\r
981 \r
982                         if (tinyMCE.settings.force_br_newlines)\r
983                                 doc.styleSheets[0].addRule("p", "margin: 0;");\r
984 \r
985                         body = inst.getBody();\r
986                         body.editorId = editor_id;\r
987                 }\r
988 \r
989                 content = tinyMCE.cleanupHTMLCode(content);\r
990 \r
991                 // Fix for bug #958637\r
992                 if (!tinyMCE.isIE) {\r
993                         contentElement = inst.getDoc().createElement("body");\r
994                         doc = inst.getDoc();\r
995 \r
996                         contentElement.innerHTML = content;\r
997 \r
998                         if (tinyMCE.settings.cleanup_on_startup)\r
999                                 tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, doc, this.settings, contentElement));\r
1000                         else\r
1001                                 tinyMCE.setInnerHTML(inst.getBody(), content);\r
1002 \r
1003                         tinyMCE.convertAllRelativeURLs(inst.getBody());\r
1004                 } else {\r
1005                         if (tinyMCE.settings.cleanup_on_startup) {\r
1006                                 tinyMCE._setHTML(inst.getDoc(), content);\r
1007 \r
1008                                 // Produces permission denied error in MSIE 5.5\r
1009                                 try {\r
1010                                         tinyMCE.setInnerHTML(inst.getBody(), tinyMCE._cleanupHTML(inst, inst.contentDocument, this.settings, inst.getBody()));\r
1011                                 } catch(e) {\r
1012                                         // Ignore\r
1013                                 }\r
1014                         } else\r
1015                                 tinyMCE._setHTML(inst.getDoc(), content);\r
1016                 }\r
1017 \r
1018                 // Fix for bug #957681\r
1019                 //inst.getDoc().designMode = inst.getDoc().designMode;\r
1020 \r
1021                 tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings.visual, inst);\r
1022                 tinyMCE.dispatchCallback(inst, 'setupcontent_callback', 'setupContent', editor_id, inst.getBody(), inst.getDoc());\r
1023 \r
1024                 // Re-add design mode on mozilla\r
1025                 if (!tinyMCE.isIE)\r
1026                         tinyMCE.addEventHandlers(inst);\r
1027 \r
1028                 // Add blur handler\r
1029                 if (tinyMCE.isIE) {\r
1030                         tinyMCE.addEvent(inst.getBody(), "blur", TinyMCE_Engine.prototype._eventPatch);\r
1031                         tinyMCE.addEvent(inst.getBody(), "beforedeactivate", TinyMCE_Engine.prototype._eventPatch); // Bug #1439953\r
1032 \r
1033                         // Workaround for drag drop/copy paste base href bug\r
1034                         if (!tinyMCE.isOpera) {\r
1035                                 tinyMCE.addEvent(doc.body, "mousemove", TinyMCE_Engine.prototype.onMouseMove);\r
1036                                 tinyMCE.addEvent(doc.body, "beforepaste", TinyMCE_Engine.prototype._eventPatch);\r
1037                                 tinyMCE.addEvent(doc.body, "drop", TinyMCE_Engine.prototype._eventPatch);\r
1038                         }\r
1039                 }\r
1040 \r
1041                 // Trigger node change, this call locks buttons for tables and so forth\r
1042                 inst.select();\r
1043                 tinyMCE.selectedElement = inst.contentWindow.document.body;\r
1044 \r
1045                 // Call custom DOM cleanup\r
1046                 tinyMCE._customCleanup(inst, "insert_to_editor_dom", inst.getBody());\r
1047                 tinyMCE._customCleanup(inst, "setup_content_dom", inst.getBody());\r
1048                 tinyMCE._setEventsEnabled(inst.getBody(), false);\r
1049                 tinyMCE.cleanupAnchors(inst.getDoc());\r
1050 \r
1051                 if (tinyMCE.getParam("convert_fonts_to_spans"))\r
1052                         tinyMCE.convertSpansToFonts(inst.getDoc());\r
1053 \r
1054                 inst.startContent = tinyMCE.trim(inst.getBody().innerHTML);\r
1055                 inst.undoRedo.add({ content : inst.startContent });\r
1056 \r
1057                 // Cleanup any mess left from storyAwayURLs\r
1058                 if (tinyMCE.isGecko) {\r
1059                         // Remove mce_src from textnodes and comments\r
1060                         tinyMCE.selectNodes(inst.getBody(), function(n) {\r
1061                                 if (n.nodeType == 3 || n.nodeType == 8)\r
1062                                         n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");\r
1063 \r
1064                                 return false;\r
1065                         });\r
1066                 }\r
1067 \r
1068                 // Remove Gecko spellchecking\r
1069                 if (tinyMCE.isGecko)\r
1070                         inst.getBody().spellcheck = tinyMCE.getParam("gecko_spellcheck");\r
1071 \r
1072                 // Cleanup any mess left from storyAwayURLs\r
1073                 tinyMCE._removeInternal(inst.getBody());\r
1074 \r
1075                 inst.select();\r
1076                 tinyMCE.triggerNodeChange(false, true);\r
1077         },\r
1078 \r
1079         storeAwayURLs : function(s) {\r
1080                 // Remove all mce_src, mce_href and replace them with new ones\r
1081                 // s = s.replace(new RegExp('mce_src\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');\r
1082                 // s = s.replace(new RegExp('mce_href\\s*=\\s*\"[^ >\"]*\"', 'gi'), '');\r
1083 \r
1084                 if (!s.match(/(mce_src|mce_href)/gi, s)) {\r
1085                         s = s.replace(new RegExp('src\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'src="$1" mce_src="$1"');\r
1086                         s = s.replace(new RegExp('href\\s*=\\s*\"([^ >\"]*)\"', 'gi'), 'href="$1" mce_href="$1"');\r
1087                 }\r
1088 \r
1089                 return s;\r
1090         },\r
1091 \r
1092         _removeInternal : function(n) {\r
1093                 if (tinyMCE.isGecko) {\r
1094                         // Remove mce_src from textnodes and comments\r
1095                         tinyMCE.selectNodes(n, function(n) {\r
1096                                 if (n.nodeType == 3 || n.nodeType == 8)\r
1097                                         n.nodeValue = n.nodeValue.replace(new RegExp('\\s(mce_src|mce_href)=\"[^\"]*\"', 'gi'), "");\r
1098 \r
1099                                 return false;\r
1100                         });\r
1101                 }\r
1102         },\r
1103 \r
1104         removeTinyMCEFormElements : function(form_obj) {\r
1105                 var i, elementId;\r
1106 \r
1107                 // Skip form element removal\r
1108                 if (!tinyMCE.getParam('hide_selects_on_submit'))\r
1109                         return;\r
1110 \r
1111                 // Check if form is valid\r
1112                 if (typeof(form_obj) == "undefined" || form_obj == null)\r
1113                         return;\r
1114 \r
1115                 // If not a form, find the form\r
1116                 if (form_obj.nodeName != "FORM") {\r
1117                         if (form_obj.form)\r
1118                                 form_obj = form_obj.form;\r
1119                         else\r
1120                                 form_obj = tinyMCE.getParentElement(form_obj, "form");\r
1121                 }\r
1122 \r
1123                 // Still nothing\r
1124                 if (form_obj == null)\r
1125                         return;\r
1126 \r
1127                 // Disable all UI form elements that TinyMCE created\r
1128                 for (i=0; i<form_obj.elements.length; i++) {\r
1129                         elementId = form_obj.elements[i].name ? form_obj.elements[i].name : form_obj.elements[i].id;\r
1130 \r
1131                         if (elementId.indexOf('mce_editor_') == 0)\r
1132                                 form_obj.elements[i].disabled = true;\r
1133                 }\r
1134         },\r
1135 \r
1136         handleEvent : function(e) {\r
1137                 var inst = tinyMCE.selectedInstance, i, elm, keys;\r
1138 \r
1139                 // Remove odd, error\r
1140                 if (typeof(tinyMCE) == "undefined")\r
1141                         return true;\r
1142 \r
1143                 //tinyMCE.debug(e.type + " " + e.target.nodeName + " " + (e.relatedTarget ? e.relatedTarget.nodeName : ""));\r
1144 \r
1145                 if (tinyMCE.executeCallback(tinyMCE.selectedInstance, 'handle_event_callback', 'handleEvent', e))\r
1146                         return false;\r
1147 \r
1148                 switch (e.type) {\r
1149                         case "beforedeactivate": // Was added due to bug #1439953\r
1150                         case "blur":\r
1151                                 if (tinyMCE.selectedInstance)\r
1152                                         tinyMCE.selectedInstance.execCommand('mceEndTyping');\r
1153 \r
1154                                 tinyMCE.hideMenus();\r
1155 \r
1156                                 return;\r
1157 \r
1158                         // Workaround for drag drop/copy paste base href bug\r
1159                         case "drop":\r
1160                         case "beforepaste":\r
1161                                 if (tinyMCE.selectedInstance)\r
1162                                         tinyMCE.selectedInstance.setBaseHREF(null);\r
1163 \r
1164                                 // Fixes odd MSIE bug where drag/droping elements in a iframe with height 100% breaks\r
1165                                 // This logic forces the width/height to be in pixels while the user is drag/dropping\r
1166                                 if (tinyMCE.isRealIE) {\r
1167                                         var ife = tinyMCE.selectedInstance.iframeElement;\r
1168 \r
1169                                         /*if (ife.style.width.indexOf('%') != -1) {\r
1170                                                 ife._oldWidth = ife.width.height;\r
1171                                                 ife.style.width = ife.clientWidth;\r
1172                                         }*/\r
1173 \r
1174                                         if (ife.style.height.indexOf('%') != -1) {\r
1175                                                 ife._oldHeight = ife.style.height;\r
1176                                                 ife.style.height = ife.clientHeight;\r
1177                                         }\r
1178                                 }\r
1179 \r
1180                                 window.setTimeout("tinyMCE.selectedInstance.setBaseHREF(tinyMCE.settings.base_href);tinyMCE._resetIframeHeight();", 1);\r
1181                                 return;\r
1182 \r
1183                         case "submit":\r
1184                                 tinyMCE.formSubmit(tinyMCE.isMSIE ? window.event.srcElement : e.target);\r
1185                                 return;\r
1186 \r
1187                         case "reset":\r
1188                                 var formObj = tinyMCE.isIE ? window.event.srcElement : e.target;\r
1189 \r
1190                                 for (i=0; i<document.forms.length; i++) {\r
1191                                         if (document.forms[i] == formObj)\r
1192                                                 window.setTimeout('tinyMCE.resetForm(' + i + ');', 10);\r
1193                                 }\r
1194 \r
1195                                 return;\r
1196 \r
1197                         case "keypress":\r
1198                                 if (inst && inst.handleShortcut(e))\r
1199                                         return false;\r
1200 \r
1201                                 if (e.target.editorId) {\r
1202                                         tinyMCE.instances[e.target.editorId].select();\r
1203                                 } else {\r
1204                                         if (e.target.ownerDocument.editorId)\r
1205                                                 tinyMCE.instances[e.target.ownerDocument.editorId].select();\r
1206                                 }\r
1207 \r
1208                                 if (tinyMCE.selectedInstance)\r
1209                                         tinyMCE.selectedInstance.switchSettings();\r
1210 \r
1211                                 // Insert P element\r
1212                                 if ((tinyMCE.isGecko || tinyMCE.isOpera || tinyMCE.isSafari) && tinyMCE.settings.force_p_newlines && e.keyCode == 13 && !e.shiftKey) {\r
1213                                         // Insert P element instead of BR\r
1214                                         if (TinyMCE_ForceParagraphs._insertPara(tinyMCE.selectedInstance, e)) {\r
1215                                                 // Cancel event\r
1216                                                 tinyMCE.execCommand("mceAddUndoLevel");\r
1217                                                 return tinyMCE.cancelEvent(e);\r
1218                                         }\r
1219                                 }\r
1220 \r
1221                                 // Handle backspace\r
1222                                 if ((tinyMCE.isGecko && !tinyMCE.isSafari) && tinyMCE.settings.force_p_newlines && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {\r
1223                                         // Insert P element instead of BR\r
1224                                         if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {\r
1225                                                 // Cancel event\r
1226                                                 tinyMCE.execCommand("mceAddUndoLevel");\r
1227                                                 return tinyMCE.cancelEvent(e);\r
1228                                         }\r
1229                                 }\r
1230 \r
1231                                 // Return key pressed\r
1232                                 if (tinyMCE.isIE && tinyMCE.settings.force_br_newlines && e.keyCode == 13) {\r
1233                                         if (e.target.editorId)\r
1234                                                 tinyMCE.instances[e.target.editorId].select();\r
1235 \r
1236                                         if (tinyMCE.selectedInstance) {\r
1237                                                 var sel = tinyMCE.selectedInstance.getDoc().selection;\r
1238                                                 var rng = sel.createRange();\r
1239 \r
1240                                                 if (tinyMCE.getParentElement(rng.parentElement(), "li") != null)\r
1241                                                         return false;\r
1242 \r
1243                                                 // Cancel event\r
1244                                                 e.returnValue = false;\r
1245                                                 e.cancelBubble = true;\r
1246 \r
1247                                                 // Insert BR element\r
1248                                                 rng.pasteHTML("<br />");\r
1249                                                 rng.collapse(false);\r
1250                                                 rng.select();\r
1251 \r
1252                                                 tinyMCE.execCommand("mceAddUndoLevel");\r
1253                                                 tinyMCE.triggerNodeChange(false);\r
1254                                                 return false;\r
1255                                         }\r
1256                                 }\r
1257 \r
1258                                 // Backspace or delete\r
1259                                 if (e.keyCode == 8 || e.keyCode == 46) {\r
1260                                         tinyMCE.selectedElement = e.target;\r
1261                                         tinyMCE.linkElement = tinyMCE.getParentElement(e.target, "a");\r
1262                                         tinyMCE.imgElement = tinyMCE.getParentElement(e.target, "img");\r
1263                                         tinyMCE.triggerNodeChange(false);\r
1264                                 }\r
1265 \r
1266                                 return false;\r
1267 \r
1268                         case "keyup":\r
1269                         case "keydown":\r
1270                                 tinyMCE.hideMenus();\r
1271                                 tinyMCE.hasMouseMoved = false;\r
1272 \r
1273                                 if (inst && inst.handleShortcut(e))\r
1274                                         return false;\r
1275 \r
1276                                 inst._fixRootBlocks();\r
1277 \r
1278                                 if (inst.settings.remove_trailing_nbsp)\r
1279                                         inst._fixTrailingNbsp();\r
1280 \r
1281                                 if (e.target.editorId)\r
1282                                         tinyMCE.instances[e.target.editorId].select();\r
1283 \r
1284                                 if (tinyMCE.selectedInstance)\r
1285                                         tinyMCE.selectedInstance.switchSettings();\r
1286 \r
1287                                 inst = tinyMCE.selectedInstance;\r
1288 \r
1289                                 // Handle backspace\r
1290                                 if (tinyMCE.isGecko && tinyMCE.settings.force_p_newlines && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) {\r
1291                                         // Insert P element instead of BR\r
1292                                         if (TinyMCE_ForceParagraphs._handleBackSpace(tinyMCE.selectedInstance, e.type)) {\r
1293                                                 // Cancel event\r
1294                                                 tinyMCE.execCommand("mceAddUndoLevel");\r
1295                                                 e.preventDefault();\r
1296                                                 return false;\r
1297                                         }\r
1298                                 }\r
1299 \r
1300                                 tinyMCE.selectedElement = null;\r
1301                                 tinyMCE.selectedNode = null;\r
1302                                 elm = tinyMCE.selectedInstance.getFocusElement();\r
1303                                 tinyMCE.linkElement = tinyMCE.getParentElement(elm, "a");\r
1304                                 tinyMCE.imgElement = tinyMCE.getParentElement(elm, "img");\r
1305                                 tinyMCE.selectedElement = elm;\r
1306 \r
1307                                 // Update visualaids on tabs\r
1308                                 if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9)\r
1309                                         tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings.visual, tinyMCE.selectedInstance);\r
1310 \r
1311                                 // Fix empty elements on return/enter, check where enter occured\r
1312                                 if (tinyMCE.isIE && e.type == "keydown" && e.keyCode == 13)\r
1313                                         tinyMCE.enterKeyElement = tinyMCE.selectedInstance.getFocusElement();\r
1314 \r
1315                                 // Fix empty elements on return/enter\r
1316                                 if (tinyMCE.isIE && e.type == "keyup" && e.keyCode == 13) {\r
1317                                         elm = tinyMCE.enterKeyElement;\r
1318                                         if (elm) {\r
1319                                                 var re = new RegExp('^HR|IMG|BR$','g'); // Skip these\r
1320                                                 var dre = new RegExp('^H[1-6]$','g'); // Add double on these\r
1321 \r
1322                                                 if (!elm.hasChildNodes() && !re.test(elm.nodeName)) {\r
1323                                                         if (dre.test(elm.nodeName))\r
1324                                                                 elm.innerHTML = "&nbsp;&nbsp;";\r
1325                                                         else\r
1326                                                                 elm.innerHTML = "&nbsp;";\r
1327                                                 }\r
1328                                         }\r
1329                                 }\r
1330 \r
1331                                 // Check if it's a position key\r
1332                                 keys = tinyMCE.posKeyCodes;\r
1333                                 var posKey = false;\r
1334                                 for (i=0; i<keys.length; i++) {\r
1335                                         if (keys[i] == e.keyCode) {\r
1336                                                 posKey = true;\r
1337                                                 break;\r
1338                                         }\r
1339                                 }\r
1340 \r
1341                                 // MSIE custom key handling\r
1342                                 if (tinyMCE.isIE && tinyMCE.settings.custom_undo_redo) {\r
1343                                         keys = [8, 46]; // Backspace,Delete\r
1344 \r
1345                                         for (i=0; i<keys.length; i++) {\r
1346                                                 if (keys[i] == e.keyCode) {\r
1347                                                         if (e.type == "keyup")\r
1348                                                                 tinyMCE.triggerNodeChange(false);\r
1349                                                 }\r
1350                                         }\r
1351                                 }\r
1352 \r
1353                                 // If Ctrl key\r
1354                                 if (e.keyCode == 17)\r
1355                                         return true;\r
1356 \r
1357                                 // Handle Undo/Redo when typing content\r
1358 \r
1359                                 if (tinyMCE.isGecko) {\r
1360                                         // Start typing (not a position key or ctrl key, but ctrl+x and ctrl+p is ok)\r
1361                                         if (!posKey && e.type == "keyup" && !e.ctrlKey || (e.ctrlKey && (e.keyCode == 86 || e.keyCode == 88)))\r
1362                                                 tinyMCE.execCommand("mceStartTyping");\r
1363                                 } else {\r
1364                                         // IE seems to be working better with this setting\r
1365                                         if (!posKey && e.type == "keyup")\r
1366                                                 tinyMCE.execCommand("mceStartTyping");\r
1367                                 }\r
1368 \r
1369                                 // Store undo bookmark\r
1370                                 if (e.type == "keydown" && (posKey || e.ctrlKey) && inst)\r
1371                                         inst.undoBookmark = inst.selection.getBookmark();\r
1372 \r
1373                                 // End typing (position key) or some Ctrl event\r
1374                                 if (e.type == "keyup" && (posKey || e.ctrlKey))\r
1375                                         tinyMCE.execCommand("mceEndTyping");\r
1376 \r
1377                                 if (posKey && e.type == "keyup")\r
1378                                         tinyMCE.triggerNodeChange(false);\r
1379 \r
1380                                 if (tinyMCE.isIE && e.ctrlKey)\r
1381                                         window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);\r
1382                         break;\r
1383 \r
1384                         case "mousedown":\r
1385                         case "mouseup":\r
1386                         case "click":\r
1387                         case "dblclick":\r
1388                         case "focus":\r
1389                                 tinyMCE.hideMenus();\r
1390 \r
1391                                 if (tinyMCE.selectedInstance) {\r
1392                                         tinyMCE.selectedInstance.switchSettings();\r
1393                                         tinyMCE.selectedInstance.isFocused = true;\r
1394                                 }\r
1395 \r
1396                                 // Check instance event trigged on\r
1397                                 var targetBody = tinyMCE.getParentElement(e.target, "html");\r
1398                                 for (var instanceName in tinyMCE.instances) {\r
1399                                         if (!tinyMCE.isInstance(tinyMCE.instances[instanceName]))\r
1400                                                 continue;\r
1401 \r
1402                                         inst = tinyMCE.instances[instanceName];\r
1403 \r
1404                                         // Reset design mode if lost (on everything just in case)\r
1405                                         inst.autoResetDesignMode();\r
1406 \r
1407                                         // Use HTML element since users might click outside of body element\r
1408                                         if (inst.getBody().parentNode == targetBody) {\r
1409                                                 inst.select();\r
1410                                                 tinyMCE.selectedElement = e.target;\r
1411                                                 tinyMCE.linkElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "a");\r
1412                                                 tinyMCE.imgElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "img");\r
1413                                                 break;\r
1414                                         }\r
1415                                 }\r
1416 \r
1417                                 // Add first bookmark location\r
1418                                 if (!tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark && (e.type == "mouseup" || e.type == "dblclick"))\r
1419                                         tinyMCE.selectedInstance.undoRedo.undoLevels[0].bookmark = tinyMCE.selectedInstance.selection.getBookmark();\r
1420 \r
1421                                 // Reset selected node\r
1422                                 if (e.type != "focus")\r
1423                                         tinyMCE.selectedNode = null;\r
1424 \r
1425                                 tinyMCE.triggerNodeChange(false);\r
1426                                 tinyMCE.execCommand("mceEndTyping");\r
1427 \r
1428                                 if (e.type == "mouseup")\r
1429                                         tinyMCE.execCommand("mceAddUndoLevel");\r
1430 \r
1431                                 // Just in case\r
1432                                 if (!tinyMCE.selectedInstance && e.target.editorId)\r
1433                                         tinyMCE.instances[e.target.editorId].select();\r
1434 \r
1435                                 return false;\r
1436                 }\r
1437         },\r
1438 \r
1439         getButtonHTML : function(id, lang, img, cmd, ui, val) {\r
1440                 var h = '', m, x, io = '';\r
1441 \r
1442                 cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';\r
1443 \r
1444                 if (typeof(ui) != "undefined" && ui != null)\r
1445                         cmd += ',' + ui;\r
1446 \r
1447                 if (typeof(val) != "undefined" && val != null)\r
1448                         cmd += ",'" + val + "'";\r
1449 \r
1450                 cmd += ');';\r
1451 \r
1452                 // Patch for IE7 bug with hover out not restoring correctly\r
1453                 if (tinyMCE.isRealIE)\r
1454                         io = 'onmouseover="tinyMCE.lastHover = this;"';\r
1455 \r
1456                 // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled\r
1457                 if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = this.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {\r
1458                         // Tiled button\r
1459                         x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);\r
1460                         h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceTiledButton mceButtonNormal" target="_self">';\r
1461                         h += '<img src="{$themeurl}/images/spacer.gif" style="background-position: ' + x + 'px 0" alt="{$'+lang+'}" title="{$' + lang + '}" />';\r
1462                         h += '</a>';\r
1463                 } else {\r
1464                         // Normal button\r
1465                         h += '<a id="{$editor_id}_' + id + '" href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" ' + io + ' class="mceButtonNormal" target="_self">';\r
1466                         h += '<img src="' + img + '" alt="{$'+lang+'}" title="{$' + lang + '}" />';\r
1467                         h += '</a>';\r
1468                 }\r
1469 \r
1470                 return h;\r
1471         },\r
1472 \r
1473         getMenuButtonHTML : function(id, lang, img, mcmd, cmd, ui, val) {\r
1474                 var h = '', m, x;\r
1475 \r
1476                 mcmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + mcmd + '\');';\r
1477                 cmd = 'tinyMCE.execInstanceCommand(\'{$editor_id}\',\'' + cmd + '\'';\r
1478 \r
1479                 if (typeof(ui) != "undefined" && ui != null)\r
1480                         cmd += ',' + ui;\r
1481 \r
1482                 if (typeof(val) != "undefined" && val != null)\r
1483                         cmd += ",'" + val + "'";\r
1484 \r
1485                 cmd += ');';\r
1486 \r
1487                 // Use tilemaps when enabled and found and never in MSIE since it loads the tile each time from cache if cahce is disabled\r
1488                 if (tinyMCE.getParam('button_tile_map') && (!tinyMCE.isIE || tinyMCE.isOpera) && (m = tinyMCE.buttonMap[id]) != null && (tinyMCE.getParam("language") == "en" || img.indexOf('$lang') == -1)) {\r
1489                         x = 0 - (m * 20) == 0 ? '0' : 0 - (m * 20);\r
1490 \r
1491                         if (tinyMCE.isRealIE)\r
1492                                 h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';\r
1493                         else\r
1494                                 h += '<span id="{$editor_id}_' + id + '" class="mceMenuButton">';\r
1495 \r
1496                         h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceTiledButton mceMenuButtonNormal" target="_self">';\r
1497                         h += '<img src="{$themeurl}/images/spacer.gif" style="width: 20px; height: 20px; background-position: ' + x + 'px 0" title="{$' + lang + '}" /></a>';\r
1498                         h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';\r
1499                         h += '</a></span>';\r
1500                 } else {\r
1501                         if (tinyMCE.isRealIE)\r
1502                                 h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton" onmouseover="tinyMCE._menuButtonEvent(\'over\',this);tinyMCE.lastHover = this;" onmouseout="tinyMCE._menuButtonEvent(\'out\',this);">';\r
1503                         else\r
1504                                 h += '<span id="{$editor_id}_' + id + '" dir="ltr" class="mceMenuButton">';\r
1505 \r
1506                         h += '<a href="javascript:' + cmd + '" onclick="' + cmd + 'return false;" onmousedown="return false;" class="mceMenuButtonNormal" target="_self">';\r
1507                         h += '<img src="' + img + '" title="{$' + lang + '}" /></a>';\r
1508                         h += '<a href="javascript:' + mcmd + '" onclick="' + mcmd + 'return false;" onmousedown="return false;"><img src="{$themeurl}/images/button_menu.gif" title="{$' + lang + '}" class="mceMenuButton" />';\r
1509                         h += '</a></span>';\r
1510                 }\r
1511 \r
1512                 return h;\r
1513         },\r
1514 \r
1515         _menuButtonEvent : function(e, o) {\r
1516                 if (o.className == 'mceMenuButtonFocus')\r
1517                         return;\r
1518 \r
1519                 if (e == 'over')\r
1520                         o.className = o.className + ' mceMenuHover';\r
1521                 else\r
1522                         o.className = o.className.replace(/\s.*$/, '');\r
1523         },\r
1524 \r
1525         addButtonMap : function(m) {\r
1526                 var i, a = m.replace(/\s+/, '').split(',');\r
1527 \r
1528                 for (i=0; i<a.length; i++)\r
1529                         this.buttonMap[a[i]] = i;\r
1530         },\r
1531 \r
1532         formSubmit : function(f, p) {\r
1533                 var n, inst, found = false;\r
1534 \r
1535                 if (f.form)\r
1536                         f = f.form;\r
1537 \r
1538                 // Is it a form that has a TinyMCE instance\r
1539                 if (tinyMCE.getParam('save_on_tinymce_forms')) {\r
1540                         for (n in tinyMCE.instances) {\r
1541                                 inst = tinyMCE.instances[n];\r
1542 \r
1543                                 if (!tinyMCE.isInstance(inst))\r
1544                                         continue;\r
1545 \r
1546                                 if (inst.formElement) {\r
1547                                         if (f == inst.formElement.form) {\r
1548                                                 found = true;\r
1549                                                 inst.isNotDirty = true;\r
1550                                         }\r
1551                                 }\r
1552                         }\r
1553                 } else\r
1554                         found  = true;\r
1555 \r
1556                 // Is valid\r
1557                 if (found) {\r
1558                         tinyMCE.removeTinyMCEFormElements(f);\r
1559                         tinyMCE.triggerSave();\r
1560                 }\r
1561 \r
1562                 // Is it patched\r
1563                 if (f.mceOldSubmit && p)\r
1564                         f.mceOldSubmit();\r
1565         },\r
1566 \r
1567         submitPatch : function() {\r
1568                 tinyMCE.formSubmit(this, true);\r
1569         },\r
1570 \r
1571         onLoad : function() {\r
1572                 var r, i, c, mode, trigger, elements, element, settings, elementId, elm;\r
1573                 var selector, deselector, elementRefAr, form;\r
1574 \r
1575                 // Wait for everything to be loaded first\r
1576                 if (tinyMCE.settings.strict_loading_mode && this.loadingIndex != -1) {\r
1577                         window.setTimeout('tinyMCE.onLoad();', 1);\r
1578                         return;\r
1579                 }\r
1580 \r
1581                 if (tinyMCE.isRealIE && window.event.type == "readystatechange" && document.readyState != "complete")\r
1582                         return true;\r
1583 \r
1584                 if (tinyMCE.isLoaded)\r
1585                         return true;\r
1586 \r
1587                 tinyMCE.isLoaded = true;\r
1588 \r
1589                 // IE produces JS error if TinyMCE is placed in a frame\r
1590                 // It seems to have something to do with the selection not beeing\r
1591                 // correctly initialized in IE so this hack solves the problem\r
1592                 if (tinyMCE.isRealIE && document.body && window.location.href != window.top.location.href) {\r
1593                         r = document.body.createTextRange();\r
1594                         r.collapse(true);\r
1595                         r.select();\r
1596                 }\r
1597 \r
1598                 tinyMCE.dispatchCallback(null, 'onpageload', 'onPageLoad');\r
1599 \r
1600                 for (c=0; c<tinyMCE.configs.length; c++) {\r
1601                         tinyMCE.settings = tinyMCE.configs[c];\r
1602 \r
1603                         selector = tinyMCE.getParam("editor_selector");\r
1604                         deselector = tinyMCE.getParam("editor_deselector");\r
1605                         elementRefAr = [];\r
1606 \r
1607                         // Add submit triggers\r
1608                         if (document.forms && tinyMCE.settings.add_form_submit_trigger && !tinyMCE.submitTriggers) {\r
1609                                 for (i=0; i<document.forms.length; i++) {\r
1610                                         form = document.forms[i];\r
1611 \r
1612                                         tinyMCE.addEvent(form, "submit", TinyMCE_Engine.prototype.handleEvent);\r
1613                                         tinyMCE.addEvent(form, "reset", TinyMCE_Engine.prototype.handleEvent);\r
1614                                         tinyMCE.submitTriggers = true; // Do it only once\r
1615 \r
1616                                         // Patch the form.submit function\r
1617                                         if (tinyMCE.settings.submit_patch) {\r
1618                                                 try {\r
1619                                                         form.mceOldSubmit = form.submit;\r
1620                                                         form.submit = TinyMCE_Engine.prototype.submitPatch;\r
1621                                                 } catch (e) {\r
1622                                                         // Do nothing\r
1623                                                 }\r
1624                                         }\r
1625                                 }\r
1626                         }\r
1627 \r
1628                         // Add editor instances based on mode\r
1629                         mode = tinyMCE.settings.mode;\r
1630                         switch (mode) {\r
1631                                 case "exact":\r
1632                                         elements = tinyMCE.getParam('elements', '', true, ',');\r
1633 \r
1634                                         for (i=0; i<elements.length; i++) {\r
1635                                                 element = tinyMCE._getElementById(elements[i]);\r
1636                                                 trigger = element ? element.getAttribute(tinyMCE.settings.textarea_trigger) : "";\r
1637 \r
1638                                                 if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(element, "class")))\r
1639                                                         continue;\r
1640 \r
1641                                                 if (trigger == "false")\r
1642                                                         continue;\r
1643 \r
1644                                                 if ((tinyMCE.settings.ask || tinyMCE.settings.convert_on_click) && element) {\r
1645                                                         elementRefAr[elementRefAr.length] = element;\r
1646                                                         continue;\r
1647                                                 }\r
1648 \r
1649                                                 if (element)\r
1650                                                         tinyMCE.addMCEControl(element, elements[i]);\r
1651                                         }\r
1652                                 break;\r
1653 \r
1654                                 case "specific_textareas":\r
1655                                 case "textareas":\r
1656                                         elements = document.getElementsByTagName("textarea");\r
1657 \r
1658                                         for (i=0; i<elements.length; i++) {\r
1659                                                 elm = elements.item(i);\r
1660                                                 trigger = elm.getAttribute(tinyMCE.settings.textarea_trigger);\r
1661 \r
1662                                                 if (selector !== '' && !new RegExp('\\b' + selector + '\\b').test(tinyMCE.getAttrib(elm, "class")))\r
1663                                                         continue;\r
1664 \r
1665                                                 if (selector !== '')\r
1666                                                         trigger = selector !== '' ? "true" : "";\r
1667 \r
1668                                                 if (new RegExp('\\b' + deselector + '\\b').test(tinyMCE.getAttrib(elm, "class")))\r
1669                                                         continue;\r
1670 \r
1671                                                 if ((mode == "specific_textareas" && trigger == "true") || (mode == "textareas" && trigger != "false"))\r
1672                                                         elementRefAr[elementRefAr.length] = elm;\r
1673                                         }\r
1674                                 break;\r
1675                         }\r
1676 \r
1677                         for (i=0; i<elementRefAr.length; i++) {\r
1678                                 element = elementRefAr[i];\r
1679                                 elementId = element.name ? element.name : element.id;\r
1680 \r
1681                                 if (tinyMCE.settings.ask || tinyMCE.settings.convert_on_click) {\r
1682                                         // Focus breaks in Mozilla\r
1683                                         if (tinyMCE.isGecko) {\r
1684                                                 settings = tinyMCE.settings;\r
1685 \r
1686                                                 tinyMCE.addEvent(element, "focus", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});\r
1687 \r
1688                                                 if (element.nodeName != "TEXTAREA" && element.nodeName != "INPUT")\r
1689                                                         tinyMCE.addEvent(element, "click", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});\r
1690                                                 // tinyMCE.addEvent(element, "mouseover", function (e) {window.setTimeout(function() {TinyMCE_Engine.prototype.confirmAdd(e, settings);}, 10);});\r
1691                                         } else {\r
1692                                                 settings = tinyMCE.settings;\r
1693 \r
1694                                                 tinyMCE.addEvent(element, "focus", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });\r
1695                                                 tinyMCE.addEvent(element, "click", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });\r
1696                                                 // tinyMCE.addEvent(element, "mouseenter", function () { TinyMCE_Engine.prototype.confirmAdd(null, settings); });\r
1697                                         }\r
1698                                 } else\r
1699                                         tinyMCE.addMCEControl(element, elementId);\r
1700                         }\r
1701 \r
1702                         // Handle auto focus\r
1703                         if (tinyMCE.settings.auto_focus) {\r
1704                                 window.setTimeout(function () {\r
1705                                         var inst = tinyMCE.getInstanceById(tinyMCE.settings.auto_focus);\r
1706                                         inst.selection.selectNode(inst.getBody(), true, true);\r
1707                                         inst.contentWindow.focus();\r
1708                                 }, 100);\r
1709                         }\r
1710 \r
1711                         tinyMCE.dispatchCallback(null, 'oninit', 'onInit');\r
1712                 }\r
1713         },\r
1714 \r
1715         isInstance : function(o) {\r
1716                 return o != null && typeof(o) == "object" && o.isTinyMCE_Control;\r
1717         },\r
1718 \r
1719         getParam : function(name, default_value, strip_whitespace, split_chr) {\r
1720                 var i, outArray, value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name];\r
1721 \r
1722                 // Fix bool values\r
1723                 if (value == "true" || value == "false")\r
1724                         return (value == "true");\r
1725 \r
1726                 if (strip_whitespace)\r
1727                         value = tinyMCE.regexpReplace(value, "[ \t\r\n]", "");\r
1728 \r
1729                 if (typeof(split_chr) != "undefined" && split_chr != null) {\r
1730                         value = value.split(split_chr);\r
1731                         outArray = [];\r
1732 \r
1733                         for (i=0; i<value.length; i++) {\r
1734                                 if (value[i] && value[i] !== '')\r
1735                                         outArray[outArray.length] = value[i];\r
1736                         }\r
1737 \r
1738                         value = outArray;\r
1739                 }\r
1740 \r
1741                 return value;\r
1742         },\r
1743 \r
1744         getLang : function(name, default_value, parse_entities, va) {\r
1745                 var v = (typeof(tinyMCELang[name]) == "undefined") ? default_value : tinyMCELang[name], n;\r
1746 \r
1747                 if (parse_entities)\r
1748                         v = tinyMCE.entityDecode(v);\r
1749 \r
1750                 if (va) {\r
1751                         for (n in va)\r
1752                                 v = this.replaceVar(v, n, va[n]);\r
1753                 }\r
1754 \r
1755                 return v;\r
1756         },\r
1757 \r
1758         entityDecode : function(s) {\r
1759                 var e = document.createElement("div");\r
1760 \r
1761                 e.innerHTML = s;\r
1762 \r
1763                 return !e.firstChild ? s : e.firstChild.nodeValue;\r
1764         },\r
1765 \r
1766         addToLang : function(prefix, ar) {\r
1767                 var k;\r
1768 \r
1769                 for (k in ar) {\r
1770                         if (typeof(ar[k]) == 'function')\r
1771                                 continue;\r
1772 \r
1773                         tinyMCELang[(k.indexOf('lang_') == -1 ? 'lang_' : '') + (prefix !== '' ? (prefix + "_") : '') + k] = ar[k];\r
1774                 }\r
1775 \r
1776                 this.loadNextScript();\r
1777         },\r
1778 \r
1779         triggerNodeChange : function(focus, setup_content) {\r
1780                 var elm, inst, editorId, undoIndex = -1, undoLevels = -1, doc, anySelection = false, st;\r
1781 \r
1782                 if (tinyMCE.selectedInstance) {\r
1783                         inst = tinyMCE.selectedInstance;\r
1784                         elm = (typeof(setup_content) != "undefined" && setup_content) ? tinyMCE.selectedElement : inst.getFocusElement();\r
1785 \r
1786 /*                      if (elm == inst.lastTriggerEl)\r
1787                                 return;\r
1788 \r
1789                         inst.lastTriggerEl = elm;*/\r
1790 \r
1791                         editorId = inst.editorId;\r
1792                         st = inst.selection.getSelectedText();\r
1793 \r
1794                         if (tinyMCE.settings.auto_resize)\r
1795                                 inst.resizeToContent();\r
1796 \r
1797                         if (setup_content && tinyMCE.isGecko && inst.isHidden())\r
1798                                 elm = inst.getBody();\r
1799 \r
1800                         inst.switchSettings();\r
1801 \r
1802                         if (tinyMCE.selectedElement)\r
1803                                 anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (st && st.length > 0);\r
1804 \r
1805                         if (tinyMCE.settings.custom_undo_redo) {\r
1806                                 undoIndex = inst.undoRedo.undoIndex;\r
1807                                 undoLevels = inst.undoRedo.undoLevels.length;\r
1808                         }\r
1809 \r
1810                         tinyMCE.dispatchCallback(inst, 'handle_node_change_callback', 'handleNodeChange', editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection, setup_content);\r
1811                 }\r
1812 \r
1813                 if (this.selectedInstance && (typeof(focus) == "undefined" || focus))\r
1814                         this.selectedInstance.contentWindow.focus();\r
1815         },\r
1816 \r
1817         _customCleanup : function(inst, type, content) {\r
1818                 var pl, po, i, customCleanup;\r
1819 \r
1820                 // Call custom cleanup\r
1821                 customCleanup = tinyMCE.settings.cleanup_callback;\r
1822                 if (customCleanup != '')\r
1823                         content = tinyMCE.resolveDots(tinyMCE.settings.cleanup_callback, window)(type, content, inst);\r
1824 \r
1825                 // Trigger theme cleanup\r
1826                 po = tinyMCE.themes[tinyMCE.settings.theme];\r
1827                 if (po && po.cleanup)\r
1828                         content = po.cleanup(type, content, inst);\r
1829 \r
1830                 // Trigger plugin cleanups\r
1831                 pl = inst.plugins;\r
1832                 for (i=0; i<pl.length; i++) {\r
1833                         po = tinyMCE.plugins[pl[i]];\r
1834 \r
1835                         if (po && po.cleanup)\r
1836                                 content = po.cleanup(type, content, inst);\r
1837                 }\r
1838 \r
1839                 return content;\r
1840         },\r
1841 \r
1842         setContent : function(h) {\r
1843                 if (tinyMCE.selectedInstance) {\r
1844                         tinyMCE.selectedInstance.execCommand('mceSetContent', false, h);\r
1845                         tinyMCE.selectedInstance.repaint();\r
1846                 }\r
1847         },\r
1848 \r
1849         importThemeLanguagePack : function(name) {\r
1850                 if (typeof(name) == "undefined")\r
1851                         name = tinyMCE.settings.theme;\r
1852 \r
1853                 tinyMCE.loadScript(tinyMCE.baseURL + '/themes/' + name + '/langs/' + tinyMCE.settings.language + '.js');\r
1854         },\r
1855 \r
1856         importPluginLanguagePack : function(name) {\r
1857                 var b = tinyMCE.baseURL + '/plugins/' + name;\r
1858 \r
1859                 if (this.plugins[name])\r
1860                         b = this.plugins[name].baseURL;\r
1861 \r
1862                 tinyMCE.loadScript(b + '/langs/' + tinyMCE.settings.language +  '.js');\r
1863         },\r
1864 \r
1865         applyTemplate : function(h, ag) {\r
1866                 return h.replace(new RegExp('\\{\\$([a-z0-9_]+)\\}', 'gi'), function(m, s) {\r
1867                         if (s.indexOf('lang_') == 0 && tinyMCELang[s])\r
1868                                 return tinyMCELang[s];\r
1869 \r
1870                         if (ag && ag[s])\r
1871                                 return ag[s];\r
1872 \r
1873                         if (tinyMCE.settings[s])\r
1874                                 return tinyMCE.settings[s];\r
1875 \r
1876                         if (m == 'themeurl')\r
1877                                 return tinyMCE.themeURL;\r
1878 \r
1879                         return m;\r
1880                 });\r
1881         },\r
1882 \r
1883         replaceVar : function(h, r, v) {\r
1884                 return h.replace(new RegExp('{\\\$' + r + '}', 'g'), v);\r
1885         },\r
1886 \r
1887         openWindow : function(template, args) {\r
1888                 var html, width, height, x, y, resizable, scrollbars, url, name, win, modal, features;\r
1889 \r
1890                 args = !args ? {} : args;\r
1891 \r
1892                 args.mce_template_file = template.file;\r
1893                 args.mce_width = template.width;\r
1894                 args.mce_height = template.height;\r
1895                 tinyMCE.windowArgs = args;\r
1896 \r
1897                 html = template.html;\r
1898                 if (!(width = parseInt(template.width)))\r
1899                         width = 320;\r
1900 \r
1901                 if (!(height = parseInt(template.height)))\r
1902                         height = 200;\r
1903 \r
1904                 // Add to height in M$ due to SP2 WHY DON'T YOU GUYS IMPLEMENT innerWidth of windows!!\r
1905                 if (tinyMCE.isIE)\r
1906                         height += 40;\r
1907                 else\r
1908                         height += 20;\r
1909 \r
1910                 x = parseInt(screen.width / 2.0) - (width / 2.0);\r
1911                 y = parseInt(screen.height / 2.0) - (height / 2.0);\r
1912 \r
1913                 resizable = (args && args.resizable) ? args.resizable : "no";\r
1914                 scrollbars = (args && args.scrollbars) ? args.scrollbars : "no";\r
1915 \r
1916                 if (template.file.charAt(0) != '/' && template.file.indexOf('://') == -1)\r
1917                         url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template.file;\r
1918                 else\r
1919                         url = template.file;\r
1920 \r
1921                 // Replace all args as variables in URL\r
1922                 for (name in args) {\r
1923                         if (typeof(args[name]) == 'function')\r
1924                                 continue;\r
1925 \r
1926                         url = tinyMCE.replaceVar(url, name, escape(args[name]));\r
1927                 }\r
1928 \r
1929                 if (html) {\r
1930                         html = tinyMCE.replaceVar(html, "css", this.settings.popups_css);\r
1931                         html = tinyMCE.applyTemplate(html, args);\r
1932 \r
1933                         win = window.open("", "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,minimizable=" + resizable + ",modal=yes,width=" + width + ",height=" + height + ",resizable=" + resizable);\r
1934                         if (win == null) {\r
1935                                 alert(tinyMCELang.lang_popup_blocked);\r
1936                                 return;\r
1937                         }\r
1938 \r
1939                         win.document.write(html);\r
1940                         win.document.close();\r
1941                         win.resizeTo(width, height);\r
1942                         win.focus();\r
1943                 } else {\r
1944                         if ((tinyMCE.isRealIE) && resizable != 'yes' && tinyMCE.settings.dialog_type == "modal") {\r
1945                                 height += 10;\r
1946 \r
1947                                 features = "resizable:" + resizable + ";scroll:" + scrollbars + ";status:yes;center:yes;help:no;dialogWidth:" + width + "px;dialogHeight:" + height + "px;";\r
1948 \r
1949                                 window.showModalDialog(url, window, features);\r
1950                         } else {\r
1951                                 modal = (resizable == "yes") ? "no" : "yes";\r
1952 \r
1953                                 if (tinyMCE.isGecko && tinyMCE.isMac)\r
1954                                         modal = "no";\r
1955 \r
1956                                 if (template.close_previous != "no")\r
1957                                         try {tinyMCE.lastWindow.close();} catch (ex) {}\r
1958 \r
1959                                 win = window.open(url, "mcePopup" + new Date().getTime(), "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=" + modal + ",minimizable=" + resizable + ",modal=" + modal + ",width=" + width + ",height=" + height + ",resizable=" + resizable);\r
1960                                 if (win == null) {\r
1961                                         alert(tinyMCELang.lang_popup_blocked);\r
1962                                         return;\r
1963                                 }\r
1964 \r
1965                                 if (template.close_previous != "no")\r
1966                                         tinyMCE.lastWindow = win;\r
1967 \r
1968                                 try {\r
1969                                         win.resizeTo(width, height);\r
1970                                 } catch(e) {\r
1971                                         // Ignore\r
1972                                 }\r
1973 \r
1974                                 // Make it bigger if statusbar is forced\r
1975                                 if (tinyMCE.isGecko) {\r
1976                                         if (win.document.defaultView.statusbar.visible)\r
1977                                                 win.resizeBy(0, tinyMCE.isMac ? 10 : 24);\r
1978                                 }\r
1979 \r
1980                                 win.focus();\r
1981                         }\r
1982                 }\r
1983         },\r
1984 \r
1985         closeWindow : function(win) {\r
1986                 win.close();\r
1987         },\r
1988 \r
1989         getVisualAidClass : function(class_name, state) {\r
1990                 var i, classNames, ar, className, aidClass = tinyMCE.settings.visual_table_class;\r
1991 \r
1992                 if (typeof(state) == "undefined")\r
1993                         state = tinyMCE.settings.visual;\r
1994 \r
1995                 // Split\r
1996                 classNames = [];\r
1997                 ar = class_name.split(' ');\r
1998                 for (i=0; i<ar.length; i++) {\r
1999                         if (ar[i] == aidClass)\r
2000                                 ar[i] = "";\r
2001 \r
2002                         if (ar[i] !== '')\r
2003                                 classNames[classNames.length] = ar[i];\r
2004                 }\r
2005 \r
2006                 if (state)\r
2007                         classNames[classNames.length] = aidClass;\r
2008 \r
2009                 // Glue\r
2010                 className = "";\r
2011                 for (i=0; i<classNames.length; i++) {\r
2012                         if (i > 0)\r
2013                                 className += " ";\r
2014 \r
2015                         className += classNames[i];\r
2016                 }\r
2017 \r
2018                 return className;\r
2019         },\r
2020 \r
2021         handleVisualAid : function(el, deep, state, inst, skip_dispatch) {\r
2022                 var i, x, y, tableElement, anchorName, oldW, oldH, bo, cn;\r
2023 \r
2024                 if (!el)\r
2025                         return;\r
2026 \r
2027                 if (!skip_dispatch)\r
2028                         tinyMCE.dispatchCallback(inst, 'handle_visual_aid_callback', 'handleVisualAid', el, deep, state, inst);\r
2029 \r
2030                 tableElement = null;\r
2031 \r
2032                 switch (el.nodeName) {\r
2033                         case "TABLE":\r
2034                                 oldW = el.style.width;\r
2035                                 oldH = el.style.height;\r
2036                                 bo = tinyMCE.getAttrib(el, "border");\r
2037 \r
2038                                 bo = bo == '' || bo == "0" ? true : false;\r
2039 \r
2040                                 tinyMCE.setAttrib(el, "class", tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el, "class"), state && bo));\r
2041 \r
2042                                 el.style.width = oldW;\r
2043                                 el.style.height = oldH;\r
2044 \r
2045                                 for (y=0; y<el.rows.length; y++) {\r
2046                                         for (x=0; x<el.rows[y].cells.length; x++) {\r
2047                                                 cn = tinyMCE.getVisualAidClass(tinyMCE.getAttrib(el.rows[y].cells[x], "class"), state && bo);\r
2048                                                 tinyMCE.setAttrib(el.rows[y].cells[x], "class", cn);\r
2049                                         }\r
2050                                 }\r
2051 \r
2052                                 break;\r
2053 \r
2054                         case "A":\r
2055                                 anchorName = tinyMCE.getAttrib(el, "name");\r
2056 \r
2057                                 if (anchorName !== '' && state) {\r
2058                                         el.title = anchorName;\r
2059                                         tinyMCE.addCSSClass(el, 'mceItemAnchor');\r
2060                                 } else if (anchorName !== '' && !state)\r
2061                                         el.className = '';\r
2062 \r
2063                                 break;\r
2064                 }\r
2065 \r
2066                 if (deep && el.hasChildNodes()) {\r
2067                         for (i=0; i<el.childNodes.length; i++)\r
2068                                 tinyMCE.handleVisualAid(el.childNodes[i], deep, state, inst, true);\r
2069                 }\r
2070         },\r
2071 \r
2072         fixGeckoBaseHREFBug : function(m, e, h) {\r
2073                 var xsrc, xhref;\r
2074 \r
2075                 if (tinyMCE.isGecko) {\r
2076                         if (m == 1) {\r
2077                                 h = h.replace(/\ssrc=/gi, " mce_tsrc=");\r
2078                                 h = h.replace(/\shref=/gi, " mce_thref=");\r
2079 \r
2080                                 return h;\r
2081                         } else {\r
2082                                 // Why bother if there is no src or href broken\r
2083                                 if (!new RegExp('(src|href)=', 'g').test(h))\r
2084                                         return h;\r
2085 \r
2086                                 // Restore src and href that gets messed up by Gecko\r
2087                                 tinyMCE.selectElements(e, 'A,IMG,SELECT,AREA,IFRAME,BASE,INPUT,SCRIPT,EMBED,OBJECT,LINK', function (n) {\r
2088                                         xsrc = tinyMCE.getAttrib(n, "mce_tsrc");\r
2089                                         xhref = tinyMCE.getAttrib(n, "mce_thref");\r
2090 \r
2091                                         if (xsrc !== '') {\r
2092                                                 try {\r
2093                                                         n.src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, xsrc);\r
2094                                                 } catch (e) {\r
2095                                                         // Ignore, Firefox cast exception if local file wasn't found\r
2096                                                 }\r
2097 \r
2098                                                 n.removeAttribute("mce_tsrc");\r
2099                                         }\r
2100 \r
2101                                         if (xhref !== '') {\r
2102                                                 try {\r
2103                                                         n.href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, xhref);\r
2104                                                 } catch (e) {\r
2105                                                         // Ignore, Firefox cast exception if local file wasn't found\r
2106                                                 }\r
2107 \r
2108                                                 n.removeAttribute("mce_thref");\r
2109                                         }\r
2110 \r
2111                                         return false;\r
2112                                 });\r
2113 \r
2114                                 // Restore text/comment nodes\r
2115                                 tinyMCE.selectNodes(e, function(n) {\r
2116                                         if (n.nodeType == 3 || n.nodeType == 8) {\r
2117                                                 n.nodeValue = n.nodeValue.replace(/\smce_tsrc=/gi, " src=");\r
2118                                                 n.nodeValue = n.nodeValue.replace(/\smce_thref=/gi, " href=");\r
2119                                         }\r
2120 \r
2121                                         return false;\r
2122                                 });\r
2123                         }\r
2124                 }\r
2125 \r
2126                 return h;\r
2127         },\r
2128 \r
2129         _setHTML : function(doc, html_content) {\r
2130                 var i, html, paras, node;\r
2131 \r
2132                 // Force closed anchors open\r
2133                 //html_content = html_content.replace(new RegExp('<a(.*?)/>', 'gi'), '<a$1></a>');\r
2134 \r
2135                 html_content = tinyMCE.cleanupHTMLCode(html_content);\r
2136 \r
2137                 // Try innerHTML if it fails use pasteHTML in MSIE\r
2138                 try {\r
2139                         tinyMCE.setInnerHTML(doc.body, html_content);\r
2140                 } catch (e) {\r
2141                         if (this.isMSIE)\r
2142                                 doc.body.createTextRange().pasteHTML(html_content);\r
2143                 }\r
2144 \r
2145                 // Content duplication bug fix\r
2146                 if (tinyMCE.isIE && tinyMCE.settings.fix_content_duplication) {\r
2147                         // Remove P elements in P elements\r
2148                         paras = doc.getElementsByTagName("P");\r
2149                         for (i=0; i<paras.length; i++) {\r
2150                                 node = paras[i];\r
2151 \r
2152                                 while ((node = node.parentNode) != null) {\r
2153                                         if (node.nodeName == "P")\r
2154                                                 node.outerHTML = node.innerHTML;\r
2155                                 }\r
2156                         }\r
2157 \r
2158                         // Content duplication bug fix (Seems to be word crap)\r
2159                         html = doc.body.innerHTML;\r
2160 \r
2161                         // Always set the htmlText output\r
2162                         tinyMCE.setInnerHTML(doc.body, html);\r
2163                 }\r
2164 \r
2165                 tinyMCE.cleanupAnchors(doc);\r
2166 \r
2167                 if (tinyMCE.getParam("convert_fonts_to_spans"))\r
2168                         tinyMCE.convertSpansToFonts(doc);\r
2169         },\r
2170 \r
2171         getEditorId : function(form_element) {\r
2172                 var inst = this.getInstanceById(form_element);\r
2173 \r
2174                 if (!inst)\r
2175                         return null;\r
2176 \r
2177                 return inst.editorId;\r
2178         },\r
2179 \r
2180         getInstanceById : function(editor_id) {\r
2181                 var inst = this.instances[editor_id], n;\r
2182 \r
2183                 if (!inst) {\r
2184                         for (n in tinyMCE.instances) {\r
2185                                 inst = tinyMCE.instances[n];\r
2186 \r
2187                                 if (!tinyMCE.isInstance(inst))\r
2188                                         continue;\r
2189 \r
2190                                 if (inst.formTargetElementId == editor_id)\r
2191                                         return inst;\r
2192                         }\r
2193                 } else\r
2194                         return inst;\r
2195 \r
2196                 return null;\r
2197         },\r
2198 \r
2199         queryInstanceCommandValue : function(editor_id, command) {\r
2200                 var inst = tinyMCE.getInstanceById(editor_id);\r
2201 \r
2202                 if (inst)\r
2203                         return inst.queryCommandValue(command);\r
2204 \r
2205                 return false;\r
2206         },\r
2207 \r
2208         queryInstanceCommandState : function(editor_id, command) {\r
2209                 var inst = tinyMCE.getInstanceById(editor_id);\r
2210 \r
2211                 if (inst)\r
2212                         return inst.queryCommandState(command);\r
2213 \r
2214                 return null;\r
2215         },\r
2216 \r
2217         setWindowArg : function(n, v) {\r
2218                 this.windowArgs[n] = v;\r
2219         },\r
2220 \r
2221         getWindowArg : function(n, d) {\r
2222                 return (typeof(this.windowArgs[n]) == "undefined") ? d : this.windowArgs[n];\r
2223         },\r
2224 \r
2225         getCSSClasses : function(editor_id, doc) {\r
2226                 var i, c, x, rule, styles, rules, csses, selectorText, inst = tinyMCE.getInstanceById(editor_id);\r
2227                 var cssClass, addClass, p;\r
2228 \r
2229                 if (!inst)\r
2230                         inst = tinyMCE.selectedInstance;\r
2231 \r
2232                 if (!inst)\r
2233                         return [];\r
2234 \r
2235                 if (!doc)\r
2236                         doc = inst.getDoc();\r
2237 \r
2238                 // Is cached, use that\r
2239                 if (inst && inst.cssClasses.length > 0)\r
2240                         return inst.cssClasses;\r
2241 \r
2242                 if (!doc)\r
2243                         return;\r
2244 \r
2245                 styles = doc.styleSheets;\r
2246 \r
2247                 if (styles && styles.length > 0) {\r
2248                         for (x=0; x<styles.length; x++) {\r
2249                                 csses = null;\r
2250 \r
2251                                 try {\r
2252                                         csses = tinyMCE.isIE ? doc.styleSheets(x).rules : styles[x].cssRules;\r
2253                                 } catch(e) {\r
2254                                         // Just ignore any errors I know this is ugly!!\r
2255                                 }\r
2256         \r
2257                                 if (!csses)\r
2258                                         return [];\r
2259 \r
2260                                 for (i=0; i<csses.length; i++) {\r
2261                                         selectorText = csses[i].selectorText;\r
2262 \r
2263                                         // Can be multiple rules per selector\r
2264                                         if (selectorText) {\r
2265                                                 rules = selectorText.split(',');\r
2266                                                 for (c=0; c<rules.length; c++) {\r
2267                                                         rule = rules[c];\r
2268 \r
2269                                                         // Strip spaces between selectors\r
2270                                                         while (rule.indexOf(' ') == 0)\r
2271                                                                 rule = rule.substring(1);\r
2272 \r
2273                                                         // Invalid rule\r
2274                                                         if (rule.indexOf(' ') != -1 || rule.indexOf(':') != -1 || rule.indexOf('mceItem') != -1)\r
2275                                                                 continue;\r
2276 \r
2277                                                         if (rule.indexOf(tinyMCE.settings.visual_table_class) != -1 || rule.indexOf('mceEditable') != -1 || rule.indexOf('mceNonEditable') != -1)\r
2278                                                                 continue;\r
2279 \r
2280                                                         // Is class rule\r
2281                                                         if (rule.indexOf('.') != -1) {\r
2282                                                                 cssClass = rule.substring(rule.indexOf('.') + 1);\r
2283                                                                 addClass = true;\r
2284 \r
2285                                                                 for (p=0; p<inst.cssClasses.length && addClass; p++) {\r
2286                                                                         if (inst.cssClasses[p] == cssClass)\r
2287                                                                                 addClass = false;\r
2288                                                                 }\r
2289 \r
2290                                                                 if (addClass)\r
2291                                                                         inst.cssClasses[inst.cssClasses.length] = cssClass;\r
2292                                                         }\r
2293                                                 }\r
2294                                         }\r
2295                                 }\r
2296                         }\r
2297                 }\r
2298 \r
2299                 return inst.cssClasses;\r
2300         },\r
2301 \r
2302         regexpReplace : function(in_str, reg_exp, replace_str, opts) {\r
2303                 var re;\r
2304 \r
2305                 if (in_str == null)\r
2306                         return in_str;\r
2307 \r
2308                 if (typeof(opts) == "undefined")\r
2309                         opts = 'g';\r
2310 \r
2311                 re = new RegExp(reg_exp, opts);\r
2312 \r
2313                 return in_str.replace(re, replace_str);\r
2314         },\r
2315 \r
2316         trim : function(s) {\r
2317                 return s.replace(/^\s*|\s*$/g, "");\r
2318         },\r
2319 \r
2320         cleanupEventStr : function(s) {\r
2321                 s = "" + s;\r
2322                 s = s.replace('function anonymous()\n{\n', '');\r
2323                 s = s.replace('\n}', '');\r
2324                 s = s.replace(/^return true;/gi, ''); // Remove event blocker\r
2325 \r
2326                 return s;\r
2327         },\r
2328 \r
2329         getControlHTML : function(c) {\r
2330                 var i, l, n, o, v, rtl = tinyMCE.getLang('lang_dir') == 'rtl';\r
2331 \r
2332                 l = tinyMCE.plugins;\r
2333                 for (n in l) {\r
2334                         o = l[n];\r
2335 \r
2336                         if (o.getControlHTML && (v = o.getControlHTML(c)) !== '') {\r
2337                                 if (rtl)\r
2338                                         return '<span dir="rtl">' + tinyMCE.replaceVar(v, "pluginurl", o.baseURL) + '</span>';\r
2339 \r
2340                                 return tinyMCE.replaceVar(v, "pluginurl", o.baseURL);\r
2341                         }\r
2342                 }\r
2343 \r
2344                 o = tinyMCE.themes[tinyMCE.settings.theme];\r
2345                 if (o.getControlHTML && (v = o.getControlHTML(c)) !== '') {\r
2346                         if (rtl)\r
2347                                 return '<span dir="rtl">' + v + '</span>';\r
2348 \r
2349                         return v;\r
2350                 }\r
2351 \r
2352                 return '';\r
2353         },\r
2354 \r
2355         evalFunc : function(f, idx, a, o) {\r
2356                 o = !o ? window : o;\r
2357                 f = typeof(f) == 'function' ? f : o[f];\r
2358 \r
2359                 return f.apply(o, Array.prototype.slice.call(a, idx));\r
2360         },\r
2361 \r
2362         dispatchCallback : function(i, p, n) {\r
2363                 return this.callFunc(i, p, n, 0, this.dispatchCallback.arguments);\r
2364         },\r
2365 \r
2366         executeCallback : function(i, p, n) {\r
2367                 return this.callFunc(i, p, n, 1, this.executeCallback.arguments);\r
2368         },\r
2369 \r
2370         execCommandCallback : function(i, p, n) {\r
2371                 return this.callFunc(i, p, n, 2, this.execCommandCallback.arguments);\r
2372         },\r
2373 \r
2374         callFunc : function(ins, p, n, m, a) {\r
2375                 var l, i, on, o, s, v;\r
2376 \r
2377                 s = m == 2;\r
2378 \r
2379                 l = tinyMCE.getParam(p, '');\r
2380 \r
2381                 if (l !== '' && (v = tinyMCE.evalFunc(l, 3, a)) == s && m > 0)\r
2382                         return true;\r
2383 \r
2384                 if (ins != null) {\r
2385                         for (i=0, l = ins.plugins; i<l.length; i++) {\r
2386                                 o = tinyMCE.plugins[l[i]];\r
2387 \r
2388                                 if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)\r
2389                                         return true;\r
2390                         }\r
2391                 }\r
2392 \r
2393                 l = tinyMCE.themes;\r
2394                 for (on in l) {\r
2395                         o = l[on];\r
2396 \r
2397                         if (o[n] && (v = tinyMCE.evalFunc(n, 3, a, o)) == s && m > 0)\r
2398                                 return true;\r
2399                 }\r
2400 \r
2401                 return false;\r
2402         },\r
2403 \r
2404         resolveDots : function(s, o) {\r
2405                 var i;\r
2406 \r
2407                 if (typeof(s) == 'string') {\r
2408                         for (i=0, s=s.split('.'); i<s.length; i++)\r
2409                                 o = o[s[i]];\r
2410                 } else\r
2411                         o = s;\r
2412 \r
2413                 return o;\r
2414         },\r
2415 \r
2416         xmlEncode : function(s) {\r
2417                 return s ? ('' + s).replace(this.xmlEncodeRe, function (c, b) {\r
2418                         switch (c) {\r
2419                                 case '&':\r
2420                                         return '&amp;';\r
2421 \r
2422                                 case '"':\r
2423                                         return '&quot;';\r
2424 \r
2425                                 case '<':\r
2426                                         return '&lt;';\r
2427 \r
2428                                 case '>':\r
2429                                         return '&gt;';\r
2430                         }\r
2431 \r
2432                         return c;\r
2433                 }) : s;\r
2434         },\r
2435 \r
2436         add : function(c, m) {\r
2437                 var n;\r
2438 \r
2439                 for (n in m) {\r
2440                         if (m.hasOwnProperty(n))\r
2441                                 c.prototype[n] = m[n];\r
2442                 }\r
2443         },\r
2444 \r
2445         extend : function(p, np) {\r
2446                 var o = {}, n;\r
2447 \r
2448                 o.parent = p;\r
2449 \r
2450                 for (n in p) {\r
2451                         if (p.hasOwnProperty(n))\r
2452                                 o[n] = p[n];\r
2453                 }\r
2454 \r
2455                 for (n in np) {\r
2456                         if (np.hasOwnProperty(n))\r
2457                                 o[n] = np[n];\r
2458                 }\r
2459 \r
2460                 return o;\r
2461         },\r
2462 \r
2463         hideMenus : function() {\r
2464                 var e = tinyMCE.lastSelectedMenuBtn;\r
2465 \r
2466                 if (tinyMCE.lastMenu) {\r
2467                         tinyMCE.lastMenu.hide();\r
2468                         tinyMCE.lastMenu = null;\r
2469                 }\r
2470 \r
2471                 if (e) {\r
2472                         tinyMCE.switchClass(e, tinyMCE.lastMenuBtnClass);\r
2473                         tinyMCE.lastSelectedMenuBtn = null;\r
2474                 }\r
2475         }\r
2476 \r
2477         };\r
2478 \r
2479 // Global instances\r
2480 var TinyMCE = TinyMCE_Engine; // Compatiblity with gzip compressors\r
2481 var tinyMCE = new TinyMCE_Engine();\r
2482 var tinyMCELang = {};\r
2483 \r
2484 /* file:jscripts/tiny_mce/classes/TinyMCE_Control.class.js */\r
2485 \r
2486 function TinyMCE_Control(settings) {\r
2487         var t, i, tos, fu, p, x, fn, fu, pn, s = settings;\r
2488 \r
2489         this.undoRedoLevel = true;\r
2490         this.isTinyMCE_Control = true;\r
2491 \r
2492         // Default settings\r
2493         this.enabled = true;\r
2494         this.settings = s;\r
2495         this.settings.theme = tinyMCE.getParam("theme", "default");\r
2496         this.settings.width = tinyMCE.getParam("width", -1);\r
2497         this.settings.height = tinyMCE.getParam("height", -1);\r
2498         this.selection = new TinyMCE_Selection(this);\r
2499         this.undoRedo = new TinyMCE_UndoRedo(this);\r
2500         this.cleanup = new TinyMCE_Cleanup();\r
2501         this.shortcuts = [];\r
2502         this.hasMouseMoved = false;\r
2503         this.foreColor = this.backColor = "#999999";\r
2504         this.data = {};\r
2505         this.cssClasses = [];\r
2506 \r
2507         this.cleanup.init({\r
2508                 valid_elements : s.valid_elements,\r
2509                 extended_valid_elements : s.extended_valid_elements,\r
2510                 valid_child_elements : s.valid_child_elements,\r
2511                 entities : s.entities,\r
2512                 entity_encoding : s.entity_encoding,\r
2513                 debug : s.cleanup_debug,\r
2514                 indent : s.apply_source_formatting,\r
2515                 invalid_elements : s.invalid_elements,\r
2516                 verify_html : s.verify_html,\r
2517                 fix_content_duplication : s.fix_content_duplication,\r
2518                 convert_fonts_to_spans : s.convert_fonts_to_spans\r
2519         });\r
2520 \r
2521         // Wrap old theme\r
2522         t = this.settings.theme;\r
2523         if (!tinyMCE.hasTheme(t)) {\r
2524                 fn = tinyMCE.callbacks;\r
2525                 tos = {};\r
2526 \r
2527                 for (i=0; i<fn.length; i++) {\r
2528                         if ((fu = window['TinyMCE_' + t + "_" + fn[i]]))\r
2529                                 tos[fn[i]] = fu;\r
2530                 }\r
2531 \r
2532                 tinyMCE.addTheme(t, tos);\r
2533         }\r
2534 \r
2535         // Wrap old plugins\r
2536         this.plugins = [];\r
2537         p = tinyMCE.getParam('plugins', '', true, ',');\r
2538         if (p.length > 0) {\r
2539                 for (i=0; i<p.length; i++) {\r
2540                         pn = p[i];\r
2541 \r
2542                         if (pn.charAt(0) == '-')\r
2543                                 pn = pn.substring(1);\r
2544 \r
2545                         if (!tinyMCE.hasPlugin(pn)) {\r
2546                                 fn = tinyMCE.callbacks;\r
2547                                 tos = {};\r
2548 \r
2549                                 for (x=0; x<fn.length; x++) {\r
2550                                         if ((fu = window['TinyMCE_' + pn + "_" + fn[x]]))\r
2551                                                 tos[fn[x]] = fu;\r
2552                                 }\r
2553 \r
2554                                 tinyMCE.addPlugin(pn, tos);\r
2555                         }\r
2556 \r
2557                         this.plugins[this.plugins.length] = pn; \r
2558                 }\r
2559         }\r
2560 };\r
2561 \r
2562 TinyMCE_Control.prototype = {\r
2563         selection : null,\r
2564 \r
2565         settings : null,\r
2566 \r
2567         cleanup : null,\r
2568 \r
2569         getData : function(na) {\r
2570                 var o = this.data[na];\r
2571 \r
2572                 if (!o)\r
2573                         o = this.data[na] = {};\r
2574 \r
2575                 return o;\r
2576         },\r
2577 \r
2578         hasPlugin : function(n) {\r
2579                 var i;\r
2580 \r
2581                 for (i=0; i<this.plugins.length; i++) {\r
2582                         if (this.plugins[i] == n)\r
2583                                 return true;\r
2584                 }\r
2585 \r
2586                 return false;\r
2587         },\r
2588 \r
2589         addPlugin : function(n, p) {\r
2590                 if (!this.hasPlugin(n)) {\r
2591                         tinyMCE.addPlugin(n, p);\r
2592                         this.plugins[this.plugins.length] = n;\r
2593                 }\r
2594         },\r
2595 \r
2596         repaint : function() {\r
2597                 var s, b, ex;\r
2598 \r
2599                 if (tinyMCE.isRealIE)\r
2600                         return;\r
2601 \r
2602                 try {\r
2603                         s = this.selection;\r
2604                         b = s.getBookmark(true);\r
2605                         this.getBody().style.display = 'none';\r
2606                         this.getDoc().execCommand('selectall', false, null);\r
2607                         this.getSel().collapseToStart();\r
2608                         this.getBody().style.display = 'block';\r
2609                         s.moveToBookmark(b);\r
2610                 } catch (ex) {\r
2611                         // Ignore\r
2612                 }\r
2613         },\r
2614 \r
2615         switchSettings : function() {\r
2616                 if (tinyMCE.configs.length > 1 && tinyMCE.currentConfig != this.settings.index) {\r
2617                         tinyMCE.settings = this.settings;\r
2618                         tinyMCE.currentConfig = this.settings.index;\r
2619                 }\r
2620         },\r
2621 \r
2622         select : function() {\r
2623                 var oldInst = tinyMCE.selectedInstance;\r
2624 \r
2625                 if (oldInst != this) {\r
2626                         if (oldInst)\r
2627                                 oldInst.execCommand('mceEndTyping');\r
2628 \r
2629                         tinyMCE.dispatchCallback(this, 'select_instance_callback', 'selectInstance', this, oldInst);\r
2630                         tinyMCE.selectedInstance = this;\r
2631                 }\r
2632         },\r
2633 \r
2634         getBody : function() {\r
2635                 return this.contentBody ? this.contentBody : this.getDoc().body;\r
2636         },\r
2637 \r
2638         getDoc : function() {\r
2639 //              return this.contentDocument ? this.contentDocument : this.contentWindow.document; // Removed due to IE 5.5 ?\r
2640                 return this.contentWindow.document;\r
2641         },\r
2642 \r
2643         getWin : function() {\r
2644                 return this.contentWindow;\r
2645         },\r
2646 \r
2647         getContainerWin : function() {\r
2648                 return this.containerWindow ? this.containerWindow : window;\r
2649         },\r
2650 \r
2651         getViewPort : function() {\r
2652                 return tinyMCE.getViewPort(this.getWin());\r
2653         },\r
2654 \r
2655         getParentNode : function(n, f) {\r
2656                 return tinyMCE.getParentNode(n, f, this.getBody());\r
2657         },\r
2658 \r
2659         getParentElement : function(n, na, f) {\r
2660                 return tinyMCE.getParentElement(n, na, f, this.getBody());\r
2661         },\r
2662 \r
2663         getParentBlockElement : function(n) {\r
2664                 return tinyMCE.getParentBlockElement(n, this.getBody());\r
2665         },\r
2666 \r
2667         resizeToContent : function() {\r
2668                 var d = this.getDoc(), b = d.body, de = d.documentElement;\r
2669 \r
2670                 this.iframeElement.style.height = (tinyMCE.isRealIE) ? b.scrollHeight : de.offsetHeight + 'px';\r
2671         },\r
2672 \r
2673         addShortcut : function(m, k, d, cmd, ui, va) {\r
2674                 var n = typeof(k) == "number", ie = tinyMCE.isIE, c, sc, i, scl = this.shortcuts;\r
2675 \r
2676                 if (!tinyMCE.getParam('custom_shortcuts'))\r
2677                         return false;\r
2678 \r
2679                 m = m.toLowerCase();\r
2680                 k = ie && !n ? k.toUpperCase() : k;\r
2681                 c = n ? null : k.charCodeAt(0);\r
2682                 d = d && d.indexOf('lang_') == 0 ? tinyMCE.getLang(d) : d;\r
2683 \r
2684                 sc = {\r
2685                         alt : m.indexOf('alt') != -1,\r
2686                         ctrl : m.indexOf('ctrl') != -1,\r
2687                         shift : m.indexOf('shift') != -1,\r
2688                         charCode : c,\r
2689                         keyCode : n ? k : (ie ? c : null),\r
2690                         desc : d,\r
2691                         cmd : cmd,\r
2692                         ui : ui,\r
2693                         val : va\r
2694                 };\r
2695 \r
2696                 for (i=0; i<scl.length; i++) {\r
2697                         if (sc.alt == scl[i].alt && sc.ctrl == scl[i].ctrl && sc.shift == scl[i].shift\r
2698                                 && sc.charCode == scl[i].charCode && sc.keyCode == scl[i].keyCode) {\r
2699                                 return false;\r
2700                         }\r
2701                 }\r
2702 \r
2703                 scl[scl.length] = sc;\r
2704 \r
2705                 return true;\r
2706         },\r
2707 \r
2708         handleShortcut : function(e) {\r
2709                 var i, s, o;\r
2710 \r
2711                 // Normal key press, then ignore it\r
2712                 if (!e.altKey && !e.ctrlKey)\r
2713                         return false;\r
2714 \r
2715                 s = this.shortcuts;\r
2716 \r
2717                 for (i=0; i<s.length; i++) {\r
2718                         o = s[i];\r
2719 \r
2720                         if (o.alt == e.altKey && o.ctrl == e.ctrlKey && (o.keyCode == e.keyCode || o.charCode == e.charCode)) {\r
2721                                 if (o.cmd && (e.type == "keydown" || (e.type == "keypress" && !tinyMCE.isOpera)))\r
2722                                         tinyMCE.execCommand(o.cmd, o.ui, o.val);\r
2723 \r
2724                                 tinyMCE.cancelEvent(e);\r
2725                                 return true;\r
2726                         }\r
2727                 }\r
2728 \r
2729                 return false;\r
2730         },\r
2731 \r
2732         autoResetDesignMode : function() {\r
2733                 // Add fix for tab/style.display none/block problems in Gecko\r
2734                 if (!tinyMCE.isIE && this.isHidden() && tinyMCE.getParam('auto_reset_designmode'))\r
2735                         eval('try { this.getDoc().designMode = "On"; this.useCSS = false; } catch(e) {}');\r
2736         },\r
2737 \r
2738         isHidden : function() {\r
2739                 var s;\r
2740 \r
2741                 if (tinyMCE.isIE)\r
2742                         return false;\r
2743 \r
2744                 s = this.getSel();\r
2745 \r
2746                 // Weird, wheres that cursor selection?\r
2747                 return (!s || !s.rangeCount || s.rangeCount == 0);\r
2748         },\r
2749 \r
2750         isDirty : function() {\r
2751                 // Is content modified and not in a submit procedure\r
2752                 return tinyMCE.trim(this.startContent) != tinyMCE.trim(this.getBody().innerHTML) && !this.isNotDirty;\r
2753         },\r
2754 \r
2755         _mergeElements : function(scmd, pa, ch, override) {\r
2756                 var st, stc, className, n;\r
2757 \r
2758                 if (scmd == "removeformat") {\r
2759                         pa.className = "";\r
2760                         pa.style.cssText = "";\r
2761                         ch.className = "";\r
2762                         ch.style.cssText = "";\r
2763                         return;\r
2764                 }\r
2765 \r
2766                 st = tinyMCE.parseStyle(tinyMCE.getAttrib(pa, "style"));\r
2767                 stc = tinyMCE.parseStyle(tinyMCE.getAttrib(ch, "style"));\r
2768                 className = tinyMCE.getAttrib(pa, "class");\r
2769 \r
2770                 // Removed class adding due to bug #1478272\r
2771                 className = tinyMCE.getAttrib(ch, "class");\r
2772 \r
2773                 if (override) {\r
2774                         for (n in st) {\r
2775                                 if (typeof(st[n]) == 'function')\r
2776                                         continue;\r
2777 \r
2778                                 stc[n] = st[n];\r
2779                         }\r
2780                 } else {\r
2781                         for (n in stc) {\r
2782                                 if (typeof(stc[n]) == 'function')\r
2783                                         continue;\r
2784 \r
2785                                 st[n] = stc[n];\r
2786                         }\r
2787                 }\r
2788 \r
2789                 tinyMCE.setAttrib(pa, "style", tinyMCE.serializeStyle(st));\r
2790                 tinyMCE.setAttrib(pa, "class", tinyMCE.trim(className));\r
2791                 ch.className = "";\r
2792                 ch.style.cssText = "";\r
2793                 ch.removeAttribute("class");\r
2794                 ch.removeAttribute("style");\r
2795         },\r
2796 \r
2797         _fixRootBlocks : function() {\r
2798                 var rb, b, ne, be, nx, bm;\r
2799 \r
2800                 rb = tinyMCE.getParam('forced_root_block');\r
2801                 if (!rb)\r
2802                         return;\r
2803 \r
2804                 b = this.getBody();\r
2805                 ne = b.firstChild;\r
2806 \r
2807                 while (ne) {\r
2808                         nx = ne.nextSibling;\r
2809 \r
2810                         // If text node or inline element wrap it in a block element\r
2811                         if ((ne.nodeType == 3 && ne.nodeValue.replace(/\s+/g, '') != '') || (ne.nodeType == 1 && !tinyMCE.blockRegExp.test(ne.nodeName))) {\r
2812                                 if (!bm)\r
2813                                         bm = this.selection.getBookmark();\r
2814 \r
2815                                 if (!be) {\r
2816                                         be = this.getDoc().createElement(rb);\r
2817                                         be.appendChild(ne.cloneNode(true));\r
2818                                         b.replaceChild(be, ne);\r
2819                                 } else {\r
2820                                         be.appendChild(ne.cloneNode(true));\r
2821                                         b.removeChild(ne);\r
2822                                 }\r
2823                         } else\r
2824                                 be = null;\r
2825 \r
2826                         ne = nx;\r
2827                 }\r
2828 \r
2829                 if (bm)\r
2830                         this.selection.moveToBookmark(bm);\r
2831         },\r
2832 \r
2833         _fixTrailingNbsp : function() {\r
2834                 var s = this.selection, e = s.getFocusElement(), bm, v;\r
2835 \r
2836                 if (e && tinyMCE.blockRegExp.test(e.nodeName) && e.firstChild) {\r
2837                         v = e.firstChild.nodeValue;\r
2838 \r
2839                         if (v && v.length > 1 && /(^\u00a0|\u00a0$)/.test(v)) {\r
2840                                 e.firstChild.nodeValue = v.replace(/(^\u00a0|\u00a0$)/, '');\r
2841                                 s.selectNode(e.firstChild, true, false, false); // Select and collapse\r
2842                         }\r
2843                 }\r
2844         },\r
2845 \r
2846         _setUseCSS : function(b) {\r
2847                 var d = this.getDoc();\r
2848 \r
2849                 try {d.execCommand("useCSS", false, !b);} catch (ex) {}\r
2850                 try {d.execCommand("styleWithCSS", false, b);} catch (ex) {}\r
2851 \r
2852                 if (!tinyMCE.getParam("table_inline_editing"))\r
2853                         try {d.execCommand('enableInlineTableEditing', false, "false");} catch (ex) {}\r
2854 \r
2855                 if (!tinyMCE.getParam("object_resizing"))\r
2856                         try {d.execCommand('enableObjectResizing', false, "false");} catch (ex) {}\r
2857         },\r
2858 \r
2859         execCommand : function(command, user_interface, value) {\r
2860                 var i, x, z, align, img, div, doc = this.getDoc(), win = this.getWin(), focusElm = this.getFocusElement();\r
2861 \r
2862                 // Is not a undo specific command\r
2863                 if (!new RegExp('mceStartTyping|mceEndTyping|mceBeginUndoLevel|mceEndUndoLevel|mceAddUndoLevel', 'gi').test(command))\r
2864                         this.undoBookmark = null;\r
2865 \r
2866                 // Mozilla issue\r
2867                 if (!tinyMCE.isIE && !this.useCSS) {\r
2868                         this._setUseCSS(false);\r
2869                         this.useCSS = true;\r
2870                 }\r
2871 \r
2872                 //debug("command: " + command + ", user_interface: " + user_interface + ", value: " + value);\r
2873                 this.contentDocument = doc; // <-- Strange, unless this is applied Mozilla 1.3 breaks\r
2874 \r
2875                 // Don't dispatch key commands\r
2876                 if (!/mceStartTyping|mceEndTyping/.test(command)) {\r
2877                         if (tinyMCE.execCommandCallback(this, 'execcommand_callback', 'execCommand', this.editorId, this.getBody(), command, user_interface, value))\r
2878                                 return;\r
2879                 }\r
2880 \r
2881                 // Fix align on images\r
2882                 if (focusElm && focusElm.nodeName == "IMG") {\r
2883                         align = focusElm.getAttribute('align');\r
2884                         img = command == "JustifyCenter" ? focusElm.cloneNode(false) : focusElm;\r
2885 \r
2886                         switch (command) {\r
2887                                 case "JustifyLeft":\r
2888                                         if (align == 'left') {\r
2889                                                 img.setAttribute('align', ''); // Needed for IE\r
2890                                                 img.removeAttribute('align');\r
2891                                         } else\r
2892                                                 img.setAttribute('align', 'left');\r
2893 \r
2894                                         // Remove the div\r
2895                                         div = focusElm.parentNode;\r
2896                                         if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)\r
2897                                                 div.parentNode.replaceChild(img, div);\r
2898 \r
2899                                         this.selection.selectNode(img);\r
2900                                         this.repaint();\r
2901                                         tinyMCE.triggerNodeChange();\r
2902                                         return;\r
2903 \r
2904                                 case "JustifyCenter":\r
2905                                         img.setAttribute('align', ''); // Needed for IE\r
2906                                         img.removeAttribute('align');\r
2907 \r
2908                                         // Is centered\r
2909                                         div = tinyMCE.getParentElement(focusElm, "div");\r
2910                                         if (div && div.style.textAlign == "center") {\r
2911                                                 // Remove div\r
2912                                                 if (div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)\r
2913                                                         div.parentNode.replaceChild(img, div);\r
2914                                         } else {\r
2915                                                 // Add div\r
2916                                                 div = this.getDoc().createElement("div");\r
2917                                                 div.style.textAlign = 'center';\r
2918                                                 div.appendChild(img);\r
2919                                                 focusElm.parentNode.replaceChild(div, focusElm);\r
2920                                         }\r
2921 \r
2922                                         this.selection.selectNode(img);\r
2923                                         this.repaint();\r
2924                                         tinyMCE.triggerNodeChange();\r
2925                                         return;\r
2926 \r
2927                                 case "JustifyRight":\r
2928                                         if (align == 'right') {\r
2929                                                 img.setAttribute('align', ''); // Needed for IE\r
2930                                                 img.removeAttribute('align');\r
2931                                         } else\r
2932                                                 img.setAttribute('align', 'right');\r
2933 \r
2934                                         // Remove the div\r
2935                                         div = focusElm.parentNode;\r
2936                                         if (div && div.nodeName == "DIV" && div.childNodes.length == 1 && div.parentNode)\r
2937                                                 div.parentNode.replaceChild(img, div);\r
2938 \r
2939                                         this.selection.selectNode(img);\r
2940                                         this.repaint();\r
2941                                         tinyMCE.triggerNodeChange();\r
2942                                         return;\r
2943                         }\r
2944                 }\r
2945 \r
2946                 if (tinyMCE.settings.force_br_newlines) {\r
2947                         var alignValue = "";\r
2948 \r
2949                         if (doc.selection.type != "Control") {\r
2950                                 switch (command) {\r
2951                                                 case "JustifyLeft":\r
2952                                                         alignValue = "left";\r
2953                                                         break;\r
2954 \r
2955                                                 case "JustifyCenter":\r
2956                                                         alignValue = "center";\r
2957                                                         break;\r
2958 \r
2959                                                 case "JustifyFull":\r
2960                                                         alignValue = "justify";\r
2961                                                         break;\r
2962 \r
2963                                                 case "JustifyRight":\r
2964                                                         alignValue = "right";\r
2965                                                         break;\r
2966                                 }\r
2967 \r
2968                                 if (alignValue !== '') {\r
2969                                         var rng = doc.selection.createRange();\r
2970 \r
2971                                         if ((divElm = tinyMCE.getParentElement(rng.parentElement(), "div")) != null)\r
2972                                                 divElm.setAttribute("align", alignValue);\r
2973                                         else if (rng.pasteHTML && rng.htmlText.length > 0)\r
2974                                                 rng.pasteHTML('<div align="' + alignValue + '">' + rng.htmlText + "</div>");\r
2975 \r
2976                                         tinyMCE.triggerNodeChange();\r
2977                                         return;\r
2978                                 }\r
2979                         }\r
2980                 }\r
2981 \r
2982                 switch (command) {\r
2983                         case "mceRepaint":\r
2984                                 this.repaint();\r
2985                                 return true;\r
2986 \r
2987                         case "JustifyLeft":\r
2988                         case "JustifyCenter":\r
2989                         case "JustifyFull":\r
2990                         case "JustifyRight":\r
2991                                 var el = tinyMCE.getParentNode(focusElm, function(n) {return tinyMCE.getAttrib(n, 'align');});\r
2992 \r
2993                                 if (el) {\r
2994                                         el.setAttribute('align', ''); // Needed for IE\r
2995                                         el.removeAttribute('align');\r
2996                                 } else\r
2997                                         this.getDoc().execCommand(command, user_interface, value);\r
2998 \r
2999                                 tinyMCE.triggerNodeChange();\r
3000 \r
3001                                 return true;\r
3002 \r
3003                         case "unlink":\r
3004                                 // Unlink if caret is inside link\r
3005                                 if (tinyMCE.isGecko && this.getSel().isCollapsed) {\r
3006                                         focusElm = tinyMCE.getParentElement(focusElm, 'A');\r
3007 \r
3008                                         if (focusElm)\r
3009                                                 this.selection.selectNode(focusElm, false);\r
3010                                 }\r
3011 \r
3012                                 this.getDoc().execCommand(command, user_interface, value);\r
3013 \r
3014                                 tinyMCE.isGecko && this.getSel().collapseToEnd();\r
3015 \r
3016                                 tinyMCE.triggerNodeChange();\r
3017 \r
3018                                 return true;\r
3019 \r
3020                         case "InsertUnorderedList":\r
3021                         case "InsertOrderedList":\r
3022                                 this.getDoc().execCommand(command, user_interface, value);\r
3023                                 tinyMCE.triggerNodeChange();\r
3024                                 break;\r
3025 \r
3026                         case "Strikethrough":\r
3027                                 this.getDoc().execCommand(command, user_interface, value);\r
3028                                 tinyMCE.triggerNodeChange();\r
3029                                 break;\r
3030 \r
3031                         case "mceSelectNode":\r
3032                                 this.selection.selectNode(value);\r
3033                                 tinyMCE.triggerNodeChange();\r
3034                                 tinyMCE.selectedNode = value;\r
3035                                 break;\r
3036 \r
3037                         case "FormatBlock":\r
3038                                 if (value == null || value == '') {\r
3039                                         var elm = tinyMCE.getParentElement(this.getFocusElement(), "p,div,h1,h2,h3,h4,h5,h6,pre,address,blockquote,dt,dl,dd,samp");\r
3040 \r
3041                                         if (elm)\r
3042                                                 this.execCommand("mceRemoveNode", false, elm);\r
3043                                 } else {\r
3044                                         if (!this.cleanup.isValid(value))\r
3045                                                 return true;\r
3046 \r
3047                                         if (tinyMCE.isGecko && new RegExp('<(div|blockquote|code|dt|dd|dl|samp)>', 'gi').test(value))\r
3048                                                 value = value.replace(/[^a-z]/gi, '');\r
3049 \r
3050                                         if (tinyMCE.isIE && new RegExp('blockquote|code|samp', 'gi').test(value)) {\r
3051                                                 var b = this.selection.getBookmark();\r
3052                                                 this.getDoc().execCommand("FormatBlock", false, '<p>');\r
3053                                                 tinyMCE.renameElement(tinyMCE.getParentBlockElement(this.getFocusElement()), value);\r
3054                                                 this.selection.moveToBookmark(b);\r
3055                                         } else\r
3056                                                 this.getDoc().execCommand("FormatBlock", false, value);\r
3057                                 }\r
3058 \r
3059                                 tinyMCE.triggerNodeChange();\r
3060 \r
3061                                 break;\r
3062 \r
3063                         case "mceRemoveNode":\r
3064                                 if (!value)\r
3065                                         value = tinyMCE.getParentElement(this.getFocusElement());\r
3066 \r
3067                                 if (tinyMCE.isIE) {\r
3068                                         value.outerHTML = value.innerHTML;\r
3069                                 } else {\r
3070                                         var rng = value.ownerDocument.createRange();\r
3071                                         rng.setStartBefore(value);\r
3072                                         rng.setEndAfter(value);\r
3073                                         rng.deleteContents();\r
3074                                         rng.insertNode(rng.createContextualFragment(value.innerHTML));\r
3075                                 }\r
3076 \r
3077                                 tinyMCE.triggerNodeChange();\r
3078 \r
3079                                 break;\r
3080 \r
3081                         case "mceSelectNodeDepth":\r
3082                                 var parentNode = this.getFocusElement();\r
3083                                 for (i=0; parentNode; i++) {\r
3084                                         if (parentNode.nodeName.toLowerCase() == "body")\r
3085                                                 break;\r
3086 \r
3087                                         if (parentNode.nodeName.toLowerCase() == "#text") {\r
3088                                                 i--;\r
3089                                                 parentNode = parentNode.parentNode;\r
3090                                                 continue;\r
3091                                         }\r
3092 \r
3093                                         if (i == value) {\r
3094                                                 this.selection.selectNode(parentNode, false);\r
3095                                                 tinyMCE.triggerNodeChange();\r
3096                                                 tinyMCE.selectedNode = parentNode;\r
3097                                                 return;\r
3098                                         }\r
3099 \r
3100                                         parentNode = parentNode.parentNode;\r
3101                                 }\r
3102 \r
3103                                 break;\r
3104 \r
3105                         case "mceSetStyleInfo":\r
3106                         case "SetStyleInfo":\r
3107                                 var rng = this.getRng();\r
3108                                 var sel = this.getSel();\r
3109                                 var scmd = value.command;\r
3110                                 var sname = value.name;\r
3111                                 var svalue = value.value == null ? '' : value.value;\r
3112                                 //var svalue = value['value'] == null ? '' : value['value'];\r
3113                                 var wrapper = value.wrapper ? value.wrapper : "span";\r
3114                                 var parentElm = null;\r
3115                                 var invalidRe = new RegExp("^BODY|HTML$", "g");\r
3116                                 var invalidParentsRe = tinyMCE.settings.merge_styles_invalid_parents !== '' ? new RegExp(tinyMCE.settings.merge_styles_invalid_parents, "gi") : null;\r
3117 \r
3118                                 // Whole element selected check\r
3119                                 if (tinyMCE.isIE) {\r
3120                                         // Control range\r
3121                                         if (rng.item)\r
3122                                                 parentElm = rng.item(0);\r
3123                                         else {\r
3124                                                 var pelm = rng.parentElement();\r
3125                                                 var prng = doc.selection.createRange();\r
3126                                                 prng.moveToElementText(pelm);\r
3127 \r
3128                                                 if (rng.htmlText == prng.htmlText || rng.boundingWidth == 0) {\r
3129                                                         if (invalidParentsRe == null || !invalidParentsRe.test(pelm.nodeName))\r
3130                                                                 parentElm = pelm;\r
3131                                                 }\r
3132                                         }\r
3133                                 } else {\r
3134                                         var felm = this.getFocusElement();\r
3135                                         if (sel.isCollapsed || (new RegExp('td|tr|tbody|table|img', 'gi').test(felm.nodeName) && sel.anchorNode == felm.parentNode))\r
3136                                                 parentElm = felm;\r
3137                                 }\r
3138 \r
3139                                 // Whole element selected\r
3140                                 if (parentElm && !invalidRe.test(parentElm.nodeName)) {\r
3141                                         if (scmd == "setstyle")\r
3142                                                 tinyMCE.setStyleAttrib(parentElm, sname, svalue);\r
3143 \r
3144                                         if (scmd == "setattrib")\r
3145                                                 tinyMCE.setAttrib(parentElm, sname, svalue);\r
3146 \r
3147                                         if (scmd == "removeformat") {\r
3148                                                 parentElm.style.cssText = '';\r
3149                                                 tinyMCE.setAttrib(parentElm, 'class', '');\r
3150                                         }\r
3151 \r
3152                                         // Remove style/attribs from all children\r
3153                                         var ch = tinyMCE.getNodeTree(parentElm, [], 1);\r
3154                                         for (z=0; z<ch.length; z++) {\r
3155                                                 if (ch[z] == parentElm)\r
3156                                                         continue;\r
3157 \r
3158                                                 if (scmd == "setstyle")\r
3159                                                         tinyMCE.setStyleAttrib(ch[z], sname, '');\r
3160 \r
3161                                                 if (scmd == "setattrib")\r
3162                                                         tinyMCE.setAttrib(ch[z], sname, '');\r
3163 \r
3164                                                 if (scmd == "removeformat") {\r
3165                                                         ch[z].style.cssText = '';\r
3166                                                         tinyMCE.setAttrib(ch[z], 'class', '');\r
3167                                                 }\r
3168                                         }\r
3169                                 } else {\r
3170                                         this._setUseCSS(false); // Bug in FF when running in fullscreen\r
3171                                         doc.execCommand("FontName", false, "#mce_temp_font#");\r
3172                                         var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#");\r
3173 \r
3174                                         // Change them all\r
3175                                         for (x=0; x<elementArray.length; x++) {\r
3176                                                 elm = elementArray[x];\r
3177                                                 if (elm) {\r
3178                                                         var spanElm = doc.createElement(wrapper);\r
3179 \r
3180                                                         if (scmd == "setstyle")\r
3181                                                                 tinyMCE.setStyleAttrib(spanElm, sname, svalue);\r
3182 \r
3183                                                         if (scmd == "setattrib")\r
3184                                                                 tinyMCE.setAttrib(spanElm, sname, svalue);\r
3185 \r
3186                                                         if (scmd == "removeformat") {\r
3187                                                                 spanElm.style.cssText = '';\r
3188                                                                 tinyMCE.setAttrib(spanElm, 'class', '');\r
3189                                                         }\r
3190 \r
3191                                                         if (elm.hasChildNodes()) {\r
3192                                                                 for (i=0; i<elm.childNodes.length; i++)\r
3193                                                                         spanElm.appendChild(elm.childNodes[i].cloneNode(true));\r
3194                                                         }\r
3195 \r
3196                                                         spanElm.setAttribute("mce_new", "true");\r
3197                                                         elm.parentNode.replaceChild(spanElm, elm);\r
3198 \r
3199                                                         // Remove style/attribs from all children\r
3200                                                         var ch = tinyMCE.getNodeTree(spanElm, [], 1);\r
3201                                                         for (z=0; z<ch.length; z++) {\r
3202                                                                 if (ch[z] == spanElm)\r
3203                                                                         continue;\r
3204 \r
3205                                                                 if (scmd == "setstyle")\r
3206                                                                         tinyMCE.setStyleAttrib(ch[z], sname, '');\r
3207 \r
3208                                                                 if (scmd == "setattrib")\r
3209                                                                         tinyMCE.setAttrib(ch[z], sname, '');\r
3210 \r
3211                                                                 if (scmd == "removeformat") {\r
3212                                                                         ch[z].style.cssText = '';\r
3213                                                                         tinyMCE.setAttrib(ch[z], 'class', '');\r
3214                                                                 }\r
3215                                                         }\r
3216                                                 }\r
3217                                         }\r
3218                                 }\r
3219 \r
3220                                 // Cleaup wrappers\r
3221                                 var nodes = doc.getElementsByTagName(wrapper);\r
3222                                 for (i=nodes.length-1; i>=0; i--) {\r
3223                                         var elm = nodes[i];\r
3224                                         var isNew = tinyMCE.getAttrib(elm, "mce_new") == "true";\r
3225 \r
3226                                         elm.removeAttribute("mce_new");\r
3227 \r
3228                                         // Is only child a element\r
3229                                         if (elm.childNodes && elm.childNodes.length == 1 && elm.childNodes[0].nodeType == 1) {\r
3230                                                 //tinyMCE.debug("merge1" + isNew);\r
3231                                                 this._mergeElements(scmd, elm, elm.childNodes[0], isNew);\r
3232                                                 continue;\r
3233                                         }\r
3234 \r
3235                                         // Is I the only child\r
3236                                         if (elm.parentNode.childNodes.length == 1 && !invalidRe.test(elm.nodeName) && !invalidRe.test(elm.parentNode.nodeName)) {\r
3237                                                 //tinyMCE.debug("merge2" + isNew + "," + elm.nodeName + "," + elm.parentNode.nodeName);\r
3238                                                 if (invalidParentsRe == null || !invalidParentsRe.test(elm.parentNode.nodeName))\r
3239                                                         this._mergeElements(scmd, elm.parentNode, elm, false);\r
3240                                         }\r
3241                                 }\r
3242 \r
3243                                 // Remove empty wrappers\r
3244                                 var nodes = doc.getElementsByTagName(wrapper);\r
3245                                 for (i=nodes.length-1; i>=0; i--) {\r
3246                                         var elm = nodes[i], isEmpty = true;\r
3247 \r
3248                                         // Check if it has any attribs\r
3249                                         var tmp = doc.createElement("body");\r
3250                                         tmp.appendChild(elm.cloneNode(false));\r
3251 \r
3252                                         // Is empty span, remove it\r
3253                                         tmp.innerHTML = tmp.innerHTML.replace(new RegExp('style=""|class=""', 'gi'), '');\r
3254                                         //tinyMCE.debug(tmp.innerHTML);\r
3255                                         if (new RegExp('<span>', 'gi').test(tmp.innerHTML)) {\r
3256                                                 for (x=0; x<elm.childNodes.length; x++) {\r
3257                                                         if (elm.parentNode != null)\r
3258                                                                 elm.parentNode.insertBefore(elm.childNodes[x].cloneNode(true), elm);\r
3259                                                 }\r
3260 \r
3261                                                 elm.parentNode.removeChild(elm);\r
3262                                         }\r
3263                                 }\r
3264 \r
3265                                 // Re add the visual aids\r
3266                                 if (scmd == "removeformat")\r
3267                                         tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);\r
3268 \r
3269                                 tinyMCE.triggerNodeChange();\r
3270 \r
3271                                 break;\r
3272 \r
3273                         case "FontName":\r
3274                                 if (value == null) {\r
3275                                         var s = this.getSel();\r
3276 \r
3277                                         // Find font and select it\r
3278                                         if (tinyMCE.isGecko && s.isCollapsed) {\r
3279                                                 var f = tinyMCE.getParentElement(this.getFocusElement(), "font");\r
3280 \r
3281                                                 if (f != null)\r
3282                                                         this.selection.selectNode(f, false);\r
3283                                         }\r
3284 \r
3285                                         // Remove format\r
3286                                         this.getDoc().execCommand("RemoveFormat", false, null);\r
3287 \r
3288                                         // Collapse range if font was found\r
3289                                         if (f != null && tinyMCE.isGecko) {\r
3290                                                 var r = this.getRng().cloneRange();\r
3291                                                 r.collapse(true);\r
3292                                                 s.removeAllRanges();\r
3293                                                 s.addRange(r);\r
3294                                         }\r
3295                                 } else\r
3296                                         this.getDoc().execCommand('FontName', false, value);\r
3297 \r
3298                                 if (tinyMCE.isGecko)\r
3299                                         window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);\r
3300 \r
3301                                 return;\r
3302 \r
3303                         case "FontSize":\r
3304                                 this.getDoc().execCommand('FontSize', false, value);\r
3305 \r
3306                                 if (tinyMCE.isGecko)\r
3307                                         window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);\r
3308 \r
3309                                 return;\r
3310 \r
3311                         case "forecolor":\r
3312                                 value = value == null ? this.foreColor : value;\r
3313                                 value = tinyMCE.trim(value);\r
3314                                 value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;\r
3315 \r
3316                                 this.foreColor = value;\r
3317                                 this.getDoc().execCommand('forecolor', false, value);\r
3318                                 break;\r
3319 \r
3320                         case "HiliteColor":\r
3321                                 value = value == null ? this.backColor : value;\r
3322                                 value = tinyMCE.trim(value);\r
3323                                 value = value.charAt(0) != '#' ? (isNaN('0x' + value) ? value : '#' + value) : value;\r
3324                                 this.backColor = value;\r
3325 \r
3326                                 if (tinyMCE.isGecko || tinyMCE.isOpera) {\r
3327                                         this._setUseCSS(true);\r
3328                                         this.getDoc().execCommand('hilitecolor', false, value);\r
3329                                         this._setUseCSS(false);\r
3330                                 } else\r
3331                                         this.getDoc().execCommand('BackColor', false, value);\r
3332                                 break;\r
3333 \r
3334                         case "Cut":\r
3335                         case "Copy":\r
3336                         case "Paste":\r
3337                                 var cmdFailed = false;\r
3338 \r
3339                                 // Try executing command\r
3340                                 eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}');\r
3341 \r
3342                                 if (tinyMCE.isOpera && cmdFailed)\r
3343                                         alert('Currently not supported by your browser, use keyboard shortcuts instead.');\r
3344 \r
3345                                 // Alert error in gecko if command failed\r
3346                                 if (tinyMCE.isGecko && cmdFailed) {\r
3347                                         // Confirm more info\r
3348                                         if (confirm(tinyMCE.entityDecode(tinyMCE.getLang('lang_clipboard_msg'))))\r
3349                                                 window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal');\r
3350 \r
3351                                         return;\r
3352                                 } else\r
3353                                         tinyMCE.triggerNodeChange();\r
3354                         break;\r
3355 \r
3356                         case "mceSetContent":\r
3357                                 if (!value)\r
3358                                         value = "";\r
3359 \r
3360                                 // Call custom cleanup code\r
3361                                 value = tinyMCE.storeAwayURLs(value);\r
3362                                 value = tinyMCE._customCleanup(this, "insert_to_editor", value);\r
3363 \r
3364                                 if (this.getBody().nodeName == 'BODY')\r
3365                                         tinyMCE._setHTML(doc, value);\r
3366                                 else\r
3367                                         this.getBody().innerHTML = value;\r
3368 \r
3369                                 tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, doc, this.settings, this.getBody(), false, false, false, true));\r
3370                                 tinyMCE.convertAllRelativeURLs(this.getBody());\r
3371 \r
3372                                 // Cleanup any mess left from storyAwayURLs\r
3373                                 tinyMCE._removeInternal(this.getBody());\r
3374 \r
3375                                 // When editing always use fonts internaly\r
3376                                 if (tinyMCE.getParam("convert_fonts_to_spans"))\r
3377                                         tinyMCE.convertSpansToFonts(doc);\r
3378 \r
3379                                 tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);\r
3380                                 tinyMCE._setEventsEnabled(this.getBody(), false);\r
3381                                 this._addBogusBR();\r
3382 \r
3383                                 return true;\r
3384 \r
3385                         case "mceCleanup":\r
3386                                 var b = this.selection.getBookmark();\r
3387                                 tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML);\r
3388                                 tinyMCE.setInnerHTML(this.getBody(), tinyMCE._cleanupHTML(this, this.contentDocument, this.settings, this.getBody(), this.visualAid));\r
3389                                 tinyMCE.convertAllRelativeURLs(doc.body);\r
3390 \r
3391                                 // When editing always use fonts internaly\r
3392                                 if (tinyMCE.getParam("convert_fonts_to_spans"))\r
3393                                         tinyMCE.convertSpansToFonts(doc);\r
3394 \r
3395                                 tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);\r
3396                                 tinyMCE._setEventsEnabled(this.getBody(), false);\r
3397                                 this._addBogusBR();\r
3398                                 this.repaint();\r
3399                                 this.selection.moveToBookmark(b);\r
3400                                 tinyMCE.triggerNodeChange();\r
3401                         break;\r
3402 \r
3403                         case "mceReplaceContent":\r
3404                                 // Force empty string\r
3405                                 if (!value)\r
3406                                         value = '';\r
3407 \r
3408                                 this.getWin().focus();\r
3409 \r
3410                                 var selectedText = "";\r
3411 \r
3412                                 if (tinyMCE.isIE) {\r
3413                                         var rng = doc.selection.createRange();\r
3414                                         selectedText = rng.text;\r
3415                                 } else\r
3416                                         selectedText = this.getSel().toString();\r
3417 \r
3418                                 if (selectedText.length > 0) {\r
3419                                         value = tinyMCE.replaceVar(value, "selection", selectedText);\r
3420                                         tinyMCE.execCommand('mceInsertContent', false, value);\r
3421                                 }\r
3422 \r
3423                                 this._addBogusBR();\r
3424                                 tinyMCE.triggerNodeChange();\r
3425                         break;\r
3426 \r
3427                         case "mceSetAttribute":\r
3428                                 if (typeof(value) == 'object') {\r
3429                                         var targetElms = (typeof(value.targets) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value.targets;\r
3430                                         var targetNode = tinyMCE.getParentElement(this.getFocusElement(), targetElms);\r
3431 \r
3432                                         if (targetNode) {\r
3433                                                 targetNode.setAttribute(value.name, value.value);\r
3434                                                 tinyMCE.triggerNodeChange();\r
3435                                         }\r
3436                                 }\r
3437                         break;\r
3438 \r
3439                         case "mceSetCSSClass":\r
3440                                 this.execCommand("mceSetStyleInfo", false, {command : "setattrib", name : "class", value : value});\r
3441                         break;\r
3442 \r
3443                         case "mceInsertRawHTML":\r
3444                                 var key = 'tiny_mce_marker';\r
3445 \r
3446                                 this.execCommand('mceBeginUndoLevel');\r
3447 \r
3448                                 // Insert marker key\r
3449                                 this.execCommand('mceInsertContent', false, key);\r
3450 \r
3451                                 // Store away scroll pos\r
3452                                 var scrollX = this.getBody().scrollLeft + this.getDoc().documentElement.scrollLeft;\r
3453                                 var scrollY = this.getBody().scrollTop + this.getDoc().documentElement.scrollTop;\r
3454 \r
3455                                 // Find marker and replace with RAW HTML\r
3456                                 var html = this.getBody().innerHTML;\r
3457                                 if ((pos = html.indexOf(key)) != -1)\r
3458                                         tinyMCE.setInnerHTML(this.getBody(), html.substring(0, pos) + value + html.substring(pos + key.length));\r
3459 \r
3460                                 // Restore scoll pos\r
3461                                 this.contentWindow.scrollTo(scrollX, scrollY);\r
3462 \r
3463                                 this.execCommand('mceEndUndoLevel');\r
3464 \r
3465                                 break;\r
3466 \r
3467                         case "mceInsertContent":\r
3468                                 // Force empty string\r
3469                                 if (!value)\r
3470                                         value = '';\r
3471 \r
3472                                 var insertHTMLFailed = false;\r
3473 \r
3474                                 // Removed since it produced problems in IE\r
3475                                 // this.getWin().focus();\r
3476 \r
3477                                 if (tinyMCE.isGecko || tinyMCE.isOpera) {\r
3478                                         try {\r
3479                                                 // Is plain text or HTML, &amp;, &nbsp; etc will be encoded wrong in FF\r
3480                                                 if (value.indexOf('<') == -1 && !value.match(/(&#38;|&#160;|&#60;|&#62;)/g)) {\r
3481                                                         var r = this.getRng();\r
3482                                                         var n = this.getDoc().createTextNode(tinyMCE.entityDecode(value));\r
3483                                                         var s = this.getSel();\r
3484                                                         var r2 = r.cloneRange();\r
3485 \r
3486                                                         // Insert text at cursor position\r
3487                                                         s.removeAllRanges();\r
3488                                                         r.deleteContents();\r
3489                                                         r.insertNode(n);\r
3490 \r
3491                                                         // Move the cursor to the end of text\r
3492                                                         r2.selectNode(n);\r
3493                                                         r2.collapse(false);\r
3494                                                         s.removeAllRanges();\r
3495                                                         s.addRange(r2);\r
3496                                                 } else {\r
3497                                                         value = tinyMCE.fixGeckoBaseHREFBug(1, this.getDoc(), value);\r
3498                                                         this.getDoc().execCommand('inserthtml', false, value);\r
3499                                                         tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);\r
3500                                                 }\r
3501                                         } catch (ex) {\r
3502                                                 insertHTMLFailed = true;\r
3503                                         }\r
3504 \r
3505                                         if (!insertHTMLFailed) {\r
3506                                                 tinyMCE.triggerNodeChange();\r
3507                                                 return;\r
3508                                         }\r
3509                                 }\r
3510 \r
3511                                 if (!tinyMCE.isIE) {\r
3512                                         var isHTML = value.indexOf('<') != -1;\r
3513                                         var sel = this.getSel();\r
3514                                         var rng = this.getRng();\r
3515 \r
3516                                         if (isHTML) {\r
3517                                                 if (tinyMCE.isSafari) {\r
3518                                                         var tmpRng = this.getDoc().createRange();\r
3519 \r
3520                                                         tmpRng.setStart(this.getBody(), 0);\r
3521                                                         tmpRng.setEnd(this.getBody(), 0);\r
3522 \r
3523                                                         value = tmpRng.createContextualFragment(value);\r
3524                                                 } else\r
3525                                                         value = rng.createContextualFragment(value);\r
3526                                         } else {\r
3527                                                 // Setup text node\r
3528                                                 value = doc.createTextNode(tinyMCE.entityDecode(value));\r
3529                                         }\r
3530 \r
3531                                         // Insert plain text in Safari\r
3532                                         if (tinyMCE.isSafari && !isHTML) {\r
3533                                                 this.execCommand('InsertText', false, value.nodeValue);\r
3534                                                 tinyMCE.triggerNodeChange();\r
3535                                                 return true;\r
3536                                         } else if (tinyMCE.isSafari && isHTML) {\r
3537                                                 rng.deleteContents();\r
3538                                                 rng.insertNode(value);\r
3539                                                 tinyMCE.triggerNodeChange();\r
3540                                                 return true;\r
3541                                         }\r
3542 \r
3543                                         rng.deleteContents();\r
3544 \r
3545                                         // If target node is text do special treatment, (Mozilla 1.3 fix)\r
3546                                         if (rng.startContainer.nodeType == 3) {\r
3547                                                 var node = rng.startContainer.splitText(rng.startOffset);\r
3548                                                 node.parentNode.insertBefore(value, node); \r
3549                                         } else\r
3550                                                 rng.insertNode(value);\r
3551 \r
3552                                         if (!isHTML) {\r
3553                                                 // Removes weird selection trails\r
3554                                                 sel.selectAllChildren(doc.body);\r
3555                                                 sel.removeAllRanges();\r
3556 \r
3557                                                 // Move cursor to end of content\r
3558                                                 var rng = doc.createRange();\r
3559 \r
3560                                                 rng.selectNode(value);\r
3561                                                 rng.collapse(false);\r
3562 \r
3563                                                 sel.addRange(rng);\r
3564                                         } else\r
3565                                                 rng.collapse(false);\r
3566 \r
3567                                         tinyMCE.fixGeckoBaseHREFBug(2, this.getDoc(), value);\r
3568                                 } else {\r
3569                                         var rng = doc.selection.createRange(), tmpRng = null;\r
3570                                         var c = value.indexOf('<!--') != -1;\r
3571 \r
3572                                         // Fix comment bug, add tag before comments\r
3573                                         if (c)\r
3574                                                 value = tinyMCE.uniqueTag + value;\r
3575 \r
3576                                         //      tmpRng = rng.duplicate(); // Store away range (Fixes Undo bookmark bug in IE)\r
3577 \r
3578                                         if (rng.item)\r
3579                                                 rng.item(0).outerHTML = value;\r
3580                                         else\r
3581                                                 rng.pasteHTML(value);\r
3582 \r
3583                                         //if (tmpRng)\r
3584                                         //      tmpRng.select(); // Restore range  (Fixes Undo bookmark bug in IE)\r
3585 \r
3586                                         // Remove unique tag\r
3587                                         if (c) {\r
3588                                                 var e = this.getDoc().getElementById('mceTMPElement');\r
3589                                                 e.parentNode.removeChild(e);\r
3590                                         }\r
3591                                 }\r
3592 \r
3593                                 tinyMCE.execCommand("mceAddUndoLevel");\r
3594                                 tinyMCE.triggerNodeChange();\r
3595                         break;\r
3596 \r
3597                         case "mceStartTyping":\r
3598                                 if (tinyMCE.settings.custom_undo_redo && this.undoRedo.typingUndoIndex == -1) {\r
3599                                         this.undoRedo.typingUndoIndex = this.undoRedo.undoIndex;\r
3600                                         tinyMCE.typingUndoIndex = tinyMCE.undoIndex;\r
3601                                         this.execCommand('mceAddUndoLevel');\r
3602                                 }\r
3603                                 break;\r
3604 \r
3605                         case "mceEndTyping":\r
3606                                 if (tinyMCE.settings.custom_undo_redo && this.undoRedo.typingUndoIndex != -1) {\r
3607                                         this.execCommand('mceAddUndoLevel');\r
3608                                         this.undoRedo.typingUndoIndex = -1;\r
3609                                 }\r
3610 \r
3611                                 tinyMCE.typingUndoIndex = -1;\r
3612                                 break;\r
3613 \r
3614                         case "mceBeginUndoLevel":\r
3615                                 this.undoRedoLevel = false;\r
3616                                 break;\r
3617 \r
3618                         case "mceEndUndoLevel":\r
3619                                 this.undoRedoLevel = true;\r
3620                                 this.execCommand('mceAddUndoLevel');\r
3621                                 break;\r
3622 \r
3623                         case "mceAddUndoLevel":\r
3624                                 if (tinyMCE.settings.custom_undo_redo && this.undoRedoLevel) {\r
3625                                         if (this.undoRedo.add())\r
3626                                                 tinyMCE.triggerNodeChange(false);\r
3627                                 }\r
3628                                 break;\r
3629 \r
3630                         case "Undo":\r
3631                                 if (tinyMCE.settings.custom_undo_redo) {\r
3632                                         tinyMCE.execCommand("mceEndTyping");\r
3633                                         this.undoRedo.undo();\r
3634                                         tinyMCE.triggerNodeChange();\r
3635                                 } else\r
3636                                         this.getDoc().execCommand(command, user_interface, value);\r
3637                                 break;\r
3638 \r
3639                         case "Redo":\r
3640                                 if (tinyMCE.settings.custom_undo_redo) {\r
3641                                         tinyMCE.execCommand("mceEndTyping");\r
3642                                         this.undoRedo.redo();\r
3643                                         tinyMCE.triggerNodeChange();\r
3644                                 } else\r
3645                                         this.getDoc().execCommand(command, user_interface, value);\r
3646                                 break;\r
3647 \r
3648                         case "mceToggleVisualAid":\r
3649                                 this.visualAid = !this.visualAid;\r
3650                                 tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid, this);\r
3651                                 tinyMCE.triggerNodeChange();\r
3652                                 break;\r
3653 \r
3654                         case "Indent":\r
3655                                 this.getDoc().execCommand(command, user_interface, value);\r
3656                                 tinyMCE.triggerNodeChange();\r
3657 \r
3658                                 if (tinyMCE.isIE) {\r
3659                                         var n = tinyMCE.getParentElement(this.getFocusElement(), "blockquote");\r
3660                                         do {\r
3661                                                 if (n && n.nodeName == "BLOCKQUOTE") {\r
3662                                                         n.removeAttribute("dir");\r
3663                                                         n.removeAttribute("style");\r
3664                                                 }\r
3665                                         } while (n != null && (n = n.parentNode) != null);\r
3666                                 }\r
3667                                 break;\r
3668 \r
3669                         case "RemoveFormat":\r
3670                         case "removeformat":\r
3671                                 var text = this.selection.getSelectedText();\r
3672 \r
3673                                 if (tinyMCE.isOpera) {\r
3674                                         this.getDoc().execCommand("RemoveFormat", false, null);\r
3675                                         return;\r
3676                                 }\r
3677 \r
3678                                 if (tinyMCE.isIE) {\r
3679                                         try {\r
3680                                                 var rng = doc.selection.createRange();\r
3681                                                 rng.execCommand("RemoveFormat", false, null);\r
3682                                         } catch (e) {\r
3683                                                 // Do nothing\r
3684                                         }\r
3685 \r
3686                                         this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});\r
3687                                 } else {\r
3688                                         this.getDoc().execCommand(command, user_interface, value);\r
3689 \r
3690                                         this.execCommand("mceSetStyleInfo", false, {command : "removeformat"});\r
3691                                 }\r
3692 \r
3693                                 // Remove class\r
3694                                 if (text.length == 0)\r
3695                                         this.execCommand("mceSetCSSClass", false, "");\r
3696 \r
3697                                 tinyMCE.triggerNodeChange();\r
3698                                 break;\r
3699 \r
3700                         default:\r
3701                                 this.getDoc().execCommand(command, user_interface, value);\r
3702 \r
3703                                 if (tinyMCE.isGecko)\r
3704                                         window.setTimeout('tinyMCE.triggerNodeChange(false);', 1);\r
3705                                 else\r
3706                                         tinyMCE.triggerNodeChange();\r
3707                 }\r
3708 \r
3709                 // Add undo level after modification\r
3710                 if (command != "mceAddUndoLevel" && command != "Undo" && command != "Redo" && command != "mceStartTyping" && command != "mceEndTyping")\r
3711                         tinyMCE.execCommand("mceAddUndoLevel");\r
3712         },\r
3713 \r
3714         queryCommandValue : function(c) {\r
3715                 try {\r
3716                         return this.getDoc().queryCommandValue(c);\r
3717                 } catch (e) {\r
3718                         return null;\r
3719                 }\r
3720         },\r
3721 \r
3722         queryCommandState : function(c) {\r
3723                 return this.getDoc().queryCommandState(c);\r
3724         },\r
3725 \r
3726         _addBogusBR : function() {\r
3727                 var b = this.getBody();\r
3728 \r
3729                 if (tinyMCE.isGecko && !b.hasChildNodes())\r
3730                         b.innerHTML = '<br _moz_editor_bogus_node="TRUE" />';\r
3731         },\r
3732 \r
3733         _onAdd : function(replace_element, form_element_name, target_document) {\r
3734                 var hc, th, tos, editorTemplate, targetDoc, deltaWidth, deltaHeight, html, rng, fragment;\r
3735                 var dynamicIFrame, tElm, doc, parentElm;\r
3736 \r
3737                 th = this.settings.theme;\r
3738                 tos = tinyMCE.themes[th];\r
3739 \r
3740                 targetDoc = target_document ? target_document : document;\r
3741 \r
3742                 this.targetDoc = targetDoc;\r
3743 \r
3744                 tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings.theme;\r
3745                 this.settings.themeurl = tinyMCE.themeURL;\r
3746 \r
3747                 if (!replace_element) {\r
3748                         alert("Error: Could not find the target element.");\r
3749                         return false;\r
3750                 }\r
3751 \r
3752                 if (tos.getEditorTemplate)\r
3753                         editorTemplate = tos.getEditorTemplate(this.settings, this.editorId);\r
3754 \r
3755                 deltaWidth = editorTemplate.delta_width ? editorTemplate.delta_width : 0;\r
3756                 deltaHeight = editorTemplate.delta_height ? editorTemplate.delta_height : 0;\r
3757                 html = '<span id="' + this.editorId + '_parent" class="mceEditorContainer">' + editorTemplate.html;\r
3758 \r
3759                 html = tinyMCE.replaceVar(html, "editor_id", this.editorId);\r
3760 \r
3761                 if (!this.settings.default_document)\r
3762                         this.settings.default_document = tinyMCE.baseURL + "/blank.htm";\r
3763 \r
3764                 this.settings.old_width = this.settings.width;\r
3765                 this.settings.old_height = this.settings.height;\r
3766 \r
3767                 // Set default width, height\r
3768                 if (this.settings.width == -1)\r
3769                         this.settings.width = replace_element.offsetWidth;\r
3770 \r
3771                 if (this.settings.height == -1)\r
3772                         this.settings.height = replace_element.offsetHeight;\r
3773 \r
3774                 // Try the style width\r
3775                 if (this.settings.width == 0)\r
3776                         this.settings.width = replace_element.style.width;\r
3777 \r
3778                 // Try the style height\r
3779                 if (this.settings.height == 0)\r
3780                         this.settings.height = replace_element.style.height; \r
3781 \r
3782                 // If no width/height then default to 320x240, better than nothing\r
3783                 if (this.settings.width == 0)\r
3784                         this.settings.width = 320;\r
3785 \r
3786                 if (this.settings.height == 0)\r
3787                         this.settings.height = 240;\r
3788 \r
3789                 this.settings.area_width = parseInt(this.settings.width);\r
3790                 this.settings.area_height = parseInt(this.settings.height);\r
3791                 this.settings.area_width += deltaWidth;\r
3792                 this.settings.area_height += deltaHeight;\r
3793                 this.settings.width_style = "" + this.settings.width;\r
3794                 this.settings.height_style = "" + this.settings.height;\r
3795 \r
3796                 // Special % handling\r
3797                 if (("" + this.settings.width).indexOf('%') != -1)\r
3798                         this.settings.area_width = "100%";\r
3799                 else\r
3800                         this.settings.width_style += 'px';\r
3801 \r
3802                 if (("" + this.settings.height).indexOf('%') != -1)\r
3803                         this.settings.area_height = "100%";\r
3804                 else\r
3805                         this.settings.height_style += 'px';\r
3806 \r
3807                 if (("" + replace_element.style.width).indexOf('%') != -1) {\r
3808                         this.settings.width = replace_element.style.width;\r
3809                         this.settings.area_width = "100%";\r
3810                         this.settings.width_style = "100%";\r
3811                 }\r
3812 \r
3813                 if (("" + replace_element.style.height).indexOf('%') != -1) {\r
3814                         this.settings.height = replace_element.style.height;\r
3815                         this.settings.area_height = "100%";\r
3816                         this.settings.height_style = "100%";\r
3817                 }\r
3818 \r
3819                 html = tinyMCE.applyTemplate(html);\r
3820 \r
3821                 this.settings.width = this.settings.old_width;\r
3822                 this.settings.height = this.settings.old_height;\r
3823 \r
3824                 this.visualAid = this.settings.visual;\r
3825                 this.formTargetElementId = form_element_name;\r
3826 \r
3827                 // Get replace_element contents\r
3828                 if (replace_element.nodeName == "TEXTAREA" || replace_element.nodeName == "INPUT")\r
3829                         this.startContent = replace_element.value;\r
3830                 else\r
3831                         this.startContent = replace_element.innerHTML;\r
3832 \r
3833                 // If not text area or input\r
3834                 if (replace_element.nodeName != "TEXTAREA" && replace_element.nodeName != "INPUT") {\r
3835                         this.oldTargetElement = replace_element;\r
3836 \r
3837                         // Debug mode\r
3838                         hc = '<input type="hidden" id="' + form_element_name + '" name="' + form_element_name + '" />';\r
3839                         this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');\r
3840                         this.oldTargetElement.style.display = "none";\r
3841 \r
3842                         html += '</span>';\r
3843 \r
3844                         if (tinyMCE.isGecko)\r
3845                                 html = hc + html;\r
3846                         else\r
3847                                 html += hc;\r
3848 \r
3849                         // Output HTML and set editable\r
3850                         if (tinyMCE.isGecko) {\r
3851                                 rng = replace_element.ownerDocument.createRange();\r
3852                                 rng.setStartBefore(replace_element);\r
3853 \r
3854                                 fragment = rng.createContextualFragment(html);\r
3855                                 tinyMCE.insertAfter(fragment, replace_element);\r
3856                         } else\r
3857                                 replace_element.insertAdjacentHTML("beforeBegin", html);\r
3858                 } else {\r
3859                         html += '</span>';\r
3860 \r
3861                         // Just hide the textarea element\r
3862                         this.oldTargetElement = replace_element;\r
3863 \r
3864                         this.oldTargetDisplay = tinyMCE.getStyle(this.oldTargetElement, 'display', 'inline');\r
3865                         this.oldTargetElement.style.display = "none";\r
3866 \r
3867                         // Output HTML and set editable\r
3868                         if (tinyMCE.isGecko) {\r
3869                                 rng = replace_element.ownerDocument.createRange();\r
3870                                 rng.setStartBefore(replace_element);\r
3871 \r
3872                                 fragment = rng.createContextualFragment(html);\r
3873                                 tinyMCE.insertAfter(fragment, replace_element);\r
3874                         } else\r
3875                                 replace_element.insertAdjacentHTML("beforeBegin", html);\r
3876                 }\r
3877 \r
3878                 // Setup iframe\r
3879                 dynamicIFrame = false;\r
3880                 tElm = targetDoc.getElementById(this.editorId);\r
3881 \r
3882                 if (!tinyMCE.isIE) {\r
3883                         // Node case is preserved in XML strict mode\r
3884                         if (tElm && (tElm.nodeName == "SPAN" || tElm.nodeName == "span")) {\r
3885                                 tElm = tinyMCE._createIFrame(tElm, targetDoc);\r
3886                                 dynamicIFrame = true;\r
3887                         }\r
3888 \r
3889                         this.targetElement = tElm;\r
3890                         this.iframeElement = tElm;\r
3891                         this.contentDocument = tElm.contentDocument;\r
3892                         this.contentWindow = tElm.contentWindow;\r
3893 \r
3894                         //this.getDoc().designMode = "on";\r
3895                 } else {\r
3896                         if (tElm && tElm.nodeName == "SPAN")\r
3897                                 tElm = tinyMCE._createIFrame(tElm, targetDoc, targetDoc.parentWindow);\r
3898                         else\r
3899                                 tElm = targetDoc.frames[this.editorId];\r
3900 \r
3901                         this.targetElement = tElm;\r
3902                         this.iframeElement = targetDoc.getElementById(this.editorId);\r
3903 \r
3904                         if (tinyMCE.isOpera) {\r
3905                                 this.contentDocument = this.iframeElement.contentDocument;\r
3906                                 this.contentWindow = this.iframeElement.contentWindow;\r
3907                                 dynamicIFrame = true;\r
3908                         } else {\r
3909                                 this.contentDocument = tElm.window.document;\r
3910                                 this.contentWindow = tElm.window;\r
3911                         }\r
3912 \r
3913                         this.getDoc().designMode = "on";\r
3914                 }\r
3915 \r
3916                 // Setup base HTML\r
3917                 doc = this.contentDocument;\r
3918                 if (dynamicIFrame) {\r
3919                         html = tinyMCE.getParam('doctype') + '<html><head xmlns="http://www.w3.org/1999/xhtml"><base href="' + tinyMCE.settings.base_href + '" /><title>blank_page</title><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body class="mceContentBody"></body></html>';\r
3920 \r
3921                         try {\r
3922                                 if (!this.isHidden())\r
3923                                         this.getDoc().designMode = "on";\r
3924 \r
3925                                 doc.open();\r
3926                                 doc.write(html);\r
3927                                 doc.close();\r
3928                         } catch (e) {\r
3929                                 // Failed Mozilla 1.3\r
3930                                 this.getDoc().location.href = tinyMCE.baseURL + "/blank.htm";\r
3931                         }\r
3932                 }\r
3933 \r
3934                 // This timeout is needed in MSIE 5.5 for some odd reason\r
3935                 // it seems that the document.frames isn't initialized yet?\r
3936                 if (tinyMCE.isIE)\r
3937                         window.setTimeout("tinyMCE.addEventHandlers(tinyMCE.instances[\"" + this.editorId + "\"]);", 1);\r
3938 \r
3939                 // Setup element references\r
3940                 parentElm = this.targetDoc.getElementById(this.editorId + '_parent');\r
3941                 this.formElement = tinyMCE.isGecko ? parentElm.previousSibling : parentElm.nextSibling;\r
3942 \r
3943                 tinyMCE.setupContent(this.editorId, true);\r
3944 \r
3945                 return true;\r
3946         },\r
3947 \r
3948         setBaseHREF : function(u) {\r
3949                 var h, b, d, nl;\r
3950 \r
3951                 d = this.getDoc();\r
3952                 nl = d.getElementsByTagName("base");\r
3953                 b = nl.length > 0 ? nl[0] : null;\r
3954 \r
3955                 if (!b) {\r
3956                         nl = d.getElementsByTagName("head");\r
3957                         h = nl.length > 0 ? nl[0] : null;\r
3958 \r
3959                         b = d.createElement("base");\r
3960                         b.setAttribute('href', u);\r
3961                         h.appendChild(b);\r
3962                 } else {\r
3963                         if (u == '' || u == null)\r
3964                                 b.parentNode.removeChild(b);\r
3965                         else\r
3966                                 b.setAttribute('href', u);\r
3967                 }\r
3968         },\r
3969 \r
3970         getHTML : function(r) {\r
3971                 var h, d = this.getDoc(), b = this.getBody();\r
3972 \r
3973                 if (r)\r
3974                         return b.innerHTML;\r
3975 \r
3976                 h = tinyMCE._cleanupHTML(this, d, this.settings, b, false, true, false, true);\r
3977 \r
3978                 if (tinyMCE.getParam("convert_fonts_to_spans"))\r
3979                         tinyMCE.convertSpansToFonts(d);\r
3980 \r
3981                 return h;\r
3982         },\r
3983 \r
3984         setHTML : function(h) {\r
3985                 this.execCommand('mceSetContent', false, h);\r
3986                 this.repaint();\r
3987         },\r
3988 \r
3989         getFocusElement : function() {\r
3990                 return this.selection.getFocusElement();\r
3991         },\r
3992 \r
3993         getSel : function() {\r
3994                 return this.selection.getSel();\r
3995         },\r
3996 \r
3997         getRng : function() {\r
3998                 return this.selection.getRng();\r
3999         },\r
4000 \r
4001         triggerSave : function(skip_cleanup, skip_callback) {\r
4002                 var e, nl = [], i, s, content, htm;\r
4003 \r
4004                 if (!this.enabled)\r
4005                         return;\r
4006 \r
4007                 this.switchSettings();\r
4008                 s = tinyMCE.settings;\r
4009 \r
4010                 // Force hidden tabs visible while serializing\r
4011                 if (tinyMCE.isRealIE) {\r
4012                         e = this.iframeElement;\r
4013 \r
4014                         do {\r
4015                                 if (e.style && e.style.display == 'none') {\r
4016                                         e.style.display = 'block';\r
4017                                         nl[nl.length] = {elm : e, type : 'style'};\r
4018                                 }\r
4019 \r
4020                                 if (e.style && s.hidden_tab_class.length > 0 && e.className.indexOf(s.hidden_tab_class) != -1) {\r
4021                                         e.className = s.display_tab_class;\r
4022                                         nl[nl.length] = {elm : e, type : 'class'};\r
4023                                 }\r
4024                         } while ((e = e.parentNode) != null)\r
4025                 }\r
4026 \r
4027                 tinyMCE.settings.preformatted = false;\r
4028 \r
4029                 // Default to false\r
4030                 if (typeof(skip_cleanup) == "undefined")\r
4031                         skip_cleanup = false;\r
4032 \r
4033                 // Default to false\r
4034                 if (typeof(skip_callback) == "undefined")\r
4035                         skip_callback = false;\r
4036 \r
4037                 tinyMCE._setHTML(this.getDoc(), this.getBody().innerHTML);\r
4038 \r
4039                 // Remove visual aids when cleanup is disabled\r
4040                 if (this.settings.cleanup == false) {\r
4041                         tinyMCE.handleVisualAid(this.getBody(), true, false, this);\r
4042                         tinyMCE._setEventsEnabled(this.getBody(), true);\r
4043                 }\r
4044 \r
4045                 tinyMCE._customCleanup(this, "submit_content_dom", this.contentWindow.document.body);\r
4046                 htm = skip_cleanup ? this.getBody().innerHTML : tinyMCE._cleanupHTML(this, this.getDoc(), this.settings, this.getBody(), tinyMCE.visualAid, true, true);\r
4047                 htm = tinyMCE._customCleanup(this, "submit_content", htm);\r
4048 \r
4049                 if (!skip_callback && tinyMCE.settings.save_callback !== '')\r
4050                         content = tinyMCE.resolveDots(tinyMCE.settings.save_callback, window)(this.formTargetElementId,htm,this.getBody());\r
4051 \r
4052                 // Use callback content if available\r
4053                 if ((typeof(content) != "undefined") && content != null)\r
4054                         htm = content;\r
4055 \r
4056                 // Replace some weird entities (Bug: #1056343)\r
4057                 htm = tinyMCE.regexpReplace(htm, "&#40;", "(", "gi");\r
4058                 htm = tinyMCE.regexpReplace(htm, "&#41;", ")", "gi");\r
4059                 htm = tinyMCE.regexpReplace(htm, "&#59;", ";", "gi");\r
4060                 htm = tinyMCE.regexpReplace(htm, "&#34;", "&quot;", "gi");\r
4061                 htm = tinyMCE.regexpReplace(htm, "&#94;", "^", "gi");\r
4062 \r
4063                 if (this.formElement)\r
4064                         this.formElement.value = htm;\r
4065 \r
4066                 if (tinyMCE.isSafari && this.formElement)\r
4067                         this.formElement.innerText = htm;\r
4068 \r
4069                 // Hide them again (tabs in MSIE)\r
4070                 for (i=0; i<nl.length; i++) {\r
4071                         if (nl[i].type == 'style')\r
4072                                 nl[i].elm.style.display = 'none';\r
4073                         else\r
4074                                 nl[i].elm.className = s.hidden_tab_class;\r
4075                 }\r
4076         }\r
4077 \r
4078         };\r
4079 \r
4080 /* file:jscripts/tiny_mce/classes/TinyMCE_Cleanup.class.js */\r
4081 \r
4082 tinyMCE.add(TinyMCE_Engine, {\r
4083         cleanupHTMLCode : function(s) {\r
4084                 s = s.replace(new RegExp('<p \\/>', 'gi'), '<p>&nbsp;</p>');\r
4085                 s = s.replace(new RegExp('<p>\\s*<\\/p>', 'gi'), '<p>&nbsp;</p>');\r
4086 \r
4087                 // Fix close BR elements\r
4088                 s = s.replace(new RegExp('<br>\\s*<\\/br>', 'gi'), '<br />');\r
4089 \r
4090                 // Open closed tags like <b/> to <b></b>\r
4091                 s = s.replace(new RegExp('<(h[1-6]|p|div|address|pre|form|table|li|ol|ul|td|b|font|em|strong|i|strike|u|span|a|ul|ol|li|blockquote)([a-z]*)([^\\\\|>]*)\\/>', 'gi'), '<$1$2$3></$1$2>');\r
4092 \r
4093                 // Remove trailing space <b > to <b>\r
4094                 s = s.replace(new RegExp('\\s+></', 'gi'), '></');\r
4095 \r
4096                 // Close tags <img></img> to <img/>\r
4097                 s = s.replace(new RegExp('<(img|br|hr)([^>]*)><\\/(img|br|hr)>', 'gi'), '<$1$2 />');\r
4098 \r
4099                 // Weird MSIE bug, <p><hr /></p> breaks runtime?\r
4100                 if (tinyMCE.isIE)\r
4101                         s = s.replace(new RegExp('<p><hr \\/><\\/p>', 'gi'), "<hr>");\r
4102 \r
4103                 // Weird tags will make IE error #bug: 1538495\r
4104                 if (tinyMCE.isIE)\r
4105                         s = s.replace(/<!(\s*)\/>/g, '');\r
4106 \r
4107                 // Convert relative anchors to absolute URLs ex: #something to file.htm#something\r
4108                 // Removed: Since local document anchors should never be forced absolute example edit.php?id=something\r
4109                 //if (tinyMCE.getParam('convert_urls'))\r
4110                 //      s = s.replace(new RegExp('(href=\"{0,1})(\\s*#)', 'gi'), '$1' + tinyMCE.settings.document_base_url + "#");\r
4111 \r
4112                 return s;\r
4113         },\r
4114 \r
4115         parseStyle : function(str) {\r
4116                 var ar = [], st, i, re, pa;\r
4117 \r
4118                 if (str == null)\r
4119                         return ar;\r
4120 \r
4121                 st = str.split(';');\r
4122 \r
4123                 tinyMCE.clearArray(ar);\r
4124 \r
4125                 for (i=0; i<st.length; i++) {\r
4126                         if (st[i] == '')\r
4127                                 continue;\r
4128 \r
4129                         re = new RegExp('^\\s*([^:]*):\\s*(.*)\\s*$');\r
4130                         pa = st[i].replace(re, '$1||$2').split('||');\r
4131         //tinyMCE.debug(str, pa[0] + "=" + pa[1], st[i].replace(re, '$1||$2'));\r
4132                         if (pa.length == 2)\r
4133                                 ar[pa[0].toLowerCase()] = pa[1];\r
4134                 }\r
4135 \r
4136                 return ar;\r
4137         },\r
4138 \r
4139         compressStyle : function(ar, pr, sf, res) {\r
4140                 var box = [], i, a;\r
4141 \r
4142                 box[0] = ar[pr + '-top' + sf];\r
4143                 box[1] = ar[pr + '-left' + sf];\r
4144                 box[2] = ar[pr + '-right' + sf];\r
4145                 box[3] = ar[pr + '-bottom' + sf];\r
4146 \r
4147                 for (i=0; i<box.length; i++) {\r
4148                         if (box[i] == null)\r
4149                                 return;\r
4150 \r
4151                         if (i && box[i] != box[i-1])\r
4152                                 return;\r
4153                 }\r
4154 \r
4155                 // They are all the same\r
4156                 ar[res] = box[0];\r
4157                 ar[pr + '-top' + sf] = null;\r
4158                 ar[pr + '-left' + sf] = null;\r
4159                 ar[pr + '-right' + sf] = null;\r
4160                 ar[pr + '-bottom' + sf] = null;\r
4161         },\r
4162 \r
4163         serializeStyle : function(ar) {\r
4164                 var str = "", key, val, m;\r
4165 \r
4166                 // Compress box\r
4167                 tinyMCE.compressStyle(ar, "border", "", "border");\r
4168                 tinyMCE.compressStyle(ar, "border", "-width", "border-width");\r
4169                 tinyMCE.compressStyle(ar, "border", "-color", "border-color");\r
4170                 tinyMCE.compressStyle(ar, "border", "-style", "border-style");\r
4171                 tinyMCE.compressStyle(ar, "padding", "", "padding");\r
4172                 tinyMCE.compressStyle(ar, "margin", "", "margin");\r
4173 \r
4174                 for (key in ar) {\r
4175                         val = ar[key];\r
4176 \r
4177                         if (typeof(val) == 'function')\r
4178                                 continue;\r
4179 \r
4180                         if (key.indexOf('mso-') == 0)\r
4181                                 continue;\r
4182 \r
4183                         if (val != null && val !== '') {\r
4184                                 val = '' + val; // Force string\r
4185 \r
4186                                 // Fix style URL\r
4187                                 val = val.replace(new RegExp("url\\(\\'?([^\\']*)\\'?\\)", 'gi'), "url('$1')");\r
4188 \r
4189                                 // Convert URL\r
4190                                 if (val.indexOf('url(') != -1 && tinyMCE.getParam('convert_urls')) {\r
4191                                         m = new RegExp("url\\('(.*?)'\\)").exec(val);\r
4192 \r
4193                                         if (m.length > 1)\r
4194                                                 val = "url('" + eval(tinyMCE.getParam('urlconverter_callback') + "(m[1], null, true);") + "')";\r
4195                                 }\r
4196 \r
4197                                 // Force HEX colors\r
4198                                 if (tinyMCE.getParam("force_hex_style_colors"))\r
4199                                         val = tinyMCE.convertRGBToHex(val, true);\r
4200 \r
4201                                 val = val.replace(/\"/g, '\'');\r
4202 \r
4203                                 if (val != "url('')")\r
4204                                         str += key.toLowerCase() + ": " + val + "; ";\r
4205                         }\r
4206                 }\r
4207 \r
4208                 if (new RegExp('; $').test(str))\r
4209                         str = str.substring(0, str.length - 2);\r
4210 \r
4211                 return str;\r
4212         },\r
4213 \r
4214         convertRGBToHex : function(s, k) {\r
4215                 var re, rgb;\r
4216 \r
4217                 if (s.toLowerCase().indexOf('rgb') != -1) {\r
4218                         re = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");\r
4219                         rgb = s.replace(re, "$1,$2,$3,$4,$5").split(',');\r
4220 \r
4221                         if (rgb.length == 5) {\r
4222                                 r = parseInt(rgb[1]).toString(16);\r
4223                                 g = parseInt(rgb[2]).toString(16);\r
4224                                 b = parseInt(rgb[3]).toString(16);\r
4225 \r
4226                                 r = r.length == 1 ? '0' + r : r;\r
4227                                 g = g.length == 1 ? '0' + g : g;\r
4228                                 b = b.length == 1 ? '0' + b : b;\r
4229 \r
4230                                 s = "#" + r + g + b;\r
4231 \r
4232                                 if (k)\r
4233                                         s = rgb[0] + s + rgb[4];\r
4234                         }\r
4235                 }\r
4236 \r
4237                 return s;\r
4238         },\r
4239 \r
4240         convertHexToRGB : function(s) {\r
4241                 if (s.indexOf('#') != -1) {\r
4242                         s = s.replace(new RegExp('[^0-9A-F]', 'gi'), '');\r
4243                         return "rgb(" + parseInt(s.substring(0, 2), 16) + "," + parseInt(s.substring(2, 4), 16) + "," + parseInt(s.substring(4, 6), 16) + ")";\r
4244                 }\r
4245 \r
4246                 return s;\r
4247         },\r
4248 \r
4249         convertSpansToFonts : function(doc) {\r
4250                 var s, i, size, fSize, x, fFace, fColor, sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');\r
4251 \r
4252                 s = tinyMCE.selectElements(doc, 'span,font');\r
4253                 for (i=0; i<s.length; i++) {\r
4254                         size = tinyMCE.trim(s[i].style.fontSize).toLowerCase();\r
4255                         fSize = 0;\r
4256 \r
4257                         for (x=0; x<sizes.length; x++) {\r
4258                                 if (sizes[x] == size) {\r
4259                                         fSize = x + 1;\r
4260                                         break;\r
4261                                 }\r
4262                         }\r
4263 \r
4264                         if (fSize > 0) {\r
4265                                 tinyMCE.setAttrib(s[i], 'size', fSize);\r
4266                                 s[i].style.fontSize = '';\r
4267                         }\r
4268 \r
4269                         fFace = s[i].style.fontFamily;\r
4270                         if (fFace != null && fFace !== '') {\r
4271                                 tinyMCE.setAttrib(s[i], 'face', fFace);\r
4272                                 s[i].style.fontFamily = '';\r
4273                         }\r
4274 \r
4275                         fColor = s[i].style.color;\r
4276                         if (fColor != null && fColor !== '') {\r
4277                                 tinyMCE.setAttrib(s[i], 'color', tinyMCE.convertRGBToHex(fColor));\r
4278                                 s[i].style.color = '';\r
4279                         }\r
4280                 }\r
4281         },\r
4282 \r
4283         convertFontsToSpans : function(doc) {\r
4284                 var fsClasses, s, i, fSize, fFace, fColor, sizes = tinyMCE.getParam('font_size_style_values').replace(/\s+/, '').split(',');\r
4285 \r
4286                 fsClasses = tinyMCE.getParam('font_size_classes');\r
4287                 if (fsClasses !== '')\r
4288                         fsClasses = fsClasses.replace(/\s+/, '').split(',');\r
4289                 else\r
4290                         fsClasses = null;\r
4291 \r
4292                 s = tinyMCE.selectElements(doc, 'span,font');\r
4293                 for (i=0; i<s.length; i++) {\r
4294                         fSize = tinyMCE.getAttrib(s[i], 'size');\r
4295                         fFace = tinyMCE.getAttrib(s[i], 'face');\r
4296                         fColor = tinyMCE.getAttrib(s[i], 'color');\r
4297 \r
4298                         if (fSize !== '') {\r
4299                                 fSize = parseInt(fSize);\r
4300 \r
4301                                 if (fSize > 0 && fSize < 8) {\r
4302                                         if (fsClasses != null)\r
4303                                                 tinyMCE.setAttrib(s[i], 'class', fsClasses[fSize-1]);\r
4304                                         else\r
4305                                                 s[i].style.fontSize = sizes[fSize-1];\r
4306                                 }\r
4307 \r
4308                                 s[i].removeAttribute('size');\r
4309                         }\r
4310 \r
4311                         if (fFace !== '') {\r
4312                                 s[i].style.fontFamily = fFace;\r
4313                                 s[i].removeAttribute('face');\r
4314                         }\r
4315 \r
4316                         if (fColor !== '') {\r
4317                                 s[i].style.color = fColor;\r
4318                                 s[i].removeAttribute('color');\r
4319                         }\r
4320                 }\r
4321         },\r
4322 \r
4323         cleanupAnchors : function(doc) {\r
4324                 var i, cn, x, an = doc.getElementsByTagName("a");\r
4325 \r
4326                 // Loops backwards due to bug #1467987\r
4327                 for (i=an.length-1; i>=0; i--) {\r
4328                         if (tinyMCE.getAttrib(an[i], "name") !== '' && tinyMCE.getAttrib(an[i], "href") == '') {\r
4329                                 cn = an[i].childNodes;\r
4330 \r
4331                                 for (x=cn.length-1; x>=0; x--)\r
4332                                         tinyMCE.insertAfter(cn[x], an[i]);\r
4333                         }\r
4334                 }\r
4335         },\r
4336 \r
4337         getContent : function(editor_id) {\r
4338                 if (typeof(editor_id) != "undefined")\r
4339                          tinyMCE.getInstanceById(editor_id).select();\r
4340 \r
4341                 if (tinyMCE.selectedInstance)\r
4342                         return tinyMCE.selectedInstance.getHTML();\r
4343 \r
4344                 return null;\r
4345         },\r
4346 \r
4347         _fixListElements : function(d) {\r
4348                 var nl, x, a = ['ol', 'ul'], i, n, p, r = new RegExp('^(OL|UL)$'), np;\r
4349 \r
4350                 for (x=0; x<a.length; x++) {\r
4351                         nl = d.getElementsByTagName(a[x]);\r
4352 \r
4353                         for (i=0; i<nl.length; i++) {\r
4354                                 n = nl[i];\r
4355                                 p = n.parentNode;\r
4356 \r
4357                                 if (r.test(p.nodeName)) {\r
4358                                         np = tinyMCE.prevNode(n, 'LI');\r
4359 \r
4360                                         if (!np) {\r
4361                                                 np = d.createElement('li');\r
4362                                                 np.innerHTML = '&nbsp;';\r
4363                                                 np.appendChild(n);\r
4364                                                 p.insertBefore(np, p.firstChild);\r
4365                                         } else\r
4366                                                 np.appendChild(n);\r
4367                                 }\r
4368                         }\r
4369                 }\r
4370         },\r
4371 \r
4372         _fixTables : function(d) {\r
4373                 var nl, i, n, p, np, x, t;\r
4374 \r
4375                 nl = d.getElementsByTagName('table');\r
4376                 for (i=0; i<nl.length; i++) {\r
4377                         n = nl[i];\r
4378 \r
4379                         if ((p = tinyMCE.getParentElement(n, 'p,h1,h2,h3,h4,h5,h6')) != null) {\r
4380                                 np = p.cloneNode(false);\r
4381                                 np.removeAttribute('id');\r
4382 \r
4383                                 t = n;\r
4384 \r
4385                                 while ((n = n.nextSibling))\r
4386                                         np.appendChild(n);\r
4387 \r
4388                                 tinyMCE.insertAfter(np, p);\r
4389                                 tinyMCE.insertAfter(t, p);\r
4390                         }\r
4391                 }\r
4392         },\r
4393 \r
4394         _cleanupHTML : function(inst, doc, config, elm, visual, on_save, on_submit, inn) {\r
4395                 var h, d, t1, t2, t3, t4, t5, c, s, nb;\r
4396 \r
4397                 if (!tinyMCE.getParam('cleanup'))\r
4398                         return elm.innerHTML;\r
4399 \r
4400                 on_save = typeof(on_save) == 'undefined' ? false : on_save;\r
4401 \r
4402                 c = inst.cleanup;\r
4403                 s = inst.settings;\r
4404                 d = c.settings.debug;\r
4405 \r
4406                 if (d)\r
4407                         t1 = new Date().getTime();\r
4408 \r
4409                 inst._fixRootBlocks();\r
4410 \r
4411                 if (tinyMCE.getParam("convert_fonts_to_spans"))\r
4412                         tinyMCE.convertFontsToSpans(doc);\r
4413 \r
4414                 if (tinyMCE.getParam("fix_list_elements"))\r
4415                         tinyMCE._fixListElements(doc);\r
4416 \r
4417                 if (tinyMCE.getParam("fix_table_elements"))\r
4418                         tinyMCE._fixTables(doc);\r
4419 \r
4420                 // Call custom cleanup code\r
4421                 tinyMCE._customCleanup(inst, on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body);\r
4422 \r
4423                 if (d)\r
4424                         t2 = new Date().getTime();\r
4425 \r
4426                 c.settings.on_save = on_save;\r
4427 \r
4428                 c.idCount = 0;\r
4429                 c.serializationId++; // Unique ID needed for the content duplication bug\r
4430                 c.serializedNodes = [];\r
4431                 c.sourceIndex = -1;\r
4432 \r
4433                 if (s.cleanup_serializer == "xml")\r
4434                         h = c.serializeNodeAsXML(elm, inn);\r
4435                 else\r
4436                         h = c.serializeNodeAsHTML(elm, inn);\r
4437 \r
4438                 if (d)\r
4439                         t3 = new Date().getTime();\r
4440 \r
4441                 // Post processing\r
4442                 nb = tinyMCE.getParam('entity_encoding') == 'numeric' ? '&#160;' : '&nbsp;';\r
4443                 h = h.replace(/<\/?(body|head|html)[^>]*>/gi, '');\r
4444                 h = h.replace(new RegExp(' (rowspan="1"|colspan="1")', 'g'), '');\r
4445                 h = h.replace(/<p><hr \/><\/p>/g, '<hr />');\r
4446                 h = h.replace(/<p>(&nbsp;|&#160;)<\/p><hr \/><p>(&nbsp;|&#160;)<\/p>/g, '<hr />');\r
4447                 h = h.replace(/<td>\s*<br \/>\s*<\/td>/g, '<td>' + nb + '</td>');\r
4448                 h = h.replace(/<p>\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');\r
4449                 h = h.replace(/<br \/>$/, ''); // Remove last BR for Gecko\r
4450                 h = h.replace(/<br \/><\/p>/g, '</p>'); // Remove last BR in P tags for Gecko\r
4451                 h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*(&nbsp;|&#160;)\s*<\/p>/g, '<p>' + nb + '</p>');\r
4452                 h = h.replace(/<p>\s*(&nbsp;|&#160;)\s*<br \/>\s*<\/p>/g, '<p>' + nb + '</p>');\r
4453                 h = h.replace(/<p>\s*<br \/>\s*&nbsp;\s*<\/p>/g, '<p>' + nb + '</p>');\r
4454                 h = h.replace(new RegExp('<a>(.*?)<\\/a>', 'g'), '$1');\r
4455                 h = h.replace(/<p([^>]*)>\s*<\/p>/g, '<p$1>' + nb + '</p>');\r
4456 \r
4457                 // Clean body\r
4458                 if (/^\s*(<br \/>|<p>&nbsp;<\/p>|<p>&#160;<\/p>|<p><\/p>)\s*$/.test(h))\r
4459                         h = '';\r
4460 \r
4461                 // If preformatted\r
4462                 if (s.preformatted) {\r
4463                         h = h.replace(/^<pre>/, '');\r
4464                         h = h.replace(/<\/pre>$/, '');\r
4465                         h = '<pre>' + h + '</pre>';\r
4466                 }\r
4467 \r
4468                 // Gecko specific processing\r
4469                 if (tinyMCE.isGecko) {\r
4470                         // Makes no sence but FF generates it!!\r
4471                         h = h.replace(/<br \/>\s*<\/li>/g, '</li>');\r
4472                         h = h.replace(/&nbsp;\s*<\/(dd|dt)>/g, '</$1>');\r
4473                         h = h.replace(/<o:p _moz-userdefined="" \/>/g, '');\r
4474                         h = h.replace(/<td([^>]*)>\s*<br \/>\s*<\/td>/g, '<td$1>' + nb + '</td>');\r
4475                 }\r
4476 \r
4477                 if (s.force_br_newlines)\r
4478                         h = h.replace(/<p>(&nbsp;|&#160;)<\/p>/g, '<br />');\r
4479 \r
4480                 // Call custom cleanup code\r
4481                 h = tinyMCE._customCleanup(inst, on_save ? "get_from_editor" : "insert_to_editor", h);\r
4482 \r
4483                 // Remove internal classes\r
4484                 if (on_save) {\r
4485                         h = h.replace(new RegExp(' ?(mceItem[a-zA-Z0-9]*|' + s.visual_table_class + ')', 'g'), '');\r
4486                         h = h.replace(new RegExp(' ?class=""', 'g'), '');\r
4487                 }\r
4488 \r
4489                 if (s.remove_linebreaks && !c.settings.indent)\r
4490                         h = h.replace(/\n|\r/g, ' ');\r
4491 \r
4492                 if (d)\r
4493                         t4 = new Date().getTime();\r
4494 \r
4495                 if (on_save && c.settings.indent)\r
4496                         h = c.formatHTML(h);\r
4497 \r
4498                 // If encoding (not recommended option)\r
4499                 if (on_submit && (s.encoding == "xml" || s.encoding == "html"))\r
4500                         h = c.xmlEncode(h);\r
4501 \r
4502                 if (d)\r
4503                         t5 = new Date().getTime();\r
4504 \r
4505                 if (c.settings.debug)\r
4506                         tinyMCE.debug("Cleanup in ms: Pre=" + (t2-t1) + ", Serialize: " + (t3-t2) + ", Post: " + (t4-t3) + ", Format: " + (t5-t4) + ", Sum: " + (t5-t1) + ".");\r
4507 \r
4508                 return h;\r
4509         }\r
4510 });\r
4511 \r
4512 function TinyMCE_Cleanup() {\r
4513         this.isIE = (navigator.appName == "Microsoft Internet Explorer");\r
4514         this.rules = tinyMCE.clearArray([]);\r
4515 \r
4516         // Default config\r
4517         this.settings = {\r
4518                 indent_elements : 'head,table,tbody,thead,tfoot,form,tr,ul,ol,blockquote,object',\r
4519                 newline_before_elements : 'h1,h2,h3,h4,h5,h6,pre,address,div,ul,ol,li,meta,option,area,title,link,base,script,td',\r
4520                 newline_after_elements : 'br,hr,p,pre,address,div,ul,ol,meta,option,area,link,base,script',\r
4521                 newline_before_after_elements : 'html,head,body,table,thead,tbody,tfoot,tr,form,ul,ol,blockquote,p,object,param,hr,div',\r
4522                 indent_char : '\t',\r
4523                 indent_levels : 1,\r
4524                 entity_encoding : 'raw',\r
4525                 valid_elements : '*[*]',\r
4526                 entities : '',\r
4527                 url_converter : '',\r
4528                 invalid_elements : '',\r
4529                 verify_html : false\r
4530         };\r
4531 \r
4532         this.vElements = tinyMCE.clearArray([]);\r
4533         this.vElementsRe = '';\r
4534         this.closeElementsRe = /^(IMG|BR|HR|LINK|META|BASE|INPUT|AREA)$/;\r
4535         this.codeElementsRe = /^(SCRIPT|STYLE)$/;\r
4536         this.serializationId = 0;\r
4537         this.mceAttribs = {\r
4538                 href : 'mce_href',\r
4539                 src : 'mce_src',\r
4540                 type : 'mce_type'\r
4541         };\r
4542 }\r
4543 \r
4544 TinyMCE_Cleanup.prototype = {\r
4545         init : function(s) {\r
4546                 var n, a, i, ir, or, st;\r
4547 \r
4548                 for (n in s)\r
4549                         this.settings[n] = s[n];\r
4550 \r
4551                 // Setup code formating\r
4552                 s = this.settings;\r
4553 \r
4554                 // Setup regexps\r
4555                 this.inRe = this._arrayToRe(s.indent_elements.split(','), '', '^<(', ')[^>]*');\r
4556                 this.ouRe = this._arrayToRe(s.indent_elements.split(','), '', '^<\\/(', ')[^>]*');\r
4557                 this.nlBeforeRe = this._arrayToRe(s.newline_before_elements.split(','), 'gi', '<(',  ')([^>]*)>');\r
4558                 this.nlAfterRe = this._arrayToRe(s.newline_after_elements.split(','), 'gi', '<(',  ')([^>]*)>');\r
4559                 this.nlBeforeAfterRe = this._arrayToRe(s.newline_before_after_elements.split(','), 'gi', '<(\\/?)(', ')([^>]*)>');\r
4560                 this.serializedNodes = [];\r
4561                 this.serializationId = 0;\r
4562 \r
4563                 if (s.invalid_elements !== '')\r
4564                         this.iveRe = this._arrayToRe(s.invalid_elements.toUpperCase().split(','), 'g', '^(', ')$');\r
4565                 else\r
4566                         this.iveRe = null;\r
4567 \r
4568                 // Setup separator\r
4569                 st = '';\r
4570                 for (i=0; i<s.indent_levels; i++)\r
4571                         st += s.indent_char;\r
4572 \r
4573                 this.inStr = st;\r
4574 \r
4575                 // If verify_html if false force *[*]\r
4576                 if (!s.verify_html) {\r
4577                         s.valid_elements = '*[*]';\r
4578                         s.extended_valid_elements = '';\r
4579                 }\r
4580 \r
4581                 this.fillStr = s.entity_encoding == "named" ? "&nbsp;" : "&#160;";\r
4582                 this.idCount = 0;\r
4583                 this.xmlEncodeRe = new RegExp('[\u007F-\uFFFF<>&"]', 'g');\r
4584         },\r
4585 \r
4586         addRuleStr : function(s) {\r
4587                 var r = this.parseRuleStr(s), n;\r
4588 \r
4589                 for (n in r) {\r
4590                         if (r[n])\r
4591                                 this.rules[n] = r[n];\r
4592                 }\r
4593 \r
4594                 this.vElements = tinyMCE.clearArray([]);\r
4595 \r
4596                 for (n in this.rules) {\r
4597                         if (this.rules[n])\r
4598                                 this.vElements[this.vElements.length] = this.rules[n].tag;\r
4599                 }\r
4600 \r
4601                 this.vElementsRe = this._arrayToRe(this.vElements, '');\r
4602         },\r
4603 \r
4604         isValid : function(n) {\r
4605                 if (!this.rulesDone)\r
4606                         this._setupRules(); // Will initialize cleanup rules\r
4607 \r
4608                 // Empty is true since it removes formatting\r
4609                 if (!n)\r
4610                         return true;\r
4611 \r
4612                 // Clean the name up a bit\r
4613                 n = n.replace(/[^a-z0-9]+/gi, '').toUpperCase();\r
4614 \r
4615                 return !tinyMCE.getParam('cleanup') || this.vElementsRe.test(n);\r
4616         },\r
4617 \r
4618         addChildRemoveRuleStr : function(s) {\r
4619                 var x, y, p, i, t, tn, ta, cl, r;\r
4620 \r
4621                 if (!s)\r
4622                         return;\r
4623 \r
4624                 ta = s.split(',');\r
4625                 for (x=0; x<ta.length; x++) {\r
4626                         s = ta[x];\r
4627 \r
4628                         // Split tag/children\r
4629                         p = this.split(/\[|\]/, s);\r
4630                         if (p == null || p.length < 1)\r
4631                                 t = s.toUpperCase();\r
4632                         else\r
4633                                 t = p[0].toUpperCase();\r
4634 \r
4635                         // Handle all tag names\r
4636                         tn = this.split('/', t);\r
4637                         for (y=0; y<tn.length; y++) {\r
4638                                 r = "^(";\r
4639 \r
4640                                 // Build regex\r
4641                                 cl = this.split(/\|/, p[1]);\r
4642                                 for (i=0; i<cl.length; i++) {\r
4643                                         if (cl[i] == '%istrict')\r
4644                                                 r += tinyMCE.inlineStrict;\r
4645                                         else if (cl[i] == '%itrans')\r
4646                                                 r += tinyMCE.inlineTransitional;\r
4647                                         else if (cl[i] == '%istrict_na')\r
4648                                                 r += tinyMCE.inlineStrict.substring(2);\r
4649                                         else if (cl[i] == '%itrans_na')\r
4650                                                 r += tinyMCE.inlineTransitional.substring(2);\r
4651                                         else if (cl[i] == '%btrans')\r
4652                                                 r += tinyMCE.blockElms;\r
4653                                         else if (cl[i] == '%strict')\r
4654                                                 r += tinyMCE.blockStrict;\r
4655                                         else\r
4656                                                 r += (cl[i].charAt(0) != '#' ? cl[i].toUpperCase() : cl[i]);\r
4657 \r
4658                                         r += (i != cl.length - 1 ? '|' : '');\r
4659                                 }\r
4660 \r
4661                                 r += ')$';\r
4662 \r
4663                                 if (this.childRules == null)\r
4664                                         this.childRules = tinyMCE.clearArray([]);\r
4665 \r
4666                                 this.childRules[tn[y]] = new RegExp(r);\r
4667 \r
4668                                 if (p.length > 1)\r
4669                                         this.childRules[tn[y]].wrapTag = p[2];\r
4670                         }\r
4671                 }\r
4672         },\r
4673 \r
4674         parseRuleStr : function(s) {\r
4675                 var ta, p, r, a, i, x, px, t, tn, y, av, or = tinyMCE.clearArray([]), dv;\r
4676 \r
4677                 if (s == null || s.length == 0)\r
4678                         return or;\r
4679 \r
4680                 ta = s.split(',');\r
4681                 for (x=0; x<ta.length; x++) {\r
4682                         s = ta[x];\r
4683                         if (s.length == 0)\r
4684                                 continue;\r
4685 \r
4686                         // Split tag/attrs\r
4687                         p = this.split(/\[|\]/, s);\r
4688                         if (p == null || p.length < 1)\r
4689                                 t = s.toUpperCase();\r
4690                         else\r
4691                                 t = p[0].toUpperCase();\r
4692 \r
4693                         // Handle all tag names\r
4694                         tn = this.split('/', t);\r
4695                         for (y=0; y<tn.length; y++) {\r
4696                                 r = {};\r
4697 \r
4698                                 r.tag = tn[y];\r
4699                                 r.forceAttribs = null;\r
4700                                 r.defaultAttribs = null;\r
4701                                 r.validAttribValues = null;\r
4702 \r
4703                                 // Handle prefixes\r
4704                                 px = r.tag.charAt(0);\r
4705                                 r.forceOpen = px == '+';\r
4706                                 r.removeEmpty = px == '-';\r
4707                                 r.fill = px == '#';\r
4708                                 r.tag = r.tag.replace(/\+|-|#/g, '');\r
4709                                 r.oTagName = tn[0].replace(/\+|-|#/g, '').toLowerCase();\r
4710                                 r.isWild = new RegExp('\\*|\\?|\\+', 'g').test(r.tag);\r
4711                                 r.validRe = new RegExp(this._wildcardToRe('^' + r.tag + '$'));\r
4712 \r
4713                                 // Setup valid attributes\r
4714                                 if (p.length > 1) {\r
4715                                         r.vAttribsRe = '^(';\r
4716                                         a = this.split(/\|/, p[1]);\r
4717 \r
4718                                         for (i=0; i<a.length; i++) {\r
4719                                                 t = a[i];\r
4720 \r
4721                                                 if (t.charAt(0) == '!') {\r
4722                                                         a[i] = t = t.substring(1);\r
4723 \r
4724                                                         if (!r.reqAttribsRe)\r
4725                                                                 r.reqAttribsRe = '\\s+(' + t;\r
4726                                                         else\r
4727                                                                 r.reqAttribsRe += '|' + t;\r
4728                                                 }\r
4729 \r
4730                                                 av = new RegExp('(=|:|<)(.*?)$').exec(t);\r
4731                                                 t = t.replace(new RegExp('(=|:|<).*?$'), '');\r
4732                                                 if (av && av.length > 0) {\r
4733                                                         if (av[0].charAt(0) == ':') {\r
4734                                                                 if (!r.forceAttribs)\r
4735                                                                         r.forceAttribs = tinyMCE.clearArray([]);\r
4736 \r
4737                                                                 r.forceAttribs[t.toLowerCase()] = av[0].substring(1);\r
4738                                                         } else if (av[0].charAt(0) == '=') {\r
4739                                                                 if (!r.defaultAttribs)\r
4740                                                                         r.defaultAttribs = tinyMCE.clearArray([]);\r
4741 \r
4742                                                                 dv = av[0].substring(1);\r
4743 \r
4744                                                                 r.defaultAttribs[t.toLowerCase()] = dv == '' ? "mce_empty" : dv;\r
4745                                                         } else if (av[0].charAt(0) == '<') {\r
4746                                                                 if (!r.validAttribValues)\r
4747                                                                         r.validAttribValues = tinyMCE.clearArray([]);\r
4748 \r
4749                                                                 r.validAttribValues[t.toLowerCase()] = this._arrayToRe(this.split('?', av[0].substring(1)), 'i');\r
4750                                                         }\r
4751                                                 }\r
4752 \r
4753                                                 r.vAttribsRe += '' + t.toLowerCase() + (i != a.length - 1 ? '|' : '');\r
4754 \r
4755                                                 a[i] = t.toLowerCase();\r
4756                                         }\r
4757 \r
4758                                         if (r.reqAttribsRe)\r
4759                                                 r.reqAttribsRe = new RegExp(r.reqAttribsRe + ')=\"', 'g');\r
4760 \r
4761                                         r.vAttribsRe += ')$';\r
4762                                         r.vAttribsRe = this._wildcardToRe(r.vAttribsRe);\r
4763                                         r.vAttribsReIsWild = new RegExp('\\*|\\?|\\+', 'g').test(r.vAttribsRe);\r
4764                                         r.vAttribsRe = new RegExp(r.vAttribsRe);\r
4765                                         r.vAttribs = a.reverse();\r
4766 \r
4767                                         //tinyMCE.debug(r.tag, r.oTagName, r.vAttribsRe, r.vAttribsReWC);\r
4768                                 } else {\r
4769                                         r.vAttribsRe = '';\r
4770                                         r.vAttribs = tinyMCE.clearArray([]);\r
4771                                         r.vAttribsReIsWild = false;\r
4772                                 }\r
4773 \r
4774                                 or[r.tag] = r;\r
4775                         }\r
4776                 }\r
4777 \r
4778                 return or;\r
4779         },\r
4780 \r
4781         serializeNodeAsXML : function(n) {\r
4782                 var s, b;\r
4783 \r
4784                 if (!this.xmlDoc) {\r
4785                         if (this.isIE) {\r
4786                                 try {this.xmlDoc = new ActiveXObject('MSXML2.DOMDocument');} catch (e) {}\r
4787 \r
4788                                 if (!this.xmlDoc)\r
4789                                         try {this.xmlDoc = new ActiveXObject('Microsoft.XmlDom');} catch (e) {}\r
4790                         } else\r
4791                                 this.xmlDoc = document.implementation.createDocument('', '', null);\r
4792 \r
4793                         if (!this.xmlDoc)\r
4794                                 alert("Error XML Parser could not be found.");\r
4795                 }\r
4796 \r
4797                 if (this.xmlDoc.firstChild)\r
4798                         this.xmlDoc.removeChild(this.xmlDoc.firstChild);\r
4799 \r
4800                 b = this.xmlDoc.createElement("html");\r
4801                 b = this.xmlDoc.appendChild(b);\r
4802 \r
4803                 this._convertToXML(n, b);\r
4804 \r
4805                 if (this.isIE)\r
4806                         return this.xmlDoc.xml;\r
4807                 else\r
4808                         return new XMLSerializer().serializeToString(this.xmlDoc);\r
4809         },\r
4810 \r
4811         _convertToXML : function(n, xn) {\r
4812                 var xd, el, i, l, cn, at, no, hc = false;\r
4813 \r
4814                 if (tinyMCE.isRealIE && this._isDuplicate(n))\r
4815                         return;\r
4816 \r
4817                 xd = this.xmlDoc;\r
4818 \r
4819                 switch (n.nodeType) {\r
4820                         case 1: // Element\r
4821                                 hc = n.hasChildNodes();\r
4822 \r
4823                                 el = xd.createElement(n.nodeName.toLowerCase());\r
4824 \r
4825                                 at = n.attributes;\r
4826                                 for (i=at.length-1; i>-1; i--) {\r
4827                                         no = at[i];\r
4828 \r
4829                                         if (no.specified && no.nodeValue)\r
4830                                                 el.setAttribute(no.nodeName.toLowerCase(), no.nodeValue);\r
4831                                 }\r
4832 \r
4833                                 if (!hc && !this.closeElementsRe.test(n.nodeName))\r
4834                                         el.appendChild(xd.createTextNode(""));\r
4835 \r
4836                                 xn = xn.appendChild(el);\r
4837                                 break;\r
4838 \r
4839                         case 3: // Text\r
4840                                 xn.appendChild(xd.createTextNode(n.nodeValue));\r
4841                                 return;\r
4842 \r
4843                         case 8: // Comment\r
4844                                 xn.appendChild(xd.createComment(n.nodeValue));\r
4845                                 return;\r
4846                 }\r
4847 \r
4848                 if (hc) {\r
4849                         cn = n.childNodes;\r
4850 \r
4851                         for (i=0, l=cn.length; i<l; i++)\r
4852                                 this._convertToXML(cn[i], xn);\r
4853                 }\r
4854         },\r
4855 \r
4856         serializeNodeAsHTML : function(n, inn) {\r
4857                 var en, no, h = '', i, l, t, st, r, cn, va = false, f = false, at, hc, cr, nn;\r
4858 \r
4859                 if (!this.rulesDone)\r
4860                         this._setupRules(); // Will initialize cleanup rules\r
4861 \r
4862                 if (tinyMCE.isRealIE && this._isDuplicate(n))\r
4863                         return '';\r
4864 \r
4865                 // Skip non valid child elements\r
4866                 if (n.parentNode && this.childRules != null) {\r
4867                         cr = this.childRules[n.parentNode.nodeName];\r
4868 \r
4869                         if (typeof(cr) != "undefined" && !cr.test(n.nodeName)) {\r
4870                                 st = true;\r
4871                                 t = null;\r
4872                         }\r
4873                 }\r
4874 \r
4875                 switch (n.nodeType) {\r
4876                         case 1: // Element\r
4877                                 hc = n.hasChildNodes();\r
4878 \r
4879                                 if (st)\r
4880                                         break;\r
4881 \r
4882                                 nn = n.nodeName;\r
4883 \r
4884                                 if (tinyMCE.isRealIE) {\r
4885                                         // MSIE sometimes produces <//tag>\r
4886                                         if (n.nodeName.indexOf('/') != -1)\r
4887                                                 break;\r
4888 \r
4889                                         // MSIE has it's NS in a separate attrib\r
4890                                         if (n.scopeName && n.scopeName != 'HTML')\r
4891                                                 nn = n.scopeName.toUpperCase() + ':' + nn.toUpperCase();\r
4892                                 } else if (tinyMCE.isOpera && nn.indexOf(':') > 0)\r
4893                                         nn = nn.toUpperCase();\r
4894 \r
4895                                 // Convert fonts to spans\r
4896                                 if (this.settings.convert_fonts_to_spans) {\r
4897                                         // On get content FONT -> SPAN\r
4898                                         if (this.settings.on_save && nn == 'FONT')\r
4899                                                 nn = 'SPAN';\r
4900 \r
4901                                         // On insert content SPAN -> FONT\r
4902                                         if (!this.settings.on_save && nn == 'SPAN')\r
4903                                                 nn = 'FONT';\r
4904                                 }\r
4905 \r
4906                                 if (this.vElementsRe.test(nn) && (!this.iveRe || !this.iveRe.test(nn)) && !inn) {\r
4907                                         va = true;\r
4908 \r
4909                                         r = this.rules[nn];\r
4910                                         if (!r) {\r
4911                                                 at = this.rules;\r
4912                                                 for (no in at) {\r
4913                                                         if (at[no] && at[no].validRe.test(nn)) {\r
4914                                                                 r = at[no];\r
4915                                                                 break;\r
4916                                                         }\r
4917                                                 }\r
4918                                         }\r
4919 \r
4920                                         en = r.isWild ? nn.toLowerCase() : r.oTagName;\r
4921                                         f = r.fill;\r
4922 \r
4923                                         if (r.removeEmpty && !hc)\r
4924                                                 return "";\r
4925 \r
4926                                         t = '<' + en;\r
4927 \r
4928                                         if (r.vAttribsReIsWild) {\r
4929                                                 // Serialize wildcard attributes\r
4930                                                 at = n.attributes;\r
4931                                                 for (i=at.length-1; i>-1; i--) {\r
4932                                                         no = at[i];\r
4933                                                         if (no.specified && r.vAttribsRe.test(no.nodeName))\r
4934                                                                 t += this._serializeAttribute(n, r, no.nodeName);\r
4935                                                 }\r
4936                                         } else {\r
4937                                                 // Serialize specific attributes\r
4938                                                 for (i=r.vAttribs.length-1; i>-1; i--)\r
4939                                                         t += this._serializeAttribute(n, r, r.vAttribs[i]);\r
4940                                         }\r
4941 \r
4942                                         // Serialize mce_ atts\r
4943                                         if (!this.settings.on_save) {\r
4944                                                 at = this.mceAttribs;\r
4945 \r
4946                                                 for (no in at) {\r
4947                                                         if (at[no])\r
4948                                                                 t += this._serializeAttribute(n, r, at[no]);\r
4949                                                 }\r
4950                                         }\r
4951 \r
4952                                         // Check for required attribs\r
4953                                         if (r.reqAttribsRe && !t.match(r.reqAttribsRe))\r
4954                                                 t = null;\r
4955 \r
4956                                         // Close these\r
4957                                         if (t != null && this.closeElementsRe.test(nn))\r
4958                                                 return t + ' />';\r
4959 \r
4960                                         if (t != null)\r
4961                                                 h += t + '>';\r
4962 \r
4963                                         if (this.isIE && this.codeElementsRe.test(nn))\r
4964                                                 h += n.innerHTML;\r
4965                                 }\r
4966                         break;\r
4967 \r
4968                         case 3: // Text\r
4969                                 if (st)\r
4970                                         break;\r
4971 \r
4972                                 if (n.parentNode && this.codeElementsRe.test(n.parentNode.nodeName))\r
4973                                         return this.isIE ? '' : n.nodeValue;\r
4974 \r
4975                                 return this.xmlEncode(n.nodeValue);\r
4976 \r
4977                         case 8: // Comment\r
4978                                 if (st)\r
4979                                         break;\r
4980 \r
4981                                 return "<!--" + this._trimComment(n.nodeValue) + "-->";\r
4982                 }\r
4983 \r
4984                 if (hc) {\r
4985                         cn = n.childNodes;\r
4986 \r
4987                         for (i=0, l=cn.length; i<l; i++)\r
4988                                 h += this.serializeNodeAsHTML(cn[i]);\r
4989                 }\r
4990 \r
4991                 // Fill empty nodes\r
4992                 if (f && !hc)\r
4993                         h += this.fillStr;\r
4994 \r
4995                 // End element\r
4996                 if (t != null && va)\r
4997                         h += '</' + en + '>';\r
4998 \r
4999                 return h;\r
5000         },\r
5001 \r
5002         _serializeAttribute : function(n, r, an) {\r
5003                 var av = '', t, os = this.settings.on_save;\r
5004 \r
5005                 if (os && (an.indexOf('mce_') == 0 || an.indexOf('_moz') == 0))\r
5006                         return '';\r
5007 \r
5008                 if (os && this.mceAttribs[an])\r
5009                         av = this._getAttrib(n, this.mceAttribs[an]);\r
5010 \r
5011                 if (av.length == 0)\r
5012                         av = this._getAttrib(n, an);\r
5013 \r
5014                 if (av.length == 0 && r.defaultAttribs && (t = r.defaultAttribs[an])) {\r
5015                         av = t;\r
5016 \r
5017                         if (av == "mce_empty")\r
5018                                 return " " + an + '=""';\r
5019                 }\r
5020 \r
5021                 if (r.forceAttribs && (t = r.forceAttribs[an]))\r
5022                         av = t;\r
5023 \r
5024                 if (os && av.length != 0 && /^(src|href|longdesc)$/.test(an))\r
5025                         av = this._urlConverter(this, n, av);\r
5026 \r
5027                 if (av.length != 0 && r.validAttribValues && r.validAttribValues[an] && !r.validAttribValues[an].test(av))\r
5028                         return "";\r
5029 \r
5030                 if (av.length != 0 && av == "{$uid}")\r
5031                         av = "uid_" + (this.idCount++);\r
5032 \r
5033                 if (av.length != 0) {\r
5034                         if (an.indexOf('on') != 0)\r
5035                                 av = this.xmlEncode(av, 1);\r
5036 \r
5037                         return " " + an + "=" + '"' + av + '"';\r
5038                 }\r
5039 \r
5040                 return "";\r
5041         },\r
5042 \r
5043         formatHTML : function(h) {\r
5044                 var s = this.settings, p = '', i = 0, li = 0, o = '', l;\r
5045 \r
5046                 // Replace BR in pre elements to \n\r
5047                 h = h.replace(/<pre([^>]*)>(.*?)<\/pre>/gi, function (a, b, c) {\r
5048                         c = c.replace(/<br\s*\/>/gi, '\n');\r
5049                         return '<pre' + b + '>' + c + '</pre>';\r
5050                 });\r
5051 \r
5052                 h = h.replace(/\r/g, ''); // Windows sux, isn't carriage return a thing of the past :)\r
5053                 h = '\n' + h;\r
5054                 h = h.replace(new RegExp('\\n\\s+', 'gi'), '\n'); // Remove previous formatting\r
5055                 h = h.replace(this.nlBeforeRe, '\n<$1$2>');\r
5056                 h = h.replace(this.nlAfterRe, '<$1$2>\n');\r
5057                 h = h.replace(this.nlBeforeAfterRe, '\n<$1$2$3>\n');\r
5058                 h += '\n';\r
5059 \r
5060                 //tinyMCE.debug(h);\r
5061 \r
5062                 while ((i = h.indexOf('\n', i + 1)) != -1) {\r
5063                         if ((l = h.substring(li + 1, i)).length != 0) {\r
5064                                 if (this.ouRe.test(l) && p.length >= s.indent_levels)\r
5065                                         p = p.substring(s.indent_levels);\r
5066 \r
5067                                 o += p + l + '\n';\r
5068         \r
5069                                 if (this.inRe.test(l))\r
5070                                         p += this.inStr;\r
5071                         }\r
5072 \r
5073                         li = i;\r
5074                 }\r
5075 \r
5076                 //tinyMCE.debug(h);\r
5077 \r
5078                 return o;\r
5079         },\r
5080 \r
5081         xmlEncode : function(s) {\r
5082                 var cl = this, re = this.xmlEncodeRe;\r
5083 \r
5084                 if (!this.entitiesDone)\r
5085                         this._setupEntities(); // Will intialize lookup table\r
5086 \r
5087                 switch (this.settings.entity_encoding) {\r
5088                         case "raw":\r
5089                                 return tinyMCE.xmlEncode(s);\r
5090 \r
5091                         case "named":\r
5092                                 return s.replace(re, function (c) {\r
5093                                         var b = cl.entities[c.charCodeAt(0)];\r
5094 \r
5095                                         return b ? '&' + b + ';' : c;\r
5096                                 });\r
5097 \r
5098                         case "numeric":\r
5099                                 return s.replace(re, function (c) {\r
5100                                         return '&#' + c.charCodeAt(0) + ';';\r
5101                                 });\r
5102                 }\r
5103 \r
5104                 return s;\r
5105         },\r
5106 \r
5107         split : function(re, s) {\r
5108                 var i, l, o = [], c = s.split(re);\r
5109 \r
5110                 for (i=0, l=c.length; i<l; i++) {\r
5111                         if (c[i] !== '')\r
5112                                 o[i] = c[i];\r
5113                 }\r
5114 \r
5115                 return o;\r
5116         },\r
5117 \r
5118         _trimComment : function(s) {\r
5119                 // Remove mce_src, mce_href\r
5120                 s = s.replace(new RegExp('\\smce_src=\"[^\"]*\"', 'gi'), "");\r
5121                 s = s.replace(new RegExp('\\smce_href=\"[^\"]*\"', 'gi'), "");\r
5122 \r
5123                 return s;\r
5124         },\r
5125 \r
5126         _getAttrib : function(e, n, d) {\r
5127                 var v, ex, nn;\r
5128 \r
5129                 if (typeof(d) == "undefined")\r
5130                         d = "";\r
5131 \r
5132                 if (!e || e.nodeType != 1)\r
5133                         return d;\r
5134 \r
5135                 try {\r
5136                         v = e.getAttribute(n, 0);\r
5137                 } catch (ex) {\r
5138                         // IE 7 may cast exception on invalid attributes\r
5139                         v = e.getAttribute(n, 2);\r
5140                 }\r
5141 \r
5142                 if (n == "class" && !v)\r
5143                         v = e.className;\r
5144 \r
5145                 if (this.isIE) {\r
5146                         if (n == "http-equiv")\r
5147                                 v = e.httpEquiv;\r
5148 \r
5149                         nn = e.nodeName;\r
5150 \r
5151                         // Skip the default values that IE returns\r
5152                         if (nn == "FORM" && n == "enctype" && v == "application/x-www-form-urlencoded")\r
5153                                 v = "";\r
5154 \r
5155                         if (nn == "INPUT" && n == "size" && v == "20")\r
5156                                 v = "";\r
5157 \r
5158                         if (nn == "INPUT" && n == "maxlength" && v == "2147483647")\r
5159                                 v = "";\r
5160 \r
5161                         // Images\r
5162                         if (n == "width" || n == "height")\r
5163                                 v = e.getAttribute(n, 2);\r
5164                 }\r
5165 \r
5166                 if (n == 'style' && v) {\r
5167                         if (!tinyMCE.isOpera)\r
5168                                 v = e.style.cssText;\r
5169 \r
5170                         v = tinyMCE.serializeStyle(tinyMCE.parseStyle(v));\r
5171                 }\r
5172 \r
5173                 if (this.settings.on_save && n.indexOf('on') != -1 && this.settings.on_save && v && v !== '')\r
5174                         v = tinyMCE.cleanupEventStr(v);\r
5175 \r
5176                 return (v && v !== '') ? '' + v : d;\r
5177         },\r
5178 \r
5179         _urlConverter : function(c, n, v) {\r
5180                 if (!c.settings.on_save)\r
5181                         return tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, v);\r
5182                 else if (tinyMCE.getParam('convert_urls')) {\r
5183                         if (!this.urlConverter)\r
5184                                 this.urlConverter = eval(tinyMCE.settings.urlconverter_callback);\r
5185 \r
5186                         return this.urlConverter(v, n, true);\r
5187                 }\r
5188 \r
5189                 return v;\r
5190         },\r
5191 \r
5192         _arrayToRe : function(a, op, be, af) {\r
5193                 var i, r;\r
5194 \r
5195                 op = typeof(op) == "undefined" ? "gi" : op;\r
5196                 be = typeof(be) == "undefined" ? "^(" : be;\r
5197                 af = typeof(af) == "undefined" ? ")$" : af;\r
5198 \r
5199                 r = be;\r
5200 \r
5201                 for (i=0; i<a.length; i++)\r
5202                         r += this._wildcardToRe(a[i]) + (i != a.length-1 ? "|" : "");\r
5203 \r
5204                 r += af;\r
5205 \r
5206                 return new RegExp(r, op);\r
5207         },\r
5208 \r
5209         _wildcardToRe : function(s) {\r
5210                 s = s.replace(/\?/g, '(\\S?)');\r
5211                 s = s.replace(/\+/g, '(\\S+)');\r
5212                 s = s.replace(/\*/g, '(\\S*)');\r
5213 \r
5214                 return s;\r
5215         },\r
5216 \r
5217         _setupEntities : function() {\r
5218                 var n, a, i, s = this.settings;\r
5219 \r
5220                 // Setup entities\r
5221                 if (s.entity_encoding == "named") {\r
5222                         n = tinyMCE.clearArray([]);\r
5223                         a = this.split(',', s.entities);\r
5224                         for (i=0; i<a.length; i+=2)\r
5225                                 n[a[i]] = a[i+1];\r
5226 \r
5227                         this.entities = n;\r
5228                 }\r
5229 \r
5230                 this.entitiesDone = true;\r
5231         },\r
5232 \r
5233         _setupRules : function() {\r
5234                 var s = this.settings;\r
5235 \r
5236                 // Setup default rule\r
5237                 this.addRuleStr(s.valid_elements);\r
5238                 this.addRuleStr(s.extended_valid_elements);\r
5239                 this.addChildRemoveRuleStr(s.valid_child_elements);\r
5240 \r
5241                 this.rulesDone = true;\r
5242         },\r
5243 \r
5244         _isDuplicate : function(n) {\r
5245                 var i, l, sn;\r
5246 \r
5247                 if (!this.settings.fix_content_duplication)\r
5248                         return false;\r
5249 \r
5250                 if (tinyMCE.isRealIE && n.nodeType == 1) {\r
5251                         // Mark elements\r
5252                         if (n.mce_serialized == this.serializationId)\r
5253                                 return true;\r
5254 \r
5255                         n.setAttribute('mce_serialized', this.serializationId);\r
5256                 } else {\r
5257                         sn = this.serializedNodes;\r
5258 \r
5259                         // Search lookup table for text nodes  and comments\r
5260                         for (i=0, l = sn.length; i<l; i++) {\r
5261                                 if (sn[i] == n)\r
5262                                         return true;\r
5263                         }\r
5264 \r
5265                         sn.push(n);\r
5266                 }\r
5267 \r
5268                 return false;\r
5269         }\r
5270 \r
5271         };\r
5272 \r
5273 /* file:jscripts/tiny_mce/classes/TinyMCE_DOMUtils.class.js */\r
5274 \r
5275 tinyMCE.add(TinyMCE_Engine, {\r
5276         createTagHTML : function(tn, a, h) {\r
5277                 var o = '', f = tinyMCE.xmlEncode, n;\r
5278 \r
5279                 o = '<' + tn;\r
5280 \r
5281                 if (a) {\r
5282                         for (n in a) {\r
5283                                 if (typeof(a[n]) != 'function' && a[n] != null)\r
5284                                         o += ' ' + f(n) + '="' + f('' + a[n]) + '"';\r
5285                         }\r
5286                 }\r
5287 \r
5288                 o += !h ? ' />' : '>' + h + '</' + tn + '>';\r
5289 \r
5290                 return o;\r
5291         },\r
5292 \r
5293         createTag : function(d, tn, a, h) {\r
5294                 var o = d.createElement(tn), n;\r
5295 \r
5296                 if (a) {\r
5297                         for (n in a) {\r
5298                                 if (typeof(a[n]) != 'function' && a[n] != null)\r
5299                                         tinyMCE.setAttrib(o, n, a[n]);\r
5300                         }\r
5301                 }\r
5302 \r
5303                 if (h)\r
5304                         o.innerHTML = h;\r
5305 \r
5306                 return o;\r
5307         },\r
5308 \r
5309         getElementByAttributeValue : function(n, e, a, v) {\r
5310                 return (n = this.getElementsByAttributeValue(n, e, a, v)).length == 0 ? null : n[0];\r
5311         },\r
5312 \r
5313         getElementsByAttributeValue : function(n, e, a, v) {\r
5314                 var i, nl = n.getElementsByTagName(e), o = [];\r
5315 \r
5316                 for (i=0; i<nl.length; i++) {\r
5317                         if (tinyMCE.getAttrib(nl[i], a).indexOf(v) != -1)\r
5318                                 o[o.length] = nl[i];\r
5319                 }\r
5320 \r
5321                 return o;\r
5322         },\r
5323 \r
5324         isBlockElement : function(n) {\r
5325                 return n != null && n.nodeType == 1 && this.blockRegExp.test(n.nodeName);\r
5326         },\r
5327 \r
5328         getParentBlockElement : function(n, r) {\r
5329                 return this.getParentNode(n, function(n) {\r
5330                         return tinyMCE.isBlockElement(n);\r
5331                 }, r);\r
5332 \r
5333                 return null;\r
5334         },\r
5335 \r
5336         insertAfter : function(n, r){\r
5337                 if (r.nextSibling)\r
5338                         r.parentNode.insertBefore(n, r.nextSibling);\r
5339                 else\r
5340                         r.parentNode.appendChild(n);\r
5341         },\r
5342 \r
5343         setInnerHTML : function(e, h) {\r
5344                 var i, nl, n;\r
5345 \r
5346                 // Convert all strong/em to b/i in Gecko\r
5347                 if (tinyMCE.isGecko) {\r
5348                         h = h.replace(/<embed([^>]*)>/gi, '<tmpembed$1>');\r
5349                         h = h.replace(/<em([^>]*)>/gi, '<i$1>');\r
5350                         h = h.replace(/<tmpembed([^>]*)>/gi, '<embed$1>');\r
5351                         h = h.replace(/<strong([^>]*)>/gi, '<b$1>');\r
5352                         h = h.replace(/<\/strong>/gi, '</b>');\r
5353                         h = h.replace(/<\/em>/gi, '</i>');\r
5354                 }\r
5355 \r
5356                 if (tinyMCE.isRealIE) {\r
5357                         // Since MSIE handles invalid HTML better that valid XHTML we\r
5358                         // need to make some things invalid. <hr /> gets converted to <hr>.\r
5359                         h = h.replace(/\s\/>/g, '>');\r
5360 \r
5361                         // Since MSIE auto generated emtpy P tags some times we must tell it to keep the real ones\r
5362                         h = h.replace(/<p([^>]*)>\u00A0?<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs\r
5363                         h = h.replace(/<p([^>]*)>\s*&nbsp;\s*<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs\r
5364                         h = h.replace(/<p([^>]*)>\s+<\/p>/gi, '<p$1 mce_keep="true">&nbsp;</p>'); // Keep empty paragraphs\r
5365 \r
5366                         // Remove first comment\r
5367                         e.innerHTML = tinyMCE.uniqueTag + h;\r
5368                         e.firstChild.removeNode(true);\r
5369 \r
5370                         // Remove weird auto generated empty paragraphs unless it's supposed to be there\r
5371                         nl = e.getElementsByTagName("p");\r
5372                         for (i=nl.length-1; i>=0; i--) {\r
5373                                 n = nl[i];\r
5374 \r
5375                                 if (n.nodeName == 'P' && !n.hasChildNodes() && !n.mce_keep)\r
5376                                         n.parentNode.removeChild(n);\r
5377                         }\r
5378                 } else {\r
5379                         h = this.fixGeckoBaseHREFBug(1, e, h);\r
5380                         e.innerHTML = h;\r
5381                         this.fixGeckoBaseHREFBug(2, e, h);\r
5382                 }\r
5383         },\r
5384 \r
5385         getOuterHTML : function(e) {\r
5386                 var d;\r
5387 \r
5388                 if (tinyMCE.isIE)\r
5389                         return e.outerHTML;\r
5390 \r
5391                 d = e.ownerDocument.createElement("body");\r
5392                 d.appendChild(e.cloneNode(true));\r
5393 \r
5394                 return d.innerHTML;\r
5395         },\r
5396 \r
5397         setOuterHTML : function(e, h, d) {\r
5398                 var d = typeof(d) == "undefined" ? e.ownerDocument : d, i, nl, t;\r
5399 \r
5400                 if (tinyMCE.isIE && e.nodeType == 1)\r
5401                         e.outerHTML = h;\r
5402                 else {\r
5403                         t = d.createElement("body");\r
5404                         t.innerHTML = h;\r
5405 \r
5406                         for (i=0, nl=t.childNodes; i<nl.length; i++)\r
5407                                 e.parentNode.insertBefore(nl[i].cloneNode(true), e);\r
5408 \r
5409                         e.parentNode.removeChild(e);\r
5410                 }\r
5411         },\r
5412 \r
5413         _getElementById : function(id, d) {\r
5414                 var e, i, j, f;\r
5415 \r
5416                 if (typeof(d) == "undefined")\r
5417                         d = document;\r
5418 \r
5419                 e = d.getElementById(id);\r
5420                 if (!e) {\r
5421                         f = d.forms;\r
5422 \r
5423                         for (i=0; i<f.length; i++) {\r
5424                                 for (j=0; j<f[i].elements.length; j++) {\r
5425                                         if (f[i].elements[j].name == id) {\r
5426                                                 e = f[i].elements[j];\r
5427                                                 break;\r
5428                                         }\r
5429                                 }\r
5430                         }\r
5431                 }\r
5432 \r
5433                 return e;\r
5434         },\r
5435 \r
5436         getNodeTree : function(n, na, t, nn) {\r
5437                 return this.selectNodes(n, function(n) {\r
5438                         return (!t || n.nodeType == t) && (!nn || n.nodeName == nn);\r
5439                 }, na ? na : []);\r
5440         },\r
5441 \r
5442         getParentElement : function(n, na, f, r) {\r
5443                 var re = na ? new RegExp('^(' + na.toUpperCase().replace(/,/g, '|') + ')$') : 0, v;\r
5444 \r
5445                 // Compatiblity with old scripts where f param was a attribute string\r
5446                 if (f && typeof(f) == 'string')\r
5447                         return this.getParentElement(n, na, function(no) {return tinyMCE.getAttrib(no, f) !== '';});\r
5448 \r
5449                 return this.getParentNode(n, function(n) {\r
5450                         return ((n.nodeType == 1 && !re) || (re && re.test(n.nodeName))) && (!f || f(n));\r
5451                 }, r);\r
5452         },\r
5453 \r
5454         getParentNode : function(n, f, r) {\r
5455                 while (n) {\r
5456                         if (n == r)\r
5457                                 return null;\r
5458 \r
5459                         if (f(n))\r
5460                                 return n;\r
5461 \r
5462                         n = n.parentNode;\r
5463                 }\r
5464 \r
5465                 return null;\r
5466         },\r
5467 \r
5468         getAttrib : function(elm, name, dv) {\r
5469                 var v;\r
5470 \r
5471                 if (typeof(dv) == "undefined")\r
5472                         dv = "";\r
5473 \r
5474                 // Not a element\r
5475                 if (!elm || elm.nodeType != 1)\r
5476                         return dv;\r
5477 \r
5478                 try {\r
5479                         v = elm.getAttribute(name, 0);\r
5480                 } catch (ex) {\r
5481                         // IE 7 may cast exception on invalid attributes\r
5482                         v = elm.getAttribute(name, 2);\r
5483                 }\r
5484 \r
5485                 // Try className for class attrib\r
5486                 if (name == "class" && !v)\r
5487                         v = elm.className;\r
5488 \r
5489                 // Workaround for a issue with Firefox 1.5rc2+\r
5490                 if (tinyMCE.isGecko) {\r
5491                         if (name == "src" && elm.src != null && elm.src !== '')\r
5492                                 v = elm.src;\r
5493 \r
5494                         // Workaround for a issue with Firefox 1.5rc2+\r
5495                         if (name == "href" && elm.href != null && elm.href !== '')\r
5496                                 v = elm.href;\r
5497                 } else if (tinyMCE.isIE) {\r
5498                         switch (name) {\r
5499                                 case "http-equiv":\r
5500                                         v = elm.httpEquiv;\r
5501                                         break;\r
5502 \r
5503                                 case "width":\r
5504                                 case "height":\r
5505                                         v = elm.getAttribute(name, 2);\r
5506                                         break;\r
5507                         }\r
5508                 }\r
5509 \r
5510                 if (name == "style" && !tinyMCE.isOpera)\r
5511                         v = elm.style.cssText;\r
5512 \r
5513                 return (v && v !== '') ? v : dv;\r
5514         },\r
5515 \r
5516         setAttrib : function(el, name, va, fix) {\r
5517                 if (typeof(va) == "number" && va != null)\r
5518                         va = "" + va;\r
5519 \r
5520                 if (fix) {\r
5521                         if (va == null)\r
5522                                 va = "";\r
5523 \r
5524                         va = va.replace(/[^0-9%]/g, '');\r
5525                 }\r
5526 \r
5527                 if (name == "style")\r
5528                         el.style.cssText = va;\r
5529 \r
5530                 if (name == "class")\r
5531                         el.className = va;\r
5532 \r
5533                 if (va != null && va !== '' && va != -1)\r
5534                         el.setAttribute(name, va);\r
5535                 else\r
5536                         el.removeAttribute(name);\r
5537         },\r
5538 \r
5539         setStyleAttrib : function(e, n, v) {\r
5540                 e.style[n] = v;\r
5541 \r
5542                 // Style attrib deleted in IE\r
5543                 if (tinyMCE.isIE && v == null || v == '') {\r
5544                         v = tinyMCE.serializeStyle(tinyMCE.parseStyle(e.style.cssText));\r
5545                         e.style.cssText = v;\r
5546                         e.setAttribute("style", v);\r
5547                 }\r
5548         },\r
5549 \r
5550         switchClass : function(ei, c) {\r
5551                 var e;\r
5552 \r
5553                 if (tinyMCE.switchClassCache[ei])\r
5554                         e = tinyMCE.switchClassCache[ei];\r
5555                 else\r
5556                         e = tinyMCE.switchClassCache[ei] = document.getElementById(ei);\r
5557 \r
5558                 if (e) {\r
5559                         // Keep tile mode\r
5560                         if (tinyMCE.settings.button_tile_map && e.className && e.className.indexOf('mceTiledButton') == 0)\r
5561                                 c = 'mceTiledButton ' + c;\r
5562 \r
5563                         e.className = c;\r
5564                 }\r
5565         },\r
5566 \r
5567         getAbsPosition : function(n, cn) {\r
5568                 var l = 0, t = 0;\r
5569 \r
5570                 while (n && n != cn) {\r
5571                         l += n.offsetLeft;\r
5572                         t += n.offsetTop;\r
5573                         n = n.offsetParent;\r
5574                 }\r
5575 \r
5576                 return {absLeft : l, absTop : t};\r
5577         },\r
5578 \r
5579         prevNode : function(e, n) {\r
5580                 var a = n.split(','), i;\r
5581 \r
5582                 while ((e = e.previousSibling) != null) {\r
5583                         for (i=0; i<a.length; i++) {\r
5584                                 if (e.nodeName == a[i])\r
5585                                         return e;\r
5586                         }\r
5587                 }\r
5588 \r
5589                 return null;\r
5590         },\r
5591 \r
5592         nextNode : function(e, n) {\r
5593                 var a = n.split(','), i;\r
5594 \r
5595                 while ((e = e.nextSibling) != null) {\r
5596                         for (i=0; i<a.length; i++) {\r
5597                                 if (e.nodeName == a[i])\r
5598                                         return e;\r
5599                         }\r
5600                 }\r
5601 \r
5602                 return null;\r
5603         },\r
5604 \r
5605         selectElements : function(n, na, f) {\r
5606                 var i, a = [], nl, x;\r
5607 \r
5608                 for (x=0, na = na.split(','); x<na.length; x++)\r
5609                         for (i=0, nl = n.getElementsByTagName(na[x]); i<nl.length; i++)\r
5610                                 (!f || f(nl[i])) && a.push(nl[i]);\r
5611 \r
5612                 return a;\r
5613         },\r
5614 \r
5615         selectNodes : function(n, f, a) {\r
5616                 var i;\r
5617 \r
5618                 if (!a)\r
5619                         a = [];\r
5620 \r
5621                 if (f(n))\r
5622                         a[a.length] = n;\r
5623 \r
5624                 if (n.hasChildNodes()) {\r
5625                         for (i=0; i<n.childNodes.length; i++)\r
5626                                 tinyMCE.selectNodes(n.childNodes[i], f, a);\r
5627                 }\r
5628 \r
5629                 return a;\r
5630         },\r
5631 \r
5632         addCSSClass : function(e, c, b) {\r
5633                 var o = this.removeCSSClass(e, c);\r
5634                 return e.className = b ? c + (o !== '' ? (' ' + o) : '') : (o !== '' ? (o + ' ') : '') + c;\r
5635         },\r
5636 \r
5637         removeCSSClass : function(e, c) {\r
5638                 c = e.className.replace(new RegExp("(^|\\s+)" + c + "(\\s+|$)"), ' ');\r
5639                 return e.className = c != ' ' ? c : '';\r
5640         },\r
5641 \r
5642         hasCSSClass : function(n, c) {\r
5643                 return new RegExp('\\b' + c + '\\b', 'g').test(n.className);\r
5644         },\r
5645 \r
5646         renameElement : function(e, n, d) {\r
5647                 var ne, i, ar;\r
5648 \r
5649                 d = typeof(d) == "undefined" ? tinyMCE.selectedInstance.getDoc() : d;\r
5650 \r
5651                 if (e) {\r
5652                         ne = d.createElement(n);\r
5653 \r
5654                         ar = e.attributes;\r
5655                         for (i=ar.length-1; i>-1; i--) {\r
5656                                 if (ar[i].specified && ar[i].nodeValue)\r
5657                                         ne.setAttribute(ar[i].nodeName.toLowerCase(), ar[i].nodeValue);\r
5658                         }\r
5659 \r
5660                         ar = e.childNodes;\r
5661                         for (i=0; i<ar.length; i++)\r
5662                                 ne.appendChild(ar[i].cloneNode(true));\r
5663 \r
5664                         e.parentNode.replaceChild(ne, e);\r
5665                 }\r
5666         },\r
5667 \r
5668         getViewPort : function(w) {\r
5669                 var d = w.document, m = d.compatMode == 'CSS1Compat', b = d.body, de = d.documentElement;\r
5670 \r
5671                 return {\r
5672                         left : w.pageXOffset || (m ? de.scrollLeft : b.scrollLeft),\r
5673                         top : w.pageYOffset || (m ? de.scrollTop : b.scrollTop),\r
5674                         width : w.innerWidth || (m ? de.clientWidth : b.clientWidth),\r
5675                         height : w.innerHeight || (m ? de.clientHeight : b.clientHeight)\r
5676                 };\r
5677         },\r
5678 \r
5679         getStyle : function(n, na, d) {\r
5680                 if (!n)\r
5681                         return false;\r
5682 \r
5683                 // Gecko\r
5684                 if (tinyMCE.isGecko && n.ownerDocument.defaultView) {\r
5685                         try {\r
5686                                 return n.ownerDocument.defaultView.getComputedStyle(n, null).getPropertyValue(na);\r
5687                         } catch (n) {\r
5688                                 // Old safari might fail\r
5689                                 return null;\r
5690                         }\r
5691                 }\r
5692 \r
5693                 // Camelcase it, if needed\r
5694                 na = na.replace(/-(\D)/g, function(a, b){\r
5695                         return b.toUpperCase();\r
5696                 });\r
5697 \r
5698                 // IE & Opera\r
5699                 if (n.currentStyle)\r
5700                         return n.currentStyle[na];\r
5701 \r
5702                 return false;\r
5703         }\r
5704 \r
5705         });\r
5706 \r
5707 /* file:jscripts/tiny_mce/classes/TinyMCE_URL.class.js */\r
5708 \r
5709 tinyMCE.add(TinyMCE_Engine, {\r
5710         parseURL : function(url_str) {\r
5711                 var urlParts = [], i, pos, lastPos, chr;\r
5712 \r
5713                 if (url_str) {\r
5714                         // Parse protocol part\r
5715                         pos = url_str.indexOf('://');\r
5716                         if (pos != -1) {\r
5717                                 urlParts.protocol = url_str.substring(0, pos);\r
5718                                 lastPos = pos + 3;\r
5719                         }\r
5720 \r
5721                         // Find port or path start\r
5722                         for (i=lastPos; i<url_str.length; i++) {\r
5723                                 chr = url_str.charAt(i);\r
5724 \r
5725                                 if (chr == ':')\r
5726                                         break;\r
5727 \r
5728                                 if (chr == '/')\r
5729                                         break;\r
5730                         }\r
5731                         pos = i;\r
5732 \r
5733                         // Get host\r
5734                         urlParts.host = url_str.substring(lastPos, pos);\r
5735 \r
5736                         // Get port\r
5737                         urlParts.port = "";\r
5738                         lastPos = pos;\r
5739                         if (url_str.charAt(pos) == ':') {\r
5740                                 pos = url_str.indexOf('/', lastPos);\r
5741                                 urlParts.port = url_str.substring(lastPos+1, pos);\r
5742                         }\r
5743 \r
5744                         // Get path\r
5745                         lastPos = pos;\r
5746                         pos = url_str.indexOf('?', lastPos);\r
5747 \r
5748                         if (pos == -1)\r
5749                                 pos = url_str.indexOf('#', lastPos);\r
5750 \r
5751                         if (pos == -1)\r
5752                                 pos = url_str.length;\r
5753 \r
5754                         urlParts.path = url_str.substring(lastPos, pos);\r
5755 \r
5756                         // Get query\r
5757                         lastPos = pos;\r
5758                         if (url_str.charAt(pos) == '?') {\r
5759                                 pos = url_str.indexOf('#');\r
5760                                 pos = (pos == -1) ? url_str.length : pos;\r
5761                                 urlParts.query = url_str.substring(lastPos+1, pos);\r
5762                         }\r
5763 \r
5764                         // Get anchor\r
5765                         lastPos = pos;\r
5766                         if (url_str.charAt(pos) == '#') {\r
5767                                 pos = url_str.length;\r
5768                                 urlParts.anchor = url_str.substring(lastPos+1, pos);\r
5769                         }\r
5770                 }\r
5771 \r
5772                 return urlParts;\r
5773         },\r
5774 \r
5775         serializeURL : function(up) {\r
5776                 var o = "";\r
5777 \r
5778                 if (up.protocol)\r
5779                         o += up.protocol + "://";\r
5780 \r
5781                 if (up.host)\r
5782                         o += up.host;\r
5783 \r
5784                 if (up.port)\r
5785                         o += ":" + up.port;\r
5786 \r
5787                 if (up.path)\r
5788                         o += up.path;\r
5789 \r
5790                 if (up.query)\r
5791                         o += "?" + up.query;\r
5792 \r
5793                 if (up.anchor)\r
5794                         o += "#" + up.anchor;\r
5795 \r
5796                 return o;\r
5797         },\r
5798 \r
5799         convertAbsoluteURLToRelativeURL : function(base_url, url_to_relative) {\r
5800                 var baseURL = this.parseURL(base_url), targetURL = this.parseURL(url_to_relative);\r
5801                 var i, strTok1, strTok2, breakPoint = 0, outPath = "", forceSlash = false;\r
5802                 var fileName, pos;\r
5803 \r
5804                 if (targetURL.path == '')\r
5805                         targetURL.path = "/";\r
5806                 else\r
5807                         forceSlash = true;\r
5808 \r
5809                 // Crop away last path part\r
5810                 base_url = baseURL.path.substring(0, baseURL.path.lastIndexOf('/'));\r
5811                 strTok1 = base_url.split('/');\r
5812                 strTok2 = targetURL.path.split('/');\r
5813 \r
5814                 if (strTok1.length >= strTok2.length) {\r
5815                         for (i=0; i<strTok1.length; i++) {\r
5816                                 if (i >= strTok2.length || strTok1[i] != strTok2[i]) {\r
5817                                         breakPoint = i + 1;\r
5818                                         break;\r
5819                                 }\r
5820                         }\r
5821                 }\r
5822 \r
5823                 if (strTok1.length < strTok2.length) {\r
5824                         for (i=0; i<strTok2.length; i++) {\r
5825                                 if (i >= strTok1.length || strTok1[i] != strTok2[i]) {\r
5826                                         breakPoint = i + 1;\r
5827                                         break;\r
5828                                 }\r
5829                         }\r
5830                 }\r
5831 \r
5832                 if (breakPoint == 1)\r
5833                         return targetURL.path;\r
5834 \r
5835                 for (i=0; i<(strTok1.length-(breakPoint-1)); i++)\r
5836                         outPath += "../";\r
5837 \r
5838                 for (i=breakPoint-1; i<strTok2.length; i++) {\r
5839                         if (i != (breakPoint-1))\r
5840                                 outPath += "/" + strTok2[i];\r
5841                         else\r
5842                                 outPath += strTok2[i];\r
5843                 }\r
5844 \r
5845                 targetURL.protocol = null;\r
5846                 targetURL.host = null;\r
5847                 targetURL.port = null;\r
5848                 targetURL.path = outPath == '' && forceSlash ? "/" : outPath;\r
5849 \r
5850                 // Remove document prefix from local anchors\r
5851                 fileName = baseURL.path;\r
5852 \r
5853                 if ((pos = fileName.lastIndexOf('/')) != -1)\r
5854                         fileName = fileName.substring(pos + 1);\r
5855 \r
5856                 // Is local anchor\r
5857                 if (fileName == targetURL.path && targetURL.anchor !== '')\r
5858                         targetURL.path = "";\r
5859 \r
5860                 // If empty and not local anchor force filename or slash\r
5861                 if (targetURL.path == '' && !targetURL.anchor)\r
5862                         targetURL.path = fileName !== '' ? fileName : "/";\r
5863 \r
5864                 return this.serializeURL(targetURL);\r
5865         },\r
5866 \r
5867         convertRelativeToAbsoluteURL : function(base_url, relative_url) {\r
5868                 var baseURL = this.parseURL(base_url), baseURLParts, relURLParts, newRelURLParts, numBack, relURL = this.parseURL(relative_url), i;\r
5869                 var len, absPath, start, end, newBaseURLParts;\r
5870 \r
5871                 if (relative_url == '' || relative_url.indexOf('://') != -1 || /^(mailto:|javascript:|#|\/)/.test(relative_url))\r
5872                         return relative_url;\r
5873 \r
5874                 // Split parts\r
5875                 baseURLParts = baseURL.path.split('/');\r
5876                 relURLParts = relURL.path.split('/');\r
5877 \r
5878                 // Remove empty chunks\r
5879                 newBaseURLParts = [];\r
5880                 for (i=baseURLParts.length-1; i>=0; i--) {\r
5881                         if (baseURLParts[i].length == 0)\r
5882                                 continue;\r
5883 \r
5884                         newBaseURLParts[newBaseURLParts.length] = baseURLParts[i];\r
5885                 }\r
5886                 baseURLParts = newBaseURLParts.reverse();\r
5887 \r
5888                 // Merge relURLParts chunks\r
5889                 newRelURLParts = [];\r
5890                 numBack = 0;\r
5891                 for (i=relURLParts.length-1; i>=0; i--) {\r
5892                         if (relURLParts[i].length == 0 || relURLParts[i] == ".")\r
5893                                 continue;\r
5894 \r
5895                         if (relURLParts[i] == '..') {\r
5896                                 numBack++;\r
5897                                 continue;\r
5898                         }\r
5899 \r
5900                         if (numBack > 0) {\r
5901                                 numBack--;\r
5902                                 continue;\r
5903                         }\r
5904 \r
5905                         newRelURLParts[newRelURLParts.length] = relURLParts[i];\r
5906                 }\r
5907 \r
5908                 relURLParts = newRelURLParts.reverse();\r
5909 \r
5910                 // Remove end from absolute path\r
5911                 len = baseURLParts.length-numBack;\r
5912                 absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/');\r
5913                 start = "";\r
5914                 end = "";\r
5915 \r
5916                 // Build output URL\r
5917                 relURL.protocol = baseURL.protocol;\r
5918                 relURL.host = baseURL.host;\r
5919                 relURL.port = baseURL.port;\r
5920 \r
5921                 // Re-add trailing slash if it's removed\r
5922                 if (relURL.path.charAt(relURL.path.length-1) == "/")\r
5923                         absPath += "/";\r
5924 \r
5925                 relURL.path = absPath;\r
5926 \r
5927                 return this.serializeURL(relURL);\r
5928         },\r
5929 \r
5930         convertURL : function(url, node, on_save) {\r
5931                 var dl = document.location, start, portPart, urlParts, baseUrlParts, tmpUrlParts, curl;\r
5932                 var prot = dl.protocol, host = dl.hostname, port = dl.port;\r
5933 \r
5934                 // Pass through file protocol\r
5935                 if (prot == "file:")\r
5936                         return url;\r
5937 \r
5938                 // Something is wrong, remove weirdness\r
5939                 url = tinyMCE.regexpReplace(url, '(http|https):///', '/');\r
5940 \r
5941                 // Mailto link or anchor (Pass through)\r
5942                 if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || /^[ \t\r\n\+]*[#\?]/.test(url))\r
5943                         return url;\r
5944 \r
5945                 // Fix relative/Mozilla\r
5946                 if (!tinyMCE.isIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/')\r
5947                         return tinyMCE.settings.base_href + url;\r
5948 \r
5949                 // Handle relative URLs\r
5950                 if (on_save && tinyMCE.getParam('relative_urls')) {\r
5951                         curl = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, url);\r
5952                         if (curl.charAt(0) == '/')\r
5953                                 curl = tinyMCE.settings.document_base_prefix + curl;\r
5954 \r
5955                         urlParts = tinyMCE.parseURL(curl);\r
5956                         tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings.document_base_url);\r
5957 \r
5958                         // Force relative\r
5959                         if (urlParts.host == tmpUrlParts.host && (urlParts.port == tmpUrlParts.port))\r
5960                                 return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings.document_base_url, curl);\r
5961                 }\r
5962 \r
5963                 // Handle absolute URLs\r
5964                 if (!tinyMCE.getParam('relative_urls')) {\r
5965                         urlParts = tinyMCE.parseURL(url);\r
5966                         baseUrlParts = tinyMCE.parseURL(tinyMCE.settings.base_href);\r
5967 \r
5968                         // Force absolute URLs from relative URLs\r
5969                         url = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, url);\r
5970 \r
5971                         // If anchor and path is the same page\r
5972                         if (urlParts.anchor && urlParts.path == baseUrlParts.path)\r
5973                                 return "#" + urlParts.anchor;\r
5974                 }\r
5975 \r
5976                 // Remove current domain\r
5977                 if (tinyMCE.getParam('remove_script_host')) {\r
5978                         start = "";\r
5979                         portPart = "";\r
5980 \r
5981                         if (port !== '')\r
5982                                 portPart = ":" + port;\r
5983 \r
5984                         start = prot + "//" + host + portPart + "/";\r
5985 \r
5986                         if (url.indexOf(start) == 0)\r
5987                                 url = url.substring(start.length-1);\r
5988                 }\r
5989 \r
5990                 return url;\r
5991         },\r
5992 \r
5993         convertAllRelativeURLs : function(body) {\r
5994                 var i, elms, src, href, mhref, msrc;\r
5995 \r
5996                 // Convert all image URL:s to absolute URL\r
5997                 elms = body.getElementsByTagName("img");\r
5998                 for (i=0; i<elms.length; i++) {\r
5999                         src = tinyMCE.getAttrib(elms[i], 'src');\r
6000 \r
6001                         msrc = tinyMCE.getAttrib(elms[i], 'mce_src');\r
6002                         if (msrc !== '')\r
6003                                 src = msrc;\r
6004 \r
6005                         if (src !== '') {\r
6006                                 src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, src);\r
6007                                 elms[i].setAttribute("src", src);\r
6008                         }\r
6009                 }\r
6010 \r
6011                 // Convert all link URL:s to absolute URL\r
6012                 elms = body.getElementsByTagName("a");\r
6013                 for (i=0; i<elms.length; i++) {\r
6014                         href = tinyMCE.getAttrib(elms[i], 'href');\r
6015 \r
6016                         mhref = tinyMCE.getAttrib(elms[i], 'mce_href');\r
6017                         if (mhref !== '')\r
6018                                 href = mhref;\r
6019 \r
6020                         if (href && href !== '') {\r
6021                                 href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings.base_href, href);\r
6022                                 elms[i].setAttribute("href", href);\r
6023                         }\r
6024                 }\r
6025         }\r
6026 \r
6027         });\r
6028 \r
6029 /* file:jscripts/tiny_mce/classes/TinyMCE_Array.class.js */\r
6030 \r
6031 tinyMCE.add(TinyMCE_Engine, {\r
6032         clearArray : function(a) {\r
6033                 var n;\r
6034 \r
6035                 for (n in a)\r
6036                         a[n] = null;\r
6037 \r
6038                 return a;\r
6039         },\r
6040 \r
6041         explode : function(d, s) {\r
6042                 var ar = s.split(d), oar = [], i;\r
6043 \r
6044                 for (i = 0; i<ar.length; i++) {\r
6045                         if (ar[i] !== '')\r
6046                                 oar[oar.length] = ar[i];\r
6047                 }\r
6048 \r
6049                 return oar;\r
6050         }\r
6051 });\r
6052 \r
6053 /* file:jscripts/tiny_mce/classes/TinyMCE_Event.class.js */\r
6054 \r
6055 tinyMCE.add(TinyMCE_Engine, {\r
6056         _setEventsEnabled : function(node, state) {\r
6057                 var evs, x, y, elms, i, event;\r
6058                 var events = ['onfocus','onblur','onclick','ondblclick',\r
6059                                         'onmousedown','onmouseup','onmouseover','onmousemove',\r
6060                                         'onmouseout','onkeypress','onkeydown','onkeydown','onkeyup'];\r
6061 \r
6062                 evs = tinyMCE.settings.event_elements.split(',');\r
6063                 for (y=0; y<evs.length; y++){\r
6064                         elms = node.getElementsByTagName(evs[y]);\r
6065                         for (i=0; i<elms.length; i++) {\r
6066                                 event = "";\r
6067 \r
6068                                 for (x=0; x<events.length; x++) {\r
6069                                         if ((event = tinyMCE.getAttrib(elms[i], events[x])) !== '') {\r
6070                                                 event = tinyMCE.cleanupEventStr("" + event);\r
6071 \r
6072                                                 if (!state)\r
6073                                                         event = "return true;" + event;\r
6074                                                 else\r
6075                                                         event = event.replace(/^return true;/gi, '');\r
6076 \r
6077                                                 elms[i].removeAttribute(events[x]);\r
6078                                                 elms[i].setAttribute(events[x], event);\r
6079                                         }\r
6080                                 }\r
6081                         }\r
6082                 }\r
6083         },\r
6084 \r
6085         _eventPatch : function(editor_id) {\r
6086                 var n, inst, win, e;\r
6087 \r
6088                 // Remove odd, error\r
6089                 if (typeof(tinyMCE) == "undefined")\r
6090                         return true;\r
6091 \r
6092                 try {\r
6093                         // Try selected instance first\r
6094                         if (tinyMCE.selectedInstance) {\r
6095                                 win = tinyMCE.selectedInstance.getWin();\r
6096 \r
6097                                 if (win && win.event) {\r
6098                                         e = win.event;\r
6099 \r
6100                                         if (!e.target)\r
6101                                                 e.target = e.srcElement;\r
6102 \r
6103                                         TinyMCE_Engine.prototype.handleEvent(e);\r
6104                                         return;\r
6105                                 }\r
6106                         }\r
6107 \r
6108                         // Search for it\r
6109                         for (n in tinyMCE.instances) {\r
6110                                 inst = tinyMCE.instances[n];\r
6111 \r
6112                                 if (!tinyMCE.isInstance(inst))\r
6113                                         continue;\r
6114 \r
6115                                 inst.select();\r
6116                                 win = inst.getWin();\r
6117 \r
6118                                 if (win && win.event) {\r
6119                                         e = win.event;\r
6120 \r
6121                                         if (!e.target)\r
6122                                                 e.target = e.srcElement;\r
6123 \r
6124                                         TinyMCE_Engine.prototype.handleEvent(e);\r
6125                                         return;\r
6126                                 }\r
6127                         }\r
6128                 } catch (ex) {\r
6129                         // Ignore error if iframe is pointing to external URL\r
6130                 }\r
6131         },\r
6132 \r
6133         findEvent : function(e) {\r
6134                 var n, inst;\r
6135 \r
6136                 if (e)\r
6137                         return e;\r
6138 \r
6139                 for (n in tinyMCE.instances) {\r
6140                         inst = tinyMCE.instances[n];\r
6141 \r
6142                         if (tinyMCE.isInstance(inst) && inst.getWin().event)\r
6143                                 return inst.getWin().event;\r
6144                 }\r
6145 \r
6146                 return null;\r
6147         },\r
6148 \r
6149         unloadHandler : function() {\r
6150                 tinyMCE.triggerSave(true, true);\r
6151         },\r
6152 \r
6153         addEventHandlers : function(inst) {\r
6154                 this.setEventHandlers(inst, 1);\r
6155         },\r
6156 \r
6157         setEventHandlers : function(inst, s) {\r
6158                 var doc = inst.getDoc(), ie, ot, i, f = s ? tinyMCE.addEvent : tinyMCE.removeEvent;\r
6159 \r
6160                 ie = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'controlselect', 'dblclick'];\r
6161                 ot = ['keypress', 'keyup', 'keydown', 'click', 'mouseup', 'mousedown', 'focus', 'blur', 'dragdrop'];\r
6162 \r
6163                 inst.switchSettings();\r
6164 \r
6165                 if (tinyMCE.isIE) {\r
6166                         for (i=0; i<ie.length; i++)\r
6167                                 f(doc, ie[i], TinyMCE_Engine.prototype._eventPatch);\r
6168                 } else {\r
6169                         for (i=0; i<ot.length; i++)\r
6170                                 f(doc, ot[i], tinyMCE.handleEvent);\r
6171 \r
6172                         // Force designmode\r
6173                         try {\r
6174                                 doc.designMode = "On";\r
6175                         } catch (e) {\r
6176                                 // Ignore\r
6177                         }\r
6178                 }\r
6179         },\r
6180 \r
6181         onMouseMove : function() {\r
6182                 var inst, lh;\r
6183 \r
6184                 // Fix for IE7 bug where it's not restoring hover on anchors correctly\r
6185                 if (tinyMCE.lastHover) {\r
6186                         lh = tinyMCE.lastHover;\r
6187 \r
6188                         // Call out on menus and refresh class on normal buttons\r
6189                         if (lh.className.indexOf('mceMenu') != -1)\r
6190                                 tinyMCE._menuButtonEvent('out', lh);\r
6191                         else\r
6192                                 lh.className = lh.className;\r
6193 \r
6194                         tinyMCE.lastHover = null;\r
6195                 }\r
6196 \r
6197                 if (!tinyMCE.hasMouseMoved) {\r
6198                         inst = tinyMCE.selectedInstance;\r
6199 \r
6200                         // Workaround for bug #1437457 (Odd MSIE bug)\r
6201                         if (inst.isFocused) {\r
6202                                 inst.undoBookmark = inst.selection.getBookmark();\r
6203                                 tinyMCE.hasMouseMoved = true;\r
6204                         }\r
6205                 }\r
6206 \r
6207         //      tinyMCE.cancelEvent(inst.getWin().event);\r
6208         //      return false;\r
6209         },\r
6210 \r
6211         cancelEvent : function(e) {\r
6212                 if (!e)\r
6213                         return false;\r
6214 \r
6215                 if (tinyMCE.isIE) {\r
6216                         e.returnValue = false;\r
6217                         e.cancelBubble = true;\r
6218                 } else {\r
6219                         e.preventDefault();\r
6220                         e.stopPropagation && e.stopPropagation();\r
6221                 }\r
6222 \r
6223                 return false;\r
6224         },\r
6225 \r
6226         addEvent : function(o, n, h) {\r
6227                 // Add cleanup for all non unload events\r
6228                 if (n != 'unload') {\r
6229                         function clean() {\r
6230                                 var ex;\r
6231 \r
6232                                 try {\r
6233                                         tinyMCE.removeEvent(o, n, h);\r
6234                                         tinyMCE.removeEvent(window, 'unload', clean);\r
6235                                         o = n = h = null;\r
6236                                 } catch (ex) {\r
6237                                         // IE may produce access denied exception on unload\r
6238                                 }\r
6239                         }\r
6240 \r
6241                         // Add memory cleaner\r
6242                         tinyMCE.addEvent(window, 'unload', clean);\r
6243                 }\r
6244 \r
6245                 if (o.attachEvent)\r
6246                         o.attachEvent("on" + n, h);\r
6247                 else\r
6248                         o.addEventListener(n, h, false);\r
6249         },\r
6250 \r
6251         removeEvent : function(o, n, h) {\r
6252                 if (o.detachEvent)\r
6253                         o.detachEvent("on" + n, h);\r
6254                 else\r
6255                         o.removeEventListener(n, h, false);\r
6256         },\r
6257 \r
6258         addSelectAccessibility : function(e, s, w) {\r
6259                 // Add event handlers \r
6260                 if (!s._isAccessible) {\r
6261                         s.onkeydown = tinyMCE.accessibleEventHandler;\r
6262                         s.onblur = tinyMCE.accessibleEventHandler;\r
6263                         s._isAccessible = true;\r
6264                         s._win = w;\r
6265                 }\r
6266 \r
6267                 return false;\r
6268         },\r
6269 \r
6270         accessibleEventHandler : function(e) {\r
6271                 var elm, win = this._win;\r
6272 \r
6273                 e = tinyMCE.isIE ? win.event : e;\r
6274                 elm = tinyMCE.isIE ? e.srcElement : e.target;\r
6275 \r
6276                 // Unpiggyback onchange on blur\r
6277                 if (e.type == "blur") {\r
6278                         if (elm.oldonchange) {\r
6279                                 elm.onchange = elm.oldonchange;\r
6280                                 elm.oldonchange = null;\r
6281                         }\r
6282 \r
6283                         return true;\r
6284                 }\r
6285 \r
6286                 // Piggyback onchange\r
6287                 if (elm.nodeName == "SELECT" && !elm.oldonchange) {\r
6288                         elm.oldonchange = elm.onchange;\r
6289                         elm.onchange = null;\r
6290                 }\r
6291 \r
6292                 // Execute onchange and remove piggyback\r
6293                 if (e.keyCode == 13 || e.keyCode == 32) {\r
6294                         elm.onchange = elm.oldonchange;\r
6295                         elm.onchange();\r
6296                         elm.oldonchange = null;\r
6297 \r
6298                         tinyMCE.cancelEvent(e);\r
6299                         return false;\r
6300                 }\r
6301 \r
6302                 return true;\r
6303         },\r
6304 \r
6305         _resetIframeHeight : function() {\r
6306                 var ife;\r
6307 \r
6308                 if (tinyMCE.isRealIE) {\r
6309                         ife = tinyMCE.selectedInstance.iframeElement;\r
6310 \r
6311         /*              if (ife._oldWidth) {\r
6312                                 ife.style.width = ife._oldWidth;\r
6313                                 ife.width = ife._oldWidth;\r
6314                         }*/\r
6315 \r
6316                         if (ife._oldHeight) {\r
6317                                 ife.style.height = ife._oldHeight;\r
6318                                 ife.height = ife._oldHeight;\r
6319                         }\r
6320                 }\r
6321         }\r
6322 \r
6323         });\r
6324 \r
6325 /* file:jscripts/tiny_mce/classes/TinyMCE_Selection.class.js */\r
6326 \r
6327 function TinyMCE_Selection(inst) {\r
6328         this.instance = inst;\r
6329 };\r
6330 \r
6331 TinyMCE_Selection.prototype = {\r
6332         getSelectedHTML : function() {\r
6333                 var inst = this.instance, e, r = this.getRng(), h;\r
6334 \r
6335                 if (!r)\r
6336                         return null;\r
6337 \r
6338                 e = document.createElement("body");\r
6339 \r
6340                 if (r.cloneContents)\r
6341                         e.appendChild(r.cloneContents());\r
6342                 else if (typeof(r.item) != 'undefined' || typeof(r.htmlText) != 'undefined')\r
6343                         e.innerHTML = r.item ? r.item(0).outerHTML : r.htmlText;\r
6344                 else\r
6345                         e.innerHTML = r.toString(); // Failed, use text for now\r
6346 \r
6347                 h = tinyMCE._cleanupHTML(inst, inst.contentDocument, inst.settings, e, e, false, true, false);\r
6348 \r
6349                 // When editing always use fonts internaly\r
6350                 //if (tinyMCE.getParam("convert_fonts_to_spans"))\r
6351                 //      tinyMCE.convertSpansToFonts(inst.getDoc());\r
6352 \r
6353                 return h;\r
6354         },\r
6355 \r
6356         getSelectedText : function() {\r
6357                 var inst = this.instance, d, r, s, t;\r
6358 \r
6359                 if (tinyMCE.isIE) {\r
6360                         d = inst.getDoc();\r
6361 \r
6362                         if (d.selection.type == "Text") {\r
6363                                 r = d.selection.createRange();\r
6364                                 t = r.text;\r
6365                         } else\r
6366                                 t = '';\r
6367                 } else {\r
6368                         s = this.getSel();\r
6369 \r
6370                         if (s && s.toString)\r
6371                                 t = s.toString();\r
6372                         else\r
6373                                 t = '';\r
6374                 }\r
6375 \r
6376                 return t;\r
6377         },\r
6378 \r
6379         getBookmark : function(simple) {\r
6380                 var inst = this.instance, rng = this.getRng(), doc = inst.getDoc(), b = inst.getBody();\r
6381                 var trng, sx, sy, xx = -999999999, vp = inst.getViewPort();\r
6382                 var sp, le, s, e, nl, i, si, ei, w;\r
6383 \r
6384                 sx = vp.left;\r
6385                 sy = vp.top;\r
6386 \r
6387                 if (simple)\r
6388                         return {rng : rng, scrollX : sx, scrollY : sy};\r
6389 \r
6390                 if (tinyMCE.isRealIE) {\r
6391                         if (rng.item) {\r
6392                                 e = rng.item(0);\r
6393 \r
6394                                 nl = b.getElementsByTagName(e.nodeName);\r
6395                                 for (i=0; i<nl.length; i++) {\r
6396                                         if (e == nl[i]) {\r
6397                                                 sp = i;\r
6398                                                 break;\r
6399                                         }\r
6400                                 }\r
6401 \r
6402                                 return {\r
6403                                         tag : e.nodeName,\r
6404                                         index : sp,\r
6405                                         scrollX : sx,\r
6406                                         scrollY : sy\r
6407                                 };\r
6408                         } else {\r
6409                                 trng = doc.body.createTextRange();\r
6410                                 trng.moveToElementText(inst.getBody());\r
6411                                 trng.collapse(true);\r
6412                                 bp = Math.abs(trng.move('character', xx));\r
6413 \r
6414                                 trng = rng.duplicate();\r
6415                                 trng.collapse(true);\r
6416                                 sp = Math.abs(trng.move('character', xx));\r
6417 \r
6418                                 trng = rng.duplicate();\r
6419                                 trng.collapse(false);\r
6420                                 le = Math.abs(trng.move('character', xx)) - sp;\r
6421 \r
6422                                 return {\r
6423                                         start : sp - bp,\r
6424                                         length : le,\r
6425                                         scrollX : sx,\r
6426                                         scrollY : sy\r
6427                                 };\r
6428                         }\r
6429                 } else {\r
6430                         s = this.getSel();\r
6431                         e = this.getFocusElement();\r
6432 \r
6433                         if (!s)\r
6434                                 return null;\r
6435 \r
6436                         if (e && e.nodeName == 'IMG') {\r
6437                                 /*nl = b.getElementsByTagName('IMG');\r
6438                                 for (i=0; i<nl.length; i++) {\r
6439                                         if (e == nl[i]) {\r
6440                                                 sp = i;\r
6441                                                 break;\r
6442                                         }\r
6443                                 }*/\r
6444 \r
6445                                 return {\r
6446                                         start : -1,\r
6447                                         end : -1,\r
6448                                         index : sp,\r
6449                                         scrollX : sx,\r
6450                                         scrollY : sy\r
6451                                 };\r
6452                         }\r
6453 \r
6454                         // Caret or selection\r
6455                         if (s.anchorNode == s.focusNode && s.anchorOffset == s.focusOffset) {\r
6456                                 e = this._getPosText(b, s.anchorNode, s.focusNode);\r
6457 \r
6458                                 if (!e)\r
6459                                         return {scrollX : sx, scrollY : sy};\r
6460 \r
6461                                 return {\r
6462                                         start : e.start + s.anchorOffset,\r
6463                                         end : e.end + s.focusOffset,\r
6464                                         scrollX : sx,\r
6465                                         scrollY : sy\r
6466                                 };\r
6467                         } else {\r
6468                                 e = this._getPosText(b, rng.startContainer, rng.endContainer);\r
6469 \r
6470                                 if (!e)\r
6471                                         return {scrollX : sx, scrollY : sy};\r
6472 \r
6473                                 return {\r
6474                                         start : e.start + rng.startOffset,\r
6475                                         end : e.end + rng.endOffset,\r
6476                                         scrollX : sx,\r
6477                                         scrollY : sy\r
6478                                 };\r
6479                         }\r
6480                 }\r
6481 \r
6482                 return null;\r
6483         },\r
6484 \r
6485         moveToBookmark : function(bookmark) {\r
6486                 var inst = this.instance, rng, nl, i, ex, b = inst.getBody(), sd;\r
6487                 var doc = inst.getDoc(), win = inst.getWin(), sel = this.getSel();\r
6488 \r
6489                 if (!bookmark)\r
6490                         return false;\r
6491 \r
6492                 if (tinyMCE.isSafari && bookmark.rng) {\r
6493                         sel.setBaseAndExtent(bookmark.rng.startContainer, bookmark.rng.startOffset, bookmark.rng.endContainer, bookmark.rng.endOffset);\r
6494                         return true;\r
6495                 }\r
6496 \r
6497                 if (tinyMCE.isRealIE) {\r
6498                         if (bookmark.rng) {\r
6499                                 try {\r
6500                                         bookmark.rng.select();\r
6501                                 } catch (ex) {\r
6502                                         // Ignore\r
6503                                 }\r
6504 \r
6505                                 return true;\r
6506                         }\r
6507 \r
6508                         win.focus();\r
6509 \r
6510                         if (bookmark.tag) {\r
6511                                 rng = b.createControlRange();\r
6512 \r
6513                                 nl = b.getElementsByTagName(bookmark.tag);\r
6514 \r
6515                                 if (nl.length > bookmark.index) {\r
6516                                         try {\r
6517                                                 rng.addElement(nl[bookmark.index]);\r
6518                                         } catch (ex) {\r
6519                                                 // Might be thrown if the node no longer exists\r
6520                                         }\r
6521                                 }\r
6522                         } else {\r
6523                                 // Try/catch needed since this operation breaks when TinyMCE is placed in hidden divs/tabs\r
6524                                 try {\r
6525                                         // Incorrect bookmark\r
6526                                         if (bookmark.start < 0)\r
6527                                                 return true;\r
6528 \r
6529                                         rng = inst.getSel().createRange();\r
6530                                         rng.moveToElementText(inst.getBody());\r
6531                                         rng.collapse(true);\r
6532                                         rng.moveStart('character', bookmark.start);\r
6533                                         rng.moveEnd('character', bookmark.length);\r
6534                                 } catch (ex) {\r
6535                                         return true;\r
6536                                 }\r
6537                         }\r
6538 \r
6539                         rng.select();\r
6540 \r
6541                         win.scrollTo(bookmark.scrollX, bookmark.scrollY);\r
6542                         return true;\r
6543                 }\r
6544 \r
6545                 if (tinyMCE.isGecko || tinyMCE.isOpera) {\r
6546                         if (!sel)\r
6547                                 return false;\r
6548 \r
6549                         if (bookmark.rng) {\r
6550                                 sel.removeAllRanges();\r
6551                                 sel.addRange(bookmark.rng);\r
6552                         }\r
6553 \r
6554                         if (bookmark.start != -1 && bookmark.end != -1) {\r
6555                                 try {\r
6556                                         sd = this._getTextPos(b, bookmark.start, bookmark.end);\r
6557                                         rng = doc.createRange();\r
6558                                         rng.setStart(sd.startNode, sd.startOffset);\r
6559                                         rng.setEnd(sd.endNode, sd.endOffset);\r
6560                                         sel.removeAllRanges();\r
6561                                         sel.addRange(rng);\r
6562 \r
6563                                         if (!tinyMCE.isOpera)\r
6564                                                 win.focus();\r
6565                                 } catch (ex) {\r
6566                                         // Ignore\r
6567                                 }\r
6568                         }\r
6569 \r
6570                         /*\r
6571                         if (typeof(bookmark.index) != 'undefined') {\r
6572                                 tinyMCE.selectElements(b, 'IMG', function (n) {\r
6573                                         if (bookmark.index-- == 0) {\r
6574                                                 // Select image in Gecko here\r
6575                                         }\r
6576 \r
6577                                         return false;\r
6578                                 });\r
6579                         }\r
6580                         */\r
6581 \r
6582                         win.scrollTo(bookmark.scrollX, bookmark.scrollY);\r
6583                         return true;\r
6584                 }\r
6585 \r
6586                 return false;\r
6587         },\r
6588 \r
6589         _getPosText : function(r, sn, en) {\r
6590                 var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};\r
6591 \r
6592                 while ((n = w.nextNode()) != null) {\r
6593                         if (n == sn)\r
6594                                 d.start = p;\r
6595 \r
6596                         if (n == en) {\r
6597                                 d.end = p;\r
6598                                 return d;\r
6599                         }\r
6600 \r
6601                         p += n.nodeValue ? n.nodeValue.length : 0;\r
6602                 }\r
6603 \r
6604                 return null;\r
6605         },\r
6606 \r
6607         _getTextPos : function(r, sp, ep) {\r
6608                 var w = document.createTreeWalker(r, NodeFilter.SHOW_TEXT, null, false), n, p = 0, d = {};\r
6609 \r
6610                 while ((n = w.nextNode()) != null) {\r
6611                         p += n.nodeValue ? n.nodeValue.length : 0;\r
6612 \r
6613                         if (p >= sp && !d.startNode) {\r
6614                                 d.startNode = n;\r
6615                                 d.startOffset = sp - (p - n.nodeValue.length);\r
6616                         }\r
6617 \r
6618                         if (p >= ep) {\r
6619                                 d.endNode = n;\r
6620                                 d.endOffset = ep - (p - n.nodeValue.length);\r
6621 \r
6622                                 return d;\r
6623                         }\r
6624                 }\r
6625 \r
6626                 return null;\r
6627         },\r
6628 \r
6629         selectNode : function(node, collapse, select_text_node, to_start) {\r
6630                 var inst = this.instance, sel, rng, nodes;\r
6631 \r
6632                 if (!node)\r
6633                         return;\r
6634 \r
6635                 if (typeof(collapse) == "undefined")\r
6636                         collapse = true;\r
6637 \r
6638                 if (typeof(select_text_node) == "undefined")\r
6639                         select_text_node = false;\r
6640 \r
6641                 if (typeof(to_start) == "undefined")\r
6642                         to_start = true;\r
6643 \r
6644                 if (inst.settings.auto_resize)\r
6645                         inst.resizeToContent();\r
6646 \r
6647                 if (tinyMCE.isRealIE) {\r
6648                         rng = inst.getDoc().body.createTextRange();\r
6649 \r
6650                         try {\r
6651                                 rng.moveToElementText(node);\r
6652 \r
6653                                 if (collapse)\r
6654                                         rng.collapse(to_start);\r
6655 \r
6656                                 rng.select();\r
6657                         } catch (e) {\r
6658                                 // Throws illigal agrument in MSIE some times\r
6659                         }\r
6660                 } else {\r
6661                         sel = this.getSel();\r
6662 \r
6663                         if (!sel)\r
6664                                 return;\r
6665 \r
6666                         if (tinyMCE.isSafari) {\r
6667                                 sel.setBaseAndExtent(node, 0, node, node.innerText.length);\r
6668 \r
6669                                 if (collapse) {\r
6670                                         if (to_start)\r
6671                                                 sel.collapseToStart();\r
6672                                         else\r
6673                                                 sel.collapseToEnd();\r
6674                                 }\r
6675 \r
6676                                 this.scrollToNode(node);\r
6677 \r
6678                                 return;\r
6679                         }\r
6680 \r
6681                         rng = inst.getDoc().createRange();\r
6682 \r
6683                         if (select_text_node) {\r
6684                                 // Find first textnode in tree\r
6685                                 nodes = tinyMCE.getNodeTree(node, [], 3);\r
6686                                 if (nodes.length > 0)\r
6687                                         rng.selectNodeContents(nodes[0]);\r
6688                                 else\r
6689                                         rng.selectNodeContents(node);\r
6690                         } else\r
6691                                 rng.selectNode(node);\r
6692 \r
6693                         if (collapse) {\r
6694                                 // Special treatment of textnode collapse\r
6695                                 if (!to_start && node.nodeType == 3) {\r
6696                                         rng.setStart(node, node.nodeValue.length);\r
6697                                         rng.setEnd(node, node.nodeValue.length);\r
6698                                 } else\r
6699                                         rng.collapse(to_start);\r
6700                         }\r
6701 \r
6702                         sel.removeAllRanges();\r
6703                         sel.addRange(rng);\r
6704                 }\r
6705 \r
6706                 this.scrollToNode(node);\r
6707 \r
6708                 // Set selected element\r
6709                 tinyMCE.selectedElement = null;\r
6710                 if (node.nodeType == 1)\r
6711                         tinyMCE.selectedElement = node;\r
6712         },\r
6713 \r
6714         scrollToNode : function(node) {\r
6715                 var inst = this.instance, w = inst.getWin(), vp = inst.getViewPort(), pos = tinyMCE.getAbsPosition(node), cvp, p, cwin;\r
6716 \r
6717                 // Only scroll if out of visible area\r
6718                 if (pos.absLeft < vp.left || pos.absLeft > vp.left + vp.width || pos.absTop < vp.top || pos.absTop > vp.top + (vp.height-25))\r
6719                         w.scrollTo(pos.absLeft, pos.absTop - vp.height + 25);\r
6720 \r
6721                 // Scroll container window\r
6722                 if (inst.settings.auto_resize) {\r
6723                         cwin = inst.getContainerWin();\r
6724                         cvp = tinyMCE.getViewPort(cwin);\r
6725                         p = this.getAbsPosition(node);\r
6726 \r
6727                         if (p.absLeft < cvp.left || p.absLeft > cvp.left + cvp.width || p.absTop < cvp.top || p.absTop > cvp.top + cvp.height)\r
6728                                 cwin.scrollTo(p.absLeft, p.absTop - cvp.height + 25);\r
6729                 }\r
6730         },\r
6731 \r
6732         getAbsPosition : function(n) {\r
6733                 var pos = tinyMCE.getAbsPosition(n), ipos = tinyMCE.getAbsPosition(this.instance.iframeElement);\r
6734 \r
6735                 return {\r
6736                         absLeft : ipos.absLeft + pos.absLeft,\r
6737                         absTop : ipos.absTop + pos.absTop\r
6738                 };\r
6739         },\r
6740 \r
6741         getSel : function() {\r
6742                 var inst = this.instance;\r
6743 \r
6744                 if (tinyMCE.isRealIE)\r
6745                         return inst.getDoc().selection;\r
6746 \r
6747                 return inst.contentWindow.getSelection();\r
6748         },\r
6749 \r
6750         getRng : function() {\r
6751                 var s = this.getSel();\r
6752 \r
6753                 if (s == null)\r
6754                         return null;\r
6755 \r
6756                 if (tinyMCE.isRealIE)\r
6757                         return s.createRange();\r
6758 \r
6759                 if (tinyMCE.isSafari && !s.getRangeAt)\r
6760                         return '' + window.getSelection();\r
6761 \r
6762                 if (s.rangeCount > 0)\r
6763                         return s.getRangeAt(0);\r
6764 \r
6765                 return null;\r
6766         },\r
6767 \r
6768         isCollapsed : function() {\r
6769                 var r = this.getRng();\r
6770 \r
6771                 if (r.item)\r
6772                         return false;\r
6773 \r
6774                 return r.boundingWidth == 0 || this.getSel().isCollapsed;\r
6775         },\r
6776 \r
6777         collapse : function(b) {\r
6778                 var r = this.getRng(), s = this.getSel();\r
6779 \r
6780                 if (r.select) {\r
6781                         r.collapse(b);\r
6782                         r.select();\r
6783                 } else {\r
6784                         if (b)\r
6785                                 s.collapseToStart();\r
6786                         else\r
6787                                 s.collapseToEnd();\r
6788                 }\r
6789         },\r
6790 \r
6791         getFocusElement : function() {\r
6792                 var inst = this.instance, doc, rng, sel, elm;\r
6793 \r
6794                 if (tinyMCE.isRealIE) {\r
6795                         doc = inst.getDoc();\r
6796                         rng = doc.selection.createRange();\r
6797 \r
6798         //              if (rng.collapse)\r
6799         //                      rng.collapse(true);\r
6800 \r
6801                         elm = rng.item ? rng.item(0) : rng.parentElement();\r
6802                 } else {\r
6803                         if (!tinyMCE.isSafari && inst.isHidden())\r
6804                                 return inst.getBody();\r
6805 \r
6806                         sel = this.getSel();\r
6807                         rng = this.getRng();\r
6808 \r
6809                         if (!sel || !rng)\r
6810                                 return null;\r
6811 \r
6812                         elm = rng.commonAncestorContainer;\r
6813                         //elm = (sel && sel.anchorNode) ? sel.anchorNode : null;\r
6814 \r
6815                         // Handle selection a image or other control like element such as anchors\r
6816                         if (!rng.collapsed) {\r
6817                                 // Is selection small\r
6818                                 if (rng.startContainer == rng.endContainer) {\r
6819                                         if (rng.startOffset - rng.endOffset < 2) {\r
6820                                                 if (rng.startContainer.hasChildNodes())\r
6821                                                         elm = rng.startContainer.childNodes[rng.startOffset];\r
6822                                         }\r
6823                                 }\r
6824                         }\r
6825 \r
6826                         // Get the element parent of the node\r
6827                         elm = tinyMCE.getParentElement(elm);\r
6828 \r
6829                         //if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img")\r
6830                         //      elm = tinyMCE.selectedElement;\r
6831                 }\r
6832 \r
6833                 return elm;\r
6834         }\r
6835 \r
6836         };\r
6837 \r
6838 /* file:jscripts/tiny_mce/classes/TinyMCE_UndoRedo.class.js */\r
6839 \r
6840 function TinyMCE_UndoRedo(inst) {\r
6841         this.instance = inst;\r
6842         this.undoLevels = [];\r
6843         this.undoIndex = 0;\r
6844         this.typingUndoIndex = -1;\r
6845         this.undoRedo = true;\r
6846 };\r
6847 \r
6848 TinyMCE_UndoRedo.prototype = {\r
6849         add : function(l) {\r
6850                 var b, customUndoLevels, newHTML, inst = this.instance, i, ul, ur;\r
6851 \r
6852                 if (l) {\r
6853                         this.undoLevels[this.undoLevels.length] = l;\r
6854                         return true;\r
6855                 }\r
6856 \r
6857                 if (this.typingUndoIndex != -1) {\r
6858                         this.undoIndex = this.typingUndoIndex;\r
6859 \r
6860                         if (tinyMCE.typingUndoIndex != -1)\r
6861                                 tinyMCE.undoIndex = tinyMCE.typingUndoIndex;\r
6862                 }\r
6863 \r
6864                 newHTML = tinyMCE.trim(inst.getBody().innerHTML);\r
6865                 if (this.undoLevels[this.undoIndex] && newHTML != this.undoLevels[this.undoIndex].content) {\r
6866                         //tinyMCE.debug(newHTML, this.undoLevels[this.undoIndex].content);\r
6867 \r
6868                         // Is dirty again\r
6869                         inst.isNotDirty = false;\r
6870 \r
6871                         tinyMCE.dispatchCallback(inst, 'onchange_callback', 'onChange', inst);\r
6872 \r
6873                         // Time to compress\r
6874                         customUndoLevels = tinyMCE.settings.custom_undo_redo_levels;\r
6875                         if (customUndoLevels != -1 && this.undoLevels.length > customUndoLevels) {\r
6876                                 for (i=0; i<this.undoLevels.length-1; i++)\r
6877                                         this.undoLevels[i] = this.undoLevels[i+1];\r
6878 \r
6879                                 this.undoLevels.length--;\r
6880                                 this.undoIndex--;\r
6881 \r
6882                                 // Todo: Implement global undo/redo logic here\r
6883                         }\r
6884 \r
6885                         b = inst.undoBookmark;\r
6886 \r
6887                         if (!b)\r
6888                                 b = inst.selection.getBookmark();\r
6889 \r
6890                         this.undoIndex++;\r
6891                         this.undoLevels[this.undoIndex] = {\r
6892                                 content : newHTML,\r
6893                                 bookmark : b\r
6894                         };\r
6895 \r
6896                         // Remove all above from global undo/redo\r
6897                         ul = tinyMCE.undoLevels;\r
6898                         for (i=tinyMCE.undoIndex + 1; i<ul.length; i++) {\r
6899                                 ur = ul[i].undoRedo;\r
6900 \r
6901                                 if (ur.undoIndex == ur.undoLevels.length -1)\r
6902                                         ur.undoIndex--;\r
6903 \r
6904                                 ur.undoLevels.length--;\r
6905                         }\r
6906 \r
6907                         // Add global undo level\r
6908                         tinyMCE.undoLevels[tinyMCE.undoIndex++] = inst;\r
6909                         tinyMCE.undoLevels.length = tinyMCE.undoIndex;\r
6910 \r
6911                         this.undoLevels.length = this.undoIndex + 1;\r
6912 \r
6913                         return true;\r
6914                 }\r
6915 \r
6916                 return false;\r
6917         },\r
6918 \r
6919         undo : function() {\r
6920                 var inst = this.instance;\r
6921 \r
6922                 // Do undo\r
6923                 if (this.undoIndex > 0) {\r
6924                         this.undoIndex--;\r
6925 \r
6926                         tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);\r
6927                         inst.repaint();\r
6928 \r
6929                         if (inst.settings.custom_undo_redo_restore_selection)\r
6930                                 inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);\r
6931                 }\r
6932         },\r
6933 \r
6934         redo : function() {\r
6935                 var inst = this.instance;\r
6936 \r
6937                 tinyMCE.execCommand("mceEndTyping");\r
6938 \r
6939                 if (this.undoIndex < (this.undoLevels.length-1)) {\r
6940                         this.undoIndex++;\r
6941 \r
6942                         tinyMCE.setInnerHTML(inst.getBody(), this.undoLevels[this.undoIndex].content);\r
6943                         inst.repaint();\r
6944 \r
6945                         if (inst.settings.custom_undo_redo_restore_selection)\r
6946                                 inst.selection.moveToBookmark(this.undoLevels[this.undoIndex].bookmark);\r
6947                 }\r
6948 \r
6949                 tinyMCE.triggerNodeChange();\r
6950         }\r
6951 \r
6952         };\r
6953 \r
6954 /* file:jscripts/tiny_mce/classes/TinyMCE_ForceParagraphs.class.js */\r
6955 \r
6956 var TinyMCE_ForceParagraphs = {\r
6957         _insertPara : function(inst, e) {\r
6958                 var doc = inst.getDoc(), sel = inst.getSel(), body = inst.getBody(), win = inst.contentWindow, rng = sel.getRangeAt(0);\r
6959                 var rootElm = doc.documentElement, blockName = "P", startNode, endNode, startBlock, endBlock;\r
6960                 var rngBefore, rngAfter, direct, startNode, startOffset, endNode, endOffset, b = tinyMCE.isOpera ? inst.selection.getBookmark() : null;\r
6961                 var paraBefore, paraAfter, startChop, endChop, contents, i;\r
6962 \r
6963                 function isEmpty(para) {\r
6964                         var nodes;\r
6965 \r
6966                         function isEmptyHTML(html) {\r
6967                                 return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == '';\r
6968                         }\r
6969 \r
6970                         // Check for images\r
6971                         if (para.getElementsByTagName("img").length > 0)\r
6972                                 return false;\r
6973 \r
6974                         // Check for tables\r
6975                         if (para.getElementsByTagName("table").length > 0)\r
6976                                 return false;\r
6977 \r
6978                         // Check for HRs\r
6979                         if (para.getElementsByTagName("hr").length > 0)\r
6980                                 return false;\r
6981 \r
6982                         // Check all textnodes\r
6983                         nodes = tinyMCE.getNodeTree(para, [], 3);\r
6984                         for (i=0; i<nodes.length; i++) {\r
6985                                 if (!isEmptyHTML(nodes[i].nodeValue))\r
6986                                         return false;\r
6987                         }\r
6988 \r
6989                         // No images, no tables, no hrs, no text content then it's empty\r
6990                         return true;\r
6991                 }\r
6992 \r
6993         //      tinyMCE.debug(body.innerHTML);\r
6994 \r
6995         //      debug(e.target, sel.anchorNode.nodeName, sel.focusNode.nodeName, rng.startContainer, rng.endContainer, rng.commonAncestorContainer, sel.anchorOffset, sel.focusOffset, rng.toString());\r
6996 \r
6997                 // Setup before range\r
6998                 rngBefore = doc.createRange();\r
6999                 rngBefore.setStart(sel.anchorNode, sel.anchorOffset);\r
7000                 rngBefore.collapse(true);\r
7001 \r
7002                 // Setup after range\r
7003                 rngAfter = doc.createRange();\r
7004                 rngAfter.setStart(sel.focusNode, sel.focusOffset);\r
7005                 rngAfter.collapse(true);\r
7006 \r
7007                 // Setup start/end points\r
7008                 direct = rngBefore.compareBoundaryPoints(rngBefore.START_TO_END, rngAfter) < 0;\r
7009                 startNode = direct ? sel.anchorNode : sel.focusNode;\r
7010                 startOffset = direct ? sel.anchorOffset : sel.focusOffset;\r
7011                 endNode = direct ? sel.focusNode : sel.anchorNode;\r
7012                 endOffset = direct ? sel.focusOffset : sel.anchorOffset;\r
7013 \r
7014                 startNode = startNode.nodeName == "HTML" ? doc.body : startNode; // Fix for Opera bug: https://bugs.opera.com/show_bug.cgi?id=273224&comments=yes\r
7015                 startNode = startNode.nodeName == "BODY" ? startNode.firstChild : startNode;\r
7016                 endNode = endNode.nodeName == "BODY" ? endNode.firstChild : endNode;\r
7017 \r
7018                 // Get block elements\r
7019                 startBlock = inst.getParentBlockElement(startNode);\r
7020                 endBlock = inst.getParentBlockElement(endNode);\r
7021 \r
7022                 // If absolute force paragraph generation within\r
7023                 if (startBlock && (startBlock.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(startBlock.style.position)))\r
7024                         startBlock = null;\r
7025 \r
7026                 if (endBlock && (endBlock.nodeName == 'CAPTION' || /absolute|relative|static/gi.test(endBlock.style.position)))\r
7027                         endBlock = null;\r
7028 \r
7029                 // Use current block name\r
7030                 if (startBlock != null) {\r
7031                         blockName = startBlock.nodeName;\r
7032 \r
7033                         // Use P instead\r
7034                         if (/(TD|TABLE|TH|CAPTION)/.test(blockName) || (blockName == "DIV" && /left|right/gi.test(startBlock.style.cssFloat)))\r
7035                                 blockName = "P";\r
7036                 }\r
7037 \r
7038                 // Within a list use normal behaviour\r
7039                 if (tinyMCE.getParentElement(startBlock, "OL,UL", null, body) != null)\r
7040                         return false;\r
7041 \r
7042                 // Within a table create new paragraphs\r
7043                 if ((startBlock != null && startBlock.nodeName == "TABLE") || (endBlock != null && endBlock.nodeName == "TABLE"))\r
7044                         startBlock = endBlock = null;\r
7045 \r
7046                 // Setup new paragraphs\r
7047                 paraBefore = (startBlock != null && startBlock.nodeName == blockName) ? startBlock.cloneNode(false) : doc.createElement(blockName);\r
7048                 paraAfter = (endBlock != null && endBlock.nodeName == blockName) ? endBlock.cloneNode(false) : doc.createElement(blockName);\r
7049 \r
7050                 // Is header, then force paragraph under\r
7051                 if (/^(H[1-6])$/.test(blockName))\r
7052                         paraAfter = doc.createElement("p");\r
7053 \r
7054                 // Setup chop nodes\r
7055                 startChop = startNode;\r
7056                 endChop = endNode;\r
7057 \r
7058                 // Get startChop node\r
7059                 node = startChop;\r
7060                 do {\r
7061                         if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))\r
7062                                 break;\r
7063 \r
7064                         startChop = node;\r
7065                 } while ((node = node.previousSibling ? node.previousSibling : node.parentNode));\r
7066 \r
7067                 // Get endChop node\r
7068                 node = endChop;\r
7069                 do {\r
7070                         if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node))\r
7071                                 break;\r
7072 \r
7073                         endChop = node;\r
7074                 } while ((node = node.nextSibling ? node.nextSibling : node.parentNode));\r
7075 \r
7076                 // Fix when only a image is within the TD\r
7077                 if (startChop.nodeName == "TD")\r
7078                         startChop = startChop.firstChild;\r
7079 \r
7080                 if (endChop.nodeName == "TD")\r
7081                         endChop = endChop.lastChild;\r
7082 \r
7083                 // If not in a block element\r
7084                 if (startBlock == null) {\r
7085                         // Delete selection\r
7086                         rng.deleteContents();\r
7087 \r
7088                         if (!tinyMCE.isSafari)\r
7089                                 sel.removeAllRanges();\r
7090 \r
7091                         if (startChop != rootElm && endChop != rootElm) {\r
7092                                 // Insert paragraph before\r
7093                                 rngBefore = rng.cloneRange();\r
7094 \r
7095                                 if (startChop == body)\r
7096                                         rngBefore.setStart(startChop, 0);\r
7097                                 else\r
7098                                         rngBefore.setStartBefore(startChop);\r
7099 \r
7100                                 paraBefore.appendChild(rngBefore.cloneContents());\r
7101 \r
7102                                 // Insert paragraph after\r
7103                                 if (endChop.parentNode.nodeName == blockName)\r
7104                                         endChop = endChop.parentNode;\r
7105 \r
7106                                 // If not after image\r
7107                                 //if (rng.startContainer.nodeName != "BODY" && rng.endContainer.nodeName != "BODY")\r
7108                                         rng.setEndAfter(endChop);\r
7109 \r
7110                                 if (endChop.nodeName != "#text" && endChop.nodeName != "BODY")\r
7111                                         rngBefore.setEndAfter(endChop);\r
7112 \r
7113                                 contents = rng.cloneContents();\r
7114                                 if (contents.firstChild && (contents.firstChild.nodeName == blockName || contents.firstChild.nodeName == "BODY"))\r
7115                                         paraAfter.innerHTML = contents.firstChild.innerHTML;\r
7116                                 else\r
7117                                         paraAfter.appendChild(contents);\r
7118 \r
7119                                 // Check if it's a empty paragraph\r
7120                                 if (isEmpty(paraBefore))\r
7121                                         paraBefore.innerHTML = "&nbsp;";\r
7122 \r
7123                                 // Check if it's a empty paragraph\r
7124                                 if (isEmpty(paraAfter))\r
7125                                         paraAfter.innerHTML = "&nbsp;";\r
7126 \r
7127                                 // Delete old contents\r
7128                                 rng.deleteContents();\r
7129                                 rngAfter.deleteContents();\r
7130                                 rngBefore.deleteContents();\r
7131 \r
7132                                 // Insert new paragraphs\r
7133                                 if (tinyMCE.isOpera) {\r
7134                                         paraBefore.normalize();\r
7135                                         rngBefore.insertNode(paraBefore);\r
7136                                         paraAfter.normalize();\r
7137                                         rngBefore.insertNode(paraAfter);\r
7138                                 } else {\r
7139                                         paraAfter.normalize();\r
7140                                         rngBefore.insertNode(paraAfter);\r
7141                                         paraBefore.normalize();\r
7142                                         rngBefore.insertNode(paraBefore);\r
7143                                 }\r
7144 \r
7145                                 //tinyMCE.debug("1: ", paraBefore.innerHTML, paraAfter.innerHTML);\r
7146                         } else {\r
7147                                 body.innerHTML = "<" + blockName + ">&nbsp;</" + blockName + "><" + blockName + ">&nbsp;</" + blockName + ">";\r
7148                                 paraAfter = body.childNodes[1];\r
7149                         }\r
7150 \r
7151                         inst.selection.moveToBookmark(b);\r
7152                         inst.selection.selectNode(paraAfter, true, true);\r
7153 \r
7154                         return true;\r
7155                 }\r
7156 \r
7157                 // Place first part within new paragraph\r
7158                 if (startChop.nodeName == blockName)\r
7159                         rngBefore.setStart(startChop, 0);\r
7160                 else\r
7161                         rngBefore.setStartBefore(startChop);\r
7162 \r
7163                 rngBefore.setEnd(startNode, startOffset);\r
7164                 paraBefore.appendChild(rngBefore.cloneContents());\r
7165 \r
7166                 // Place secound part within new paragraph\r
7167                 rngAfter.setEndAfter(endChop);\r
7168                 rngAfter.setStart(endNode, endOffset);\r
7169                 contents = rngAfter.cloneContents();\r
7170 \r
7171                 if (contents.firstChild && contents.firstChild.nodeName == blockName) {\r
7172         /*              var nodes = contents.firstChild.childNodes;\r
7173                         for (i=0; i<nodes.length; i++) {\r
7174                                 //tinyMCE.debug(nodes[i].nodeName);\r
7175                                 if (nodes[i].nodeName != "BODY")\r
7176                                         paraAfter.appendChild(nodes[i]);\r
7177                         }\r
7178         */\r
7179                         paraAfter.innerHTML = contents.firstChild.innerHTML;\r
7180                 } else\r
7181                         paraAfter.appendChild(contents);\r
7182 \r
7183                 // Check if it's a empty paragraph\r
7184                 if (isEmpty(paraBefore))\r
7185                         paraBefore.innerHTML = "&nbsp;";\r
7186 \r
7187                 // Check if it's a empty paragraph\r
7188                 if (isEmpty(paraAfter))\r
7189                         paraAfter.innerHTML = "&nbsp;";\r
7190 \r
7191                 // Create a range around everything\r
7192                 rng = doc.createRange();\r
7193 \r
7194                 if (!startChop.previousSibling && startChop.parentNode.nodeName.toUpperCase() == blockName) {\r
7195                         rng.setStartBefore(startChop.parentNode);\r
7196                 } else {\r
7197                         if (rngBefore.startContainer.nodeName.toUpperCase() == blockName && rngBefore.startOffset == 0)\r
7198                                 rng.setStartBefore(rngBefore.startContainer);\r
7199                         else\r
7200                                 rng.setStart(rngBefore.startContainer, rngBefore.startOffset);\r
7201                 }\r
7202 \r
7203                 if (!endChop.nextSibling && endChop.parentNode.nodeName.toUpperCase() == blockName)\r
7204                         rng.setEndAfter(endChop.parentNode);\r
7205                 else\r
7206                         rng.setEnd(rngAfter.endContainer, rngAfter.endOffset);\r
7207 \r
7208                 // Delete all contents and insert new paragraphs\r
7209                 rng.deleteContents();\r
7210 \r
7211                 if (tinyMCE.isOpera) {\r
7212                         rng.insertNode(paraBefore);\r
7213                         rng.insertNode(paraAfter);\r
7214                 } else {\r
7215                         rng.insertNode(paraAfter);\r
7216                         rng.insertNode(paraBefore);\r
7217                 }\r
7218 \r
7219                 //tinyMCE.debug("2", paraBefore.innerHTML, paraAfter.innerHTML);\r
7220 \r
7221                 // Normalize\r
7222                 paraAfter.normalize();\r
7223                 paraBefore.normalize();\r
7224 \r
7225                 inst.selection.moveToBookmark(b);\r
7226                 inst.selection.selectNode(paraAfter, true, true);\r
7227 \r
7228                 return true;\r
7229         },\r
7230 \r
7231         _handleBackSpace : function(inst) {\r
7232                 var r = inst.getRng(), sn = r.startContainer, nv, s = false;\r
7233 \r
7234                 // Added body check for bug #1527787\r
7235                 if (sn && sn.nextSibling && sn.nextSibling.nodeName == "BR" && sn.parentNode.nodeName != "BODY") {\r
7236                         nv = sn.nodeValue;\r
7237 \r
7238                         // Handle if a backspace is pressed after a space character #bug 1466054 removed since fix for #1527787\r
7239                         /*if (nv != null && nv.length >= r.startOffset && nv.charAt(r.startOffset - 1) == ' ')\r
7240                                 s = true;*/\r
7241 \r
7242                         // Only remove BRs if we are at the end of line #bug 1464152\r
7243                         if (nv != null && r.startOffset == nv.length)\r
7244                                 sn.nextSibling.parentNode.removeChild(sn.nextSibling);\r
7245                 }\r
7246 \r
7247                 if (inst.settings.auto_resize)\r
7248                         inst.resizeToContent();\r
7249 \r
7250                 return s;\r
7251         }\r
7252 \r
7253         };\r
7254 \r
7255 /* file:jscripts/tiny_mce/classes/TinyMCE_Layer.class.js */\r
7256 \r
7257 function TinyMCE_Layer(id, bm) {\r
7258         this.id = id;\r
7259         this.blockerElement = null;\r
7260         this.events = false;\r
7261         this.element = null;\r
7262         this.blockMode = typeof(bm) != 'undefined' ? bm : true;\r
7263         this.doc = document;\r
7264 };\r
7265 \r
7266 TinyMCE_Layer.prototype = {\r
7267         moveRelativeTo : function(re, p) {\r
7268                 var rep = this.getAbsPosition(re), e = this.getElement(), x, y;\r
7269                 var w = parseInt(re.offsetWidth), h = parseInt(re.offsetHeight);\r
7270                 var ew = parseInt(e.offsetWidth), eh = parseInt(e.offsetHeight);\r
7271 \r
7272                 switch (p) {\r
7273                         case "tl":\r
7274                                 x = rep.absLeft;\r
7275                                 y = rep.absTop;\r
7276                                 break;\r
7277 \r
7278                         case "tr":\r
7279                                 x = rep.absLeft + w;\r
7280                                 y = rep.absTop;\r
7281                                 break;\r
7282 \r
7283                         case "bl":\r
7284                                 x = rep.absLeft;\r
7285                                 y = rep.absTop + h;\r
7286                                 break;\r
7287 \r
7288                         case "br":\r
7289                                 x = rep.absLeft + w;\r
7290                                 y = rep.absTop + h;\r
7291                                 break;\r
7292 \r
7293                         case "cc":\r
7294                                 x = rep.absLeft + (w / 2) - (ew / 2);\r
7295                                 y = rep.absTop + (h / 2) - (eh / 2);\r
7296                                 break;\r
7297                 }\r
7298 \r
7299                 this.moveTo(x, y);\r
7300         },\r
7301 \r
7302         moveBy : function(x, y) {\r
7303                 var e = this.getElement();\r
7304                 this.moveTo(parseInt(e.style.left) + x, parseInt(e.style.top) + y);\r
7305         },\r
7306 \r
7307         moveTo : function(x, y) {\r
7308                 var e = this.getElement();\r
7309 \r
7310                 e.style.left = x + "px";\r
7311                 e.style.top = y + "px";\r
7312 \r
7313                 this.updateBlocker();\r
7314         },\r
7315 \r
7316         resizeBy : function(w, h) {\r
7317                 var e = this.getElement();\r
7318                 this.resizeTo(parseInt(e.style.width) + w, parseInt(e.style.height) + h);\r
7319         },\r
7320 \r
7321         resizeTo : function(w, h) {\r
7322                 var e = this.getElement();\r
7323 \r
7324                 if (w != null)\r
7325                         e.style.width = w + "px";\r
7326 \r
7327                 if (h != null)\r
7328                         e.style.height = h + "px";\r
7329 \r
7330                 this.updateBlocker();\r
7331         },\r
7332 \r
7333         show : function() {\r
7334                 var el = this.getElement();\r
7335 \r
7336                 if (el) {\r
7337                         el.style.display = 'block';\r
7338                         this.updateBlocker();\r
7339                 }\r
7340         },\r
7341 \r
7342         hide : function() {\r
7343                 var el = this.getElement();\r
7344 \r
7345                 if (el) {\r
7346                         el.style.display = 'none';\r
7347                         this.updateBlocker();\r
7348                 }\r
7349         },\r
7350 \r
7351         isVisible : function() {\r
7352                 return this.getElement().style.display == 'block';\r
7353         },\r
7354 \r
7355         getElement : function() {\r
7356                 if (!this.element)\r
7357                         this.element = this.doc.getElementById(this.id);\r
7358 \r
7359                 return this.element;\r
7360         },\r
7361 \r
7362         setBlockMode : function(s) {\r
7363                 this.blockMode = s;\r
7364         },\r
7365 \r
7366         updateBlocker : function() {\r
7367                 var e, b, x, y, w, h;\r
7368 \r
7369                 b = this.getBlocker();\r
7370                 if (b) {\r
7371                         if (this.blockMode) {\r
7372                                 e = this.getElement();\r
7373                                 x = this.parseInt(e.style.left);\r
7374                                 y = this.parseInt(e.style.top);\r
7375                                 w = this.parseInt(e.offsetWidth);\r
7376                                 h = this.parseInt(e.offsetHeight);\r
7377 \r
7378                                 b.style.left = x + 'px';\r
7379                                 b.style.top = y + 'px';\r
7380                                 b.style.width = w + 'px';\r
7381                                 b.style.height = h + 'px';\r
7382                                 b.style.display = e.style.display;\r
7383                         } else\r
7384                                 b.style.display = 'none';\r
7385                 }\r
7386         },\r
7387 \r
7388         getBlocker : function() {\r
7389                 var d, b;\r
7390 \r
7391                 if (!this.blockerElement && this.blockMode) {\r
7392                         d = this.doc;\r
7393                         b = d.getElementById(this.id + "_blocker");\r
7394 \r
7395                         if (!b) {\r
7396                                 b = d.createElement("iframe");\r
7397 \r
7398                                 b.setAttribute('id', this.id + "_blocker");\r
7399                                 b.style.cssText = 'display: none; position: absolute; left: 0; top: 0';\r
7400                                 b.src = 'javascript:false;';\r
7401                                 b.frameBorder = '0';\r
7402                                 b.scrolling = 'no';\r
7403         \r
7404                                 d.body.appendChild(b);\r
7405                         }\r
7406 \r
7407                         this.blockerElement = b;\r
7408                 }\r
7409 \r
7410                 return this.blockerElement;\r
7411         },\r
7412 \r
7413         getAbsPosition : function(n) {\r
7414                 var p = {absLeft : 0, absTop : 0};\r
7415 \r
7416                 while (n) {\r
7417                         p.absLeft += n.offsetLeft;\r
7418                         p.absTop += n.offsetTop;\r
7419                         n = n.offsetParent;\r
7420                 }\r
7421 \r
7422                 return p;\r
7423         },\r
7424 \r
7425         create : function(n, c, p, h) {\r
7426                 var d = this.doc, e = d.createElement(n);\r
7427 \r
7428                 e.setAttribute('id', this.id);\r
7429 \r
7430                 if (c)\r
7431                         e.className = c;\r
7432 \r
7433                 if (!p)\r
7434                         p = d.body;\r
7435 \r
7436                 if (h)\r
7437                         e.innerHTML = h;\r
7438 \r
7439                 p.appendChild(e);\r
7440 \r
7441                 return this.element = e;\r
7442         },\r
7443 \r
7444         exists : function() {\r
7445                 return this.doc.getElementById(this.id) != null;\r
7446         },\r
7447 \r
7448         parseInt : function(s) {\r
7449                 if (s == null || s == '')\r
7450                         return 0;\r
7451 \r
7452                 return parseInt(s);\r
7453         },\r
7454 \r
7455         remove : function() {\r
7456                 var e = this.getElement(), b = this.getBlocker();\r
7457 \r
7458                 if (e)\r
7459                         e.parentNode.removeChild(e);\r
7460 \r
7461                 if (b)\r
7462                         b.parentNode.removeChild(b);\r
7463         }\r
7464 \r
7465         };\r
7466 \r
7467 /* file:jscripts/tiny_mce/classes/TinyMCE_Menu.class.js */\r
7468 \r
7469 function TinyMCE_Menu() {\r
7470         var id;\r
7471 \r
7472         if (typeof(tinyMCE.menuCounter) == "undefined")\r
7473                 tinyMCE.menuCounter = 0;\r
7474 \r
7475         id = "mc_menu_" + tinyMCE.menuCounter++;\r
7476 \r
7477         TinyMCE_Layer.call(this, id, true);\r
7478 \r
7479         this.id = id;\r
7480         this.items = [];\r
7481         this.needsUpdate = true;\r
7482 };\r
7483 \r
7484 TinyMCE_Menu.prototype = tinyMCE.extend(TinyMCE_Layer.prototype, {\r
7485         init : function(s) {\r
7486                 var n;\r
7487 \r
7488                 // Default params\r
7489                 this.settings = {\r
7490                         separator_class : 'mceMenuSeparator',\r
7491                         title_class : 'mceMenuTitle',\r
7492                         disabled_class : 'mceMenuDisabled',\r
7493                         menu_class : 'mceMenu',\r
7494                         drop_menu : true\r
7495                 };\r
7496 \r
7497                 for (n in s)\r
7498                         this.settings[n] = s[n];\r
7499 \r
7500                 this.create('div', this.settings.menu_class);\r
7501         },\r
7502 \r
7503         clear : function() {\r
7504                 this.items = [];\r
7505         },\r
7506 \r
7507         addTitle : function(t) {\r
7508                 this.add({type : 'title', text : t});\r
7509         },\r
7510 \r
7511         addDisabled : function(t) {\r
7512                 this.add({type : 'disabled', text : t});\r
7513         },\r
7514 \r
7515         addSeparator : function() {\r
7516                 this.add({type : 'separator'});\r
7517         },\r
7518 \r
7519         addItem : function(t, js) {\r
7520                 this.add({text : t, js : js});\r
7521         },\r
7522 \r
7523         add : function(mi) {\r
7524                 this.items[this.items.length] = mi;\r
7525                 this.needsUpdate = true;\r
7526         },\r
7527 \r
7528         update : function() {\r
7529                 var e = this.getElement(), h = '', i, t, m = this.items, s = this.settings;\r
7530 \r
7531                 if (this.settings.drop_menu)\r
7532                         h += '<span class="mceMenuLine"></span>';\r
7533 \r
7534                 h += '<table border="0" cellpadding="0" cellspacing="0">';\r
7535 \r
7536                 for (i=0; i<m.length; i++) {\r
7537                         t = tinyMCE.xmlEncode(m[i].text);\r
7538                         c = m[i].class_name ? ' class="' + m[i].class_name + '"' : '';\r
7539 \r
7540                         switch (m[i].type) {\r
7541                                 case 'separator':\r
7542                                         h += '<tr class="' + s.separator_class + '"><td>';\r
7543                                         break;\r
7544 \r
7545                                 case 'title':\r
7546                                         h += '<tr class="' + s.title_class + '"><td><span' + c +'>' + t + '</span>';\r
7547                                         break;\r
7548 \r
7549                                 case 'disabled':\r
7550                                         h += '<tr class="' + s.disabled_class + '"><td><span' + c +'>' + t + '</span>';\r
7551                                         break;\r
7552 \r
7553                                 default:\r
7554                                         h += '<tr><td><a href="' + tinyMCE.xmlEncode(m[i].js) + '" onmousedown="' + tinyMCE.xmlEncode(m[i].js) + ';return tinyMCE.cancelEvent(event);" onclick="return tinyMCE.cancelEvent(event);" onmouseup="return tinyMCE.cancelEvent(event);"><span' + c +'>' + t + '</span></a>';\r
7555                         }\r
7556 \r
7557                         h += '</td></tr>';\r
7558                 }\r
7559 \r
7560                 h += '</table>';\r
7561 \r
7562                 e.innerHTML = h;\r
7563 \r
7564                 this.needsUpdate = false;\r
7565                 this.updateBlocker();\r
7566         },\r
7567 \r
7568         show : function() {\r
7569                 var nl, i;\r
7570 \r
7571                 if (tinyMCE.lastMenu == this)\r
7572                         return;\r
7573 \r
7574                 if (this.needsUpdate)\r
7575                         this.update();\r
7576 \r
7577                 if (tinyMCE.lastMenu && tinyMCE.lastMenu != this)\r
7578                         tinyMCE.lastMenu.hide();\r
7579 \r
7580                 TinyMCE_Layer.prototype.show.call(this);\r
7581 \r
7582                 if (!tinyMCE.isOpera) {\r
7583                         // Accessibility stuff\r
7584 /*                      nl = this.getElement().getElementsByTagName("a");\r
7585                         if (nl.length > 0)\r
7586                                 nl[0].focus();*/\r
7587                 }\r
7588 \r
7589                 tinyMCE.lastMenu = this;\r
7590         }\r
7591 \r
7592         });\r
7593 \r
7594 /* file:jscripts/tiny_mce/classes/TinyMCE_Debug.class.js */\r
7595 \r
7596 tinyMCE.add(TinyMCE_Engine, {\r
7597         debug : function() {\r
7598                 var m = "", a, i, l = tinyMCE.log.length;\r
7599 \r
7600                 for (i=0, a = this.debug.arguments; i<a.length; i++) {\r
7601                         m += a[i];\r
7602 \r
7603                         if (i<a.length-1)\r
7604                                 m += ', ';\r
7605                 }\r
7606 \r
7607                 if (l < 1000)\r
7608                         tinyMCE.log[l] = "[debug] " + m;\r
7609         }\r
7610 \r
7611         });\r
7612 \r