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