/** * $RCSfile$ * $Revision$ * $Date$ * * @author Moxiecode * @copyright Copyright � 2004, Moxiecode Systems AB, All rights reserved. */ function TinyMCE() { this.instances = new Array(); this.stickyClassesLookup = new Array(); this.windowArgs = new Array(); this.loadedFiles = new Array(); this.configs = new Array(); this.currentConfig = 0; this.eventHandlers = new Array(); // Browser check this.isMSIE = (navigator.appName == "Microsoft Internet Explorer"); this.isMSIE5 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5') != -1); this.isMSIE5_0 = this.isMSIE && (navigator.userAgent.indexOf('MSIE 5.0') != -1); this.isGecko = navigator.userAgent.indexOf('Gecko') != -1; this.isSafari = navigator.userAgent.indexOf('Safari') != -1; if (this.isSafari) alert("Safari support is very limited and should be considered experimental.\nSo there is no need to even submit bugreports on this early version."); // TinyMCE editor id instance counter this.idCounter = 0; }; TinyMCE.prototype.defParam = function(key, def_val) { this.settings[key] = tinyMCE.getParam(key, def_val); }; TinyMCE.prototype.init = function(settings) { var theme; this.settings = settings; // Check if valid browser has execcommand support if (typeof(document.execCommand) == 'undefined') return; // Get script base path if (!tinyMCE.baseURL) { var elements = document.getElementsByTagName('script'); for (var i=0; i'); this.loadedFiles[this.loadedFiles.length] = url; }; TinyMCE.prototype.loadCSS = function(url) { for (var i=0; i'); this.loadedFiles[this.loadedFiles.length] = url; }; TinyMCE.prototype.importCSS = function(doc, css_file) { if (tinyMCE.isMSIE) var styleSheet = doc.createStyleSheet(css_file); else { var elm = doc.createElement("link"); elm.rel = "stylesheet"; elm.href = css_file; if (headArr = doc.getElementsByTagName("head")) headArr[0].appendChild(elm); } }; TinyMCE.prototype.confirmAdd = function(e, settings) { var elm = tinyMCE.isMSIE ? event.srcElement : e.target; var elementId = elm.name ? elm.name : elm.id; tinyMCE.settings = settings; if (!elm.getAttribute('mce_noask') && confirm(tinyMCELang['lang_edit_confirm'])) tinyMCE.addMCEControl(elm, elementId); elm.setAttribute('mce_noask', 'true'); }; TinyMCE.prototype.queryInstanceCommandValue = function(editor_id, command) { var inst = tinyMCE.getInstanceById(editor_id); if (inst) return inst.getDoc().queryCommandValue(command); return null; }; TinyMCE.prototype.queryInstanceCommandState = function(editor_id, command) { var inst = tinyMCE.getInstanceById(editor_id); if (inst) return inst.getDoc().queryCommandState(command); return null; }; TinyMCE.prototype.updateContent = function(form_element_name) { // Find MCE instance linked to given form element and copy it's value var formElement = document.getElementById(form_element_name); for (var n in tinyMCE.instances) { var inst = tinyMCE.instances[n]; inst.switchSettings(); if (inst.formElement == formElement) { var doc = inst.getDoc(); tinyMCE._setHTML(doc, inst.formElement.value); if (!tinyMCE.isMSIE) doc.body.innerHTML = tinyMCE._cleanupHTML(doc, this.settings, doc.body, inst.visualAid); } } }; TinyMCE.prototype.addMCEControl = function(replace_element, form_element_name, target_document) { var id = "mce_editor_" + tinyMCE.idCounter++; var inst = new TinyMCEControl(tinyMCE.settings); inst.editorId = id; this.instances[id] = inst; inst.onAdd(replace_element, form_element_name, target_document); }; TinyMCE.prototype.triggerSave = function(skip_cleanup, skip_callback) { // Cleanup and set all form fields for (var n in tinyMCE.instances) { var inst = tinyMCE.instances[n]; inst.switchSettings(); tinyMCE.settings['preformatted'] = false; // Default to false if (typeof(skip_cleanup) == "undefined") skip_cleanup = false; // Default to false if (typeof(skip_callback) == "undefined") skip_callback = false; tinyMCE._setHTML(inst.getDoc(), inst.getBody().innerHTML); var htm = skip_cleanup ? inst.getBody().innerHTML : tinyMCE._cleanupHTML(inst.getDoc(), this.settings, inst.getBody(), this.visualAid, true); //var htm = tinyMCE._cleanupHTML(inst.getDoc(), tinyMCE.settings, inst.getBody(), false, true); if (tinyMCE.settings["encoding"] == "xml" || tinyMCE.settings["encoding"] == "html") htm = tinyMCE.convertStringToXML(htm); if (!skip_callback && tinyMCE.settings['save_callback'] != "") var content = eval(tinyMCE.settings['save_callback'] + "(inst.formTargetElementId,htm,inst.getBody());"); // Use callback content if available if ((typeof(content) != "undefined") && content != null) htm = content; // Replace some weird entities (Bug: #1056343) htm = tinyMCE.regexpReplace(htm, "(", "(", "gi"); htm = tinyMCE.regexpReplace(htm, ")", ")", "gi"); htm = tinyMCE.regexpReplace(htm, ";", ";", "gi"); htm = tinyMCE.regexpReplace(htm, """, """, "gi"); htm = tinyMCE.regexpReplace(htm, "^", "^", "gi"); if (inst.formElement) inst.formElement.value = htm; } }; TinyMCE.prototype._convertOnClick = function(node) { // Skip on MSIE < 6+ if (tinyMCE.isMSIE5) return; // Convert all onclick to mce_onclick var elms = node.getElementsByTagName("a"); for (var i=0; i", "gi"); content = tinyMCE.regexpReplace(content, "\r", "
", "gi"); content = tinyMCE.regexpReplace(content, "\n", "
", "gi"); } // Call custom cleanup code content = tinyMCE._customCleanup("insert_to_editor", content); if (tinyMCE.isMSIE) { // Ugly!!! window.setInterval('try{tinyMCE.getCSSClasses(document.frames["' + editor_id + '"].document, "' + editor_id + '");}catch(e){}', 500); if (tinyMCE.settings["force_br_newlines"]) document.frames[editor_id].document.styleSheets[0].addRule("p", "margin: 0px;"); var body = document.frames[editor_id].document.body; tinyMCE.addEvent(body, "beforepaste", TinyMCE.prototype.eventPatch); tinyMCE.addEvent(body, "beforecut", TinyMCE.prototype.eventPatch); tinyMCE.addEvent(body, "paste", TinyMCE.prototype.eventPatch); body.editorId = editor_id; } // Fix for bug #958637 if (!tinyMCE.isMSIE) { var contentElement = inst.getDoc().createElement("body"); var doc = inst.getDoc(); contentElement.innerHTML = content; // Remove weridness! if (tinyMCE.settings['force_p_newlines']) content = content.replace(new RegExp('<>', 'g'), ""); if (tinyMCE.settings['cleanup_on_startup']) inst.getBody().innerHTML = tinyMCE._cleanupHTML(doc, this.settings, contentElement); else { // Convert all strong/em to b/i content = tinyMCE.regexpReplace(content, "", "", "gi"); content = tinyMCE.regexpReplace(content, "", "", "gi"); inst.getBody().innerHTML = content; } inst.convertAllRelativeURLs(); } else { if (tinyMCE.settings['cleanup_on_startup']) { tinyMCE._setHTML(inst.getDoc(), content); // Produces permission denied error in MSIE 5.5 eval('try {inst.getBody().innerHTML = tinyMCE._cleanupHTML(inst.contentDocument, this.settings, inst.getBody());} catch(e) {}'); } else inst.getBody().innerHTML = content; } tinyMCE._convertOnClick(inst.getBody()); // Fix for bug #957681 //inst.getDoc().designMode = inst.getDoc().designMode; // Setup element references var parentElm = document.getElementById(inst.editorId + '_parent'); if (parentElm.lastChild.nodeName.toLowerCase() == "input") inst.formElement = parentElm.lastChild; else inst.formElement = parentElm.nextSibling; tinyMCE.handleVisualAid(inst.getBody(), true, tinyMCE.settings['visual']); tinyMCE.executeCallback('setupcontent_callback', '_setupContent', 0, editor_id, inst.getBody(), inst.getDoc()); // Re-add design mode on mozilla if (!tinyMCE.isMSIE) TinyMCE.prototype.addEventHandlers(editor_id); inst.startContent = inst.getBody().innerHTML; // Trigger node change, this call locks buttons for tables and so forth tinyMCE.selectedInstance = inst; tinyMCE.selectedElement = inst.contentWindow.document.body; tinyMCE.triggerNodeChange(false, true); // Call custom DOM cleanup tinyMCE._customCleanup("insert_to_editor_dom", inst.contentWindow.document.body); }; TinyMCE.prototype.cancelEvent = function(e) { if (tinyMCE.isMSIE) { e.returnValue = false; e.cancelBubble = true; } else e.preventDefault(); }; TinyMCE.prototype.removeTinyMCEFormElements = function(form_obj) { // Disable all UI form elements that TinyMCE created for (var i=0; i"); rng.collapse(false); rng.select(); tinyMCE.triggerNodeChange(false); return false; } } // Backspace or delete if (e.keyCode == 8 || e.keyCode == 46) { tinyMCE.selectedElement = e.target; tinyMCE.linkElement = tinyMCE.getParentElement(e.target, "a"); tinyMCE.imgElement = tinyMCE.getParentElement(e.target, "img"); tinyMCE.triggerNodeChange(false); } return false; break; case "keyup": case "keydown": if (e.target.editorId) tinyMCE.selectedInstance = tinyMCE.instances[e.target.editorId]; else return; if (tinyMCE.selectedInstance) tinyMCE.selectedInstance.switchSettings(); // Handle backspace if (tinyMCE.isGecko && tinyMCE.settings['force_p_newlines'] && (e.keyCode == 8 || e.keyCode == 46) && !e.shiftKey) { // Insert P element instead of BR if (tinyMCE.selectedInstance._handleBackSpace(e.type)) { // Cancel event e.preventDefault(); return false; } } tinyMCE.selectedElement = null; tinyMCE.selectedNode = null; var elm = tinyMCE.selectedInstance.getFocusElement(); tinyMCE.linkElement = tinyMCE.getParentElement(elm, "a"); tinyMCE.imgElement = tinyMCE.getParentElement(elm, "img"); tinyMCE.selectedElement = elm; // Update visualaids on tabs if (tinyMCE.isGecko && e.type == "keyup" && e.keyCode == 9) tinyMCE.handleVisualAid(tinyMCE.selectedInstance.getBody(), true, tinyMCE.settings['visual']); // Run image/link fix on Gecko if diffrent document base on paste if (tinyMCE.isGecko && tinyMCE.settings['document_base_url'] != "" + document.location.href && e.type == "keyup" && e.ctrlKey && e.keyCode == 86) tinyMCE.selectedInstance.fixBrokenURLs(); // Insert space instead of   /* if (e.type == "keydown" && e.keyCode == 32) { if (tinyMCE.selectedInstance._insertSpace()) { // Cancel event e.returnValue = false; e.cancelBubble = true; return false; } }*/ // MSIE custom key handling if (tinyMCE.isMSIE && tinyMCE.settings['custom_undo_redo']) { // Check if it's a position key press var keys = new Array(13,45,36,35,33,34,37,38,39,40); var posKey = false; for (var i=0; i 18 && e.keyCode != 255)) { tinyMCE.selectedInstance.execCommand("mceAddUndoLevel"); tinyMCE.selectedInstance.typing = true; tinyMCE.triggerNodeChange(false); } if (posKey && e.type == "keyup") tinyMCE.triggerNodeChange(false); var keys = new Array(8,46); // Backspace,Delete for (var i=0; i 0) { for (var i=0; i" + this.convertStringToXML(String.fromCharCode(160)) + ""; // Is MSIE script element if (tinyMCE.isMSIE && elementName == "script") return "<" + elementName + elementAttribs + ">" + node.text + ""; // Clean up children if (node.hasChildNodes()) { // Force BR if (elementName == "p" && tinyMCE.cleanup_force_br_newlines) output += ""; else output += "<" + elementName + elementAttribs + ">"; for (var i=0; i"; } else { // Allways leave anchor elements open if (openTag) output += "<" + elementName + elementAttribs + ">"; else { // No children output += "<" + elementName + elementAttribs + " />"; } } return output; case 3: // Text // Do not convert script elements if (node.parentNode.nodeName.toLowerCase() == "script") return node.nodeValue; return this.convertStringToXML(node.nodeValue); case 8: // Comment return ""; default: // Unknown return "[UNKNOWN NODETYPE " + node.nodeType + "]"; } }; TinyMCE.prototype.convertStringToXML = function(html_data) { var output = ""; for (var i=0; i 127) output += '&#' + chr + ";"; else output += String.fromCharCode(chr); continue; } // Raw entities if (tinyMCE.settings['entity_encoding'] == "raw") { output += String.fromCharCode(chr); continue; } // Named entities if (typeof(tinyMCE.cleanup_entities["c" + chr]) != 'undefined' && tinyMCE.cleanup_entities["c" + chr] != '') output += '&' + tinyMCE.cleanup_entities["c" + chr] + ';'; else output += '' + String.fromCharCode(chr); } return output; }; TinyMCE.prototype._getCleanupElementName = function(chunk) { var pos; if (chunk.charAt(0) == '+') chunk = chunk.substring(1); if ((pos = chunk.indexOf('/')) != -1) chunk = chunk.substring(0, pos); if ((pos = chunk.indexOf('[')) != -1) chunk = chunk.substring(0, pos); return chunk; }; TinyMCE.prototype._initCleanup = function() { // Parse valid elements and attributes var validElements = tinyMCE.settings["valid_elements"]; validElements = validElements.split(','); // Handle extended valid elements var extendedValidElements = tinyMCE.settings["extended_valid_elements"]; extendedValidElements = extendedValidElements.split(','); for (var i=0; i[ \n\r]*
[ \n\r]*

