[ Index ] |
|
Code source de eGroupWare 1.2.106-2 |
1 /** 2 * $RCSfile$ 3 * $Revision: 19345 $ 4 * $Date: 2005-10-11 01:20:11 +0200 (Di, 11 Okt 2005) $ 5 * 6 * @author Moxiecode 7 * @copyright Copyright � 2004, Moxiecode Systems AB, All rights reserved. 8 */ 9 10 function TinyMCE() { 11 this.instances = new Array(); 12 this.stickyClassesLookup = new Array(); 13 this.windowArgs = new Array(); 14 this.loadedFiles = new Array(); 15 this.configs = new Array(); 16 this.currentConfig = 0; 17 this.eventHandlers = new Array(); 18 19 // Browser check 20 this.isMSIE = (navigator.appName == "Microsoft Internet Explorer"); 21 this.isMSIE5 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5') != -1); 22 this.isMSIE5_0 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5.0') != -1); 23 this.isGecko = navigator.userAgent.indexOf('Gecko') != -1; 24 this.isSafari = navigator.userAgent.indexOf('Safari') != -1; 25 26 if (this.isSafari) 27 alert("Safari support is very limited and should be considered experimental.\nSo there is no need to even submit bugreports on this early version."); 28 29 // TinyMCE editor id instance counter 30 this.idCounter = 0; 31 }; 32 33 TinyMCE.prototype.defParam = function(key, def_val) { 34 this.settings[key] = tinyMCE.getParam(key, def_val); 35 }; 36 37 TinyMCE.prototype.init = function(settings) { 38 var theme; 39 40 this.settings = settings; 41 42 // Check if valid browser has execcommand support 43 if (typeof(document.execCommand) == 'undefined') 44 return; 45 46 // Get script base path 47 if (!tinyMCE.baseURL) { 48 var elements = document.getElementsByTagName('script'); 49 50 for (var i=0; i<elements.length; i++) { 51 if (elements[i].src && (elements[i].src.indexOf("tiny_mce.js") != -1 || elements[i].src.indexOf("tiny_mce_src.js") != -1)) { 52 var src = elements[i].src; 53 54 tinyMCE.srcMode = (src.indexOf('_src') != -1) ? '_src' : ''; 55 src = src.substring(0, src.lastIndexOf('/')); 56 57 tinyMCE.baseURL = src; 58 break; 59 } 60 } 61 } 62 63 // Get document base path 64 this.documentBasePath = document.location.href; 65 if (this.documentBasePath.indexOf('?') != -1) 66 this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.indexOf('?')); 67 this.documentURL = this.documentBasePath; 68 this.documentBasePath = this.documentBasePath.substring(0, this.documentBasePath.lastIndexOf('/')); 69 70 // If not HTTP absolute 71 if (tinyMCE.baseURL.indexOf('://') == -1 && tinyMCE.baseURL.charAt(0) != '/') { 72 // If site absolute 73 tinyMCE.baseURL = this.documentBasePath + "/" + tinyMCE.baseURL; 74 } 75 76 // Set default values on settings 77 this.defParam("mode", "none"); 78 this.defParam("theme", "advanced"); 79 this.defParam("plugins", "", true); 80 this.defParam("language", "en"); 81 this.defParam("docs_language", this.settings['language']); 82 this.defParam("elements", ""); 83 this.defParam("textarea_trigger", "mce_editable"); 84 this.defParam("valid_elements", "+a[name|href|target|title],strong/b[class],em/i[class],strike[class],u[class],p[dir|class|align],ol,ul,li,br,img[class|src|border=0|alt|title|hspace|vspace|width|height|align],sub,sup,blockquote[dir|style],table[border=0|cellspacing|cellpadding|width|height|class|align],tr[class|rowspan|width|height|align|valign],td[dir|class|colspan|rowspan|width|height|align|valign],div[dir|class|align],span[class|align],pre[class|align],address[class|align],h1[dir|class|align],h2[dir|class|align],h3[dir|class|align],h4[dir|class|align],h5[dir|class|align],h6[dir|class|align],hr"); 85 this.defParam("extended_valid_elements", ""); 86 this.defParam("invalid_elements", ""); 87 this.defParam("encoding", ""); 88 this.defParam("urlconverter_callback", tinyMCE.getParam("urlconvertor_callback", "TinyMCE.prototype.convertURL")); 89 this.defParam("save_callback", ""); 90 this.defParam("debug", false); 91 this.defParam("force_br_newlines", false); 92 this.defParam("force_p_newlines", true); 93 this.defParam("add_form_submit_trigger", true); 94 this.defParam("relative_urls", true); 95 this.defParam("remove_script_host", true); 96 this.defParam("focus_alert", true); 97 this.defParam("document_base_url", this.documentURL); 98 this.defParam("visual", true); 99 this.defParam("visual_table_class", "mceVisualAid"); 100 this.defParam("setupcontent_callback", ""); 101 this.defParam("fix_content_duplication", true); 102 this.defParam("custom_undo_redo", true); 103 this.defParam("custom_undo_redo_levels", -1); 104 this.defParam("custom_undo_redo_keyboard_shortcuts", true); 105 this.defParam("verify_css_classes", false); 106 this.defParam("trim_span_elements", true); 107 this.defParam("verify_html", true); 108 this.defParam("apply_source_formatting", false); 109 this.defParam("directionality", "ltr"); 110 this.defParam("auto_cleanup_word", false); 111 this.defParam("cleanup_on_startup", false); 112 this.defParam("inline_styles", false); 113 this.defParam("convert_newlines_to_brs", false); 114 this.defParam("auto_reset_designmode", false); 115 this.defParam("entities", "160,nbsp,38,amp,34,quot,162,cent,8364,euro,163,pound,165,yen,169,copy,174,reg,8482,trade,8240,permil,181,micro,183,middot,8226,bull,8230,hellip,8242,prime,8243,Prime,167,sect,182,para,223,szlig,8249,lsaquo,8250,rsaquo,171,laquo,187,raquo,8216,lsquo,8217,rsquo,8220,ldquo,8221,rdquo,8218,sbquo,8222,bdquo,60,lt,62,gt,8804,le,8805,ge,8211,ndash,8212,mdash,175,macr,8254,oline,164,curren,166,brvbar,168,uml,161,iexcl,191,iquest,710,circ,732,tilde,176,deg,8722,minus,177,plusmn,247,divide,8260,frasl,215,times,185,sup1,178,sup2,179,sup3,188,frac14,189,frac12,190,frac34,402,fnof,8747,int,8721,sum,8734,infin,8730,radic,8764,sim,8773,cong,8776,asymp,8800,ne,8801,equiv,8712,isin,8713,notin,8715,ni,8719,prod,8743,and,8744,or,172,not,8745,cap,8746,cup,8706,part,8704,forall,8707,exist,8709,empty,8711,nabla,8727,lowast,8733,prop,8736,ang,180,acute,184,cedil,170,ordf,186,ordm,8224,dagger,8225,Dagger,192,Agrave,194,Acirc,195,Atilde,196,Auml,197,Aring,198,AElig,199,Ccedil,200,Egrave,202,Ecirc,203,Euml,204,Igrave,206,Icirc,207,Iuml,208,ETH,209,Ntilde,210,Ograve,212,Ocirc,213,Otilde,214,Ouml,216,Oslash,338,OElig,217,Ugrave,219,Ucirc,220,Uuml,376,Yuml,222,THORN,224,agrave,226,acirc,227,atilde,228,auml,229,aring,230,aelig,231,ccedil,232,egrave,234,ecirc,235,euml,236,igrave,238,icirc,239,iuml,240,eth,241,ntilde,242,ograve,244,ocirc,245,otilde,246,ouml,248,oslash,339,oelig,249,ugrave,251,ucirc,252,uuml,254,thorn,255,yuml,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,8501,alefsym,982,piv,8476,real,977,thetasym,978,upsih,8472,weierp,8465,image,8592,larr,8593,uarr,8594,rarr,8595,darr,8596,harr,8629,crarr,8656,lArr,8657,uArr,8658,rArr,8659,dArr,8660,hArr,8756,there4,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,8194,ensp,8195,emsp,8201,thinsp,8204,zwnj,8205,zwj,8206,lrm,8207,rlm,173,shy,233,eacute"); 116 this.defParam("entity_encoding", "named"); 117 this.defParam("cleanup_callback", ""); 118 this.defParam("add_unload_trigger", true); 119 this.defParam("ask", false); 120 this.defParam("nowrap", false); 121 this.defParam("auto_resize", false); 122 this.defParam("auto_focus", false); 123 this.defParam("cleanup", true); 124 this.defParam("remove_linebreaks", true); 125 this.defParam("button_tile_map", false); 126 this.defParam("submit_patch", true); 127 128 // Setup baseHREF 129 var baseHREF = tinyMCE.settings['document_base_url']; 130 if (baseHREF.indexOf('?') != -1) 131 baseHREF = baseHREF.substring(0, baseHREF.indexOf('?')); 132 this.settings['base_href'] = baseHREF.substring(0, baseHREF.lastIndexOf('/')) + "/"; 133 134 theme = this.settings['theme']; 135 136 this.blockRegExp = new RegExp("^(h1|h2|h3|h4|h5|h6|p|div|address|pre|form|table|li|ol|ul|td)$", "i"); 137 138 // Theme url 139 this.settings['theme_href'] = tinyMCE.baseURL + "/themes/" + theme; 140 141 if (!tinyMCE.isMSIE) 142 this.settings['force_br_newlines'] = false; 143 144 if (tinyMCE.getParam("content_css", false)) { 145 var cssPath = tinyMCE.getParam("content_css", ""); 146 147 // Is relative 148 if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/') 149 this.settings['content_css'] = this.documentBasePath + "/" + cssPath; 150 else 151 this.settings['content_css'] = cssPath; 152 } else 153 this.settings['content_css'] = tinyMCE.baseURL + "/themes/" + theme + "/editor_content.css"; 154 155 if (tinyMCE.getParam("popups_css", false)) { 156 var cssPath = tinyMCE.getParam("popups_css", ""); 157 158 // Is relative 159 if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/') 160 this.settings['popups_css'] = this.documentBasePath + "/" + cssPath; 161 else 162 this.settings['popups_css'] = cssPath; 163 } else 164 this.settings['popups_css'] = tinyMCE.baseURL + "/themes/" + theme + "/editor_popup.css"; 165 166 if (tinyMCE.getParam("editor_css", false)) { 167 var cssPath = tinyMCE.getParam("editor_css", ""); 168 169 // Is relative 170 if (cssPath.indexOf('://') == -1 && cssPath.charAt(0) != '/') 171 this.settings['editor_css'] = this.documentBasePath + "/" + cssPath; 172 else 173 this.settings['editor_css'] = cssPath; 174 } else 175 this.settings['editor_css'] = tinyMCE.baseURL + "/themes/" + theme + "/editor_ui.css"; 176 177 if (tinyMCE.settings['debug']) { 178 var msg = "Debug: \n"; 179 180 msg += "baseURL: " + this.baseURL + "\n"; 181 msg += "documentBasePath: " + this.documentBasePath + "\n"; 182 msg += "content_css: " + this.settings['content_css'] + "\n"; 183 msg += "popups_css: " + this.settings['popups_css'] + "\n"; 184 msg += "editor_css: " + this.settings['editor_css'] + "\n"; 185 186 alert(msg); 187 } 188 189 // Init HTML cleanup 190 this._initCleanup(); 191 192 // Only do this once 193 if (this.configs.length == 0) { 194 tinyMCE.addEvent(window, "load", TinyMCE.prototype.onLoad); 195 196 if (tinyMCE.isMSIE) { 197 if (tinyMCE.settings['add_unload_trigger']) { 198 tinyMCE.addEvent(window, "unload", TinyMCE.prototype.unloadHandler); 199 tinyMCE.addEvent(window.document, "beforeunload", TinyMCE.prototype.unloadHandler); 200 } 201 } else { 202 if (tinyMCE.settings['add_unload_trigger']) 203 tinyMCE.addEvent(window, "unload", function () {tinyMCE.triggerSave(true, true);}); 204 } 205 } 206 207 this.loadScript(tinyMCE.baseURL + '/themes/' + this.settings['theme'] + '/editor_template' + tinyMCE.srcMode + '.js'); 208 //this.loadScript(tinyMCE.baseURL + '/langs/' + this.settings['language'] + '.js'); 209 this.loadScript(tinyMCE.baseURL + '/langs/lang.php?lang=' + this.settings['language']); 210 this.loadCSS(this.settings['editor_css']); 211 212 // Add theme plugins 213 var themePlugins = tinyMCE.getParam('plugins', '', true, ','); 214 if (this.settings['plugins'] != '') { 215 for (var i=0; i<themePlugins.length; i++) 216 this.loadScript(tinyMCE.baseURL + '/plugins/' + themePlugins[i] + '/editor_plugin' + tinyMCE.srcMode + '.js'); 217 } 218 219 // Save away this config 220 settings['index'] = this.configs.length; 221 this.configs[this.configs.length] = settings; 222 }; 223 224 TinyMCE.prototype.loadScript = function(url) { 225 for (var i=0; i<this.loadedFiles.length; i++) { 226 if (this.loadedFiles[i] == url) 227 return; 228 } 229 230 document.write('<sc'+'ript language="javascript" type="text/javascript" src="' + url + '"></script>'); 231 232 this.loadedFiles[this.loadedFiles.length] = url; 233 }; 234 235 TinyMCE.prototype.loadCSS = function(url) { 236 for (var i=0; i<this.loadedFiles.length; i++) { 237 if (this.loadedFiles[i] == url) 238 return; 239 } 240 241 document.write('<link href="' + url + '" rel="stylesheet" type="text/css" />'); 242 243 this.loadedFiles[this.loadedFiles.length] = url; 244 }; 245 246 TinyMCE.prototype.importCSS = function(doc, css_file) { 247 if (tinyMCE.isMSIE) 248 var styleSheet = doc.createStyleSheet(css_file); 249 else { 250 var elm = doc.createElement("link"); 251 252 elm.rel = "stylesheet"; 253 elm.href = css_file; 254 255 if (headArr = doc.getElementsByTagName("head")) 256 headArr[0].appendChild(elm); 257 } 258 }; 259 260 TinyMCE.prototype.confirmAdd = function(e, settings) { 261 var elm = tinyMCE.isMSIE ? event.srcElement : e.target; 262 var elementId = elm.name ? elm.name : elm.id; 263 264 tinyMCE.settings = settings; 265 266 if (!elm.getAttribute('mce_noask') && confirm(tinyMCELang['lang_edit_confirm'])) 267 tinyMCE.addMCEControl(elm, elementId); 268 269 elm.setAttribute('mce_noask', 'true'); 270 }; 271 272 TinyMCE.prototype.queryInstanceCommandValue = function(editor_id, command) { 273 var inst = tinyMCE.getInstanceById(editor_id); 274 if (inst) 275 return inst.getDoc().queryCommandValue(command); 276 277 return null; 278 }; 279 280 TinyMCE.prototype.queryInstanceCommandState = function(editor_id, command) { 281 var inst = tinyMCE.getInstanceById(editor_id); 282 if (inst) 283 return inst.getDoc().queryCommandState(command); 284 285 return null; 286 }; 287 288 TinyMCE.prototype.updateContent = function(form_element_name) { 289 // Find MCE instance linked to given form element and copy it's value 290 var formElement = document.getElementById(form_element_name); 291 for (var n in tinyMCE.instances) { 292 var inst = tinyMCE.instances[n]; 293 294 inst.switchSettings(); 295 296 if (inst.formElement == formElement) { 297 var doc = inst.getDoc(); 298 299 tinyMCE._setHTML(doc, inst.formElement.value); 300 301 if (!tinyMCE.isMSIE) 302 doc.body.innerHTML = tinyMCE._cleanupHTML(doc, this.settings, doc.body, inst.visualAid); 303 } 304 } 305 }; 306 307 TinyMCE.prototype.addMCEControl = function(replace_element, form_element_name, target_document) { 308 var id = "mce_editor_" + tinyMCE.idCounter++; 309 var inst = new TinyMCEControl(tinyMCE.settings); 310 311 inst.editorId = id; 312 this.instances[id] = inst; 313 314 inst.onAdd(replace_element, form_element_name, target_document); 315 }; 316 317 TinyMCE.prototype.triggerSave = function(skip_cleanup, skip_callback) { 318 // Cleanup and set all form fields 319 for (var n in tinyMCE.instances) { 320 var inst = tinyMCE.instances[n]; 321 322 inst.switchSettings(); 323 324 tinyMCE.settings['preformatted'] = false; 325 326 // Default to false 327 if (typeof(skip_cleanup) == "undefined") 328 skip_cleanup = false; 329 330 // Default to false 331 if (typeof(skip_callback) == "undefined") 332 skip_callback = false; 333 334 tinyMCE._setHTML(inst.getDoc(), inst.getBody().innerHTML); 335 336 var htm = skip_cleanup ? inst.getBody().innerHTML : tinyMCE._cleanupHTML(inst.getDoc(), this.settings, inst.getBody(), this.visualAid, true); 337 338 //var htm = tinyMCE._cleanupHTML(inst.getDoc(), tinyMCE.settings, inst.getBody(), false, true); 339 340 if (tinyMCE.settings["encoding"] == "xml" || tinyMCE.settings["encoding"] == "html") 341 htm = tinyMCE.convertStringToXML(htm); 342 343 if (!skip_callback && tinyMCE.settings['save_callback'] != "") 344 var content = eval(tinyMCE.settings['save_callback'] + "(inst.formTargetElementId,htm,inst.getBody());"); 345 346 // Use callback content if available 347 if ((typeof(content) != "undefined") && content != null) 348 htm = content; 349 350 // Replace some weird entities (Bug: #1056343) 351 htm = tinyMCE.regexpReplace(htm, "(", "(", "gi"); 352 htm = tinyMCE.regexpReplace(htm, ")", ")", "gi"); 353 htm = tinyMCE.regexpReplace(htm, ";", ";", "gi"); 354 htm = tinyMCE.regexpReplace(htm, """, """, "gi"); 355 htm = tinyMCE.regexpReplace(htm, "^", "^", "gi"); 356 357 if (inst.formElement) 358 inst.formElement.value = htm; 359 } 360 }; 361 362 TinyMCE.prototype._convertOnClick = function(node) { 363 // Skip on MSIE < 6+ 364 if (tinyMCE.isMSIE5) 365 return; 366 367 // Convert all onclick to mce_onclick 368 var elms = node.getElementsByTagName("a"); 369 for (var i=0; i<elms.length; i++) { 370 var onclick = elms[i].getAttribute('onclick'); 371 if (onclick && onclick != "") { 372 elms[i].removeAttribute("onclick"); 373 elms[i].setAttribute("mce_onclick", tinyMCE.cleanupEventStr("" + onclick)); 374 elms[i].onclick = null; 375 } 376 } 377 }; 378 379 TinyMCE.prototype.resetForm = function(form_index) { 380 var formObj = document.forms[form_index]; 381 382 for (var n in tinyMCE.instances) { 383 var inst = tinyMCE.instances[n]; 384 385 inst.switchSettings(); 386 387 for (var i=0; i<formObj.elements.length; i++) { 388 if (inst.formTargetElementId == formObj.elements[i].name) { 389 inst.getBody().innerHTML = formObj.elements[i].value; 390 return; 391 } 392 } 393 } 394 }; 395 396 TinyMCE.prototype.execInstanceCommand = function(editor_id, command, user_interface, value, focus) { 397 var inst = tinyMCE.getInstanceById(editor_id); 398 if (inst) { 399 if (typeof(focus) == "undefined") 400 focus = true; 401 402 if (focus) 403 inst.contentWindow.focus(); 404 405 // Reset design mode if lost 406 inst.autoResetDesignMode(); 407 408 this.selectedElement = inst.getFocusElement(); 409 this.selectedInstance = inst; 410 tinyMCE.execCommand(command, user_interface, value); 411 } 412 }; 413 414 TinyMCE.prototype.execCommand = function(command, user_interface, value) { 415 // Default input 416 user_interface = user_interface ? user_interface : false; 417 value = value ? value : null; 418 419 if (tinyMCE.selectedInstance) 420 tinyMCE.selectedInstance.switchSettings(); 421 422 switch (command) { 423 case 'mceHelp': 424 window.open(tinyMCE.themeURL + "/docs/" + this.settings['docs_language'] + "/index.htm", "mceHelp", "menubar=yes,toolbar=yes,scrollbars=yes,left=20,top=20,width=550,height=600"); 425 return; 426 427 case 'mceFocus': 428 var inst = tinyMCE.getInstanceById(value); 429 if (inst) 430 inst.contentWindow.focus(); 431 return; 432 433 case "mceAddControl": 434 case "mceAddEditor": 435 tinyMCE.addMCEControl(tinyMCE._getElementById(value), value); 436 return; 437 438 case "mceAddFrameControl": 439 tinyMCE.addMCEControl(tinyMCE._getElementById(value), value['element'], value['document']); 440 return; 441 442 case "mceRemoveControl": 443 case "mceRemoveEditor": 444 tinyMCE.removeMCEControl(value); 445 return; 446 447 case "mceResetDesignMode": 448 // Resets the designmode state of the editors in Gecko 449 if (!tinyMCE.isMSIE) { 450 for (var n in tinyMCE.instances) { 451 try { 452 tinyMCE.instances[n].getDoc().designMode = "on"; 453 } catch (e) { 454 // Ignore any errors 455 } 456 } 457 } 458 459 return; 460 } 461 462 if (this.selectedInstance) 463 this.selectedInstance.execCommand(command, user_interface, value); 464 else if (tinyMCE.settings['focus_alert']) 465 alert(tinyMCELang['lang_focus_alert']); 466 }; 467 468 TinyMCE.prototype.eventPatch = function(editor_id) { 469 // Remove odd, error 470 if (typeof(tinyMCE) == "undefined") 471 return true; 472 473 for (var i=0; i<document.frames.length; i++) { 474 if (document.frames[i].event) { 475 var event = document.frames[i].event; 476 477 event.target = event.srcElement; 478 event.target.editor_id = document.frames[i].editor_id; 479 480 TinyMCE.prototype.handleEvent(event); 481 return; 482 } 483 } 484 }; 485 486 TinyMCE.prototype.unloadHandler = function() { 487 tinyMCE.triggerSave(true, true); 488 }; 489 490 TinyMCE.prototype.addEventHandlers = function(editor_id) { 491 if (tinyMCE.isMSIE) { 492 var doc = document.frames[editor_id].document; 493 494 // Event patch 495 document.frames[editor_id].editor_id = editor_id; 496 tinyMCE.addEvent(doc, "keypress", TinyMCE.prototype.eventPatch); 497 tinyMCE.addEvent(doc, "keyup", TinyMCE.prototype.eventPatch); 498 tinyMCE.addEvent(doc, "keydown", TinyMCE.prototype.eventPatch); 499 tinyMCE.addEvent(doc, "mouseup", TinyMCE.prototype.eventPatch); 500 tinyMCE.addEvent(doc, "click", TinyMCE.prototype.eventPatch); 501 } else { 502 var inst = tinyMCE.instances[editor_id]; 503 var doc = inst.getDoc(); 504 505 inst.switchSettings(); 506 507 doc.editor_id = editor_id; 508 tinyMCE.addEvent(doc, "keypress", tinyMCE.handleEvent); 509 tinyMCE.addEvent(doc, "keypress", tinyMCE.handleEvent); 510 tinyMCE.addEvent(doc, "keydown", tinyMCE.handleEvent); 511 tinyMCE.addEvent(doc, "keyup", tinyMCE.handleEvent); 512 tinyMCE.addEvent(doc, "click", tinyMCE.handleEvent); 513 tinyMCE.addEvent(doc, "mouseup", tinyMCE.handleEvent); 514 tinyMCE.addEvent(doc, "mousedown", tinyMCE.handleEvent); 515 tinyMCE.addEvent(doc, "focus", tinyMCE.handleEvent); 516 517 eval('try { doc.designMode = "On"; } catch(e) {}'); 518 } 519 }; 520 521 TinyMCE.prototype._createIFrame = function(replace_element) { 522 var iframe = document.createElement("iframe"); 523 var id = replace_element.getAttribute("id"); 524 525 iframe.setAttribute("id", id); 526 iframe.setAttribute("className", "mceEditorArea"); 527 iframe.setAttribute("border", "0"); 528 iframe.setAttribute("frameBorder", "0"); 529 iframe.setAttribute("marginWidth", "0"); 530 iframe.setAttribute("marginHeight", "0"); 531 iframe.setAttribute("leftMargin", "0"); 532 iframe.setAttribute("topMargin", "0"); 533 iframe.setAttribute("width", tinyMCE.settings['area_width']); 534 iframe.setAttribute("height", tinyMCE.settings['area_height']); 535 536 if (tinyMCE.settings["auto_resize"]) 537 iframe.setAttribute("scrolling", "no"); 538 539 // Must have a src element in MSIE HTTPs breaks aswell as absoute URLs 540 if (tinyMCE.isMSIE) 541 iframe.setAttribute("src", this.settings['default_document']); 542 543 iframe.style.width = tinyMCE.settings['area_width']; 544 iframe.style.height = tinyMCE.settings['area_height']; 545 546 // MSIE 5.0 issue 547 if (tinyMCE.isMSIE) 548 replace_element.outerHTML = iframe.outerHTML; 549 else 550 replace_element.parentNode.replaceChild(iframe, replace_element); 551 552 if (tinyMCE.isMSIE) 553 return window.frames[id]; 554 else 555 return iframe; 556 }; 557 558 TinyMCE.prototype.setupContent = function(editor_id) { 559 var inst = tinyMCE.instances[editor_id]; 560 var doc = inst.getDoc(); 561 var head = doc.getElementsByTagName('head').item(0); 562 var content = inst.startContent; 563 564 inst.switchSettings(); 565 566 // Not loaded correctly hit it again, Mozilla bug #997860 567 if (!tinyMCE.isMSIE && doc.title != "blank_page") { 568 // This part will remove the designMode status 569 doc.location.href = tinyMCE.baseURL + "/blank.htm"; 570 window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 1000); 571 return; 572 } 573 574 if (!head) { 575 window.setTimeout("tinyMCE.setupContent('" + editor_id + "');", 10); 576 return; 577 } 578 579 tinyMCE.importCSS(inst.getDoc(), inst.settings['content_css']); 580 tinyMCE.executeCallback('init_instance_callback', '_initInstance', 0, inst); 581 582 if (tinyMCE.settings['nowrap']) 583 doc.body.style.whiteSpace = "nowrap"; 584 585 doc.body.dir = this.settings['directionality']; 586 doc.editorId = editor_id; 587 588 // Add on document element in Mozilla 589 if (!tinyMCE.isMSIE) 590 doc.documentElement.editorId = editor_id; 591 592 // Setup base element 593 base = doc.createElement("base"); 594 base.setAttribute('href', tinyMCE.settings['base_href']); 595 head.appendChild(base); 596 597 // Replace new line characters to BRs 598 if (tinyMCE.settings['convert_newlines_to_brs']) { 599 content = tinyMCE.regexpReplace(content, "\r\n", "<br />", "gi"); 600 content = tinyMCE.regexpReplace(content, "\r", "<br />", "gi"); 601 content = tinyMCE.regexpReplace(content, "\n", "<br />", "gi"); 602 } 603 604 // Call custom cleanup code 605 content = tinyMCE._customCleanup("insert_to_editor", content); 606 607 if (tinyMCE.isMSIE) { 608 // Ugly!!! 609 window.setInterval('try{tinyMCE.getCSSClasses(document.frames["' + editor_id + '"].document, "' + editor_id + '");}catch(e){}', 500); 610 611 if (tinyMCE.settings["force_br_newlines"]) 612 document.frames[editor_id].document.styleSheets[0].addRule("p", "margin: 0px;"); 613 614 var body = document.frames[editor_id].document.body; 615 616 tinyMCE.addEvent(body, "beforepaste", TinyMCE.prototype.eventPatch); 617 tinyMCE.addEvent(body, "beforecut", TinyMCE.prototype.eventPatch); 618 tinyMCE.addEvent(body, "paste", TinyMCE.prototype.eventPatch); 619 620 body.editorId = editor_id; 621 } 622 623 // Fix for bug #958637 624 if (!tinyMCE.isMSIE) { 625 var contentElement = inst.getDoc().createElement("body"); 626 var doc = inst.getDoc(); 627 628 contentElement.innerHTML = content; 629 630 // Remove weridness! 631 if (tinyMCE.settings['force_p_newlines']) 632 content = content.replace(new RegExp('<>', 'g'), ""); 633 634 if (tinyMCE.settings['cleanup_on_startup']) 635 inst.getBody().innerHTML = tinyMCE._cleanupHTML(doc, this.settings, contentElement); 636 else { 637 // Convert all strong/em to b/i 638 content = tinyMCE.regexpReplace(content, "<strong", "<b", "gi"); 639 content = tinyMCE.regexpReplace(content, "<em", "<i", "gi"); 640 content = tinyMCE.regexpReplace(content, "</strong>", "</b>", "gi"); 641 content = tinyMCE.regexpReplace(content, "</em>", "</i>", "gi"); 642 inst.getBody().innerHTML = content; 643 } 644 645 inst.convertAllRelativeURLs(); 646 } else { 647 if (tinyMCE.settings['cleanup_on_startup']) { 648 tinyMCE._setHTML(inst.getDoc(), content); 649 // Produces permission denied error in MSIE 5.5 650 eval('try {inst.getBody().innerHTML = tinyMCE._cleanupHTML(inst.contentDocument, this.settings, inst.getBody());} catch(e) {}'); 651 } else 652 inst.getBody().innerHTML = content; 653 } 654 655 tinyMCE._convertOnClick(inst.getBody()); 656 657 // Fix for bug #957681 658 //inst.getDoc().designMode = inst.getDoc().designMode; 659 660 // Setup element references 661 var parentElm = document.getElementById(inst.editorId + '_parent'); 662 if (parentElm.lastChild.nodeName.toLowerCase() == "input") 663 inst.formElement = parentElm.lastChild; 664 else 665 inst.formElement = parentElm.nextSibling; 666 667 tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual']); 668 tinyMCE.executeCallback('setupcontent_callback', '_setupContent', 0, editor_id, inst.getBody(), inst.getDoc()); 669 670 // Re-add design mode on mozilla 671 if (!tinyMCE.isMSIE) 672 TinyMCE.prototype.addEventHandlers(editor_id); 673 674 inst.startContent = inst.getBody().innerHTML; 675 676 // Trigger node change, this call locks buttons for tables and so forth 677 tinyMCE.selectedInstance = inst; 678 tinyMCE.selectedElement = inst.contentWindow.document.body; 679 tinyMCE.triggerNodeChange(false, true); 680 681 // Call custom DOM cleanup 682 tinyMCE._customCleanup("insert_to_editor_dom", inst.contentWindow.document.body); 683 }; 684 685 TinyMCE.prototype.cancelEvent = function(e) { 686 if (tinyMCE.isMSIE) { 687 e.returnValue = false; 688 e.cancelBubble = true; 689 } else 690 e.preventDefault(); 691 }; 692 693 TinyMCE.prototype.removeTinyMCEFormElements = function(form_obj) { 694 // Disable all UI form elements that TinyMCE created 695 for (var i=0; i<form_obj.elements.length; i++) { 696 var elementId = form_obj.elements[i].name ? form_obj.elements[i].name : form_obj.elements[i].id; 697 698 if (elementId.indexOf('mce_editor_') == 0) 699 form_obj.elements[i].disabled = true; 700 } 701 }; 702 703 TinyMCE.prototype.handleEvent = function(e) { 704 // Remove odd, error 705 if (typeof(tinyMCE) == "undefined") 706 return true; 707 708 //debug(e.type + " " + e.target.nodeName + " " + (e.relatedTarget ? e.relatedTarget.nodeName : "")); 709 710 switch (e.type) { 711 case "submit": 712 tinyMCE.removeTinyMCEFormElements(tinyMCE.isMSIE ? window.event.srcElement : e.target); 713 tinyMCE.triggerSave(); 714 return; 715 716 case "reset": 717 var formObj = tinyMCE.isMSIE ? window.event.srcElement : e.target; 718 719 for (var i=0; i<document.forms.length; i++) { 720 if (document.forms[i] == formObj) 721 window.setTimeout('tinyMCE.resetForm(' + i + ');', 10); 722 } 723 return; 724 725 case "paste": 726 if (tinyMCE.settings['auto_cleanup_word']) 727 window.setTimeout("tinyMCE.execInstanceCommand('" + e.target.editorId + "', 'mceCleanupWord', false, null);", 1); 728 729 break; 730 731 case "beforecut": 732 case "beforepaste": 733 if (tinyMCE.selectedInstance) 734 tinyMCE.selectedInstance.execCommand("mceAddUndoLevel"); 735 break; 736 737 case "keypress": 738 if (e.target.editorId) { 739 tinyMCE.selectedInstance = tinyMCE.instances[e.target.editorId]; 740 } else { 741 if (e.target.ownerDocument.editorId) 742 tinyMCE.selectedInstance = tinyMCE.instances[e.target.ownerDocument.editorId]; 743 } 744 745 if (tinyMCE.selectedInstance) 746 tinyMCE.selectedInstance.switchSettings(); 747 748 // Insert space instead of 749 /* if (tinyMCE.isGecko && e.charCode == 32) { 750 if (tinyMCE.selectedInstance._insertSpace()) { 751 // Cancel event 752 e.preventDefault(); 753 return false; 754 } 755 }*/ 756 757 // Insert P element 758 if (tinyMCE.isGecko && tinyMCE.settings['force_p_newlines'] && e.keyCode == 13 && !e.shiftKey) { 759 // Insert P element instead of BR 760 if (tinyMCE.selectedInstance._insertPara(e)) { 761 // Cancel event 762 e.preventDefault(); 763 return false; 764 } 765 } 766 767 // Handle backspace 768 if (tinyMCE.isGecko && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) { 769 // Insert P element instead of BR 770 if (tinyMCE.selectedInstance._handleBackSpace(e.type)) { 771 // Cancel event 772 e.preventDefault(); 773 return false; 774 } 775 } 776 777 // Mozilla custom key handling 778 if (!tinyMCE.isMSIE && e.ctrlKey && tinyMCE.settings['custom_undo_redo']) { 779 if (e.charCode == 120 || e.charCode == 118) { // Ctrl+X, Ctrl+V 780 tinyMCE.selectedInstance.execCommand("mceAddUndoLevel"); 781 return; 782 } 783 784 if (tinyMCE.settings['custom_undo_redo_keyboard_shortcuts']) { 785 if (e.charCode == 122) { // Ctrl+Z 786 tinyMCE.selectedInstance.execCommand("Undo"); 787 788 // Cancel event 789 e.preventDefault(); 790 return false; 791 } 792 793 if (e.charCode == 121) { // Ctrl+Y 794 tinyMCE.selectedInstance.execCommand("Redo"); 795 796 // Cancel event 797 e.preventDefault(); 798 return false; 799 } 800 } 801 802 if (e.charCode == 98) { // Ctrl+B 803 tinyMCE.selectedInstance.execCommand("Bold"); 804 805 // Cancel event 806 e.preventDefault(); 807 return false; 808 } 809 810 if (e.charCode == 105) { // Ctrl+I 811 tinyMCE.selectedInstance.execCommand("Italic"); 812 813 // Cancel event 814 e.preventDefault(); 815 return false; 816 } 817 818 if (e.charCode == 117) { // Ctrl+U 819 tinyMCE.selectedInstance.execCommand("Underline"); 820 821 // Cancel event 822 e.preventDefault(); 823 return false; 824 } 825 } 826 827 if (tinyMCE.settings['custom_undo_redo']) { 828 // Check if it's a position key press 829 var keys = new Array(13,45,36,35,33,34,37,38,39,40); 830 var posKey = false; 831 for (var i=0; i<keys.length; i++) { 832 if (keys[i] == e.keyCode) { 833 tinyMCE.selectedInstance.typing = false; 834 posKey = true; 835 break; 836 } 837 } 838 839 // Add typing undo level 840 if (!tinyMCE.selectedInstance.typing && !posKey) { 841 tinyMCE.selectedInstance.execCommand("mceAddUndoLevel"); 842 tinyMCE.selectedInstance.typing = true; 843 } 844 } 845 846 //window.status = e.keyCode; 847 //window.status = e.type + " " + e.target.nodeName; 848 849 // Return key pressed 850 if (tinyMCE.isMSIE && tinyMCE.settings['force_br_newlines'] && e.keyCode == 13) { 851 if (e.target.editorId) 852 tinyMCE.selectedInstance = tinyMCE.instances[e.target.editorId]; 853 854 if (tinyMCE.selectedInstance) { 855 var sel = tinyMCE.selectedInstance.getDoc().selection; 856 var rng = sel.createRange(); 857 858 if (tinyMCE.getParentElement(rng.parentElement(), "li") != null) 859 return false; 860 861 // Cancel event 862 e.returnValue = false; 863 e.cancelBubble = true; 864 865 // Insert BR element 866 rng.pasteHTML("<br />"); 867 rng.collapse(false); 868 rng.select(); 869 870 tinyMCE.triggerNodeChange(false); 871 return false; 872 } 873 } 874 875 // Backspace or delete 876 if (e.keyCode == 8 || e.keyCode == 46) { 877 tinyMCE.selectedElement = e.target; 878 tinyMCE.linkElement = tinyMCE.getParentElement(e.target, "a"); 879 tinyMCE.imgElement = tinyMCE.getParentElement(e.target, "img"); 880 tinyMCE.triggerNodeChange(false); 881 } 882 883 return false; 884 break; 885 886 case "keyup": 887 case "keydown": 888 if (e.target.editorId) 889 tinyMCE.selectedInstance = tinyMCE.instances[e.target.editorId]; 890 else 891 return; 892 893 if (tinyMCE.selectedInstance) 894 tinyMCE.selectedInstance.switchSettings(); 895 896 // Handle backspace 897 if (tinyMCE.isGecko && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) { 898 // Insert P element instead of BR 899 if (tinyMCE.selectedInstance._handleBackSpace(e.type)) { 900 // Cancel event 901 e.preventDefault(); 902 return false; 903 } 904 } 905 906 tinyMCE.selectedElement = null; 907 tinyMCE.selectedNode = null; 908 var elm = tinyMCE.selectedInstance.getFocusElement(); 909 tinyMCE.linkElement = tinyMCE.getParentElement(elm, "a"); 910 tinyMCE.imgElement = tinyMCE.getParentElement(elm, "img"); 911 tinyMCE.selectedElement = elm; 912 913 // Update visualaids on tabs 914 if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9) 915 tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings['visual']); 916 917 // Run image/link fix on Gecko if diffrent document base on paste 918 if (tinyMCE.isGecko && tinyMCE.settings['document_base_url'] != "" + document.location.href && e.type == "keyup" && e.ctrlKey && e.keyCode == 86) 919 tinyMCE.selectedInstance.fixBrokenURLs(); 920 921 // Insert space instead of 922 /* if (e.type == "keydown" && e.keyCode == 32) { 923 if (tinyMCE.selectedInstance._insertSpace()) { 924 // Cancel event 925 e.returnValue = false; 926 e.cancelBubble = true; 927 return false; 928 } 929 }*/ 930 931 // MSIE custom key handling 932 if (tinyMCE.isMSIE && tinyMCE.settings['custom_undo_redo']) { 933 // Check if it's a position key press 934 var keys = new Array(13,45,36,35,33,34,37,38,39,40); 935 var posKey = false; 936 for (var i=0; i<keys.length; i++) { 937 if (keys[i] == e.keyCode) { 938 tinyMCE.selectedInstance.typing = false; 939 posKey = true; 940 break; 941 } 942 } 943 944 // Add typing undo level (unless pos keys or shift, alt, ctrl, capslock) 945 if (!tinyMCE.selectedInstance.typing && !posKey && (e.keyCode < 16 || e.keyCode > 18 && e.keyCode != 255)) { 946 tinyMCE.selectedInstance.execCommand("mceAddUndoLevel"); 947 tinyMCE.selectedInstance.typing = true; 948 tinyMCE.triggerNodeChange(false); 949 } 950 951 if (posKey && e.type == "keyup") 952 tinyMCE.triggerNodeChange(false); 953 954 var keys = new Array(8,46); // Backspace,Delete 955 for (var i=0; i<keys.length; i++) { 956 if (keys[i] == e.keyCode) { 957 if (!tinyMCE.selectedInstance.typing) { 958 tinyMCE.selectedInstance.execCommand("mceAddUndoLevel"); 959 tinyMCE.selectedInstance.typing = true; 960 } 961 962 if (e.type == "keyup") 963 tinyMCE.triggerNodeChange(false); 964 965 return true; 966 } 967 } 968 969 var ctrlKeys = new Array(66,73,85,86,88); // B/I/U/V/X 970 for (var i=0; i<keys.length; i++) { 971 if (ctrlKeys[i] == e.keyCode && e.ctrlKey) { 972 tinyMCE.selectedInstance.execCommand("mceAddUndoLevel"); 973 tinyMCE.triggerNodeChange(false); 974 return true; 975 } 976 } 977 978 if (tinyMCE.settings['custom_undo_redo_keyboard_shortcuts']) { 979 if (e.keyCode == 90 && e.ctrlKey && e.type == "keydown") { // Ctrl+Z 980 tinyMCE.selectedInstance.execCommand("Undo"); 981 tinyMCE.triggerNodeChange(false); 982 983 // Cancel event 984 e.returnValue = false; 985 e.cancelBubble = true; 986 return false; 987 } 988 989 if (e.keyCode == 89 && e.ctrlKey && e.type == "keydown") { // Ctrl+Y 990 tinyMCE.selectedInstance.execCommand("Redo"); 991 tinyMCE.triggerNodeChange(false); 992 993 // Cancel event 994 e.returnValue = false; 995 e.cancelBubble = true; 996 return false; 997 } 998 } 999 } 1000 1001 // Check if it's a position key press 1002 var keys = new Array(13,45,36,35,33,34,37,38,39,40); 1003 var posKey = false; 1004 for (var i=0; i<keys.length; i++) { 1005 if (keys[i] == e.keyCode) { 1006 posKey = true; 1007 break; 1008 } 1009 } 1010 1011 // Trigger some nodechange on keyup 1012 if (posKey && e.type == "keyup") 1013 tinyMCE.triggerNodeChange(false); 1014 break; 1015 1016 case "mousedown": 1017 case "mouseup": 1018 case "click": 1019 case "focus": 1020 if (tinyMCE.selectedInstance) 1021 tinyMCE.selectedInstance.switchSettings(); 1022 1023 // Check instance event trigged on 1024 var targetBody = tinyMCE.getParentElement(e.target, "body"); 1025 for (var instanceName in tinyMCE.instances) { 1026 var inst = tinyMCE.instances[instanceName]; 1027 1028 // Reset design mode if lost (on everything just in case) 1029 inst.autoResetDesignMode(); 1030 1031 if (inst.getBody() == targetBody) { 1032 tinyMCE.selectedInstance = inst; 1033 tinyMCE.selectedElement = e.target; 1034 tinyMCE.linkElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "a"); 1035 tinyMCE.imgElement = tinyMCE.getParentElement(tinyMCE.selectedElement, "img"); 1036 1037 // Reset typing 1038 tinyMCE.selectedInstance.typing = false; 1039 break; 1040 } 1041 } 1042 1043 // Reset selected node 1044 if (e.type != "focus") 1045 tinyMCE.selectedNode = null; 1046 1047 tinyMCE.triggerNodeChange(false); 1048 1049 // Just in case 1050 if (!tinyMCE.selectedInstance && e.target.editorId) 1051 tinyMCE.selectedInstance = tinyMCE.instances[e.target.editorId]; 1052 1053 // Was it alt click on link 1054 if (e.target.nodeName.toLowerCase() == "a" && e.type == "click" && e.altKey) { 1055 var evalCode = "" + tinyMCE.cleanupEventStr(e.target.getAttribute("mce_onclick")); 1056 1057 // Remove any return too 1058 eval(evalCode.replace('return false;', '')); 1059 } 1060 1061 //if (tinyMCE.selectedInstance) 1062 // tinyMCE.selectedInstance.fixBrokenURLs(); 1063 1064 // Run image/link fix on Gecko if diffrent document base 1065 if (tinyMCE.isGecko && tinyMCE.settings['document_base_url'] != "" + document.location.href) 1066 window.setTimeout('tinyMCE.getInstanceById("' + inst.editorId + '").fixBrokenURLs();', 10); 1067 1068 return false; 1069 break; 1070 } // end switch 1071 }; // end function 1072 1073 TinyMCE.prototype.switchClass = function(element, class_name, lock_state) { 1074 var lockChanged = false; 1075 1076 if (typeof(lock_state) != "undefined" && element != null) { 1077 element.classLock = lock_state; 1078 lockChanged = true; 1079 } 1080 1081 if (element != null && (lockChanged || !element.classLock)) { 1082 element.oldClassName = element.className; 1083 element.className = class_name; 1084 } 1085 }; 1086 1087 TinyMCE.prototype.restoreAndSwitchClass = function(element, class_name) { 1088 if (element != null && !element.classLock) { 1089 this.restoreClass(element); 1090 this.switchClass(element, class_name); 1091 } 1092 }; 1093 1094 TinyMCE.prototype.switchClassSticky = function(element_name, class_name, lock_state) { 1095 var element, lockChanged = false; 1096 1097 // Performance issue 1098 if (!this.stickyClassesLookup[element_name]) 1099 this.stickyClassesLookup[element_name] = document.getElementById(element_name); 1100 1101 // element = document.getElementById(element_name); 1102 element = this.stickyClassesLookup[element_name]; 1103 1104 if (typeof(lock_state) != "undefined" && element != null) { 1105 element.classLock = lock_state; 1106 lockChanged = true; 1107 } 1108 1109 if (element != null && (lockChanged || !element.classLock)) { 1110 element.className = class_name; 1111 element.oldClassName = class_name; 1112 } 1113 }; 1114 1115 TinyMCE.prototype.restoreClass = function(element) { 1116 if (element != null && element.oldClassName && !element.classLock) { 1117 element.className = element.oldClassName; 1118 element.oldClassName = null; 1119 } 1120 }; 1121 1122 TinyMCE.prototype.setClassLock = function(element, lock_state) { 1123 if (element != null) 1124 element.classLock = lock_state; 1125 }; 1126 1127 TinyMCE.prototype.addEvent = function(obj, name, handler) { 1128 if (tinyMCE.isMSIE) { 1129 obj.attachEvent("on" + name, handler); 1130 } else 1131 obj.addEventListener(name, handler, false); 1132 }; 1133 1134 TinyMCE.prototype.submitPatch = function() { 1135 tinyMCE.removeTinyMCEFormElements(this); 1136 tinyMCE.triggerSave(); 1137 this.oldSubmit(); 1138 }; 1139 1140 TinyMCE.prototype.onLoad = function() { 1141 for (var c=0; c<tinyMCE.configs.length; c++) { 1142 tinyMCE.settings = tinyMCE.configs[c]; 1143 1144 var elementRefAr = new Array(); 1145 1146 // Add submit triggers 1147 if (document.forms && tinyMCE.settings['add_form_submit_trigger'] && !tinyMCE.submitTriggers) { 1148 for (var i=0; i<document.forms.length; i++) { 1149 var form = document.forms[i]; 1150 1151 tinyMCE.addEvent(form, "submit", TinyMCE.prototype.handleEvent); 1152 tinyMCE.addEvent(form, "reset", TinyMCE.prototype.handleEvent); 1153 tinyMCE.submitTriggers = true; // Do it only once 1154 1155 // Patch the form.submit function 1156 if (tinyMCE.settings['submit_patch']) { 1157 try { 1158 form.oldSubmit = form.submit; 1159 form.submit = TinyMCE.prototype.submitPatch; 1160 } catch (e) { 1161 // Do nothing 1162 } 1163 } 1164 } 1165 } 1166 1167 // Add editor instances based on mode 1168 var mode = tinyMCE.settings['mode']; 1169 switch (mode) { 1170 case "exact": 1171 var elements = tinyMCE.getParam('elements', '', true, ','); 1172 1173 for (var i=0; i<elements.length; i++) { 1174 var element = tinyMCE._getElementById(elements[i]); 1175 var trigger = element ? element.getAttribute(tinyMCE.settings['textarea_trigger']) : ""; 1176 1177 if (trigger == "false") 1178 continue; 1179 1180 if (tinyMCE.settings['ask'] && element) { 1181 elementRefAr[elementRefAr.length] = element; 1182 continue; 1183 } 1184 1185 if (element) 1186 tinyMCE.addMCEControl(element, elements[i]); 1187 else if (tinyMCE.settings['debug']) 1188 alert("Error: Could not find element by id or name: " + elements[i]); 1189 } 1190 break; 1191 1192 case "specific_textareas": 1193 case "textareas": 1194 var nodeList = document.getElementsByTagName("textarea"); 1195 1196 for (var i=0; i<nodeList.length; i++) { 1197 var trigger = nodeList.item(i).getAttribute(tinyMCE.settings['textarea_trigger']); 1198 1199 if ((mode == "specific_textareas" && trigger == "true") || (mode == "textareas" && trigger != "false")) 1200 elementRefAr[elementRefAr.length] = nodeList.item(i); 1201 } 1202 break; 1203 } 1204 1205 for (var i=0; i<elementRefAr.length; i++) { 1206 var element = elementRefAr[i]; 1207 var elementId = element.name ? element.name : element.id; 1208 1209 if (tinyMCE.settings['ask']) { 1210 // Focus breaks in Mozilla 1211 if (tinyMCE.isGecko) { 1212 var settings = tinyMCE.settings; 1213 1214 tinyMCE.addEvent(element, "focus", function (e) {window.setTimeout(function() {TinyMCE.prototype.confirmAdd(e, settings);}, 10);}); 1215 } else { 1216 var settings = tinyMCE.settings; 1217 1218 tinyMCE.addEvent(element, "focus", function () { TinyMCE.prototype.confirmAdd(null, settings); }); 1219 } 1220 } else 1221 tinyMCE.addMCEControl(element, elementId); 1222 } 1223 1224 // Handle auto focus 1225 if (tinyMCE.settings['auto_focus']) { 1226 window.setTimeout(function () { 1227 var inst = tinyMCE.getInstanceById(tinyMCE.settings['auto_focus']); 1228 inst.selectNode(inst.getBody(), true, true); 1229 inst.contentWindow.focus(); 1230 }, 10); 1231 } 1232 1233 tinyMCE.executeCallback('oninit', '_oninit', 0); 1234 } 1235 }; 1236 1237 TinyMCE.prototype.removeMCEControl = function(editor_id) { 1238 var inst = tinyMCE.getInstanceById(editor_id); 1239 1240 if (inst) { 1241 inst.switchSettings(); 1242 1243 editor_id = inst.editorId; 1244 var html = tinyMCE.getContent(editor_id); 1245 1246 // Remove editor instance from instances array 1247 var tmpInstances = new Array(); 1248 for (var instanceName in tinyMCE.instances) { 1249 var instance = tinyMCE.instances[instanceName]; 1250 if (instanceName != editor_id) 1251 tmpInstances[instanceName] = instance; 1252 } 1253 tinyMCE.instances = tmpInstances; 1254 1255 tinyMCE.selectedElement = null; 1256 tinyMCE.selectedInstance = null; 1257 1258 // Remove element 1259 var replaceElement = document.getElementById(editor_id + "_parent"); 1260 var oldTargetElement = inst.oldTargetElement; 1261 var targetName = oldTargetElement.nodeName.toLowerCase(); 1262 1263 if (targetName == "textarea" || targetName == "input") { 1264 // Just show the old text area 1265 replaceElement.parentNode.removeChild(replaceElement); 1266 oldTargetElement.style.display = "inline"; 1267 oldTargetElement.value = html; 1268 } else { 1269 oldTargetElement.innerHTML = html; 1270 1271 replaceElement.parentNode.insertBefore(oldTargetElement, replaceElement); 1272 replaceElement.parentNode.removeChild(replaceElement); 1273 } 1274 } 1275 }; 1276 1277 TinyMCE.prototype._cleanupElementName = function(element_name, element) { 1278 element_name = element_name.toLowerCase(); 1279 1280 // Never include body 1281 if (element_name == "body") 1282 return null; 1283 1284 // If verification mode 1285 if (tinyMCE.cleanup_verify_html) { 1286 // Check if invalid element 1287 for (var i=0; i<tinyMCE.cleanup_invalidElements.length; i++) { 1288 if (tinyMCE.cleanup_invalidElements[i] == element_name) 1289 return null; 1290 } 1291 1292 // Check if valid element 1293 var validElement = false; 1294 var elementAttribs = null; 1295 for (var i=0; i<tinyMCE.cleanup_validElements.length && !elementAttribs; i++) { 1296 for (var x=0, n=tinyMCE.cleanup_validElements[i][0].length; x<n; x++) { 1297 var elmMatch = tinyMCE.cleanup_validElements[i][0][x]; 1298 1299 if (elmMatch.charAt(0) == '+') 1300 elmMatch = elmMatch.substring(1); 1301 1302 // Handle wildcard/regexp 1303 if (elmMatch.match(new RegExp('\\*|\\?|\\+', 'g')) != null) { 1304 elmMatch = elmMatch.replace(new RegExp('\\?', 'g'), '(\\S?)'); 1305 elmMatch = elmMatch.replace(new RegExp('\\+', 'g'), '(\\S+)'); 1306 elmMatch = elmMatch.replace(new RegExp('\\*', 'g'), '(\\S*)'); 1307 elmMatch = "^" + elmMatch + "$"; 1308 if (element_name.match(new RegExp(elmMatch, 'g'))) { 1309 elementAttribs = tinyMCE.cleanup_validElements[i]; 1310 validElement = true; 1311 break; 1312 } 1313 } 1314 1315 // Handle non regexp 1316 if (element_name == elmMatch) { 1317 elementAttribs = tinyMCE.cleanup_validElements[i]; 1318 validElement = true; 1319 element_name = elementAttribs[0][0]; 1320 break; 1321 } 1322 } 1323 } 1324 1325 if (!validElement) 1326 return null; 1327 } 1328 1329 // Special Mozilla stuff 1330 if (!tinyMCE.isMSIE) { 1331 // Fix for bug #958498 1332 if (element_name == "strong" && !tinyMCE.cleanup_on_save) 1333 element_name = "b"; 1334 else if (element_name == "em" && !tinyMCE.cleanup_on_save) 1335 element_name = "i"; 1336 } 1337 1338 // Special MSIE stuff 1339 if (tinyMCE.isMSIE) { 1340 if (element_name == "table") { 1341 var attribValue = element.style.pixelWidth == 0 ? element.getAttribute("width") : element.style.pixelWidth; 1342 element.setAttribute("width", attribValue); 1343 1344 attribValue = element.style.pixelHeight == 0 ? element.getAttribute("height") : element.style.pixelHeight; 1345 element.setAttribute("height", attribValue); 1346 } 1347 } 1348 1349 var elmData = new Object(); 1350 1351 elmData.element_name = element_name; 1352 elmData.valid_attribs = elementAttribs; 1353 1354 return elmData; 1355 }; 1356 1357 /** 1358 * Converts some element attributes to inline styles. 1359 */ 1360 TinyMCE.prototype._fixInlineStyles = function(elm) { 1361 // Handle non table elements 1362 if (elm.nodeName.toLowerCase() != "table") { 1363 var value; 1364 1365 // Setup width 1366 value = tinyMCE.isMSIE ? elm.width : elm.getAttribute("width"); 1367 if (value && value != "") { 1368 if (typeof(value) != "string" || !value.indexOf("%")) 1369 value += "px"; 1370 1371 elm.style.width = value; 1372 } 1373 1374 // Setup height 1375 value = tinyMCE.isMSIE ? elm.height : elm.getAttribute("height"); 1376 if (value && value != "") { 1377 if (typeof(value) != "string" || !value.indexOf("%")) 1378 value += "px"; 1379 1380 elm.style.height = value; 1381 } 1382 1383 // Setup border 1384 value = tinyMCE.isMSIE ? elm.border : elm.getAttribute("border"); 1385 if (value && value != "") 1386 elm.style.borderWidth = value + "px"; 1387 } 1388 1389 // Setup align 1390 value = elm.getAttribute("align"); 1391 if (value && value != "") { 1392 if (elm.nodeName.toLowerCase() == "img") { 1393 if (tinyMCE.isMSIE) 1394 elm.style.styleFloat = value; 1395 else 1396 elm.style.cssFloat = value; 1397 } else 1398 elm.style.textAlign = value; 1399 } 1400 1401 // Setup vspace 1402 value = elm.getAttribute("vspace"); 1403 if (value && value != "") { 1404 elm.style.marginTop = value + "px"; 1405 elm.style.marginBottom = value + "px"; 1406 } 1407 1408 // Setup hspace 1409 value = elm.getAttribute("hspace"); 1410 if (value && value != "") { 1411 elm.style.marginLeft = value + "px"; 1412 elm.style.marginRight = value + "px"; 1413 } 1414 }; 1415 1416 TinyMCE.prototype._cleanupAttribute = function(valid_attributes, element_name, attribute_node, element_node) { 1417 var attribName = attribute_node.nodeName.toLowerCase(); 1418 var attribValue = attribute_node.nodeValue; 1419 var attribMustBeValue = null; 1420 var verified = false; 1421 1422 // Inline styling, skip them 1423 if (tinyMCE.cleanup_inline_styles && element_name != "table" && element_name != "td") { 1424 if (attribName == "width" || attribName == "height" || attribName == "border" || attribName == "align" || attribName == "valign" || attribName == "hspace" || attribName == "vspace") 1425 return null; 1426 } 1427 1428 // Mozilla attibute, remove them 1429 if (attribName.indexOf('moz_') != -1) 1430 return null; 1431 1432 // Mozilla fix for drag-drop/copy/paste images 1433 if (!tinyMCE.isMSIE && (attribName == "mce_real_href" || attribName == "mce_real_src")) { 1434 if (!tinyMCE.cleanup_on_save) { 1435 var attrib = new Object(); 1436 1437 attrib.name = attribName; 1438 attrib.value = attribValue; 1439 1440 return attrib; 1441 } else 1442 return null; 1443 } 1444 1445 // Auto verify 1446 if (attribName == "mce_onclick") 1447 verified = true; 1448 1449 // Verify attrib 1450 if (tinyMCE.cleanup_verify_html && !verified) { 1451 for (var i=1; i<valid_attributes.length; i++) { 1452 var attribMatch = valid_attributes[i][0]; 1453 var re = null; 1454 1455 // Build regexp from wildcard 1456 if (attribMatch.match(new RegExp('\\*|\\?|\\+', 'g')) != null) { 1457 attribMatch = attribMatch.replace(new RegExp('\\?', 'g'), '(\\S?)'); 1458 attribMatch = attribMatch.replace(new RegExp('\\+', 'g'), '(\\S+)'); 1459 attribMatch = attribMatch.replace(new RegExp('\\*', 'g'), '(\\S*)'); 1460 attribMatch = "^" + attribMatch + "$"; 1461 re = new RegExp(attribMatch, 'g'); 1462 } 1463 1464 if ((re && attribName.match(re) != null) || attribName == attribMatch) { 1465 verified = true; 1466 attribMustBeValue = valid_attributes[i][3]; 1467 break; 1468 } 1469 } 1470 1471 // Allways pass styles on table and td elements if visual_aid 1472 if ((element_name == "table" || element_name == "td") && attribName == "style") 1473 verified = true; 1474 1475 if (!verified) 1476 return false; 1477 } else 1478 verified = true; 1479 1480 // Treat some attribs diffrent 1481 switch (attribName) { 1482 case "size": 1483 if (tinyMCE.isMSIE5 && element_name == "font") 1484 attribValue = element_node.size; 1485 break; 1486 1487 case "color": 1488 if (tinyMCE.isMSIE5 && element_name == "font") 1489 attribValue = element_node.color; 1490 break; 1491 1492 case "width": 1493 // MSIE 5.5 issue 1494 if (tinyMCE.isMSIE) 1495 attribValue = element_node.width; 1496 break; 1497 1498 case "height": 1499 // MSIE 5.5 issue 1500 if (tinyMCE.isMSIE) 1501 attribValue = element_node.height; 1502 break; 1503 1504 case "border": 1505 // MSIE 5.5 issue 1506 if (tinyMCE.isMSIE) 1507 attribValue = element_node.border; 1508 break; 1509 1510 // case "className": 1511 case "class": 1512 if (element_name == "table" || element_name == "td") { 1513 // Handle visual aid 1514 if (tinyMCE.cleanup_visual_table_class != "") 1515 attribValue = tinyMCE.getVisualAidClass(attribValue, !tinyMCE.cleanup_on_save); 1516 } 1517 1518 if (!tinyMCE._verifyClass(element_node) || attribValue == "") 1519 return null; 1520 1521 // if (tinyMCE.isMSIE) 1522 // attribValue = node.getAttribute('className'); 1523 1524 break; 1525 1526 case "style": 1527 attribValue = element_node.style.cssText.toLowerCase(); 1528 1529 // Compress borders some 1530 if (tinyMCE.isMSIE) { 1531 var border = element_node.style.border; 1532 var bt = element_node.style.borderTop; 1533 var bl = element_node.style.borderLeft; 1534 var br = element_node.style.borderRight; 1535 var bb = element_node.style.borderBottom; 1536 1537 // All the same 1538 if (border != "" && (bt == border && bl == border && br == border && bb == border)) { 1539 attribValue = tinyMCE.regexpReplace(attribValue, 'border-top: ' + border + '?; ?', ''); 1540 attribValue = tinyMCE.regexpReplace(attribValue, 'border-left: ' + border + '?; ?', ''); 1541 attribValue = tinyMCE.regexpReplace(attribValue, 'border-right: ' + border + '?; ?', ''); 1542 attribValue = tinyMCE.regexpReplace(attribValue, 'border-bottom: ' + border + '?;( ?)', 'border: ' + border + ';$1'); 1543 } 1544 } 1545 break; 1546 1547 // Handle onclick 1548 case "onclick": 1549 case "mce_onclick": 1550 // Skip on MSIE < 6+ 1551 if (tinyMCE.isMSIE5) 1552 break; 1553 1554 // Fix onclick attrib 1555 if (tinyMCE.cleanup_on_save) { 1556 if (element_node.getAttribute("mce_onclick")) { 1557 attribName = "onclick"; 1558 attribValue = "" + element_node.getAttribute("mce_onclick"); 1559 } 1560 } else { 1561 if (attribName == "onclick" && !tinyMCE.cleanup_on_save) 1562 return null; 1563 } 1564 1565 break; 1566 1567 // Convert the URLs of these 1568 case "href": 1569 case "src": 1570 // Fix for dragdrop/copy paste Mozilla issue 1571 if (!tinyMCE.isMSIE && attribName == "href" && element_node.getAttribute("mce_real_href")) 1572 attribValue = element_node.getAttribute("mce_real_href"); 1573 1574 // Fix for dragdrop/copy paste Mozilla issue 1575 if (!tinyMCE.isMSIE && attribName == "src" && element_node.getAttribute("mce_real_src")) 1576 attribValue = element_node.getAttribute("mce_real_src"); 1577 1578 // Force absolute URLs in Firefox 1579 if (tinyMCE.isGecko && !tinyMCE.settings['relative_urls']) 1580 attribValue = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], attribValue); 1581 1582 attribValue = eval(tinyMCE.cleanup_urlconverter_callback + "(attribValue, element_node, tinyMCE.cleanup_on_save);"); 1583 break; 1584 1585 case "colspan": 1586 case "rowspan": 1587 // Not needed 1588 if (attribValue == "1") 1589 return null; 1590 break; 1591 1592 // Skip these 1593 case "_moz-userdefined": 1594 case "editorid": 1595 case "editor_id": 1596 case "mce_real_href": 1597 case "mce_real_src": 1598 return null; 1599 } 1600 1601 // Not the must be value 1602 if (attribMustBeValue != null) { 1603 var isCorrect = false; 1604 for (var i=0; i<attribMustBeValue.length; i++) { 1605 if (attribValue == attribMustBeValue[i]) { 1606 isCorrect = true; 1607 break; 1608 } 1609 } 1610 1611 if (!isCorrect) 1612 return null; 1613 } 1614 1615 var attrib = new Object(); 1616 1617 attrib.name = attribName; 1618 attrib.value = attribValue; 1619 1620 return attrib; 1621 }; 1622 1623 TinyMCE.prototype._verifyClass = function(node) { 1624 // Sometimes the class gets set to null, weird Gecko bug? 1625 if (tinyMCE.isGecko) { 1626 var className = node.getAttribute('class'); 1627 if (!className) 1628 return false; 1629 } 1630 1631 // Trim CSS class 1632 if (tinyMCE.isMSIE) 1633 var className = node.getAttribute('className'); 1634 1635 if (tinyMCE.cleanup_verify_css_classes && tinyMCE.cleanup_on_save) { 1636 var csses = tinyMCE.getCSSClasses(); 1637 nonDefinedCSS = true; 1638 for (var c=0; c<csses.length; c++) { 1639 if (csses[c] == className) { 1640 nonDefinedCSS = false; 1641 break; 1642 } 1643 } 1644 1645 if (nonDefinedCSS && className.indexOf('mce_') != 0) { 1646 node.removeAttribute('className'); 1647 node.removeAttribute('class'); 1648 return false; 1649 } 1650 } 1651 1652 return true; 1653 }; 1654 1655 TinyMCE.prototype.cleanupNode = function(node) { 1656 var output = ""; 1657 1658 switch (node.nodeType) { 1659 case 1: // Element 1660 var elementData = tinyMCE._cleanupElementName(node.nodeName, node); 1661 var elementName = elementData ? elementData.element_name : null; 1662 var elementValidAttribs = elementData ? elementData.valid_attribs : null; 1663 var elementAttribs = ""; 1664 var openTag = false; 1665 1666 if (elementName != null && elementName.charAt(0) == '+') { 1667 elementName = elementName.substring(1); 1668 openTag = true; 1669 } 1670 1671 // Checking DOM tree for MSIE weirdness!! 1672 if (tinyMCE.isMSIE && tinyMCE.settings['fix_content_duplication']) { 1673 var lookup = tinyMCE.cleanup_elementLookupTable; 1674 1675 for (var i=0; i<lookup.length; i++) { 1676 // Found element reference else were, hmm? 1677 if (lookup[i] == node) 1678 return output; 1679 } 1680 1681 // Add element to lookup table 1682 lookup[lookup.length] = node; 1683 } 1684 1685 // Element not valid (only render children) 1686 if (!elementName) { 1687 if (node.hasChildNodes()) { 1688 for (var i=0; i<node.childNodes.length; i++) 1689 output += this.cleanupNode(node.childNodes[i]); 1690 } 1691 1692 return output; 1693 } 1694 1695 // Has mso/microsuck crap or empty attrib 1696 if (node.style && (node.style.cssText.indexOf('mso-') != -1 && tinyMCE.settings['auto_cleanup_word']) || node.style.cssText == "") { 1697 node.style.cssText = ""; 1698 node.removeAttribute("style"); 1699 } 1700 1701 // Handle inline styles 1702 if (tinyMCE.cleanup_inline_styles) 1703 tinyMCE._fixInlineStyles(node); 1704 1705 // Set attrib data 1706 if (elementValidAttribs) { 1707 for (var a=1; a<elementValidAttribs.length; a++) { 1708 var attribName, attribDefaultValue, attribForceValue, attribValue; 1709 1710 attribName = elementValidAttribs[a][0]; 1711 attribDefaultValue = elementValidAttribs[a][1]; 1712 attribForceValue = elementValidAttribs[a][2]; 1713 1714 if (attribDefaultValue != null || attribForceValue != null) { 1715 var attribValue = node.getAttribute(attribName); 1716 1717 if (node.getAttribute(attribName) == null || node.getAttribute(attribName) == "") 1718 attribValue = attribDefaultValue; 1719 1720 attribValue = attribForceValue ? attribForceValue : attribValue; 1721 1722 // Is to generate id 1723 if (attribValue == "{$uid}") 1724 attribValue = "uid_" + (tinyMCE.cleanup_idCount++); 1725 1726 node.setAttribute(attribName, attribValue); 1727 //alert(attribName + "=" + attribValue); 1728 } 1729 } 1730 } 1731 1732 // Remove non needed span elements 1733 if (elementName == "span" && tinyMCE.cleanup_trim_span_elements) { 1734 var re = new RegExp('^[ \t]+', 'g'); 1735 var onlyWhiteSpace = true; 1736 for (var a=0; a<node.childNodes.length; a++) { 1737 var tmpNode = node.childNodes[a]; 1738 if ((tmpNode.nodeType == 3 && !tmpNode.nodeValue.match(re)) || tmpNode.nodeName.toLowerCase() != "span") { 1739 onlyWhiteSpace = false; 1740 break; 1741 } 1742 } 1743 1744 // Count attributes 1745 tinyMCE._verifyClass(node); 1746 var numAttribs = 0; 1747 for (var i=0; i<node.attributes.length; i++) { 1748 if (node.attributes[i].specified) 1749 numAttribs++; 1750 } 1751 1752 // Is not a valid span, remove it 1753 if (onlyWhiteSpace || numAttribs == 0) { 1754 if (node.hasChildNodes()) { 1755 for (var i=0; i<node.childNodes.length; i++) 1756 output += this.cleanupNode(node.childNodes[i]); 1757 } 1758 1759 return output; 1760 } 1761 } 1762 1763 // Add some visual aids 1764 /* if (elementName == "table" || elementName == "td") { 1765 // Handle visual aid 1766 if (tinyMCE.cleanup_visual_table_class != "") { 1767 // Find parent table 1768 var tableElement = node; 1769 if (elementName == "td") 1770 tableElement = tinyMCE.getParentElement(tableElement, "table"); 1771 1772 if (tableElement && tableElement.getAttribute("border") == 0) { 1773 if (tinyMCE.cleanup_visual_aid) 1774 elementAttribs += ' class="' + tinyMCE.getVisualAidClass(tinyMCE.getAttrib(node, "class")) + '"'; 1775 } 1776 } 1777 }*/ 1778 1779 // Remove empty tables 1780 if (elementName == "table" && !node.hasChildNodes()) 1781 return ""; 1782 1783 // Fix width/height attributes if the styles is specified 1784 if (tinyMCE.isGecko && elementName == "img") { 1785 var w = node.style.width; 1786 if (w != null && w != "") 1787 node.setAttribute("width", w); 1788 1789 var h = node.style.height; 1790 if (h != null && h != "") 1791 node.setAttribute("height", h); 1792 } 1793 1794 // Handle element attributes 1795 if (node.attributes.length > 0) { 1796 for (var i=0; i<node.attributes.length; i++) { 1797 if (node.attributes[i].specified) { 1798 var attrib = tinyMCE._cleanupAttribute(elementValidAttribs, elementName, node.attributes[i], node); 1799 if (attrib) 1800 elementAttribs += " " + attrib.name + "=" + '"' + attrib.value + '"'; 1801 } 1802 } 1803 1804 //alert(elementAttribs); 1805 } 1806 1807 // MSIE form element issue 1808 if (tinyMCE.isMSIE && elementName == "input") { 1809 if (node.type) 1810 elementAttribs += " type=" + '"' + node.type + '"'; 1811 1812 if (node.value) 1813 elementAttribs += " value=" + '"' + node.value + '"'; 1814 } 1815 1816 // Add nbsp to some elements 1817 if ((elementName == "p" || elementName == "td") && (node.innerHTML == "" || node.innerHTML == " ")) 1818 return "<" + elementName + elementAttribs + ">" + this.convertStringToXML(String.fromCharCode(160)) + "</" + elementName + ">"; 1819 1820 // Is MSIE script element 1821 if (tinyMCE.isMSIE && elementName == "script") 1822 return "<" + elementName + elementAttribs + ">" + node.text + "</" + elementName + ">"; 1823 1824 // Clean up children 1825 if (node.hasChildNodes()) { 1826 // Force BR 1827 if (elementName == "p" && tinyMCE.cleanup_force_br_newlines) 1828 output += "<div" + elementAttribs + ">"; 1829 else 1830 output += "<" + elementName + elementAttribs + ">"; 1831 1832 for (var i=0; i<node.childNodes.length; i++) 1833 output += this.cleanupNode(node.childNodes[i]); 1834 1835 // Force BR 1836 if (elementName == "p" && tinyMCE.cleanup_force_br_newlines) 1837 output += "</div><br />"; 1838 else 1839 output += "</" + elementName + ">"; 1840 } else { 1841 // Allways leave anchor elements open 1842 if (openTag) 1843 output += "<" + elementName + elementAttribs + "></" + elementName + ">"; 1844 else { 1845 // No children 1846 output += "<" + elementName + elementAttribs + " />"; 1847 } 1848 } 1849 1850 return output; 1851 1852 case 3: // Text 1853 // Do not convert script elements 1854 if (node.parentNode.nodeName.toLowerCase() == "script") 1855 return node.nodeValue; 1856 1857 return this.convertStringToXML(node.nodeValue); 1858 1859 case 8: // Comment 1860 return "<!--" + node.nodeValue + "-->"; 1861 1862 default: // Unknown 1863 return "[UNKNOWN NODETYPE " + node.nodeType + "]"; 1864 } 1865 }; 1866 1867 TinyMCE.prototype.convertStringToXML = function(html_data) { 1868 var output = ""; 1869 1870 for (var i=0; i<html_data.length; i++) { 1871 var chr = html_data.charCodeAt(i); 1872 1873 // Numeric entities 1874 if (tinyMCE.settings['entity_encoding'] == "numeric") { 1875 if (chr > 127) 1876 output += '&#' + chr + ";"; 1877 else 1878 output += String.fromCharCode(chr); 1879 1880 continue; 1881 } 1882 1883 // Raw entities 1884 if (tinyMCE.settings['entity_encoding'] == "raw") { 1885 output += String.fromCharCode(chr); 1886 continue; 1887 } 1888 1889 // Named entities 1890 if (typeof(tinyMCE.cleanup_entities["c" + chr]) != 'undefined' && tinyMCE.cleanup_entities["c" + chr] != '') 1891 output += '&' + tinyMCE.cleanup_entities["c" + chr] + ';'; 1892 else 1893 output += '' + String.fromCharCode(chr); 1894 } 1895 1896 return output; 1897 }; 1898 1899 TinyMCE.prototype._getCleanupElementName = function(chunk) { 1900 var pos; 1901 1902 if (chunk.charAt(0) == '+') 1903 chunk = chunk.substring(1); 1904 1905 if ((pos = chunk.indexOf('/')) != -1) 1906 chunk = chunk.substring(0, pos); 1907 1908 if ((pos = chunk.indexOf('[')) != -1) 1909 chunk = chunk.substring(0, pos); 1910 1911 return chunk; 1912 }; 1913 1914 TinyMCE.prototype._initCleanup = function() { 1915 // Parse valid elements and attributes 1916 var validElements = tinyMCE.settings["valid_elements"]; 1917 validElements = validElements.split(','); 1918 1919 // Handle extended valid elements 1920 var extendedValidElements = tinyMCE.settings["extended_valid_elements"]; 1921 extendedValidElements = extendedValidElements.split(','); 1922 for (var i=0; i<extendedValidElements.length; i++) { 1923 var elementName = this._getCleanupElementName(extendedValidElements[i]); 1924 var skipAdd = false; 1925 1926 // Check if it's defined before, if so override that one 1927 for (var x=0; x<validElements.length; x++) { 1928 if (this._getCleanupElementName(validElements[x]) == elementName) { 1929 validElements[x] = extendedValidElements[i]; 1930 skipAdd = true; 1931 break; 1932 } 1933 } 1934 1935 if (!skipAdd) 1936 validElements[validElements.length] = extendedValidElements[i]; 1937 } 1938 1939 for (var i=0; i<validElements.length; i++) { 1940 var item = validElements[i]; 1941 1942 item = item.replace('[','|'); 1943 item = item.replace(']',''); 1944 1945 // Split and convert 1946 var attribs = item.split('|'); 1947 for (var x=0; x<attribs.length; x++) 1948 attribs[x] = attribs[x].toLowerCase(); 1949 1950 // Handle change elements 1951 attribs[0] = attribs[0].split('/'); 1952 1953 // Handle default attribute values 1954 for (var x=1; x<attribs.length; x++) { 1955 var attribName = attribs[x]; 1956 var attribDefault = null; 1957 var attribForce = null; 1958 var attribMustBe = null; 1959 1960 // Default value 1961 if ((pos = attribName.indexOf('=')) != -1) { 1962 attribDefault = attribName.substring(pos+1); 1963 attribName = attribName.substring(0, pos); 1964 } 1965 1966 // Force check 1967 if ((pos = attribName.indexOf(':')) != -1) { 1968 attribForce = attribName.substring(pos+1); 1969 attribName = attribName.substring(0, pos); 1970 } 1971 1972 // Force check 1973 if ((pos = attribName.indexOf('<')) != -1) { 1974 attribMustBe = attribName.substring(pos+1).split('?'); 1975 attribName = attribName.substring(0, pos); 1976 } 1977 1978 attribs[x] = new Array(attribName, attribDefault, attribForce, attribMustBe); 1979 } 1980 1981 validElements[i] = attribs; 1982 } 1983 1984 var invalidElements = tinyMCE.settings['invalid_elements'].split(','); 1985 for (var i=0; i<invalidElements.length; i++) 1986 invalidElements[i] = invalidElements[i].toLowerCase(); 1987 1988 // Set these for performance 1989 tinyMCE.settings['cleanup_validElements'] = validElements; 1990 tinyMCE.settings['cleanup_invalidElements'] = invalidElements; 1991 1992 // Setup entities 1993 tinyMCE.settings['cleanup_entities'] = new Array(); 1994 var entities = tinyMCE.getParam('entities', '', true, ','); 1995 for (var i=0; i<entities.length; i+=2) 1996 tinyMCE.settings['cleanup_entities']['c' + entities[i]] = entities[i+1]; 1997 }; 1998 1999 TinyMCE.prototype._cleanupHTML = function(doc, config, element, visual, on_save) { 2000 if (!tinyMCE.settings['cleanup']) 2001 return element.innerHTML; 2002 2003 // Call custom cleanup code 2004 tinyMCE._customCleanup(on_save ? "get_from_editor_dom" : "insert_to_editor_dom", doc.body); 2005 2006 // Set these for performance 2007 tinyMCE.cleanup_validElements = tinyMCE.settings['cleanup_validElements']; 2008 tinyMCE.cleanup_entities = tinyMCE.settings['cleanup_entities']; 2009 tinyMCE.cleanup_invalidElements = tinyMCE.settings['cleanup_invalidElements']; 2010 tinyMCE.cleanup_verify_html = tinyMCE.settings['verify_html']; 2011 tinyMCE.cleanup_force_br_newlines = tinyMCE.settings['force_br_newlines']; 2012 tinyMCE.cleanup_urlconverter_callback = tinyMCE.settings['urlconverter_callback']; 2013 tinyMCE.cleanup_verify_css_classes = tinyMCE.settings['verify_css_classes']; 2014 tinyMCE.cleanup_visual_table_class = tinyMCE.settings['visual_table_class']; 2015 tinyMCE.cleanup_apply_source_formatting = tinyMCE.settings['apply_source_formatting']; 2016 tinyMCE.cleanup_trim_span_elements = tinyMCE.settings['trim_span_elements']; 2017 tinyMCE.cleanup_inline_styles = tinyMCE.settings['inline_styles']; 2018 tinyMCE.cleanup_visual_aid = visual; 2019 tinyMCE.cleanup_on_save = on_save; 2020 tinyMCE.cleanup_idCount = 0; 2021 tinyMCE.cleanup_elementLookupTable = new Array(); 2022 2023 var startTime = new Date().getTime(); 2024 2025 tinyMCE._convertOnClick(element); 2026 2027 // Cleanup madness that breaks the editor in MSIE 2028 if (tinyMCE.isMSIE) { 2029 element.innerHTML = tinyMCE.regexpReplace(element.innerHTML, '<p>[ \n\r]*<hr id=null>[ \n\r]*</p>', '<hr />', 'gi'); 2030 element.innerHTML = tinyMCE.regexpReplace(element.innerHTML, '<!([^-(DOCTYPE)]* )|<!/[^-]*>', '', 'gi'); 2031 } 2032 2033 var html = this.cleanupNode(element); 2034 2035 if (tinyMCE.settings['debug']) 2036 alert("Cleanup process executed in: " + (new Date().getTime()-startTime) + " ms."); 2037 2038 // Remove pesky HR paragraphs 2039 html = tinyMCE.regexpReplace(html, '<p><hr /></p>', '<hr />'); 2040 html = tinyMCE.regexpReplace(html, '<p> </p><hr /><p> </p>', '<hr />'); 2041 2042 // Remove some mozilla crap 2043 if (!tinyMCE.isMSIE) 2044 html = html.replace(new RegExp('<o:p _moz-userdefined="" />', 'g'), ""); 2045 2046 if (tinyMCE.settings['apply_source_formatting']) { 2047 html = html.replace(new RegExp('<(p|div)([^>]*)>', 'g'), "\n<$1$2>\n"); 2048 html = html.replace(new RegExp('<\/(p|div)([^>]*)>', 'g'), "\n</$1$2>\n"); 2049 html = html.replace(new RegExp('<br />', 'g'), "<br />\n"); 2050 } 2051 2052 if (tinyMCE.settings['force_br_newlines']) { 2053 var re = new RegExp('<p> </p>', 'g'); 2054 html = html.replace(re, "<br />"); 2055 } 2056 2057 if (tinyMCE.settings['force_p_newlines']) { 2058 // Remove weridness! 2059 var re = new RegExp('<>', 'g'); 2060 html = html.replace(re, ""); 2061 } 2062 2063 if (tinyMCE.settings['remove_linebreaks']) 2064 html = html.replace(new RegExp('\r|\n', 'g'), ' '); 2065 2066 // Call custom cleanup code 2067 html = tinyMCE._customCleanup(on_save ? "get_from_editor" : "insert_to_editor", html); 2068 2069 // Emtpy node, return empty 2070 var chk = tinyMCE.regexpReplace(html, "[ \t\r\n]", ""); 2071 if (chk == "<br/>" || chk == "<br>" || chk == "<p> </p>" || chk == "<p> </p>" || chk == "<p></p>") 2072 html = ""; 2073 2074 if (tinyMCE.settings["preformatted"]) 2075 return "<pre>" + html + "</pre>"; 2076 2077 return html; 2078 }; 2079 2080 TinyMCE.prototype.setAttrib = function(element, name, value, no_fix_value) { 2081 if (!no_fix_value && value != null) { 2082 var re = new RegExp('[^0-9%]', 'g'); 2083 value = value.replace(re, ''); 2084 } 2085 2086 if (value != null && value != "") 2087 element.setAttribute(name, value); 2088 else 2089 element.removeAttribute(name); 2090 2091 if (value != null && value != "") 2092 element.setAttribute(name, value); 2093 else 2094 element.removeAttribute(name); 2095 }; 2096 2097 TinyMCE.prototype.insertLink = function(href, target, title, onclick) { 2098 this.execCommand("mceAddUndoLevel"); 2099 2100 if (this.selectedInstance && this.selectedElement && this.selectedElement.nodeName.toLowerCase() == "img") { 2101 var doc = this.selectedInstance.getDoc(); 2102 var linkElement = tinyMCE.getParentElement(this.selectedElement, "a"); 2103 var newLink = false; 2104 2105 if (!linkElement) { 2106 linkElement = doc.createElement("a"); 2107 newLink = true; 2108 } 2109 2110 href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, linkElement);"); 2111 tinyMCE.setAttrib(linkElement, 'href', href); 2112 tinyMCE.setAttrib(linkElement, 'target', target); 2113 tinyMCE.setAttrib(linkElement, 'title', title); 2114 tinyMCE.setAttrib(linkElement, 'mce_onclick', onclick); 2115 2116 if (newLink) { 2117 linkElement.appendChild(this.selectedElement.cloneNode(true)); 2118 this.selectedElement.parentNode.replaceChild(linkElement, this.selectedElement); 2119 } 2120 2121 return; 2122 } 2123 2124 if (!this.linkElement && this.selectedInstance) { 2125 this.selectedInstance.contentDocument.execCommand("createlink", false, "#mce_temp_url#"); 2126 tinyMCE.linkElement = this.getElementByAttributeValue(this.selectedInstance.contentDocument.body, "a", "href", "#mce_temp_url#"); 2127 2128 var elementArray = this.getElementsByAttributeValue(this.selectedInstance.contentDocument.body, "a", "href", "#mce_temp_url#"); 2129 2130 for (var i=0; i<elementArray.length; i++) { 2131 href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, elementArray[i]);"); 2132 tinyMCE.setAttrib(elementArray[i], 'href', href); 2133 tinyMCE.setAttrib(elementArray[i], 'mce_real_href', href); 2134 tinyMCE.setAttrib(elementArray[i], 'target', target); 2135 tinyMCE.setAttrib(elementArray[i], 'title', title); 2136 tinyMCE.setAttrib(elementArray[i], 'mce_onclick', onclick); 2137 } 2138 2139 tinyMCE.linkElement = elementArray[0]; 2140 } 2141 2142 if (this.linkElement) { 2143 href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, this.linkElement);"); 2144 tinyMCE.setAttrib(this.linkElement, 'href', href); 2145 tinyMCE.setAttrib(this.linkElement, 'mce_real_href', href); 2146 tinyMCE.setAttrib(this.linkElement, 'target', target); 2147 tinyMCE.setAttrib(this.linkElement, 'title', title); 2148 tinyMCE.setAttrib(this.linkElement, 'mce_onclick', onclick); 2149 } 2150 }; 2151 2152 TinyMCE.prototype.insertImage = function(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout) { 2153 if (src == "") 2154 return; 2155 2156 this.execCommand("mceAddUndoLevel"); 2157 2158 if (!this.imgElement && this.selectedInstance) { 2159 this.selectedInstance.contentDocument.execCommand("insertimage", false, "#mce_temp_url#"); 2160 tinyMCE.imgElement = this.getElementByAttributeValue(this.selectedInstance.contentDocument.body, "img", "src", "#mce_temp_url#"); 2161 } 2162 2163 if (this.imgElement) { 2164 var needsRepaint = false; 2165 2166 src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, tinyMCE.imgElement);"); 2167 2168 if (onmouseover && onmouseover != "") 2169 onmouseover = "this.src='" + eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, tinyMCE.imgElement);") + "';"; 2170 2171 if (onmouseout && onmouseout != "") 2172 onmouseout = "this.src='" + eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseout, tinyMCE.imgElement);") + "';"; 2173 2174 // Use alt as title if it's undefined 2175 if (typeof(title) == "undefined") 2176 title = alt; 2177 2178 if (width != this.imgElement.getAttribute("width") || height != this.imgElement.getAttribute("height") || align != this.imgElement.getAttribute("align")) 2179 needsRepaint = true; 2180 2181 tinyMCE.setAttrib(this.imgElement, 'src', src); 2182 tinyMCE.setAttrib(this.imgElement, 'mce_real_src', src); 2183 tinyMCE.setAttrib(this.imgElement, 'alt', alt); 2184 tinyMCE.setAttrib(this.imgElement, 'title', title); 2185 tinyMCE.setAttrib(this.imgElement, 'align', align); 2186 tinyMCE.setAttrib(this.imgElement, 'border', border, true); 2187 tinyMCE.setAttrib(this.imgElement, 'hspace', hspace, true); 2188 tinyMCE.setAttrib(this.imgElement, 'vspace', vspace, true); 2189 tinyMCE.setAttrib(this.imgElement, 'width', width, true); 2190 tinyMCE.setAttrib(this.imgElement, 'height', height, true); 2191 tinyMCE.setAttrib(this.imgElement, 'onmouseover', onmouseover); 2192 tinyMCE.setAttrib(this.imgElement, 'onmouseout', onmouseout); 2193 2194 // Fix for bug #989846 - Image resize bug 2195 if (width && width != "") 2196 this.imgElement.style.pixelWidth = width; 2197 2198 if (height && height != "") 2199 this.imgElement.style.pixelHeight = height; 2200 2201 if (needsRepaint) 2202 tinyMCE.selectedInstance.repaint(); 2203 } 2204 }; 2205 2206 TinyMCE.prototype.getElementByAttributeValue = function(node, element_name, attrib, value) { 2207 var elements = this.getElementsByAttributeValue(node, element_name, attrib, value); 2208 if (elements.length == 0) 2209 return null; 2210 2211 return elements[0]; 2212 }; 2213 2214 TinyMCE.prototype.getElementsByAttributeValue = function(node, element_name, attrib, value) { 2215 var elements = new Array(); 2216 2217 if (node && node.nodeName.toLowerCase() == element_name) { 2218 if (node.getAttribute(attrib) && node.getAttribute(attrib).indexOf(value) != -1) 2219 elements[elements.length] = node; 2220 } 2221 2222 if (node.hasChildNodes) { 2223 for (var x=0, n=node.childNodes.length; x<n; x++) { 2224 var childElements = this.getElementsByAttributeValue(node.childNodes[x], element_name, attrib, value); 2225 for (var i=0, m=childElements.length; i<m; i++) 2226 elements[elements.length] = childElements[i]; 2227 } 2228 } 2229 2230 return elements; 2231 }; 2232 2233 TinyMCE.prototype.isBlockElement = function(node) { 2234 return node != null && node.nodeType == 1 && this.blockRegExp.test(node.nodeName); 2235 }; 2236 2237 TinyMCE.prototype.getParentBlockElement = function(node) { 2238 // Search up the tree for block element 2239 while (node) { 2240 if (this.blockRegExp.test(node.nodeName)) 2241 return node; 2242 2243 node = node.parentNode; 2244 } 2245 2246 return null; 2247 }; 2248 2249 TinyMCE.prototype.getNodeTree = function(node, node_array, type, node_name) { 2250 if (typeof(type) == "undefined" || node.nodeType == type && (typeof(node_name) == "undefined" || node.nodeName.toLowerCase() == node_name.toLowerCase())) 2251 node_array[node_array.length] = node; 2252 2253 if (node.hasChildNodes()) { 2254 for (var i=0; i<node.childNodes.length; i++) 2255 tinyMCE.getNodeTree(node.childNodes[i], node_array, type, node_name); 2256 } 2257 2258 return node_array; 2259 }; 2260 2261 TinyMCE.prototype.getParentElement = function(node, names, attrib_name, attrib_value) { 2262 if (typeof(names) == "undefined") { 2263 if (node.nodeType == 1) 2264 return node; 2265 2266 // Find parent node that is a element 2267 while ((node = node.parentNode) != null && node.nodeType != 1) ; 2268 2269 return node; 2270 } 2271 2272 var namesAr = names.split(','); 2273 2274 if (node == null) 2275 return null; 2276 2277 do { 2278 for (var i=0; i<namesAr.length; i++) { 2279 if (node.nodeName.toLowerCase() == namesAr[i].toLowerCase() || names == "*") { 2280 if (typeof(attrib_name) == "undefined") 2281 return node; 2282 else if (node.getAttribute(attrib_name)) { 2283 if (typeof(attrib_value) == "undefined") { 2284 if (node.getAttribute(attrib_name) != "") 2285 return node; 2286 } else if (node.getAttribute(attrib_name) == attrib_value) 2287 return node; 2288 } 2289 } 2290 } 2291 } while (node = node.parentNode); 2292 2293 return null; 2294 }; 2295 2296 TinyMCE.prototype.convertURL = function(url, node, on_save) { 2297 var prot = document.location.protocol; 2298 var host = document.location.hostname; 2299 var port = document.location.port; 2300 2301 var fileProto = (prot == "file:"); 2302 2303 // Something is wrong, remove weirdness 2304 url = tinyMCE.regexpReplace(url, '(http|https):///', '/'); 2305 2306 // Mailto link or anchor (Pass through) 2307 if (url.indexOf('mailto:') != -1 || url.indexOf('javascript:') != -1 || tinyMCE.regexpReplace(url,'[ \t\r\n\+]|%20','').charAt(0) == "#") 2308 return url; 2309 2310 // Fix relative/Mozilla 2311 if (!tinyMCE.isMSIE && !on_save && url.indexOf("://") == -1 && url.charAt(0) != '/') 2312 return tinyMCE.settings['base_href'] + url; 2313 2314 // Handle absolute url anchors 2315 if (!tinyMCE.settings['relative_urls']) { 2316 var urlParts = tinyMCE.parseURL(url); 2317 var baseUrlParts = tinyMCE.parseURL(tinyMCE.settings['base_href']); 2318 2319 // If anchor and path is the same page 2320 if (urlParts['anchor'] && urlParts['path'] == baseUrlParts['path']) 2321 return "#" + urlParts['anchor']; 2322 } 2323 2324 // Convert to relative urls 2325 if (on_save && tinyMCE.settings['relative_urls']) { 2326 var urlParts = tinyMCE.parseURL(url); 2327 2328 // If not absolute url, do nothing (Mozilla) 2329 // WEIRD STUFF?! 2330 /* if (!urlParts['protocol'] && !tinyMCE.isMSIE) { 2331 var urlPrefix = "http://"; 2332 urlPrefix += host; 2333 if (port != "") 2334 urlPrefix += ":" + port; 2335 2336 url = urlPrefix + url; 2337 urlParts = tinyMCE.parseURL(url); 2338 }*/ 2339 2340 var tmpUrlParts = tinyMCE.parseURL(tinyMCE.settings['document_base_url']); 2341 2342 // Link is within this site 2343 if (urlParts['host'] == tmpUrlParts['host'] && (!urlParts['port'] || urlParts['port'] == tmpUrlParts['port'])) 2344 return tinyMCE.convertAbsoluteURLToRelativeURL(tinyMCE.settings['document_base_url'], url); 2345 } 2346 2347 // Remove current domain 2348 if (!fileProto && tinyMCE.settings['remove_script_host']) { 2349 var start = "", portPart = ""; 2350 2351 if (port != "") 2352 portPart = ":" + port; 2353 2354 start = prot + "//" + host + portPart + "/"; 2355 2356 if (url.indexOf(start) == 0) 2357 url = url.substring(start.length-1); 2358 2359 // Add first slash if missing on a absolute URL 2360 if (!tinyMCE.settings['relative_urls'] && url.indexOf('://') == -1 && url.charAt(0) != '/') 2361 url = '/' + url; 2362 } 2363 2364 return url; 2365 }; 2366 2367 /** 2368 * Parses a URL in to its diffrent components. 2369 */ 2370 TinyMCE.prototype.parseURL = function(url_str) { 2371 var urlParts = new Array(); 2372 2373 if (url_str) { 2374 var pos, lastPos; 2375 2376 // Parse protocol part 2377 pos = url_str.indexOf('://'); 2378 if (pos != -1) { 2379 urlParts['protocol'] = url_str.substring(0, pos); 2380 lastPos = pos + 3; 2381 } 2382 2383 // Find port or path start 2384 for (var i=lastPos; i<url_str.length; i++) { 2385 var chr = url_str.charAt(i); 2386 2387 if (chr == ':') 2388 break; 2389 2390 if (chr == '/') 2391 break; 2392 } 2393 pos = i; 2394 2395 // Get host 2396 urlParts['host'] = url_str.substring(lastPos, pos); 2397 2398 // Get port 2399 lastPos = pos; 2400 if (url_str.charAt(pos) == ':') { 2401 pos = url_str.indexOf('/', lastPos); 2402 urlParts['port'] = url_str.substring(lastPos+1, pos); 2403 } 2404 2405 // Get path 2406 lastPos = pos; 2407 pos = url_str.indexOf('?', lastPos); 2408 2409 if (pos == -1) 2410 pos = url_str.indexOf('#', lastPos); 2411 2412 if (pos == -1) 2413 pos = url_str.length; 2414 2415 urlParts['path'] = url_str.substring(lastPos, pos); 2416 2417 // Get query 2418 lastPos = pos; 2419 if (url_str.charAt(pos) == '?') { 2420 pos = url_str.indexOf('#'); 2421 pos = (pos == -1) ? url_str.length : pos; 2422 urlParts['query'] = url_str.substring(lastPos+1, pos); 2423 } 2424 2425 // Get anchor 2426 lastPos = pos; 2427 if (url_str.charAt(pos) == '#') { 2428 pos = url_str.length; 2429 urlParts['anchor'] = url_str.substring(lastPos+1, pos); 2430 } 2431 } 2432 2433 return urlParts; 2434 }; 2435 2436 /** 2437 * Converts an absolute path to relative path. 2438 */ 2439 TinyMCE.prototype.convertAbsoluteURLToRelativeURL = function(base_url, url_to_relative) { 2440 var strTok1; 2441 var strTok2; 2442 var breakPoint = 0; 2443 var outputString = ""; 2444 2445 // Crop away last path part 2446 base_url = base_url.substring(0, base_url.lastIndexOf('/')); 2447 strTok1 = base_url.split('/'); 2448 strTok2 = url_to_relative.split('/'); 2449 2450 if (strTok1.length >= strTok2.length) { 2451 for (var i=0; i<strTok1.length; i++) { 2452 if (i >= strTok2.length || strTok1[i] != strTok2[i]) { 2453 breakPoint = i + 1; 2454 break; 2455 } 2456 } 2457 } 2458 2459 if (strTok1.length < strTok2.length) { 2460 for (var i=0; i<strTok2.length; i++) { 2461 if (i >= strTok1.length || strTok1[i] != strTok2[i]) { 2462 breakPoint = i + 1; 2463 break; 2464 } 2465 } 2466 } 2467 2468 if (breakPoint == 1) 2469 return url_to_relative; 2470 2471 for (var i=0; i<(strTok1.length-(breakPoint-1)); i++) 2472 outputString += "../"; 2473 2474 for (var i=breakPoint-1; i<strTok2.length; i++) { 2475 if (i != (breakPoint-1)) 2476 outputString += "/" + strTok2[i]; 2477 else 2478 outputString += strTok2[i]; 2479 } 2480 2481 return outputString; 2482 }; 2483 2484 TinyMCE.prototype.convertRelativeToAbsoluteURL = function(base_url, relative_url) { 2485 var baseURL = TinyMCE.prototype.parseURL(base_url); 2486 var relURL = TinyMCE.prototype.parseURL(relative_url); 2487 2488 if (relative_url == "" || relative_url.charAt(0) == '/' || relative_url.indexOf('://') != -1 || relative_url.indexOf('mailto:') != -1 || relative_url.indexOf('javascript:') != -1 || tinyMCE.regexpReplace(relative_url,'[ \t\r\n\+]|%20','').charAt(0) == "#") 2489 return relative_url; 2490 2491 // Split parts 2492 baseURLParts = baseURL['path'].split('/'); 2493 relURLParts = relURL['path'].split('/'); 2494 2495 // Remove empty chunks 2496 var newBaseURLParts = new Array(); 2497 for (var i=baseURLParts.length-1; i>=0; i--) { 2498 if (baseURLParts[i].length == 0) 2499 continue; 2500 2501 newBaseURLParts[newBaseURLParts.length] = baseURLParts[i]; 2502 } 2503 baseURLParts = newBaseURLParts.reverse(); 2504 2505 // Merge relURLParts chunks 2506 var newRelURLParts = new Array(); 2507 var numBack = 0; 2508 for (var i=relURLParts.length-1; i>=0; i--) { 2509 if (relURLParts[i].length == 0 || relURLParts[i] == ".") 2510 continue; 2511 2512 if (relURLParts[i] == '..') { 2513 numBack++; 2514 continue; 2515 } 2516 2517 if (numBack > 0) { 2518 numBack--; 2519 continue; 2520 } 2521 2522 newRelURLParts[newRelURLParts.length] = relURLParts[i]; 2523 } 2524 2525 relURLParts = newRelURLParts.reverse(); 2526 2527 // Remove end from absolute path 2528 var len = baseURLParts.length-numBack; 2529 var absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/'); 2530 var start = "", end = ""; 2531 2532 // Build start part 2533 if (baseURL['protocol']) 2534 start += baseURL['protocol'] + "://"; 2535 2536 if (baseURL['host']) 2537 start += baseURL['host']; 2538 2539 if (baseURL['port']) 2540 start += ":" + baseURL['port']; 2541 2542 // Build end part 2543 if (relURL['query']) 2544 end += "?" + relURL['query']; 2545 2546 if (relURL['anchor']) 2547 end += "#" + relURL['anchor']; 2548 2549 // Re-add trailing slash if it's removed 2550 if (relative_url.charAt(relative_url.length-1) == "/") 2551 end += "/"; 2552 2553 return start + absPath + end; 2554 }; 2555 2556 TinyMCE.prototype.getParam = function(name, default_value, strip_whitespace, split_chr) { 2557 var value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name]; 2558 2559 // Fix bool values 2560 if (value == "true" || value == "false") 2561 return (value == "true"); 2562 2563 if (strip_whitespace) 2564 value = tinyMCE.regexpReplace(value, "[ \t\r\n]", ""); 2565 2566 if (typeof(split_chr) != "undefined" && split_chr != null) { 2567 value = value.split(split_chr); 2568 var outArray = new Array(); 2569 2570 for (var i=0; i<value.length; i++) { 2571 if (value[i] && value[i] != "") 2572 outArray[outArray.length] = value[i]; 2573 } 2574 2575 value = outArray; 2576 } 2577 2578 return value; 2579 }; 2580 2581 TinyMCE.prototype.getLang = function(name, default_value, parse_entities) { 2582 var value = (typeof(tinyMCELang[name]) == "undefined") ? default_value : tinyMCELang[name]; 2583 2584 if (parse_entities) { 2585 var el = document.createElement("div"); 2586 el.innerHTML = value; 2587 value = el.innerHTML; 2588 } 2589 2590 return value; 2591 }; 2592 2593 TinyMCE.prototype.replaceVar = function(replace_haystack, replace_var, replace_str) { 2594 var re = new RegExp('{\\\$' + replace_var + '}', 'g'); 2595 return replace_haystack.replace(re, replace_str); 2596 }; 2597 2598 TinyMCE.prototype.replaceVars = function(replace_haystack, replace_vars) { 2599 for (var key in replace_vars) { 2600 var value = replace_vars[key]; 2601 replace_haystack = tinyMCE.replaceVar(replace_haystack, key, value); 2602 } 2603 2604 return replace_haystack; 2605 }; 2606 2607 TinyMCE.prototype.triggerNodeChange = function(focus, setup_content) { 2608 if (tinyMCE.settings['handleNodeChangeCallback']) { 2609 if (tinyMCE.selectedInstance) { 2610 var inst = tinyMCE.selectedInstance; 2611 var editorId = inst.editorId; 2612 var elm = (typeof(setup_content) != "undefined" && setup_content) ? tinyMCE.selectedElement : inst.getFocusElement(); 2613 var undoIndex = -1; 2614 var undoLevels = -1; 2615 var anySelection = false; 2616 var selectedText = inst.getSelectedText(); 2617 2618 if (tinyMCE.settings["auto_resize"]) { 2619 var doc = inst.getDoc(); 2620 2621 inst.iframeElement.style.width = doc.body.offsetWidth + "px"; 2622 inst.iframeElement.style.height = doc.body.offsetHeight + "px"; 2623 } 2624 2625 if (tinyMCE.selectedElement) 2626 anySelection = (tinyMCE.selectedElement.nodeName.toLowerCase() == "img") || (selectedText && selectedText.length > 0); 2627 2628 if (tinyMCE.settings['custom_undo_redo']) { 2629 undoIndex = inst.undoIndex; 2630 undoLevels = inst.undoLevels.length; 2631 } 2632 2633 tinyMCE.executeCallback('handleNodeChangeCallback', '_handleNodeChange', 0, editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection); 2634 } 2635 } 2636 2637 if (this.selectedInstance && (typeof(focus) == "undefined" || focus)) 2638 this.selectedInstance.contentWindow.focus(); 2639 }; 2640 2641 TinyMCE.prototype._customCleanup = function(type, content) { 2642 // Call custom cleanup 2643 var customCleanup = tinyMCE.settings['cleanup_callback']; 2644 if (customCleanup != "" && eval("typeof(" + customCleanup + ")") != "undefined") 2645 content = eval(customCleanup + "(type, content);"); 2646 2647 // Trigger plugin cleanups 2648 var plugins = tinyMCE.getParam('plugins', '', true, ','); 2649 for (var i=0; i<plugins.length; i++) { 2650 if (eval("typeof(TinyMCE_" + plugins[i] + "_cleanup)") != "undefined") 2651 content = eval("TinyMCE_" + plugins[i] + "_cleanup(type, content);"); 2652 } 2653 2654 return content; 2655 }; 2656 2657 TinyMCE.prototype.getContent = function(editor_id) { 2658 if (typeof(editor_id) != "undefined") 2659 tinyMCE.selectedInstance = tinyMCE.getInstanceById(editor_id); 2660 2661 if (tinyMCE.selectedInstance) 2662 return tinyMCE._cleanupHTML(this.selectedInstance.getDoc(), tinyMCE.settings, this.selectedInstance.getBody(), false, true); 2663 2664 return null; 2665 }; 2666 2667 TinyMCE.prototype.setContent = function(html_content) { 2668 if (tinyMCE.selectedInstance) 2669 tinyMCE.selectedInstance.execCommand('mceSetContent', false, html_content); 2670 }; 2671 2672 TinyMCE.prototype.importThemeLanguagePack = function(name) { 2673 if (typeof(name) == "undefined") 2674 name = tinyMCE.settings['theme']; 2675 2676 tinyMCE.loadScript(tinyMCE.baseURL + '/themes/' + name + '/langs/' + tinyMCE.settings['language'] + '.js'); 2677 }; 2678 2679 TinyMCE.prototype.importPluginLanguagePack = function(name, valid_languages) { 2680 var lang = "en"; 2681 2682 valid_languages = valid_languages.split(','); 2683 for (var i=0; i<valid_languages.length; i++) { 2684 if (tinyMCE.settings['language'] == valid_languages[i]) 2685 lang = tinyMCE.settings['language']; 2686 } 2687 2688 // tinyMCE.loadScript(tinyMCE.baseURL + '/plugins/' + name + '/langs/' + lang + '.js'); 2689 }; 2690 2691 /** 2692 * Adds themeurl, settings and lang to HTML code. 2693 */ 2694 TinyMCE.prototype.applyTemplate = function(html, args) { 2695 html = tinyMCE.replaceVar(html, "themeurl", tinyMCE.themeURL); 2696 2697 if (typeof(args) != "undefined") 2698 html = tinyMCE.replaceVars(html, args); 2699 2700 html = tinyMCE.replaceVars(html, tinyMCE.settings); 2701 html = tinyMCE.replaceVars(html, tinyMCELang); 2702 2703 return html; 2704 }; 2705 2706 TinyMCE.prototype.openWindow = function(template, args) { 2707 var html, width, height, x, y, resizable, scrollbars, url; 2708 2709 args['mce_template_file'] = template['file']; 2710 tinyMCE.windowArgs = args; 2711 2712 html = template['html']; 2713 if (!(width = template['width'])) 2714 width = 320; 2715 2716 if (!(height = template['height'])) 2717 height = 200; 2718 2719 // Add to height in M$ due to SP2 WHY DON'T YOU GUYS IMPLEMENT innerWidth of windows!! 2720 if (tinyMCE.isMSIE) 2721 height += 30; 2722 2723 x = parseInt(screen.width / 2.0) - (width / 2.0); 2724 y = parseInt(screen.height / 2.0) - (height / 2.0); 2725 2726 resizable = (args && args['resizable']) ? args['resizable'] : "no"; 2727 scrollbars = (args && args['scrollbars']) ? args['scrollbars'] : "no"; 2728 url = tinyMCE.baseURL + "/themes/" + tinyMCE.getParam("theme") + "/" + template['file']; 2729 2730 // Replace all args as variables in URL 2731 for (var name in args) 2732 url = tinyMCE.replaceVar(url, name, escape(args[name])); 2733 2734 if (html) { 2735 html = tinyMCE.replaceVar(html, "css", this.settings['popups_css']); 2736 html = tinyMCE.applyTemplate(html, args); 2737 2738 var win = window.open("", "mcePopup", "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=yes,minimizable=" + resizable + ",modal=yes,width=" + width + ",height=" + height + ",resizable=" + resizable); 2739 win.document.write(html); 2740 win.document.close(); 2741 win.resizeTo(width, height); 2742 win.focus(); 2743 } else { 2744 if (tinyMCE.isMSIE && resizable != 'yes') { 2745 var features = "resizable:" + resizable 2746 + ";scroll:" 2747 + scrollbars + ";status:yes;center:yes;help:no;dialogWidth:" 2748 + width + "px;dialogHeight:" + height + "px;"; 2749 2750 window.showModalDialog(url, window, features); 2751 } else { 2752 var modal = (resizable == "yes") ? "no" : "yes"; 2753 2754 var win = window.open(url, "mcePopup", "top=" + y + ",left=" + x + ",scrollbars=" + scrollbars + ",dialog=" + modal + ",minimizable=" + resizable + ",modal=" + modal + ",width=" + width + ",height=" + height + ",resizable=" + resizable); 2755 eval('try { win.resizeTo(width, height); } catch(e) { }'); 2756 win.focus(); 2757 } 2758 } 2759 }; 2760 2761 TinyMCE.prototype.getVisualAidClass = function(class_name, state) { 2762 var aidClass = tinyMCE.settings['visual_table_class']; 2763 2764 if (typeof(state) == "undefined") 2765 state = tinyMCE.settings['visual']; 2766 2767 // Split 2768 var classNames = new Array(); 2769 var ar = class_name.split(' '); 2770 for (var i=0; i<ar.length; i++) { 2771 if (ar[i] == aidClass) 2772 ar[i] = ""; 2773 2774 if (ar[i] != "") 2775 classNames[classNames.length] = ar[i]; 2776 } 2777 2778 if (state) 2779 classNames[classNames.length] = aidClass; 2780 2781 // Glue 2782 var className = ""; 2783 for (var i=0; i<classNames.length; i++) { 2784 if (i > 0) 2785 className += " "; 2786 2787 className += classNames[i]; 2788 } 2789 2790 return className; 2791 }; 2792 2793 TinyMCE.prototype.handleVisualAid = function(element, deep, state) { 2794 if (!element) 2795 return; 2796 2797 var tableElement = null; 2798 2799 switch (element.nodeName.toLowerCase()) { 2800 case "table": 2801 var oldW = element.style.width; 2802 var oldH = element.style.height; 2803 2804 element.className = tinyMCE.getVisualAidClass(element.className, state && element.getAttribute("border") == 0); 2805 2806 element.style.width = oldW; 2807 element.style.height = oldH; 2808 2809 for (var y=0; y<element.rows.length; y++) { 2810 for (var x=0; x<element.rows[y].cells.length; x++) { 2811 var className = tinyMCE.getVisualAidClass(element.rows[y].cells[x].className, state && element.getAttribute("border") == 0); 2812 element.rows[y].cells[x].className = className; 2813 } 2814 } 2815 2816 break; 2817 2818 /* case "a": 2819 var name = element.getAttribute("name"); 2820 if (name && name != "" && state) { 2821 //element.innerHTML += '<img mceVisualAid="true" src="' + (tinyMCE.themeURL + "/images/anchor.gif") + '" />'; 2822 return; 2823 } 2824 2825 break;*/ 2826 } 2827 2828 if (deep && element.hasChildNodes()) { 2829 for (var i=0; i<element.childNodes.length; i++) 2830 tinyMCE.handleVisualAid(element.childNodes[i], deep, state); 2831 } 2832 }; 2833 2834 TinyMCE.prototype.getAttrib = function(elm, name, default_value) { 2835 var v = elm.getAttribute(name); 2836 2837 // Try className for class attrib 2838 if (name == "class" && !v) 2839 v = elm.className; 2840 2841 if (typeof(default_value) == "undefined") 2842 default_value = ""; 2843 2844 return (v && v != "") ? v : default_value; 2845 }; 2846 2847 TinyMCE.prototype.setAttrib = function(element, name, value, fix_value) { 2848 if (typeof(value) == "number") 2849 value = "" + value; 2850 2851 if (fix_value) { 2852 if (value == null) 2853 value = ""; 2854 2855 var re = new RegExp('[^0-9%]', 'g'); 2856 value = value.replace(re, ''); 2857 } 2858 2859 if (name == "class") 2860 element.className = value; 2861 2862 if (value != null && value != "" && value != -1) 2863 element.setAttribute(name, value); 2864 else 2865 element.removeAttribute(name); 2866 }; 2867 2868 TinyMCE.prototype._setHTML = function(doc, html_content) { 2869 // Weird MSIE bug, <p><hr /></p> breaks runtime? 2870 if (tinyMCE.isMSIE) { 2871 var re = new RegExp('<p><hr /></p>', 'g'); 2872 html_content = html_content.replace(re, "<hr>"); 2873 } 2874 2875 doc.body.innerHTML = html_content; 2876 2877 // Content duplication bug fix 2878 if (tinyMCE.isMSIE && tinyMCE.settings['fix_content_duplication']) { 2879 // Remove P elements in P elements 2880 var paras = doc.getElementsByTagName("P"); 2881 for (var i=0; i<paras.length; i++) { 2882 var node = paras[i]; 2883 while ((node = node.parentNode) != null) { 2884 if (node.nodeName.toLowerCase() == "p") 2885 node.outerHTML = node.innerHTML; 2886 } 2887 } 2888 2889 // Content duplication bug fix (Seems to be word crap) 2890 var html = doc.body.innerHTML; 2891 2892 if (html.indexOf('="mso') != -1) { 2893 for (var i=0; i<doc.body.all.length; i++) { 2894 var el = doc.body.all[i]; 2895 el.removeAttribute("className","",0); 2896 el.removeAttribute("style","",0); 2897 } 2898 2899 html = doc.body.innerHTML; 2900 html = tinyMCE.regexpReplace(html, "<o:p><\/o:p>", "<br />"); 2901 html = tinyMCE.regexpReplace(html, "<o:p> <\/o:p>", ""); 2902 html = tinyMCE.regexpReplace(html, "<st1:.*?>", ""); 2903 html = tinyMCE.regexpReplace(html, "<p><\/p>", ""); 2904 html = tinyMCE.regexpReplace(html, "<p><\/p>\r\n<p><\/p>", ""); 2905 html = tinyMCE.regexpReplace(html, "<p> <\/p>", "<br />"); 2906 html = tinyMCE.regexpReplace(html, "<p>\s*(<p>\s*)?", "<p>"); 2907 html = tinyMCE.regexpReplace(html, "<\/p>\s*(<\/p>\s*)?", "</p>"); 2908 } 2909 2910 // Always set the htmlText output 2911 doc.body.innerHTML = html; 2912 } 2913 }; 2914 2915 TinyMCE.prototype.getImageSrc = function(str) { 2916 var pos = -1; 2917 2918 if (!str) 2919 return ""; 2920 2921 if ((pos = str.indexOf('this.src=')) != -1) { 2922 var src = str.substring(pos + 10); 2923 2924 src = src.substring(0, src.indexOf('\'')); 2925 2926 return src; 2927 } 2928 2929 return ""; 2930 }; 2931 2932 TinyMCE.prototype._getElementById = function(element_id) { 2933 var elm = document.getElementById(element_id); 2934 if (!elm) { 2935 // Check for element in forms 2936 for (var j=0; j<document.forms.length; j++) { 2937 for (var k=0; k<document.forms[j].elements.length; k++) { 2938 if (document.forms[j].elements[k].name == element_id) { 2939 elm = document.forms[j].elements[k]; 2940 break; 2941 } 2942 } 2943 } 2944 } 2945 2946 return elm; 2947 }; 2948 2949 TinyMCE.prototype.getEditorId = function(form_element) { 2950 var inst = this.getInstanceById(form_element); 2951 if (!inst) 2952 return null; 2953 2954 return inst.editorId; 2955 }; 2956 2957 TinyMCE.prototype.getInstanceById = function(editor_id) { 2958 var inst = this.instances[editor_id]; 2959 if (!inst) { 2960 for (var instanceName in tinyMCE.instances) { 2961 var instance = tinyMCE.instances[instanceName]; 2962 if (instance.formTargetElementId == editor_id) { 2963 inst = instance; 2964 break; 2965 } 2966 } 2967 } 2968 2969 return inst; 2970 }; 2971 2972 TinyMCE.prototype.queryInstanceCommandValue = function(editor_id, command) { 2973 var inst = tinyMCE.getInstanceById(editor_id); 2974 if (inst) 2975 return inst.queryCommandValue(command); 2976 2977 return false; 2978 }; 2979 2980 TinyMCE.prototype.queryInstanceCommandState = function(editor_id, command) { 2981 var inst = tinyMCE.getInstanceById(editor_id); 2982 if (inst) 2983 return inst.queryCommandState(command); 2984 2985 return null; 2986 }; 2987 2988 TinyMCE.prototype.setWindowArg = function(name, value) { 2989 this.windowArgs[name] = value; 2990 }; 2991 2992 TinyMCE.prototype.getWindowArg = function(name, default_value) { 2993 return (typeof(this.windowArgs[name]) == "undefined") ? default_value : this.windowArgs[name]; 2994 }; 2995 2996 TinyMCE.prototype.getCSSClasses = function(editor_id, doc) { 2997 var output = new Array(); 2998 2999 // Is cached, use that 3000 if (typeof(tinyMCE.cssClasses) != "undefined") 3001 return tinyMCE.cssClasses; 3002 3003 if (typeof(editor_id) == "undefined" && typeof(doc) == "undefined") { 3004 var instance; 3005 3006 for (var instanceName in tinyMCE.instances) { 3007 instance = tinyMCE.instances[instanceName]; 3008 break; 3009 } 3010 3011 doc = instance.getDoc(); 3012 } 3013 3014 if (typeof(doc) == "undefined") { 3015 var instance = tinyMCE.getInstanceById(editor_id); 3016 doc = instance.getDoc(); 3017 } 3018 3019 if (doc) { 3020 var styles = tinyMCE.isMSIE ? doc.styleSheets : doc.styleSheets; 3021 3022 if (styles && styles.length > 0) { 3023 var csses = null; 3024 3025 // Just ignore any errors 3026 eval("try {var csses = tinyMCE.isMSIE ? doc.styleSheets(0).rules : doc.styleSheets[0].cssRules;} catch(e) {}"); 3027 if (!csses) 3028 return new Array(); 3029 3030 for (var i=0; i<csses.length; i++) { 3031 var selectorText = csses[i].selectorText; 3032 3033 // Can be multiple rules per selector 3034 if (selectorText) { 3035 var rules = selectorText.split(','); 3036 for (var c=0; c<rules.length; c++) { 3037 // Invalid rule 3038 if (rules[c].indexOf(' ') != -1 || rules[c].indexOf(':') != -1 || rules[c].indexOf('mce_') == 1) 3039 continue; 3040 3041 if (rules[c] == "." + tinyMCE.settings['visual_table_class']) 3042 continue; 3043 3044 // Is class rule 3045 if (rules[c].indexOf('.') != -1) { 3046 //alert(rules[c].substring(rules[c].indexOf('.'))); 3047 output[output.length] = rules[c].substring(rules[c].indexOf('.')+1); 3048 } 3049 } 3050 } 3051 } 3052 } 3053 } 3054 3055 // Cache em 3056 if (output.length > 0) 3057 tinyMCE.cssClasses = output; 3058 3059 return output; 3060 }; 3061 3062 TinyMCE.prototype.regexpReplace = function(in_str, reg_exp, replace_str, opts) { 3063 if (typeof(opts) == "undefined") 3064 opts = 'g'; 3065 3066 var re = new RegExp(reg_exp, opts); 3067 return in_str.replace(re, replace_str); 3068 }; 3069 3070 TinyMCE.prototype.cleanupEventStr = function(str) { 3071 str = "" + str; 3072 str = str.replace('function anonymous()\n{\n', ''); 3073 str = str.replace('\n}', ''); 3074 3075 return str; 3076 }; 3077 3078 TinyMCE.prototype.getAbsPosition = function(node) { 3079 var pos = new Object(); 3080 3081 pos.absLeft = pos.absTop = 0; 3082 3083 var parentNode = node; 3084 while (parentNode) { 3085 pos.absLeft += parentNode.offsetLeft; 3086 pos.absTop += parentNode.offsetTop; 3087 3088 parentNode = parentNode.offsetParent; 3089 } 3090 3091 return pos; 3092 }; 3093 3094 TinyMCE.prototype.openFileBrowser = function(field_name, url, type, win) { 3095 var cb = tinyMCE.getParam("file_browser_callback"); 3096 3097 this.setWindowArg("window", win); 3098 3099 // Call to external callback 3100 if(eval('typeof('+cb+')') == "undefined") 3101 alert("Callback function: " + cb + " could not be found."); 3102 else 3103 eval(cb + "(field_name, url, type, win);"); 3104 }; 3105 3106 TinyMCE.prototype.getControlHTML = function(control_name) { 3107 var themePlugins = tinyMCE.getParam('plugins', '', true, ','); 3108 var templateFunction; 3109 3110 // Is it defined in any plugins 3111 for (var i=themePlugins.length; i>=0; i--) { 3112 templateFunction = 'TinyMCE_' + themePlugins[i] + "_getControlHTML"; 3113 if (eval("typeof(" + templateFunction + ")") != 'undefined') { 3114 var html = eval(templateFunction + "('" + control_name + "');"); 3115 if (html != "") 3116 return tinyMCE.replaceVar(html, "pluginurl", tinyMCE.baseURL + "/plugins/" + themePlugins[i]); 3117 } 3118 } 3119 3120 return eval('TinyMCE_' + tinyMCE.settings['theme'] + "_getControlHTML" + "('" + control_name + "');"); 3121 }; 3122 3123 TinyMCE.prototype._themeExecCommand = function(editor_id, element, command, user_interface, value) { 3124 var themePlugins = tinyMCE.getParam('plugins', '', true, ','); 3125 var templateFunction; 3126 3127 // Is it defined in any plugins 3128 for (var i=themePlugins.length; i>=0; i--) { 3129 templateFunction = 'TinyMCE_' + themePlugins[i] + "_execCommand"; 3130 if (eval("typeof(" + templateFunction + ")") != 'undefined') { 3131 if (eval(templateFunction + "(editor_id, element, command, user_interface, value);")) 3132 return true; 3133 } 3134 } 3135 3136 // Theme funtion 3137 templateFunction = 'TinyMCE_' + tinyMCE.settings['theme'] + "_execCommand"; 3138 if (eval("typeof(" + templateFunction + ")") != 'undefined') 3139 return eval(templateFunction + "(editor_id, element, command, user_interface, value);"); 3140 3141 // Pass to normal 3142 return false; 3143 }; 3144 3145 TinyMCE.prototype._getThemeFunction = function(suffix, skip_plugins) { 3146 if (skip_plugins) 3147 return 'TinyMCE_' + tinyMCE.settings['theme'] + suffix; 3148 3149 var themePlugins = tinyMCE.getParam('plugins', '', true, ','); 3150 var templateFunction; 3151 3152 // Is it defined in any plugins 3153 for (var i=themePlugins.length; i>=0; i--) { 3154 templateFunction = 'TinyMCE_' + themePlugins[i] + suffix; 3155 if (eval("typeof(" + templateFunction + ")") != 'undefined') 3156 return templateFunction; 3157 } 3158 3159 return 'TinyMCE_' + tinyMCE.settings['theme'] + suffix; 3160 }; 3161 3162 3163 TinyMCE.prototype.isFunc = function(func_name) { 3164 if (func_name == null || func_name == "") 3165 return false; 3166 3167 return eval("typeof(" + func_name + ")") != "undefined"; 3168 }; 3169 3170 TinyMCE.prototype.exec = function(func_name, args) { 3171 var str = func_name + '('; 3172 3173 // Add all arguments 3174 for (var i=3; i<args.length; i++) { 3175 str += 'args[' + i + ']'; 3176 3177 if (i < args.length-1) 3178 str += ','; 3179 } 3180 3181 str += ');'; 3182 3183 return eval(str); 3184 }; 3185 3186 TinyMCE.prototype.executeCallback = function(param, suffix, mode) { 3187 switch (mode) { 3188 // No chain 3189 case 0: 3190 var state = false; 3191 3192 // Execute each plugin callback 3193 var plugins = tinyMCE.getParam('plugins', '', true, ','); 3194 for (var i=0; i<plugins.length; i++) { 3195 var func = "TinyMCE_" + plugins[i] + suffix; 3196 if (tinyMCE.isFunc(func)) { 3197 tinyMCE.exec(func, this.executeCallback.arguments); 3198 state = true; 3199 } 3200 } 3201 3202 // Execute theme callback 3203 var func = 'TinyMCE_' + tinyMCE.settings['theme'] + suffix; 3204 if (tinyMCE.isFunc(func)) { 3205 tinyMCE.exec(func, this.executeCallback.arguments); 3206 state = true; 3207 } 3208 3209 // Execute settings callback 3210 var func = tinyMCE.getParam(param, ''); 3211 if (tinyMCE.isFunc(func)) { 3212 tinyMCE.exec(func, this.executeCallback.arguments); 3213 state = true; 3214 } 3215 3216 return state; 3217 3218 // Chain mode 3219 case 1: 3220 // Execute each plugin callback 3221 var plugins = tinyMCE.getParam('plugins', '', true, ','); 3222 for (var i=0; i<plugins.length; i++) { 3223 var func = "TinyMCE_" + plugins[i] + suffix; 3224 if (tinyMCE.isFunc(func)) { 3225 if (tinyMCE.exec(func, this.executeCallback.arguments)) 3226 return true; 3227 } 3228 } 3229 3230 // Execute theme callback 3231 var func = 'TinyMCE_' + tinyMCE.settings['theme'] + suffix; 3232 if (tinyMCE.isFunc(func)) { 3233 if (tinyMCE.exec(func, this.executeCallback.arguments)) 3234 return true; 3235 } 3236 3237 // Execute settings callback 3238 var func = tinyMCE.getParam(param, ''); 3239 if (tinyMCE.isFunc(func)) { 3240 if (tinyMCE.exec(func, this.executeCallback.arguments)) 3241 return true; 3242 } 3243 3244 return false; 3245 } 3246 }; 3247 3248 // TinyMCEControl 3249 function TinyMCEControl(settings) { 3250 // Undo levels 3251 this.undoLevels = new Array(); 3252 this.undoIndex = 0; 3253 this.isDirty = false; 3254 3255 // Default settings 3256 this.settings = settings; 3257 this.settings['theme'] = tinyMCE.getParam("theme", "default"); 3258 this.settings['width'] = tinyMCE.getParam("width", -1); 3259 this.settings['height'] = tinyMCE.getParam("height", -1); 3260 }; 3261 3262 TinyMCEControl.prototype.repaint = function() { 3263 if (tinyMCE.isMSIE) 3264 return; 3265 3266 this.getBody().style.display = 'none'; 3267 this.getBody().style.display = 'block'; 3268 }; 3269 3270 TinyMCEControl.prototype.switchSettings = function() { 3271 if (tinyMCE.configs.length > 1 && tinyMCE.currentConfig != this.settings['index']) { 3272 tinyMCE.settings = this.settings; 3273 tinyMCE.currentConfig = this.settings['index']; 3274 } 3275 }; 3276 3277 TinyMCEControl.prototype.fixBrokenURLs = function() { 3278 var body = this.getBody(); 3279 3280 var elms = body.getElementsByTagName("img"); 3281 for (var i=0; i<elms.length; i++) { 3282 var src = elms[i].getAttribute('mce_real_src'); 3283 if (src && src != "") 3284 elms[i].setAttribute("src", src); 3285 } 3286 3287 var elms = body.getElementsByTagName("a"); 3288 for (var i=0; i<elms.length; i++) { 3289 var href = elms[i].getAttribute('mce_real_href'); 3290 if (href && href != "") 3291 elms[i].setAttribute("href", href); 3292 } 3293 }; 3294 3295 TinyMCEControl.prototype.convertAllRelativeURLs = function() { 3296 var body = this.getBody(); 3297 3298 // Convert all image URL:s to absolute URL 3299 var elms = body.getElementsByTagName("img"); 3300 for (var i=0; i<elms.length; i++) { 3301 var src = elms[i].getAttribute('src'); 3302 if (src && src != "") { 3303 src = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], src); 3304 elms[i].setAttribute("src", src); 3305 elms[i].setAttribute("mce_real_src", src); 3306 } 3307 } 3308 3309 // Convert all link URL:s to absolute URL 3310 var elms = body.getElementsByTagName("a"); 3311 for (var i=0; i<elms.length; i++) { 3312 var href = elms[i].getAttribute('href'); 3313 if (href && href != "") { 3314 href = tinyMCE.convertRelativeToAbsoluteURL(tinyMCE.settings['base_href'], href); 3315 elms[i].setAttribute("href", href); 3316 elms[i].setAttribute("mce_real_href", href); 3317 } 3318 } 3319 }; 3320 3321 TinyMCEControl.prototype.getSelectedHTML = function() { 3322 var elm = document.createElement("body"); 3323 3324 if (tinyMCE.isGecko) 3325 elm.appendChild(this.getRng().cloneContents()); 3326 else 3327 elm.innerHTML = this.getRng().htmlText; 3328 3329 return tinyMCE._cleanupHTML(this.contentDocument, this.settings, elm, this.visualAid); 3330 }; 3331 3332 TinyMCEControl.prototype.getSelectedText = function() { 3333 if (tinyMCE.isMSIE) { 3334 var doc = this.getDoc(); 3335 3336 if (doc.selection.type == "Text") { 3337 var rng = doc.selection.createRange(); 3338 selectedText = rng.text; 3339 } else 3340 selectedText = ''; 3341 } else { 3342 var sel = this.getSel(); 3343 3344 if (sel && sel.toString) 3345 selectedText = sel.toString(); 3346 else 3347 selectedText = ''; 3348 } 3349 3350 return selectedText; 3351 }; 3352 3353 TinyMCEControl.prototype.selectNode = function(node, collapse, select_text_node, to_start) { 3354 if (!node) 3355 return; 3356 3357 if (typeof(collapse) == "undefined") 3358 collapse = true; 3359 3360 if (typeof(select_text_node) == "undefined") 3361 select_text_node = false; 3362 3363 if (typeof(to_start) == "undefined") 3364 to_start = true; 3365 3366 if (tinyMCE.isMSIE) { 3367 var rng = this.getBody().createTextRange(); 3368 3369 try { 3370 rng.moveToElementText(node); 3371 3372 if (collapse) 3373 rng.collapse(to_start); 3374 3375 rng.select(); 3376 } catch (e) { 3377 // Throws illigal agrument in MSIE some times 3378 } 3379 } else { 3380 var sel = this.getSel(); 3381 3382 if (!sel) 3383 return; 3384 3385 if (tinyMCE.isSafari) { 3386 sel.realSelection.setBaseAndExtent(node, 0, node, node.innerText.length); 3387 3388 if (collapse) { 3389 if (to_start) 3390 sel.realSelection.collapseToStart(); 3391 else 3392 sel.realSelection.collapseToEnd(); 3393 } 3394 3395 this.scrollToNode(node); 3396 3397 return; 3398 } 3399 3400 var rng = this.getDoc().createRange(); 3401 3402 if (select_text_node) { 3403 // Find first textnode in tree 3404 var nodes = tinyMCE.getNodeTree(node, new Array(), 3); 3405 if (nodes.length > 0) 3406 rng.selectNodeContents(nodes[0]); 3407 else 3408 rng.selectNodeContents(node); 3409 } else 3410 rng.selectNode(node); 3411 3412 if (collapse) { 3413 // Special treatment of textnode collapse 3414 if (!to_start && node.nodeType == 3) { 3415 rng.setStart(node, node.nodeValue.length); 3416 rng.setEnd(node, node.nodeValue.length); 3417 } else 3418 rng.collapse(to_start); 3419 } 3420 3421 sel.removeAllRanges(); 3422 sel.addRange(rng); 3423 } 3424 3425 this.scrollToNode(node); 3426 3427 // Set selected element 3428 tinyMCE.selectedElement = null; 3429 if (node.nodeType == 1) 3430 tinyMCE.selectedElement = node; 3431 }; 3432 3433 TinyMCEControl.prototype.scrollToNode = function(node) { 3434 // Scroll to node position 3435 var pos = tinyMCE.getAbsPosition(node); 3436 var doc = this.getDoc(); 3437 var scrollX = doc.body.scrollLeft + doc.documentElement.scrollLeft; 3438 var scrollY = doc.body.scrollTop + doc.documentElement.scrollTop; 3439 var height = tinyMCE.isMSIE ? document.getElementById(this.editorId).style.pixelHeight : this.targetElement.clientHeight; 3440 3441 // Only scroll if out of visible area 3442 if (!tinyMCE.settings['auto_resize'] && !(node.absTop > scrollY && node.absTop < (scrollY - 25 + height))) 3443 this.contentWindow.scrollTo(pos.absLeft, pos.absTop - height + 25); 3444 }; 3445 3446 TinyMCEControl.prototype.getBody = function() { 3447 return this.getDoc().body; 3448 }; 3449 3450 TinyMCEControl.prototype.getDoc = function() { 3451 return this.contentWindow.document; 3452 }; 3453 3454 TinyMCEControl.prototype.getWin = function() { 3455 return this.contentWindow; 3456 }; 3457 3458 TinyMCEControl.prototype.getSel = function() { 3459 if (tinyMCE.isMSIE) 3460 return this.getDoc().selection; 3461 3462 var sel = this.contentWindow.getSelection(); 3463 3464 // Fake getRangeAt 3465 if (tinyMCE.isSafari && !sel.getRangeAt) { 3466 var newSel = new Object(); 3467 var doc = this.getDoc(); 3468 3469 function getRangeAt(idx) { 3470 var rng = new Object(); 3471 3472 rng.startContainer = this.focusNode; 3473 rng.endContainer = this.anchorNode; 3474 rng.commonAncestorContainer = this.focusNode; 3475 rng.createContextualFragment = function (html) { 3476 // Seems to be a tag 3477 if (html.charAt(0) == '<') { 3478 var elm = doc.createElement("div"); 3479 3480 elm.innerHTML = html; 3481 3482 return elm.firstChild; 3483 } 3484 3485 return doc.createTextNode("UNSUPPORTED, DUE TO LIMITATIONS IN SAFARI!"); 3486 }; 3487 3488 rng.deleteContents = function () { 3489 doc.execCommand("Delete", false, ""); 3490 }; 3491 3492 return rng; 3493 } 3494 3495 // Patch selection 3496 3497 newSel.focusNode = sel.baseNode; 3498 newSel.focusOffset = sel.baseOffset; 3499 newSel.anchorNode = sel.extentNode; 3500 newSel.anchorOffset = sel.extentOffset; 3501 newSel.getRangeAt = getRangeAt; 3502 newSel.text = "" + sel; 3503 newSel.realSelection = sel; 3504 3505 newSel.toString = function () {return this.text;}; 3506 3507 return newSel; 3508 } 3509 3510 return sel; 3511 }; 3512 3513 TinyMCEControl.prototype.getRng = function() { 3514 var sel = this.getSel(); 3515 if (sel == null) 3516 return null; 3517 3518 if (tinyMCE.isMSIE) 3519 return sel.createRange(); 3520 3521 return this.getSel().getRangeAt(0); 3522 }; 3523 3524 TinyMCEControl.prototype._insertPara = function(e) { 3525 function isEmpty(para) { 3526 function isEmptyHTML(html) { 3527 return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == ""; 3528 } 3529 3530 // Check for images 3531 if (para.getElementsByTagName("img").length > 0) 3532 return false; 3533 3534 // Check for tables 3535 if (para.getElementsByTagName("table").length > 0) 3536 return false; 3537 3538 // Check for HRs 3539 if (para.getElementsByTagName("hr").length > 0) 3540 return false; 3541 3542 // Check all textnodes 3543 var nodes = tinyMCE.getNodeTree(para, new Array(), 3); 3544 for (var i=0; i<nodes.length; i++) { 3545 if (!isEmptyHTML(nodes[i].nodeValue)) 3546 return false; 3547 } 3548 3549 // No images, no tables, no hrs, no text content then it's empty 3550 return true; 3551 } 3552 3553 var doc = this.getDoc(); 3554 var sel = this.getSel(); 3555 var win = this.contentWindow; 3556 var rng = sel.getRangeAt(0); 3557 var body = doc.body; 3558 var rootElm = doc.documentElement; 3559 var self = this; 3560 var blockName = "P"; 3561 3562 // debug(e.target, sel.anchorNode.nodeName, sel.focusNode.nodeName, rng.startContainer, rng.endContainer, rng.commonAncestorContainer, sel.anchorOffset, sel.focusOffset, rng.toString()); 3563 3564 // Setup before range 3565 var rngBefore = doc.createRange(); 3566 rngBefore.setStart(sel.anchorNode, sel.anchorOffset); 3567 rngBefore.collapse(true); 3568 3569 // Setup after range 3570 var rngAfter = doc.createRange(); 3571 rngAfter.setStart(sel.focusNode, sel.focusOffset); 3572 rngAfter.collapse(true); 3573 3574 // Setup start/end points 3575 var direct = rngBefore.compareBoundaryPoints(rngBefore.START_TO_END, rngAfter) < 0; 3576 var startNode = direct ? sel.anchorNode : sel.focusNode; 3577 var startOffset = direct ? sel.anchorOffset : sel.focusOffset; 3578 var endNode = direct ? sel.focusNode : sel.anchorNode; 3579 var endOffset = direct ? sel.focusOffset : sel.anchorOffset; 3580 3581 // Get block elements 3582 var startBlock = tinyMCE.getParentBlockElement(startNode); 3583 var endBlock = tinyMCE.getParentBlockElement(endNode); 3584 3585 // Use current block name 3586 if (startBlock != null) { 3587 blockName = startBlock.nodeName.toUpperCase(); 3588 3589 // Use P instead 3590 if (blockName == "TD" || blockName == "TABLE") 3591 blockName = "P"; 3592 } 3593 3594 // Within a list item (use normal behavior) 3595 if ((startBlock != null && startBlock.nodeName.toLowerCase() == "li") || (endBlock != null && endBlock.nodeName.toLowerCase() == "li")) 3596 return false; 3597 3598 // Within a table create new paragraphs 3599 if ((startBlock != null && startBlock.nodeName.toLowerCase() == "table") || (endBlock != null && endBlock.nodeName.toLowerCase() == "table")) 3600 startBlock = endBlock = null; 3601 3602 // Setup new paragraphs 3603 var paraBefore = (startBlock != null && startBlock.nodeName.toUpperCase() == blockName) ? startBlock.cloneNode(false) : doc.createElement(blockName); 3604 var paraAfter = (endBlock != null && endBlock.nodeName.toUpperCase() == blockName) ? endBlock.cloneNode(false) : doc.createElement(blockName); 3605 3606 // Setup chop nodes 3607 var startChop = startNode; 3608 var endChop = endNode; 3609 3610 // Get startChop node 3611 node = startChop; 3612 do { 3613 if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node)) 3614 break; 3615 3616 startChop = node; 3617 } while ((node = node.previousSibling ? node.previousSibling : node.parentNode)); 3618 3619 // Get endChop node 3620 node = endChop; 3621 do { 3622 if (node == body || node.nodeType == 9 || tinyMCE.isBlockElement(node)) 3623 break; 3624 3625 endChop = node; 3626 } while ((node = node.nextSibling ? node.nextSibling : node.parentNode)); 3627 3628 // If not in a block element 3629 if (startBlock == null) { 3630 // Delete selection 3631 rng.deleteContents(); 3632 sel.removeAllRanges(); 3633 3634 if (startChop != rootElm && endChop != rootElm) { 3635 // Insert paragraph before 3636 rngBefore = rng.cloneRange(); 3637 3638 if (startChop == body) 3639 rngBefore.setStart(startChop, 0); 3640 else 3641 rngBefore.setStartBefore(startChop); 3642 3643 paraBefore.appendChild(rngBefore.cloneContents()); 3644 3645 // Insert paragraph after 3646 if (endChop.parentNode.nodeName == blockName) 3647 endChop = endChop.parentNode; 3648 3649 rng.setEndAfter(endChop); 3650 3651 var contents = rng.cloneContents(); 3652 if (contents.firstChild && (contents.firstChild.nodeName == blockName || contents.firstChild.nodeName.toLowerCase() == "body")) { 3653 var nodes = contents.firstChild.childNodes; 3654 for (var i=0; i<nodes.length; i++) { 3655 if (nodes[i].nodeName.toLowerCase() != "body") 3656 paraAfter.appendChild(nodes[i]); 3657 } 3658 } else 3659 paraAfter.appendChild(contents); 3660 3661 // Check if it's a empty paragraph 3662 if (isEmpty(paraBefore)) 3663 paraBefore.innerHTML = " "; 3664 3665 // Check if it's a empty paragraph 3666 if (isEmpty(paraAfter)) 3667 paraAfter.innerHTML = " "; 3668 3669 // Delete old contents 3670 rng.deleteContents(); 3671 rngAfter.deleteContents(); 3672 rngBefore.deleteContents(); 3673 3674 // Insert new paragraphs 3675 paraAfter.normalize(); 3676 rngBefore.insertNode(paraAfter); 3677 paraBefore.normalize(); 3678 rngBefore.insertNode(paraBefore); 3679 3680 // debug("1: ", paraBefore.innerHTML, paraAfter.innerHTML); 3681 } else { 3682 body.innerHTML = "<" + blockName + "> </" + blockName + "><" + blockName + "> </" + blockName + ">"; 3683 paraAfter = body.childNodes[1]; 3684 } 3685 3686 this.selectNode(paraAfter, true, true); 3687 3688 return true; 3689 } 3690 3691 // Place first part within new paragraph 3692 if (startChop.nodeName == blockName) 3693 rngBefore.setStart(startChop, 0); 3694 else 3695 rngBefore.setStartBefore(startChop); 3696 rngBefore.setEnd(startNode, startOffset); 3697 paraBefore.appendChild(rngBefore.cloneContents()); 3698 3699 // Place secound part within new paragraph 3700 rngAfter.setEndAfter(endChop); 3701 rngAfter.setStart(endNode, endOffset); 3702 var contents = rngAfter.cloneContents(); 3703 if (contents.firstChild && contents.firstChild.nodeName == blockName) { 3704 var nodes = contents.firstChild.childNodes; 3705 for (var i=0; i<nodes.length; i++) { 3706 if (nodes[i].nodeName.toLowerCase() != "body") 3707 paraAfter.appendChild(nodes[i]); 3708 } 3709 } else 3710 paraAfter.appendChild(contents); 3711 3712 // Check if it's a empty paragraph 3713 if (isEmpty(paraBefore)) 3714 paraBefore.innerHTML = " "; 3715 3716 // Check if it's a empty paragraph 3717 if (isEmpty(paraAfter)) 3718 paraAfter.innerHTML = " "; 3719 3720 // Create a range around everything 3721 var rng = doc.createRange(); 3722 3723 if (!startChop.previousSibling && startChop.parentNode.nodeName.toUpperCase() == blockName) { 3724 rng.setStartBefore(startChop.parentNode); 3725 } else { 3726 if (rngBefore.startContainer.nodeName.toUpperCase() == blockName && rngBefore.startOffset == 0) 3727 rng.setStartBefore(rngBefore.startContainer); 3728 else 3729 rng.setStart(rngBefore.startContainer, rngBefore.startOffset); 3730 } 3731 3732 if (!endChop.nextSibling && endChop.parentNode.nodeName.toUpperCase() == blockName) 3733 rng.setEndAfter(endChop.parentNode); 3734 else 3735 rng.setEnd(rngAfter.endContainer, rngAfter.endOffset); 3736 3737 // Delete all contents and insert new paragraphs 3738 rng.deleteContents(); 3739 rng.insertNode(paraAfter); 3740 rng.insertNode(paraBefore); 3741 // debug("2", paraBefore.innerHTML, paraAfter.innerHTML); 3742 3743 // Normalize 3744 paraAfter.normalize(); 3745 paraBefore.normalize(); 3746 3747 this.selectNode(paraAfter, true, true); 3748 3749 return true; 3750 }; 3751 3752 TinyMCEControl.prototype._handleBackSpace = function(evt_type) { 3753 var doc = this.getDoc(); 3754 var sel = this.getSel(); 3755 if (sel == null) 3756 return false; 3757 3758 var rng = sel.getRangeAt(0); 3759 var node = rng.startContainer; 3760 var elm = node.nodeType == 3 ? node.parentNode : node; 3761 3762 if (node == null) 3763 return; 3764 3765 // Empty node, wrap contents in paragraph 3766 if (elm && elm.nodeName == "") { 3767 var para = doc.createElement("p"); 3768 3769 while (elm.firstChild) 3770 para.appendChild(elm.firstChild); 3771 3772 elm.parentNode.insertBefore(para, elm); 3773 elm.parentNode.removeChild(elm); 3774 3775 var rng = rng.cloneRange(); 3776 rng.setStartBefore(node.nextSibling); 3777 rng.setEndAfter(node.nextSibling); 3778 rng.extractContents(); 3779 3780 this.selectNode(node.nextSibling, true, true); 3781 } 3782 3783 // Remove empty paragraphs 3784 var para = tinyMCE.getParentBlockElement(node); 3785 if (para != null && para.nodeName.toLowerCase() == 'p' && evt_type == "keypress") { 3786 var htm = para.innerHTML; 3787 var block = tinyMCE.getParentBlockElement(node); 3788 3789 // Empty node, we do the killing!! 3790 if (htm == "" || htm == " " || block.nodeName.toLowerCase() == "li") { 3791 var prevElm = para.previousSibling; 3792 3793 while (prevElm != null && prevElm.nodeType != 1) 3794 prevElm = prevElm.previousSibling; 3795 3796 if (prevElm == null) 3797 return false; 3798 3799 // Get previous elements last text node 3800 var nodes = tinyMCE.getNodeTree(prevElm, new Array(), 3); 3801 var lastTextNode = nodes.length == 0 ? null : nodes[nodes.length-1]; 3802 3803 // Select the last text node and move curstor to end 3804 if (lastTextNode != null) 3805 this.selectNode(lastTextNode, true, false, false); 3806 3807 // Remove the empty paragrapsh 3808 para.parentNode.removeChild(para); 3809 3810 //debug("within p element" + para.innerHTML); 3811 //showHTML(this.getBody().innerHTML); 3812 return true; 3813 } 3814 } 3815 3816 // Remove BR elements 3817 /* while (node != null && (node = node.nextSibling) != null) { 3818 if (node.nodeName.toLowerCase() == 'br') 3819 node.parentNode.removeChild(node); 3820 else if (node.nodeType == 1) // Break at other element 3821 break; 3822 }*/ 3823 3824 //showHTML(this.getBody().innerHTML); 3825 3826 return false; 3827 }; 3828 3829 TinyMCEControl.prototype._insertSpace = function() { 3830 return true; 3831 }; 3832 3833 TinyMCEControl.prototype.autoResetDesignMode = function() { 3834 // Add fix for tab/style.display none/block problems in Gecko 3835 if (!tinyMCE.isMSIE && tinyMCE.settings['auto_reset_designmode']) { 3836 var sel = this.getSel(); 3837 3838 // Weird, wheres that cursor selection? 3839 if (!sel || !sel.rangeCount || sel.rangeCount == 0) 3840 eval('try { this.getDoc().designMode = "On"; } catch(e) {}'); 3841 } 3842 }; 3843 3844 TinyMCEControl.prototype.isDirty = function() { 3845 return this.isDirty; 3846 }; 3847 3848 TinyMCEControl.prototype.execCommand = function(command, user_interface, value) { 3849 var doc = this.getDoc(); 3850 var win = this.getWin(); 3851 3852 // Mozilla issue 3853 if (!tinyMCE.isMSIE && !this.useCSS) { 3854 doc.execCommand("useCSS", false, true); 3855 this.useCSS = true; 3856 } 3857 3858 //debug("command: " + command + ", user_interface: " + user_interface + ", value: " + value); 3859 this.contentDocument = doc; // <-- Strange, unless this is applied Mozilla 1.3 breaks 3860 3861 // Call theme execcommand 3862 if (tinyMCE._themeExecCommand(this.editorId, this.getBody(), command, user_interface, value)) 3863 return; 3864 3865 // Add undo level of operation 3866 if (command != "mceAddUndoLevel" && command != "Undo" && command != "Redo" && command != "mceImage" && command != "mceLink" && command != "mceToggleVisualAid" && (command != "mceInsertTable" && !user_interface)) 3867 this.execCommand("mceAddUndoLevel"); 3868 3869 // Fix align on images 3870 if (this.getFocusElement() && this.getFocusElement().nodeName.toLowerCase() == "img") { 3871 var align = this.getFocusElement().getAttribute('align'); 3872 3873 switch (command) { 3874 case "JustifyLeft": 3875 if (align == 'left') 3876 this.getFocusElement().removeAttribute('align'); 3877 else 3878 this.getFocusElement().setAttribute('align', 'left'); 3879 3880 tinyMCE.triggerNodeChange(); 3881 return; 3882 3883 case "JustifyCenter": 3884 if (align == 'middle') 3885 this.getFocusElement().removeAttribute('align'); 3886 else 3887 this.getFocusElement().setAttribute('align', 'middle'); 3888 3889 tinyMCE.triggerNodeChange(); 3890 return; 3891 3892 case "JustifyRight": 3893 if (align == 'right') 3894 this.getFocusElement().removeAttribute('align'); 3895 else 3896 this.getFocusElement().setAttribute('align', 'right'); 3897 3898 tinyMCE.triggerNodeChange(); 3899 return; 3900 } 3901 } 3902 3903 if (tinyMCE.settings['force_br_newlines']) { 3904 var alignValue = ""; 3905 3906 if (doc.selection.type != "Control") { 3907 switch (command) { 3908 case "JustifyLeft": 3909 alignValue = "left"; 3910 break; 3911 3912 case "JustifyCenter": 3913 alignValue = "center"; 3914 break; 3915 3916 case "JustifyFull": 3917 alignValue = "justify"; 3918 break; 3919 3920 case "JustifyRight": 3921 alignValue = "right"; 3922 break; 3923 } 3924 3925 if (alignValue != "") { 3926 var rng = doc.selection.createRange(); 3927 3928 if ((divElm = tinyMCE.getParentElement(rng.parentElement(), "div")) != null) 3929 divElm.setAttribute("align", alignValue); 3930 else if (rng.pasteHTML && rng.htmlText.length > 0) 3931 rng.pasteHTML('<div align="' + alignValue + '">' + rng.htmlText + "</div>"); 3932 3933 tinyMCE.triggerNodeChange(); 3934 return; 3935 } 3936 } 3937 } 3938 3939 switch (command) { 3940 case "mceSelectNode": 3941 this.selectNode(value); 3942 tinyMCE.triggerNodeChange(); 3943 tinyMCE.selectedNode = value; 3944 break; 3945 3946 case "mceSelectNodeDepth": 3947 var parentNode = this.getFocusElement(); 3948 for (var i=0; parentNode; i++) { 3949 if (parentNode.nodeName.toLowerCase() == "body") 3950 break; 3951 3952 if (parentNode.nodeName.toLowerCase() == "#text") { 3953 i--; 3954 parentNode = parentNode.parentNode; 3955 continue; 3956 } 3957 3958 if (i == value) { 3959 this.selectNode(parentNode, false); 3960 tinyMCE.triggerNodeChange(); 3961 tinyMCE.selectedNode = parentNode; 3962 return; 3963 } 3964 3965 parentNode = parentNode.parentNode; 3966 } 3967 3968 break; 3969 3970 case "HiliteColor": 3971 if (tinyMCE.isGecko) { 3972 this.getDoc().execCommand("useCSS", false, false); 3973 this.getDoc().execCommand('hilitecolor', false, value); 3974 this.getDoc().execCommand("useCSS", false, true); 3975 } else 3976 this.getDoc().execCommand('BackColor', false, value); 3977 3978 break; 3979 3980 case "Cut": 3981 case "Copy": 3982 case "Paste": 3983 var cmdFailed = false; 3984 3985 // Try executing command 3986 eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}'); 3987 3988 // Alert error in gecko if command failed 3989 if (tinyMCE.isGecko && cmdFailed) { 3990 // Confirm more info 3991 if (confirm(tinyMCE.getLang('lang_clipboard_msg'))) 3992 window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal'); 3993 3994 return; 3995 } else 3996 tinyMCE.triggerNodeChange(); 3997 break; 3998 3999 case "mceSetContent": 4000 if (!value) 4001 value = ""; 4002 4003 // Call custom cleanup code 4004 html_content = tinyMCE._customCleanup("insert_to_editor", value); 4005 tinyMCE._setHTML(doc, value); 4006 doc.body.innerHTML = tinyMCE._cleanupHTML(doc, tinyMCE.settings, doc.body); 4007 tinyMCE.handleVisualAid(doc.body, true, this.visualAid); 4008 return true; 4009 4010 case "mceLink": 4011 var selectedText = ""; 4012 4013 if (tinyMCE.isMSIE) { 4014 var rng = doc.selection.createRange(); 4015 selectedText = rng.text; 4016 } else 4017 selectedText = this.getSel().toString(); 4018 4019 if (!tinyMCE.linkElement) { 4020 if ((tinyMCE.selectedElement.nodeName.toLowerCase() != "img") && (selectedText.length <= 0)) 4021 return; 4022 } 4023 4024 var href = "", target = "", title = "", onclick = "", action = "insert"; 4025 4026 if (tinyMCE.selectedElement.nodeName.toLowerCase() == "a") 4027 tinyMCE.linkElement = tinyMCE.selectedElement; 4028 4029 // Is anchor not a link 4030 if (tinyMCE.linkElement != null && tinyMCE.getAttrib(tinyMCE.linkElement, 'href') == "") 4031 tinyMCE.linkElement = null; 4032 4033 if (tinyMCE.linkElement) { 4034 href = tinyMCE.getAttrib(tinyMCE.linkElement, 'href'); 4035 target = tinyMCE.getAttrib(tinyMCE.linkElement, 'target'); 4036 title = tinyMCE.getAttrib(tinyMCE.linkElement, 'title'); 4037 onclick = tinyMCE.getAttrib(tinyMCE.linkElement, 'mce_onclick'); 4038 4039 // Try old onclick to if copy/pasted content 4040 if (onclick == "") 4041 onclick = tinyMCE.getAttrib(tinyMCE.linkElement, 'onclick'); 4042 4043 onclick = tinyMCE.cleanupEventStr(onclick); 4044 4045 // Fix for drag-drop/copy paste bug in Mozilla 4046 mceRealHref = tinyMCE.getAttrib(tinyMCE.linkElement, 'mce_real_href'); 4047 if (mceRealHref != "") 4048 href = mceRealHref; 4049 4050 href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);"); 4051 action = "update"; 4052 } 4053 4054 if (this.settings['insertlink_callback']) { 4055 var returnVal = eval(this.settings['insertlink_callback'] + "(href, target, title, onclick, action);"); 4056 if (returnVal && returnVal['href']) 4057 tinyMCE.insertLink(returnVal['href'], returnVal['target'], returnVal['title'], returnVal['onclick']); 4058 } else { 4059 tinyMCE.openWindow(this.insertLinkTemplate, {href : href, target : target, title : title, onclick : onclick, action : action}); 4060 } 4061 break; 4062 4063 case "mceImage": 4064 var src = "", alt = "", border = "", hspace = "", vspace = "", width = "", height = "", align = ""; 4065 var title = "", onmouseover = "", onmouseout = "", action = "insert"; 4066 var img = tinyMCE.imgElement; 4067 4068 if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") { 4069 img = tinyMCE.selectedElement; 4070 tinyMCE.imgElement = img; 4071 } 4072 4073 if (img) { 4074 // Is it a internal MCE visual aid image, then skip this one. 4075 if (tinyMCE.getAttrib(img, 'name').indexOf('mce_') == 0) 4076 return; 4077 4078 src = tinyMCE.getAttrib(img, 'src'); 4079 alt = tinyMCE.getAttrib(img, 'alt'); 4080 4081 // Try polling out the title 4082 if (alt == "") 4083 alt = tinyMCE.getAttrib(img, 'title'); 4084 4085 // Fix width/height attributes if the styles is specified 4086 if (tinyMCE.isGecko) { 4087 var w = img.style.width; 4088 if (w != null && w != "") 4089 img.setAttribute("width", w); 4090 4091 var h = img.style.height; 4092 if (h != null && h != "") 4093 img.setAttribute("height", h); 4094 } 4095 4096 border = tinyMCE.getAttrib(img, 'border'); 4097 hspace = tinyMCE.getAttrib(img, 'hspace'); 4098 vspace = tinyMCE.getAttrib(img, 'vspace'); 4099 width = tinyMCE.getAttrib(img, 'width'); 4100 height = tinyMCE.getAttrib(img, 'height'); 4101 align = tinyMCE.getAttrib(img, 'align'); 4102 onmouseover = tinyMCE.getAttrib(img, 'onmouseover'); 4103 onmouseout = tinyMCE.getAttrib(img, 'onmouseout'); 4104 title = tinyMCE.getAttrib(img, 'title'); 4105 4106 // Is realy specified? 4107 if (tinyMCE.isMSIE) { 4108 width = img.attributes['width'].specified ? width : ""; 4109 height = img.attributes['height'].specified ? height : ""; 4110 } 4111 4112 onmouseover = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseover)); 4113 onmouseout = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseout)); 4114 4115 // Fix for drag-drop/copy paste bug in Mozilla 4116 mceRealSrc = tinyMCE.getAttrib(img, 'mce_real_src'); 4117 if (mceRealSrc != "") 4118 src = mceRealSrc; 4119 4120 src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);"); 4121 4122 if (onmouseover != "") 4123 onmouseover = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, img, true);"); 4124 4125 if (onmouseout != "") 4126 onmouseout = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseout, img, true);"); 4127 4128 action = "update"; 4129 } 4130 4131 if (this.settings['insertimage_callback']) { 4132 var returnVal = eval(this.settings['insertimage_callback'] + "(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout, action);"); 4133 if (returnVal && returnVal['src']) 4134 tinyMCE.insertImage(returnVal['src'], returnVal['alt'], returnVal['border'], returnVal['hspace'], returnVal['vspace'], returnVal['width'], returnVal['height'], returnVal['align'], returnVal['title'], returnVal['onmouseover'], returnVal['onmouseout']); 4135 } else 4136 tinyMCE.openWindow(this.insertImageTemplate, {src : src, alt : alt, border : border, hspace : hspace, vspace : vspace, width : width, height : height, align : align, title : title, onmouseover : onmouseover, onmouseout : onmouseout, action : action}); 4137 break; 4138 4139 case "mceCleanupWord": 4140 if (tinyMCE.isMSIE) { 4141 var html = this.getBody().createTextRange().htmlText; 4142 4143 if (html.indexOf('="mso') != -1) { 4144 tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML); 4145 html = tinyMCE._cleanupHTML(this.contentDocument, this.settings, this.getBody(), this.visualAid); 4146 } 4147 4148 this.getBody().innerHTML = html; 4149 } 4150 break; 4151 4152 case "mceCleanup": 4153 tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML); 4154 this.getBody().innerHTML = tinyMCE._cleanupHTML(this.contentDocument, this.settings, this.getBody(), this.visualAid); 4155 tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid); 4156 this.repaint(); 4157 tinyMCE.triggerNodeChange(); 4158 break; 4159 4160 case "mceAnchor": 4161 if (!user_interface) { 4162 var aElm = tinyMCE.getParentElement(this.getFocusElement(), "a", "name"); 4163 if (aElm) { 4164 if (value == null || value == "") { 4165 if (tinyMCE.isMSIE) { 4166 aElm.outerHTML = aElm.innerHTML; 4167 } else { 4168 var rng = aElm.ownerDocument.createRange(); 4169 rng.setStartBefore(aElm); 4170 rng.setEndAfter(aElm); 4171 rng.deleteContents(); 4172 rng.insertNode(rng.createContextualFragment(aElm.innerHTML)); 4173 } 4174 } else 4175 aElm.setAttribute('name', value); 4176 } else { 4177 this.getDoc().execCommand("fontname", false, "#mce_temp_font#"); 4178 var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#"); 4179 for (var x=0; x<elementArray.length; x++) { 4180 elm = elementArray[x]; 4181 4182 var aElm = this.getDoc().createElement("a"); 4183 aElm.setAttribute('name', value); 4184 4185 if (elm.hasChildNodes()) { 4186 for (var i=0; i<elm.childNodes.length; i++) 4187 aElm.appendChild(elm.childNodes[i].cloneNode(true)); 4188 } 4189 4190 elm.parentNode.replaceChild(aElm, elm); 4191 } 4192 } 4193 4194 tinyMCE.triggerNodeChange(); 4195 } 4196 break; 4197 4198 case "mceReplaceContent": 4199 var selectedText = ""; 4200 4201 if (tinyMCE.isMSIE) { 4202 var rng = doc.selection.createRange(); 4203 selectedText = rng.text; 4204 } else 4205 selectedText = this.getSel().toString(); 4206 4207 if (selectedText.length > 0) { 4208 value = tinyMCE.replaceVar(value, "selection", selectedText); 4209 tinyMCE.execCommand('mceInsertContent',false,value); 4210 } 4211 4212 tinyMCE.triggerNodeChange(); 4213 break; 4214 4215 case "mceSetAttribute": 4216 if (typeof(value) == 'object') { 4217 var targetElms = (typeof(value['targets']) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value['targets']; 4218 var targetNode = tinyMCE.getParentElement(this.getFocusElement(), targetElms); 4219 4220 if (targetNode) { 4221 targetNode.setAttribute(value['name'], value['value']); 4222 tinyMCE.triggerNodeChange(); 4223 } 4224 } 4225 break; 4226 4227 case "mceSetCSSClass": 4228 var selectedText = false; 4229 4230 if (tinyMCE.isMSIE) { 4231 var rng = doc.selection.createRange(); 4232 selectedText = (rng.text && rng.text.length > 0); 4233 } else 4234 selectedText = (this.getSel().toString().length > 0); 4235 4236 // Use selectedNode instead if defined 4237 if (tinyMCE.selectedNode) 4238 tinyMCE.selectedElement = tinyMCE.selectedNode; 4239 4240 if (selectedText && !tinyMCE.selectedNode) { 4241 this.getDoc().execCommand("RemoveFormat", false, null); 4242 if (value == null) 4243 return this.execCommand("RemoveFormat", false, null); 4244 4245 this.getDoc().execCommand("fontname", false, "#mce_temp_font#"); 4246 var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#"); 4247 4248 // Change them all 4249 for (var x=0; x<elementArray.length; x++) { 4250 elm = elementArray[x]; 4251 if (elm) { 4252 var spanElm = this.getDoc().createElement("span"); 4253 spanElm.className = value; 4254 if (elm.hasChildNodes()) { 4255 for (var i=0; i<elm.childNodes.length; i++) 4256 spanElm.appendChild(elm.childNodes[i].cloneNode(true)); 4257 } 4258 4259 elm.parentNode.replaceChild(spanElm, elm); 4260 } 4261 } 4262 } else { 4263 var targetElm = this.getFocusElement(); 4264 4265 // Select element 4266 if (tinyMCE.selectedElement.nodeName.toLowerCase() == "img" || tinyMCE.selectedElement.nodeName.toLowerCase() == "table") 4267 targetElm = tinyMCE.selectedElement; 4268 4269 var targetNode = tinyMCE.getParentElement(targetElm, "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address"); 4270 4271 // Selected element 4272 if (tinyMCE.selectedElement.nodeType == 1) 4273 targetNode = tinyMCE.selectedElement; 4274 4275 // Mozilla img patch 4276 if (!tinyMCE.isMSIE && !targetNode) 4277 targetNode = tinyMCE.imgElement; 4278 4279 if (targetNode) { 4280 if (targetNode.nodeName.toLowerCase() == "span" && (!value || value == "")) { 4281 if (targetNode.hasChildNodes()) { 4282 for (var i=0; i<targetNode.childNodes.length; i++) 4283 targetNode.parentNode.insertBefore(targetNode.childNodes[i].cloneNode(true), targetNode); 4284 } 4285 4286 targetNode.parentNode.removeChild(targetNode); 4287 } else { 4288 if (value != null && value != "") 4289 targetNode.className = value; 4290 else { 4291 targetNode.removeAttribute("className"); 4292 targetNode.removeAttribute("class"); 4293 } 4294 } 4295 } 4296 } 4297 4298 tinyMCE.triggerNodeChange(); 4299 break; 4300 4301 case "mceInsertRawHTML": 4302 var key = 'tiny_mce_marker'; 4303 4304 // Insert marker key 4305 this.execCommand('mceInsertContent', false, key); 4306 4307 // Find marker and replace with RAW HTML 4308 var html = this.getBody().innerHTML; 4309 if ((pos = html.indexOf(key)) != -1) 4310 this.getBody().innerHTML = html.substring(0, pos) + value + html.substring(pos + key.length); 4311 4312 break; 4313 4314 case "mceInsertContent": 4315 if (!tinyMCE.isMSIE) { 4316 var sel = this.getSel(); 4317 var rng = sel.getRangeAt(0); 4318 var isHTML = value.indexOf('<') != -1; 4319 4320 if (isHTML) 4321 value = rng.createContextualFragment(value); 4322 else { 4323 // Setup text node 4324 var el = document.createElement("div"); 4325 el.innerHTML = value; 4326 value = el.firstChild.nodeValue; 4327 value = doc.createTextNode(value); 4328 } 4329 4330 // Insert plain text in Safari 4331 if (tinyMCE.isSafari && !isHTML) { 4332 this.execCommand('InsertText', false, value.nodeValue); 4333 tinyMCE.triggerNodeChange(); 4334 return true; 4335 } 4336 4337 rng.deleteContents(); 4338 4339 // If target node is text do special treatment, (Mozilla 1.3 fix) 4340 if (rng.startContainer.nodeType == 3) { 4341 var node = rng.startContainer.splitText(rng.startOffset); 4342 node.parentNode.insertBefore(value, node); 4343 } else 4344 rng.insertNode(value); 4345 4346 if (!isHTML) { 4347 // Removes weird selection trails 4348 sel.selectAllChildren(doc.body); 4349 sel.removeAllRanges(); 4350 4351 // Move cursor to end of content 4352 var rng = doc.createRange(); 4353 4354 rng.selectNode(value); 4355 rng.collapse(false); 4356 4357 sel.addRange(rng); 4358 } else 4359 rng.collapse(false); 4360 } else { 4361 var rng = doc.selection.createRange(); 4362 4363 if (rng.item) 4364 rng.item(0).outerHTML = value; 4365 else 4366 rng.pasteHTML(value); 4367 } 4368 4369 tinyMCE.triggerNodeChange(); 4370 break; 4371 4372 case "mceAddUndoLevel": 4373 if (tinyMCE.settings['custom_undo_redo']) { 4374 var customUndoLevels = tinyMCE.settings['custom_undo_redo_levels']; 4375 4376 var newHTML = this.getBody().innerHTML; 4377 //debug("x: " + newHTML, this.undoLevels[this.undoLevels.length-1] + "\n"); 4378 if (newHTML != this.undoLevels[this.undoLevels.length-1]) { 4379 // debug(newHTML, this.undoLevels[this.undoLevels.length-1]); 4380 // Trigger onchange and set is dirty 4381 tinyMCE.executeCallback('onchange_callback', '_onchange', 0, this); 4382 this.isDirty = true; 4383 4384 // Time to compress 4385 if (customUndoLevels != -1 && this.undoLevels.length > customUndoLevels) { 4386 for (var i=0; i<this.undoLevels.length-1; i++) { 4387 //alert(this.undoLevels[i] + "=" + this.undoLevels[i+1]); 4388 this.undoLevels[i] = this.undoLevels[i+1]; 4389 } 4390 4391 this.undoLevels.length--; 4392 this.undoIndex--; 4393 } 4394 4395 //alert(newHTML + "=" + this.undoLevels[this.undoIndex]); 4396 // Add new level 4397 this.undoLevels[this.undoIndex++] = newHTML; 4398 this.undoLevels.length = this.undoIndex; 4399 // debug("mceAddUndoLevel - undo levels:" + this.undoLevels.length + ", undo index: " + this.undoIndex); 4400 //window.status = "mceAddUndoLevel - undo levels:" + this.undoLevels.length + ", undo index: " + this.undoIndex; 4401 } 4402 4403 tinyMCE.triggerNodeChange(false); 4404 } 4405 break; 4406 4407 case "Undo": 4408 if (tinyMCE.settings['custom_undo_redo']) { 4409 // Is first level 4410 if (this.undoIndex == this.undoLevels.length) { 4411 this.execCommand("mceAddUndoLevel"); 4412 this.undoIndex--; 4413 } 4414 4415 // Do undo 4416 if (this.undoIndex > 0) { 4417 this.undoIndex--; 4418 this.getBody().innerHTML = this.undoLevels[this.undoIndex]; 4419 } 4420 4421 // debug("Undo - undo levels:" + this.undoLevels.length + ", undo index: " + this.undoIndex); 4422 tinyMCE.triggerNodeChange(); 4423 } else 4424 this.getDoc().execCommand(command, user_interface, value); 4425 break; 4426 4427 case "Redo": 4428 if (tinyMCE.settings['custom_undo_redo']) { 4429 if (this.undoIndex < (this.undoLevels.length-1)) { 4430 this.undoIndex++; 4431 this.getBody().innerHTML = this.undoLevels[this.undoIndex]; 4432 // debug("Redo - undo levels:" + this.undoLevels.length + ", undo index: " + this.undoIndex); 4433 } 4434 4435 tinyMCE.triggerNodeChange(); 4436 } else 4437 this.getDoc().execCommand(command, user_interface, value); 4438 break; 4439 4440 case "mceToggleVisualAid": 4441 this.visualAid = !this.visualAid; 4442 tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid); 4443 tinyMCE.triggerNodeChange(); 4444 break; 4445 4446 case "removeformat": 4447 var text = this.getSelectedText(); 4448 4449 if (tinyMCE.isMSIE) { 4450 try { 4451 win.focus(); 4452 var rng = doc.selection.createRange(); 4453 rng.execCommand("RemoveFormat", false, null); 4454 rng.pasteHTML(rng.text); 4455 } catch (e) { 4456 // Do nothing 4457 } 4458 } else 4459 this.getDoc().execCommand(command, user_interface, value); 4460 4461 // Remove class 4462 if (text.length == 0) 4463 this.execCommand("mceSetCSSClass", false, ""); 4464 4465 tinyMCE.triggerNodeChange(); 4466 break; 4467 4468 default: 4469 this.getDoc().execCommand(command, user_interface, value); 4470 tinyMCE.triggerNodeChange(); 4471 } 4472 }; 4473 4474 TinyMCEControl.prototype.queryCommandValue = function(command) { 4475 return this.getDoc().queryCommandValue(command); 4476 }; 4477 4478 TinyMCEControl.prototype.queryCommandState = function(command) { 4479 return this.getDoc().queryCommandState(command); 4480 }; 4481 4482 TinyMCEControl.prototype.onAdd = function(replace_element, form_element_name, target_document) { 4483 var targetDoc = target_document ? target_document : document; 4484 4485 this.targetDoc = targetDoc; 4486 4487 tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings['theme']; 4488 this.settings['themeurl'] = tinyMCE.themeURL; 4489 4490 if (!replace_element) { 4491 alert("Error: Could not find the target element."); 4492 return false; 4493 } 4494 4495 var templateFunction = tinyMCE._getThemeFunction('_getInsertLinkTemplate'); 4496 if (eval("typeof(" + templateFunction + ")") != 'undefined') 4497 this.insertLinkTemplate = eval(templateFunction + '(this.settings);'); 4498 4499 var templateFunction = tinyMCE._getThemeFunction('_getInsertImageTemplate'); 4500 if (eval("typeof(" + templateFunction + ")") != 'undefined') 4501 this.insertImageTemplate = eval(templateFunction + '(this.settings);'); 4502 4503 var templateFunction = tinyMCE._getThemeFunction('_getEditorTemplate'); 4504 if (eval("typeof(" + templateFunction + ")") == 'undefined') { 4505 alert("Error: Could not find the template function: " + templateFunction); 4506 return false; 4507 } 4508 4509 var editorTemplate = eval(templateFunction + '(this.settings, this.editorId);'); 4510 4511 var deltaWidth = editorTemplate['delta_width'] ? editorTemplate['delta_width'] : 0; 4512 var deltaHeight = editorTemplate['delta_height'] ? editorTemplate['delta_height'] : 0; 4513 var html = '<span id="' + this.editorId + '_parent">' + editorTemplate['html']; 4514 4515 var templateFunction = tinyMCE._getThemeFunction('_handleNodeChange', true); 4516 if (eval("typeof(" + templateFunction + ")") != 'undefined') 4517 this.settings['handleNodeChangeCallback'] = templateFunction; 4518 4519 html = tinyMCE.replaceVar(html, "editor_id", this.editorId); 4520 html = tinyMCE.replaceVar(html, "default_document", tinyMCE.baseURL + "/blank.htm"); 4521 this.settings['default_document'] = tinyMCE.baseURL + "/blank.htm"; 4522 4523 this.settings['old_width'] = this.settings['width']; 4524 this.settings['old_height'] = this.settings['height']; 4525 4526 // Set default width, height 4527 if (this.settings['width'] == -1) 4528 this.settings['width'] = replace_element.offsetWidth; 4529 4530 if (this.settings['height'] == -1) 4531 this.settings['height'] = replace_element.offsetHeight; 4532 4533 // Try the style width 4534 if (this.settings['width'] == 0) 4535 this.settings['width'] = replace_element.style.width; 4536 4537 // Try the style height 4538 if (this.settings['height'] == 0) 4539 this.settings['height'] = replace_element.style.height; 4540 4541 // If no width/height then default to 320x240, better than nothing 4542 if (this.settings['width'] == 0) 4543 this.settings['width'] = 320; 4544 4545 if (this.settings['height'] == 0) 4546 this.settings['height'] = 240; 4547 4548 this.settings['area_width'] = parseInt(this.settings['width']); 4549 this.settings['area_height'] = parseInt(this.settings['height']); 4550 this.settings['area_width'] += deltaWidth; 4551 this.settings['area_height'] += deltaHeight; 4552 4553 // Special % handling 4554 if (("" + this.settings['width']).indexOf('%') != -1) 4555 this.settings['area_width'] = "100%"; 4556 4557 if (("" + this.settings['height']).indexOf('%') != -1) 4558 this.settings['area_height'] = "100%"; 4559 4560 if (("" + replace_element.style.width).indexOf('%') != -1) { 4561 this.settings['width'] = replace_element.style.width; 4562 this.settings['area_width'] = "100%"; 4563 } 4564 4565 if (("" + replace_element.style.height).indexOf('%') != -1) { 4566 this.settings['height'] = replace_element.style.height; 4567 this.settings['area_height'] = "100%"; 4568 } 4569 4570 html = tinyMCE.applyTemplate(html); 4571 4572 this.settings['width'] = this.settings['old_width']; 4573 this.settings['height'] = this.settings['old_height']; 4574 4575 this.visualAid = this.settings['visual']; 4576 this.formTargetElementId = form_element_name; 4577 4578 // Get replace_element contents 4579 if (replace_element.nodeName.toLowerCase() == "textarea") 4580 this.startContent = replace_element.value; 4581 else 4582 this.startContent = replace_element.innerHTML; 4583 4584 // If not text area 4585 if (replace_element.nodeName.toLowerCase() != "textarea") { 4586 this.oldTargetElement = replace_element.cloneNode(true); 4587 4588 // Debug mode 4589 if (tinyMCE.settings['debug']) 4590 html += '<textarea wrap="off" id="' + form_element_name + '" name="' + form_element_name + '" cols="100" rows="15"></textarea>'; 4591 else 4592 html += '<input type="hidden" type="text" id="' + form_element_name + '" name="' + form_element_name + '" />'; 4593 4594 html += '</span>'; 4595 4596 // Output HTML and set editable 4597 if (!tinyMCE.isMSIE) { 4598 var rng = replace_element.ownerDocument.createRange(); 4599 rng.setStartBefore(replace_element); 4600 4601 var fragment = rng.createContextualFragment(html); 4602 replace_element.parentNode.replaceChild(fragment, replace_element); 4603 } else 4604 replace_element.outerHTML = html; 4605 } else { 4606 html += '</span>'; 4607 4608 // Just hide the textarea element 4609 this.oldTargetElement = replace_element; 4610 4611 if (!tinyMCE.settings['debug']) 4612 this.oldTargetElement.style.display = "none"; 4613 4614 // Output HTML and set editable 4615 if (!tinyMCE.isMSIE) { 4616 var rng = replace_element.ownerDocument.createRange(); 4617 rng.setStartBefore(replace_element); 4618 4619 var fragment = rng.createContextualFragment(html); 4620 replace_element.parentNode.insertBefore(fragment, replace_element); 4621 } else 4622 replace_element.insertAdjacentHTML("beforeBegin", html); 4623 } 4624 4625 // Setup iframe 4626 var dynamicIFrame = false; 4627 var tElm = targetDoc.getElementById(this.editorId); 4628 4629 if (!tinyMCE.isMSIE) { 4630 if (tElm && tElm.nodeName.toLowerCase() == "span") { 4631 tElm = tinyMCE._createIFrame(tElm); 4632 dynamicIFrame = true; 4633 } 4634 4635 this.targetElement = tElm; 4636 this.iframeElement = tElm; 4637 this.contentDocument = tElm.contentDocument; 4638 this.contentWindow = tElm.contentWindow; 4639 4640 //this.getDoc().designMode = "on"; 4641 } else { 4642 if (tElm && tElm.nodeName.toLowerCase() == "span") 4643 tElm = tinyMCE._createIFrame(tElm); 4644 else 4645 tElm = targetDoc.frames[this.editorId]; 4646 4647 this.targetElement = tElm; 4648 this.iframeElement = targetDoc.getElementById(this.editorId); 4649 this.contentDocument = tElm.window.document; 4650 this.contentWindow = tElm.window; 4651 this.getDoc().designMode = "on"; 4652 } 4653 4654 // Setup base HTML 4655 var doc = this.contentDocument; 4656 if (dynamicIFrame) { 4657 var html = "" 4658 + '<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">' 4659 + '<html>' 4660 + '<head>' 4661 + '<base href="' + tinyMCE.settings['base_href'] + '" />' 4662 + '<title>blank_page</title>' 4663 + '<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">' 4664 + '</head>' 4665 + '<body>' 4666 + '</body>' 4667 + '</html>'; 4668 4669 try { 4670 this.getDoc().designMode = "on"; 4671 doc.open(); 4672 doc.write(html); 4673 doc.close(); 4674 } catch (e) { 4675 // Failed Mozilla 1.3 4676 this.getDoc().location.href = tinyMCE.baseURL + "/blank.htm"; 4677 } 4678 } 4679 4680 // This timeout is needed in MSIE 5.5 for some odd reason 4681 // it seems that the document.frames isn't initialized yet? 4682 if (tinyMCE.isMSIE) 4683 window.setTimeout("TinyMCE.prototype.addEventHandlers('" + this.editorId + "');", 1); 4684 4685 tinyMCE.setupContent(this.editorId, true); 4686 4687 return true; 4688 }; 4689 4690 TinyMCEControl.prototype.getFocusElement = function() { 4691 if (tinyMCE.isMSIE) { 4692 var doc = this.getDoc(); 4693 var rng = doc.selection.createRange(); 4694 4695 if (rng.collapse) 4696 rng.collapse(true); 4697 4698 var elm = rng.item ? rng.item(0) : rng.parentElement(); 4699 } else { 4700 var sel = this.getSel(); 4701 var elm = (sel && sel.anchorNode) ? sel.anchorNode : null; 4702 4703 if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") 4704 elm = tinyMCE.selectedElement; 4705 } 4706 4707 return elm; 4708 }; 4709 4710 // Global instances 4711 var tinyMCE = new TinyMCE(); 4712 var tinyMCELang = new Array(); 4713 4714 function debug() { 4715 var msg = ""; 4716 4717 var elm = document.getElementById("tinymce_debug"); 4718 if (!elm) { 4719 var debugDiv = document.createElement("div"); 4720 debugDiv.setAttribute("className", "debugger"); 4721 debugDiv.className = "debugger"; 4722 debugDiv.innerHTML = '\ 4723 Debug output:\ 4724 <textarea id="tinymce_debug" style="width: 100%; height: 300px">\ 4725 </textarea>'; 4726 4727 document.body.appendChild(debugDiv); 4728 elm = document.getElementById("tinymce_debug"); 4729 } 4730 4731 var args = this.debug.arguments; 4732 for (var i=0; i<args.length; i++) { 4733 msg += args[i]; 4734 if (i<args.length-1) 4735 msg += ', '; 4736 } 4737 4738 elm.value += msg + "\n"; 4739 };
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Sun Feb 25 17:20:01 2007 | par Balluche grâce à PHPXref 0.7 |