', '
', 'gi'); element.innerHTML = tinyMCE.regexpReplace(element.innerHTML, '', '', 'gi'); } var html = this.cleanupNode(element); if (tinyMCE.settings['debug']) alert("Cleanup process executed in: " + (new Date().getTime()-startTime) + " ms."); // Remove pesky HR paragraphs html = tinyMCE.regexpReplace(html, '


', '
'); html = tinyMCE.regexpReplace(html, '

 


 

', '
'); // Remove some mozilla crap if (!tinyMCE.isMSIE) html = html.replace(new RegExp('', 'g'), ""); if (tinyMCE.settings['apply_source_formatting']) { html = html.replace(new RegExp('<(p|div)([^>]*)>', 'g'), "\n<$1$2>\n"); html = html.replace(new RegExp('<\/(p|div)([^>]*)>', 'g'), "\n\n"); html = html.replace(new RegExp('
', 'g'), "
\n"); } if (tinyMCE.settings['force_br_newlines']) { var re = new RegExp('

 

', 'g'); html = html.replace(re, "
"); } if (tinyMCE.settings['force_p_newlines']) { // Remove weridness! var re = new RegExp('<>', 'g'); html = html.replace(re, ""); } if (tinyMCE.settings['remove_linebreaks']) html = html.replace(new RegExp('\r|\n', 'g'), ' '); // Call custom cleanup code html = tinyMCE._customCleanup(on_save ? "get_from_editor" : "insert_to_editor", html); // Emtpy node, return empty var chk = tinyMCE.regexpReplace(html, "[ \t\r\n]", ""); if (chk == "
" || chk == "
" || chk == "

 

" || chk == "

 

" || chk == "

") html = ""; if (tinyMCE.settings["preformatted"]) return "
" + html + "
"; return html; }; TinyMCE.prototype.setAttrib = function(element, name, value, no_fix_value) { if (!no_fix_value && value != null) { var re = new RegExp('[^0-9%]', 'g'); value = value.replace(re, ''); } if (value != null && value != "") element.setAttribute(name, value); else element.removeAttribute(name); if (value != null && value != "") element.setAttribute(name, value); else element.removeAttribute(name); }; TinyMCE.prototype.insertLink = function(href, target, title, onclick) { this.execCommand("mceAddUndoLevel"); if (this.selectedInstance && this.selectedElement && this.selectedElement.nodeName.toLowerCase() == "img") { var doc = this.selectedInstance.getDoc(); var linkElement = tinyMCE.getParentElement(this.selectedElement, "a"); var newLink = false; if (!linkElement) { linkElement = doc.createElement("a"); newLink = true; } href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, linkElement);"); tinyMCE.setAttrib(linkElement, 'href', href); tinyMCE.setAttrib(linkElement, 'target', target); tinyMCE.setAttrib(linkElement, 'title', title); tinyMCE.setAttrib(linkElement, 'mce_onclick', onclick); if (newLink) { linkElement.appendChild(this.selectedElement.cloneNode(true)); this.selectedElement.parentNode.replaceChild(linkElement, this.selectedElement); } return; } if (!this.linkElement && this.selectedInstance) { this.selectedInstance.contentDocument.execCommand("createlink", false, "#mce_temp_url#"); tinyMCE.linkElement = this.getElementByAttributeValue(this.selectedInstance.contentDocument.body, "a", "href", "#mce_temp_url#"); var elementArray = this.getElementsByAttributeValue(this.selectedInstance.contentDocument.body, "a", "href", "#mce_temp_url#"); for (var i=0; i= strTok2.length) { for (var i=0; i= strTok2.length || strTok1[i] != strTok2[i]) { breakPoint = i + 1; break; } } } if (strTok1.length < strTok2.length) { for (var i=0; i= strTok1.length || strTok1[i] != strTok2[i]) { breakPoint = i + 1; break; } } } if (breakPoint == 1) return url_to_relative; for (var i=0; i<(strTok1.length-(breakPoint-1)); i++) outputString += "../"; for (var i=breakPoint-1; i=0; i--) { if (baseURLParts[i].length == 0) continue; newBaseURLParts[newBaseURLParts.length] = baseURLParts[i]; } baseURLParts = newBaseURLParts.reverse(); // Merge relURLParts chunks var newRelURLParts = new Array(); var numBack = 0; for (var i=relURLParts.length-1; i>=0; i--) { if (relURLParts[i].length == 0 || relURLParts[i] == ".") continue; if (relURLParts[i] == '..') { numBack++; continue; } if (numBack > 0) { numBack--; continue; } newRelURLParts[newRelURLParts.length] = relURLParts[i]; } relURLParts = newRelURLParts.reverse(); // Remove end from absolute path var len = baseURLParts.length-numBack; var absPath = (len <= 0 ? "" : "/") + baseURLParts.slice(0, len).join('/') + "/" + relURLParts.join('/'); var start = "", end = ""; // Build start part if (baseURL['protocol']) start += baseURL['protocol'] + "://"; if (baseURL['host']) start += baseURL['host']; if (baseURL['port']) start += ":" + baseURL['port']; // Build end part if (relURL['query']) end += "?" + relURL['query']; if (relURL['anchor']) end += "#" + relURL['anchor']; // Re-add trailing slash if it's removed if (relative_url.charAt(relative_url.length-1) == "/") end += "/"; return start + absPath + end; }; TinyMCE.prototype.getParam = function(name, default_value, strip_whitespace, split_chr) { var value = (typeof(this.settings[name]) == "undefined") ? default_value : this.settings[name]; // Fix bool values if (value == "true" || value == "false") return (value == "true"); if (strip_whitespace) value = tinyMCE.regexpReplace(value, "[ \t\r\n]", ""); if (typeof(split_chr) != "undefined" && split_chr != null) { value = value.split(split_chr); var outArray = new Array(); for (var i=0; i 0); if (tinyMCE.settings['custom_undo_redo']) { undoIndex = inst.undoIndex; undoLevels = inst.undoLevels.length; } tinyMCE.executeCallback('handleNodeChangeCallback', '_handleNodeChange', 0, editorId, elm, undoIndex, undoLevels, inst.visualAid, anySelection); } } if (this.selectedInstance && (typeof(focus) == "undefined" || focus)) this.selectedInstance.contentWindow.focus(); }; TinyMCE.prototype._customCleanup = function(type, content) { // Call custom cleanup var customCleanup = tinyMCE.settings['cleanup_callback']; if (customCleanup != "" && eval("typeof(" + customCleanup + ")") != "undefined") content = eval(customCleanup + "(type, content);"); // Trigger plugin cleanups var plugins = tinyMCE.getParam('plugins', '', true, ','); for (var i=0; i 0) className += " "; className += classNames[i]; } return className; }; TinyMCE.prototype.handleVisualAid = function(element, deep, state) { if (!element) return; var tableElement = null; switch (element.nodeName.toLowerCase()) { case "table": var oldW = element.style.width; var oldH = element.style.height; element.className = tinyMCE.getVisualAidClass(element.className, state && element.getAttribute("border") == 0); element.style.width = oldW; element.style.height = oldH; for (var y=0; y'; return; } break;*/ } if (deep && element.hasChildNodes()) { for (var i=0; i

breaks runtime? if (tinyMCE.isMSIE) { var re = new RegExp('


', 'g'); html_content = html_content.replace(re, "
"); } doc.body.innerHTML = html_content; // Content duplication bug fix if (tinyMCE.isMSIE && tinyMCE.settings['fix_content_duplication']) { // Remove P elements in P elements var paras = doc.getElementsByTagName("P"); for (var i=0; i<\/o:p>", "
"); html = tinyMCE.regexpReplace(html, " <\/o:p>", ""); html = tinyMCE.regexpReplace(html, "", ""); html = tinyMCE.regexpReplace(html, "

<\/p>", ""); html = tinyMCE.regexpReplace(html, "

<\/p>\r\n

<\/p>", ""); html = tinyMCE.regexpReplace(html, "

 <\/p>", "
"); html = tinyMCE.regexpReplace(html, "

\s*(

\s*)?", "

"); html = tinyMCE.regexpReplace(html, "<\/p>\s*(<\/p>\s*)?", "

"); } // Always set the htmlText output doc.body.innerHTML = html; } }; TinyMCE.prototype.getImageSrc = function(str) { var pos = -1; if (!str) return ""; if ((pos = str.indexOf('this.src=')) != -1) { var src = str.substring(pos + 10); src = src.substring(0, src.indexOf('\'')); return src; } return ""; }; TinyMCE.prototype._getElementById = function(element_id) { var elm = document.getElementById(element_id); if (!elm) { // Check for element in forms for (var j=0; j 0) { var csses = null; // Just ignore any errors eval("try {var csses = tinyMCE.isMSIE ? doc.styleSheets(0).rules : doc.styleSheets[0].cssRules;} catch(e) {}"); if (!csses) return new Array(); for (var i=0; i 0) tinyMCE.cssClasses = output; return output; }; TinyMCE.prototype.regexpReplace = function(in_str, reg_exp, replace_str, opts) { if (typeof(opts) == "undefined") opts = 'g'; var re = new RegExp(reg_exp, opts); return in_str.replace(re, replace_str); }; TinyMCE.prototype.cleanupEventStr = function(str) { str = "" + str; str = str.replace('function anonymous()\n{\n', ''); str = str.replace('\n}', ''); return str; }; TinyMCE.prototype.getAbsPosition = function(node) { var pos = new Object(); pos.absLeft = pos.absTop = 0; var parentNode = node; while (parentNode) { pos.absLeft += parentNode.offsetLeft; pos.absTop += parentNode.offsetTop; parentNode = parentNode.offsetParent; } return pos; }; TinyMCE.prototype.openFileBrowser = function(field_name, url, type, win) { var cb = tinyMCE.getParam("file_browser_callback"); this.setWindowArg("window", win); // Call to external callback if(eval('typeof('+cb+')') == "undefined") alert("Callback function: " + cb + " could not be found."); else eval(cb + "(field_name, url, type, win);"); }; TinyMCE.prototype.getControlHTML = function(control_name) { var themePlugins = tinyMCE.getParam('plugins', '', true, ','); var templateFunction; // Is it defined in any plugins for (var i=themePlugins.length; i>=0; i--) { templateFunction = 'TinyMCE_' + themePlugins[i] + "_getControlHTML"; if (eval("typeof(" + templateFunction + ")") != 'undefined') { var html = eval(templateFunction + "('" + control_name + "');"); if (html != "") return tinyMCE.replaceVar(html, "pluginurl", tinyMCE.baseURL + "/plugins/" + themePlugins[i]); } } return eval('TinyMCE_' + tinyMCE.settings['theme'] + "_getControlHTML" + "('" + control_name + "');"); }; TinyMCE.prototype._themeExecCommand = function(editor_id, element, command, user_interface, value) { var themePlugins = tinyMCE.getParam('plugins', '', true, ','); var templateFunction; // Is it defined in any plugins for (var i=themePlugins.length; i>=0; i--) { templateFunction = 'TinyMCE_' + themePlugins[i] + "_execCommand"; if (eval("typeof(" + templateFunction + ")") != 'undefined') { if (eval(templateFunction + "(editor_id, element, command, user_interface, value);")) return true; } } // Theme funtion templateFunction = 'TinyMCE_' + tinyMCE.settings['theme'] + "_execCommand"; if (eval("typeof(" + templateFunction + ")") != 'undefined') return eval(templateFunction + "(editor_id, element, command, user_interface, value);"); // Pass to normal return false; }; TinyMCE.prototype._getThemeFunction = function(suffix, skip_plugins) { if (skip_plugins) return 'TinyMCE_' + tinyMCE.settings['theme'] + suffix; var themePlugins = tinyMCE.getParam('plugins', '', true, ','); var templateFunction; // Is it defined in any plugins for (var i=themePlugins.length; i>=0; i--) { templateFunction = 'TinyMCE_' + themePlugins[i] + suffix; if (eval("typeof(" + templateFunction + ")") != 'undefined') return templateFunction; } return 'TinyMCE_' + tinyMCE.settings['theme'] + suffix; }; TinyMCE.prototype.isFunc = function(func_name) { if (func_name == null || func_name == "") return false; return eval("typeof(" + func_name + ")") != "undefined"; }; TinyMCE.prototype.exec = function(func_name, args) { var str = func_name + '('; // Add all arguments for (var i=3; i 1 && tinyMCE.currentConfig != this.settings['index']) { tinyMCE.settings = this.settings; tinyMCE.currentConfig = this.settings['index']; } }; TinyMCEControl.prototype.fixBrokenURLs = function() { var body = this.getBody(); var elms = body.getElementsByTagName("img"); for (var i=0; i 0) rng.selectNodeContents(nodes[0]); else rng.selectNodeContents(node); } else rng.selectNode(node); if (collapse) { // Special treatment of textnode collapse if (!to_start && node.nodeType == 3) { rng.setStart(node, node.nodeValue.length); rng.setEnd(node, node.nodeValue.length); } else rng.collapse(to_start); } sel.removeAllRanges(); sel.addRange(rng); } this.scrollToNode(node); // Set selected element tinyMCE.selectedElement = null; if (node.nodeType == 1) tinyMCE.selectedElement = node; }; TinyMCEControl.prototype.scrollToNode = function(node) { // Scroll to node position var pos = tinyMCE.getAbsPosition(node); var doc = this.getDoc(); var scrollX = doc.body.scrollLeft + doc.documentElement.scrollLeft; var scrollY = doc.body.scrollTop + doc.documentElement.scrollTop; var height = tinyMCE.isMSIE ? document.getElementById(this.editorId).style.pixelHeight : this.targetElement.clientHeight; // Only scroll if out of visible area if (!tinyMCE.settings['auto_resize'] && !(node.absTop > scrollY && node.absTop < (scrollY - 25 + height))) this.contentWindow.scrollTo(pos.absLeft, pos.absTop - height + 25); }; TinyMCEControl.prototype.getBody = function() { return this.getDoc().body; }; TinyMCEControl.prototype.getDoc = function() { return this.contentWindow.document; }; TinyMCEControl.prototype.getWin = function() { return this.contentWindow; }; TinyMCEControl.prototype.getSel = function() { if (tinyMCE.isMSIE) return this.getDoc().selection; var sel = this.contentWindow.getSelection(); // Fake getRangeAt if (tinyMCE.isSafari && !sel.getRangeAt) { var newSel = new Object(); var doc = this.getDoc(); function getRangeAt(idx) { var rng = new Object(); rng.startContainer = this.focusNode; rng.endContainer = this.anchorNode; rng.commonAncestorContainer = this.focusNode; rng.createContextualFragment = function (html) { // Seems to be a tag if (html.charAt(0) == '<') { var elm = doc.createElement("div"); elm.innerHTML = html; return elm.firstChild; } return doc.createTextNode("UNSUPPORTED, DUE TO LIMITATIONS IN SAFARI!"); }; rng.deleteContents = function () { doc.execCommand("Delete", false, ""); }; return rng; } // Patch selection newSel.focusNode = sel.baseNode; newSel.focusOffset = sel.baseOffset; newSel.anchorNode = sel.extentNode; newSel.anchorOffset = sel.extentOffset; newSel.getRangeAt = getRangeAt; newSel.text = "" + sel; newSel.realSelection = sel; newSel.toString = function () {return this.text;}; return newSel; } return sel; }; TinyMCEControl.prototype.getRng = function() { var sel = this.getSel(); if (sel == null) return null; if (tinyMCE.isMSIE) return sel.createRange(); return this.getSel().getRangeAt(0); }; TinyMCEControl.prototype._insertPara = function(e) { function isEmpty(para) { function isEmptyHTML(html) { return html.replace(new RegExp('[ \t\r\n]+', 'g'), '').toLowerCase() == ""; } // Check for images if (para.getElementsByTagName("img").length > 0) return false; // Check for tables if (para.getElementsByTagName("table").length > 0) return false; // Check for HRs if (para.getElementsByTagName("hr").length > 0) return false; // Check all textnodes var nodes = tinyMCE.getNodeTree(para, new Array(), 3); for (var i=0; i <" + blockName + "> "; paraAfter = body.childNodes[1]; } this.selectNode(paraAfter, true, true); return true; } // Place first part within new paragraph if (startChop.nodeName == blockName) rngBefore.setStart(startChop, 0); else rngBefore.setStartBefore(startChop); rngBefore.setEnd(startNode, startOffset); paraBefore.appendChild(rngBefore.cloneContents()); // Place secound part within new paragraph rngAfter.setEndAfter(endChop); rngAfter.setStart(endNode, endOffset); var contents = rngAfter.cloneContents(); if (contents.firstChild && contents.firstChild.nodeName == blockName) { var nodes = contents.firstChild.childNodes; for (var i=0; i 0) rng.pasteHTML('
' + rng.htmlText + "
"); tinyMCE.triggerNodeChange(); return; } } } switch (command) { case "mceSelectNode": this.selectNode(value); tinyMCE.triggerNodeChange(); tinyMCE.selectedNode = value; break; case "mceSelectNodeDepth": var parentNode = this.getFocusElement(); for (var i=0; parentNode; i++) { if (parentNode.nodeName.toLowerCase() == "body") break; if (parentNode.nodeName.toLowerCase() == "#text") { i--; parentNode = parentNode.parentNode; continue; } if (i == value) { this.selectNode(parentNode, false); tinyMCE.triggerNodeChange(); tinyMCE.selectedNode = parentNode; return; } parentNode = parentNode.parentNode; } break; case "HiliteColor": if (tinyMCE.isGecko) { this.getDoc().execCommand("useCSS", false, false); this.getDoc().execCommand('hilitecolor', false, value); this.getDoc().execCommand("useCSS", false, true); } else this.getDoc().execCommand('BackColor', false, value); break; case "Cut": case "Copy": case "Paste": var cmdFailed = false; // Try executing command eval('try {this.getDoc().execCommand(command, user_interface, value);} catch (e) {cmdFailed = true;}'); // Alert error in gecko if command failed if (tinyMCE.isGecko && cmdFailed) { // Confirm more info if (confirm(tinyMCE.getLang('lang_clipboard_msg'))) window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html', 'mceExternal'); return; } else tinyMCE.triggerNodeChange(); break; case "mceSetContent": if (!value) value = ""; // Call custom cleanup code html_content = tinyMCE._customCleanup("insert_to_editor", value); tinyMCE._setHTML(doc, value); doc.body.innerHTML = tinyMCE._cleanupHTML(doc, tinyMCE.settings, doc.body); tinyMCE.handleVisualAid(doc.body, true, this.visualAid); return true; case "mceLink": var selectedText = ""; if (tinyMCE.isMSIE) { var rng = doc.selection.createRange(); selectedText = rng.text; } else selectedText = this.getSel().toString(); if (!tinyMCE.linkElement) { if ((tinyMCE.selectedElement.nodeName.toLowerCase() != "img") && (selectedText.length <= 0)) return; } var href = "", target = "", title = "", onclick = "", action = "insert"; if (tinyMCE.selectedElement.nodeName.toLowerCase() == "a") tinyMCE.linkElement = tinyMCE.selectedElement; // Is anchor not a link if (tinyMCE.linkElement != null && tinyMCE.getAttrib(tinyMCE.linkElement, 'href') == "") tinyMCE.linkElement = null; if (tinyMCE.linkElement) { href = tinyMCE.getAttrib(tinyMCE.linkElement, 'href'); target = tinyMCE.getAttrib(tinyMCE.linkElement, 'target'); title = tinyMCE.getAttrib(tinyMCE.linkElement, 'title'); onclick = tinyMCE.getAttrib(tinyMCE.linkElement, 'mce_onclick'); // Try old onclick to if copy/pasted content if (onclick == "") onclick = tinyMCE.getAttrib(tinyMCE.linkElement, 'onclick'); onclick = tinyMCE.cleanupEventStr(onclick); // Fix for drag-drop/copy paste bug in Mozilla mceRealHref = tinyMCE.getAttrib(tinyMCE.linkElement, 'mce_real_href'); if (mceRealHref != "") href = mceRealHref; href = eval(tinyMCE.settings['urlconverter_callback'] + "(href, tinyMCE.linkElement, true);"); action = "update"; } if (this.settings['insertlink_callback']) { var returnVal = eval(this.settings['insertlink_callback'] + "(href, target, title, onclick, action);"); if (returnVal && returnVal['href']) tinyMCE.insertLink(returnVal['href'], returnVal['target'], returnVal['title'], returnVal['onclick']); } else { tinyMCE.openWindow(this.insertLinkTemplate, {href : href, target : target, title : title, onclick : onclick, action : action}); } break; case "mceImage": var src = "", alt = "", border = "", hspace = "", vspace = "", width = "", height = "", align = ""; var title = "", onmouseover = "", onmouseout = "", action = "insert"; var img = tinyMCE.imgElement; if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") { img = tinyMCE.selectedElement; tinyMCE.imgElement = img; } if (img) { // Is it a internal MCE visual aid image, then skip this one. if (tinyMCE.getAttrib(img, 'name').indexOf('mce_') == 0) return; src = tinyMCE.getAttrib(img, 'src'); alt = tinyMCE.getAttrib(img, 'alt'); // Try polling out the title if (alt == "") alt = tinyMCE.getAttrib(img, 'title'); // Fix width/height attributes if the styles is specified if (tinyMCE.isGecko) { var w = img.style.width; if (w != null && w != "") img.setAttribute("width", w); var h = img.style.height; if (h != null && h != "") img.setAttribute("height", h); } border = tinyMCE.getAttrib(img, 'border'); hspace = tinyMCE.getAttrib(img, 'hspace'); vspace = tinyMCE.getAttrib(img, 'vspace'); width = tinyMCE.getAttrib(img, 'width'); height = tinyMCE.getAttrib(img, 'height'); align = tinyMCE.getAttrib(img, 'align'); onmouseover = tinyMCE.getAttrib(img, 'onmouseover'); onmouseout = tinyMCE.getAttrib(img, 'onmouseout'); title = tinyMCE.getAttrib(img, 'title'); // Is realy specified? if (tinyMCE.isMSIE) { width = img.attributes['width'].specified ? width : ""; height = img.attributes['height'].specified ? height : ""; } onmouseover = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseover)); onmouseout = tinyMCE.getImageSrc(tinyMCE.cleanupEventStr(onmouseout)); // Fix for drag-drop/copy paste bug in Mozilla mceRealSrc = tinyMCE.getAttrib(img, 'mce_real_src'); if (mceRealSrc != "") src = mceRealSrc; src = eval(tinyMCE.settings['urlconverter_callback'] + "(src, img, true);"); if (onmouseover != "") onmouseover = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseover, img, true);"); if (onmouseout != "") onmouseout = eval(tinyMCE.settings['urlconverter_callback'] + "(onmouseout, img, true);"); action = "update"; } if (this.settings['insertimage_callback']) { var returnVal = eval(this.settings['insertimage_callback'] + "(src, alt, border, hspace, vspace, width, height, align, title, onmouseover, onmouseout, action);"); if (returnVal && returnVal['src']) tinyMCE.insertImage(returnVal['src'], returnVal['alt'], returnVal['border'], returnVal['hspace'], returnVal['vspace'], returnVal['width'], returnVal['height'], returnVal['align'], returnVal['title'], returnVal['onmouseover'], returnVal['onmouseout']); } else tinyMCE.openWindow(this.insertImageTemplate, {src : src, alt : alt, border : border, hspace : hspace, vspace : vspace, width : width, height : height, align : align, title : title, onmouseover : onmouseover, onmouseout : onmouseout, action : action}); break; case "mceCleanupWord": if (tinyMCE.isMSIE) { var html = this.getBody().createTextRange().htmlText; if (html.indexOf('="mso') != -1) { tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML); html = tinyMCE._cleanupHTML(this.contentDocument, this.settings, this.getBody(), this.visualAid); } this.getBody().innerHTML = html; } break; case "mceCleanup": tinyMCE._setHTML(this.contentDocument, this.getBody().innerHTML); this.getBody().innerHTML = tinyMCE._cleanupHTML(this.contentDocument, this.settings, this.getBody(), this.visualAid); tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid); this.repaint(); tinyMCE.triggerNodeChange(); break; case "mceAnchor": if (!user_interface) { var aElm = tinyMCE.getParentElement(this.getFocusElement(), "a", "name"); if (aElm) { if (value == null || value == "") { if (tinyMCE.isMSIE) { aElm.outerHTML = aElm.innerHTML; } else { var rng = aElm.ownerDocument.createRange(); rng.setStartBefore(aElm); rng.setEndAfter(aElm); rng.deleteContents(); rng.insertNode(rng.createContextualFragment(aElm.innerHTML)); } } else aElm.setAttribute('name', value); } else { this.getDoc().execCommand("fontname", false, "#mce_temp_font#"); var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#"); for (var x=0; x 0) { value = tinyMCE.replaceVar(value, "selection", selectedText); tinyMCE.execCommand('mceInsertContent',false,value); } tinyMCE.triggerNodeChange(); break; case "mceSetAttribute": if (typeof(value) == 'object') { var targetElms = (typeof(value['targets']) == "undefined") ? "p,img,span,div,td,h1,h2,h3,h4,h5,h6,pre,address" : value['targets']; var targetNode = tinyMCE.getParentElement(this.getFocusElement(), targetElms); if (targetNode) { targetNode.setAttribute(value['name'], value['value']); tinyMCE.triggerNodeChange(); } } break; case "mceSetCSSClass": var selectedText = false; if (tinyMCE.isMSIE) { var rng = doc.selection.createRange(); selectedText = (rng.text && rng.text.length > 0); } else selectedText = (this.getSel().toString().length > 0); // Use selectedNode instead if defined if (tinyMCE.selectedNode) tinyMCE.selectedElement = tinyMCE.selectedNode; if (selectedText && !tinyMCE.selectedNode) { this.getDoc().execCommand("RemoveFormat", false, null); if (value == null) return this.execCommand("RemoveFormat", false, null); this.getDoc().execCommand("fontname", false, "#mce_temp_font#"); var elementArray = tinyMCE.getElementsByAttributeValue(this.getBody(), "font", "face", "#mce_temp_font#"); // Change them all for (var x=0; x customUndoLevels) { for (var i=0; i 0) { this.undoIndex--; this.getBody().innerHTML = this.undoLevels[this.undoIndex]; } // debug("Undo - undo levels:" + this.undoLevels.length + ", undo index: " + this.undoIndex); tinyMCE.triggerNodeChange(); } else this.getDoc().execCommand(command, user_interface, value); break; case "Redo": if (tinyMCE.settings['custom_undo_redo']) { if (this.undoIndex < (this.undoLevels.length-1)) { this.undoIndex++; this.getBody().innerHTML = this.undoLevels[this.undoIndex]; // debug("Redo - undo levels:" + this.undoLevels.length + ", undo index: " + this.undoIndex); } tinyMCE.triggerNodeChange(); } else this.getDoc().execCommand(command, user_interface, value); break; case "mceToggleVisualAid": this.visualAid = !this.visualAid; tinyMCE.handleVisualAid(this.getBody(), true, this.visualAid); tinyMCE.triggerNodeChange(); break; case "removeformat": var text = this.getSelectedText(); if (tinyMCE.isMSIE) { try { win.focus(); var rng = doc.selection.createRange(); rng.execCommand("RemoveFormat", false, null); rng.pasteHTML(rng.text); } catch (e) { // Do nothing } } else this.getDoc().execCommand(command, user_interface, value); // Remove class if (text.length == 0) this.execCommand("mceSetCSSClass", false, ""); tinyMCE.triggerNodeChange(); break; default: this.getDoc().execCommand(command, user_interface, value); tinyMCE.triggerNodeChange(); } }; TinyMCEControl.prototype.queryCommandValue = function(command) { return this.getDoc().queryCommandValue(command); }; TinyMCEControl.prototype.queryCommandState = function(command) { return this.getDoc().queryCommandState(command); }; TinyMCEControl.prototype.onAdd = function(replace_element, form_element_name, target_document) { var targetDoc = target_document ? target_document : document; this.targetDoc = targetDoc; tinyMCE.themeURL = tinyMCE.baseURL + "/themes/" + this.settings['theme']; this.settings['themeurl'] = tinyMCE.themeURL; if (!replace_element) { alert("Error: Could not find the target element."); return false; } var templateFunction = tinyMCE._getThemeFunction('_getInsertLinkTemplate'); if (eval("typeof(" + templateFunction + ")") != 'undefined') this.insertLinkTemplate = eval(templateFunction + '(this.settings);'); var templateFunction = tinyMCE._getThemeFunction('_getInsertImageTemplate'); if (eval("typeof(" + templateFunction + ")") != 'undefined') this.insertImageTemplate = eval(templateFunction + '(this.settings);'); var templateFunction = tinyMCE._getThemeFunction('_getEditorTemplate'); if (eval("typeof(" + templateFunction + ")") == 'undefined') { alert("Error: Could not find the template function: " + templateFunction); return false; } var editorTemplate = eval(templateFunction + '(this.settings, this.editorId);'); var deltaWidth = editorTemplate['delta_width'] ? editorTemplate['delta_width'] : 0; var deltaHeight = editorTemplate['delta_height'] ? editorTemplate['delta_height'] : 0; var html = '' + editorTemplate['html']; var templateFunction = tinyMCE._getThemeFunction('_handleNodeChange', true); if (eval("typeof(" + templateFunction + ")") != 'undefined') this.settings['handleNodeChangeCallback'] = templateFunction; html = tinyMCE.replaceVar(html, "editor_id", this.editorId); html = tinyMCE.replaceVar(html, "default_document", tinyMCE.baseURL + "/blank.htm"); this.settings['default_document'] = tinyMCE.baseURL + "/blank.htm"; this.settings['old_width'] = this.settings['width']; this.settings['old_height'] = this.settings['height']; // Set default width, height if (this.settings['width'] == -1) this.settings['width'] = replace_element.offsetWidth; if (this.settings['height'] == -1) this.settings['height'] = replace_element.offsetHeight; // Try the style width if (this.settings['width'] == 0) this.settings['width'] = replace_element.style.width; // Try the style height if (this.settings['height'] == 0) this.settings['height'] = replace_element.style.height; // If no width/height then default to 320x240, better than nothing if (this.settings['width'] == 0) this.settings['width'] = 320; if (this.settings['height'] == 0) this.settings['height'] = 240; this.settings['area_width'] = parseInt(this.settings['width']); this.settings['area_height'] = parseInt(this.settings['height']); this.settings['area_width'] += deltaWidth; this.settings['area_height'] += deltaHeight; // Special % handling if (("" + this.settings['width']).indexOf('%') != -1) this.settings['area_width'] = "100%"; if (("" + this.settings['height']).indexOf('%') != -1) this.settings['area_height'] = "100%"; if (("" + replace_element.style.width).indexOf('%') != -1) { this.settings['width'] = replace_element.style.width; this.settings['area_width'] = "100%"; } if (("" + replace_element.style.height).indexOf('%') != -1) { this.settings['height'] = replace_element.style.height; this.settings['area_height'] = "100%"; } html = tinyMCE.applyTemplate(html); this.settings['width'] = this.settings['old_width']; this.settings['height'] = this.settings['old_height']; this.visualAid = this.settings['visual']; this.formTargetElementId = form_element_name; // Get replace_element contents if (replace_element.nodeName.toLowerCase() == "textarea") this.startContent = replace_element.value; else this.startContent = replace_element.innerHTML; // If not text area if (replace_element.nodeName.toLowerCase() != "textarea") { this.oldTargetElement = replace_element.cloneNode(true); // Debug mode if (tinyMCE.settings['debug']) html += ''; else html += ''; html += ''; // Output HTML and set editable if (!tinyMCE.isMSIE) { var rng = replace_element.ownerDocument.createRange(); rng.setStartBefore(replace_element); var fragment = rng.createContextualFragment(html); replace_element.parentNode.replaceChild(fragment, replace_element); } else replace_element.outerHTML = html; } else { html += ''; // Just hide the textarea element this.oldTargetElement = replace_element; if (!tinyMCE.settings['debug']) this.oldTargetElement.style.display = "none"; // Output HTML and set editable if (!tinyMCE.isMSIE) { var rng = replace_element.ownerDocument.createRange(); rng.setStartBefore(replace_element); var fragment = rng.createContextualFragment(html); replace_element.parentNode.insertBefore(fragment, replace_element); } else replace_element.insertAdjacentHTML("beforeBegin", html); } // Setup iframe var dynamicIFrame = false; var tElm = targetDoc.getElementById(this.editorId); if (!tinyMCE.isMSIE) { if (tElm && tElm.nodeName.toLowerCase() == "span") { tElm = tinyMCE._createIFrame(tElm); dynamicIFrame = true; } this.targetElement = tElm; this.iframeElement = tElm; this.contentDocument = tElm.contentDocument; this.contentWindow = tElm.contentWindow; //this.getDoc().designMode = "on"; } else { if (tElm && tElm.nodeName.toLowerCase() == "span") tElm = tinyMCE._createIFrame(tElm); else tElm = targetDoc.frames[this.editorId]; this.targetElement = tElm; this.iframeElement = targetDoc.getElementById(this.editorId); this.contentDocument = tElm.window.document; this.contentWindow = tElm.window; this.getDoc().designMode = "on"; } // Setup base HTML var doc = this.contentDocument; if (dynamicIFrame) { var html = "" + '' + '' + '' + '' + 'blank_page' + '' + '' + '' + '' + ''; try { this.getDoc().designMode = "on"; doc.open(); doc.write(html); doc.close(); } catch (e) { // Failed Mozilla 1.3 this.getDoc().location.href = tinyMCE.baseURL + "/blank.htm"; } } // This timeout is needed in MSIE 5.5 for some odd reason // it seems that the document.frames isn't initialized yet? if (tinyMCE.isMSIE) window.setTimeout("TinyMCE.prototype.addEventHandlers('" + this.editorId + "');", 1); tinyMCE.setupContent(this.editorId, true); return true; }; TinyMCEControl.prototype.getFocusElement = function() { if (tinyMCE.isMSIE) { var doc = this.getDoc(); var rng = doc.selection.createRange(); if (rng.collapse) rng.collapse(true); var elm = rng.item ? rng.item(0) : rng.parentElement(); } else { var sel = this.getSel(); var elm = (sel && sel.anchorNode) ? sel.anchorNode : null; if (tinyMCE.selectedElement != null && tinyMCE.selectedElement.nodeName.toLowerCase() == "img") elm = tinyMCE.selectedElement; } return elm; }; // Global instances var tinyMCE = new TinyMCE(); var tinyMCELang = new Array(); function debug() { var msg = ""; var elm = document.getElementById("tinymce_debug"); if (!elm) { var debugDiv = document.createElement("div"); debugDiv.setAttribute("className", "debugger"); debugDiv.className = "debugger"; debugDiv.innerHTML = '\ Debug output:\ '; document.body.appendChild(debugDiv); elm = document.getElementById("tinymce_debug"); } var args = this.debug.arguments; for (var i=0; i