/******************************************************************** * openWYSIWYG v1.46c Copyright (c) 2006 openWebWare.com * Contact us at devs@openwebware.com * This copyright notice MUST stay intact for use. * * $Id: wysiwyg.js,v 1.10 2006/12/25 09:17:07 xhaggi Exp $ * * An open source WYSIWYG editor for use in web based applications. * For full source code and docs, visit http://www.openwebware.com * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public * License for more details. * * You should have received a copy of the GNU Lesser General Public License along * with this library; if not, write to the Free Software Foundation, Inc., 59 * Temple Place, Suite 330, Boston, MA 02111-1307 USA ********************************************************************/ var WYSIWYG = { /** * Settings class, holds all customizeable properties */ Settings: function() { // Images Directory this.ImagesDir = "popups/images/"; // Popups Directory this.PopupsDir = "popups/"; // CSS Directory File this.CSSFile = "styles/wysiwyg.css"; // Default WYSIWYG width and height (use px or %) this.Width = "900px"; this.Height = "360px"; // Form name where WYSIWYG is attached to textarea this.FormName = "edit"; // Page that opened the WYSIWYG (Used for the return command) this.Opener = "admin.asp"; // Default stylesheet of the WYSIWYG editor window this.DefaultStyle = "font-family: arial, verdana, helvetica; font-size: 10pt;"; // Stylesheet if editor is disabled this.DisabledStyle = "font-family: Arial; font-size: 10pt; background-color: #EEEEEE"; // Width + Height of the preview window this.PreviewWidth = 980; this.PreviewHeight = 700; // Action of the preview window this.Preview = "" // Confirmation message if you strip any HTML added by word this.RemoveFormatConfMessage = "Clean HTML inserted by MS Word ?"; // Nofication if browser is not supported by openWYSIWYG, leave it blank for no message output. this.NoValidBrowserMessage = "openWYSIWYG does not support your browser."; // Anchor path to strip, leave it blank to ignore // or define auto to strip the path where the editor is placed // (only IE) this.AnchorPathToStrip = "auto"; // Image path to strip, leave it blank to ignore // or define auto to strip the path where the editor is placed // (only IE) this.ImagePathToStrip = "auto"; // Enable / Disable the custom context menu this.ContextMenu = true; // Enabled the status bar update. Within the status bar // node tree of the actually selected element will build this.StatusBarEnabled = true; // If enabled than the capability of the IE inserting line breaks will be inverted. // Normal: ENTER =

, SHIFT + ENTER =
// Inverted: ENTER =
, SHIFT + ENTER =

this.InvertIELineBreaks = false; // Replace line breaks with
tags this.ReplaceLineBreaks = false; // Insert image implementation this.ImagePopupFile = ""; this.ImagePopupWidth = 0; this.ImagePopupHeight = 0; // Holds the available buttons displayed // on the toolbar of the editor this.Toolbar = new Array(); this.Toolbar[0] = new Array( "bold", "italic", "underline", "strikethrough", "seperator", "forecolor", "backcolor", "seperator", "justifyleft", "justifycenter", "justifyright", "seperator", "unorderedlist", "orderedlist", "outdent", "indent", "seperator", "subscript", "superscript", "seperator", "cut", "copy", "paste", "removeformat", "seperator", "undo", "redo", "seperator", "inserttable", "insertimage", "createlink", "seperator", "viewSource" ); // List of available font types this.Fonts = new Array( "Arial", "Sans Serif", "Tahoma", "Verdana", "Courier New", "Georgia", "Times New Roman", "Impact", "Comic Sans MS" ); // List of available font sizes this.Fontsizes = new Array( "1", "2", "3", "4", "5", "6", "7" ); // Add the given element to the defined toolbar // on the defined position this.addToolbarElement = function(element, toolbar, position) { if(element != "seperator") {this.removeToolbarElement(element);} if(this.Toolbar[toolbar-1] == null) { this.Toolbar[toolbar-1] = new Array(); } this.Toolbar[toolbar-1].splice(position+1, 1, element); }; // Remove an element from the toolbar this.removeToolbarElement = function(element) { if(element == "seperator") {return;} // do not remove seperators for(var i=0;i])*>( )*\s*<\/span>/gi, ''); str = str.replace(/]*>/gi, ''); str = str.replace(/<\/span[^>]*>/gi, ''); str = str.replace(/])*>( )*\s*<\/p>/gi, ''); str = str.replace(/]*>/gi, ''); str = str.replace(/<\/p[^>]*>/gi, ''); str = str.replace(/])[0-9]>( )*\s*<\/h>/gi, ''); str = str.replace(/][0-9]>/gi, ''); str = str.replace(/<\/h[^>][0-9]>/gi, ''); str = str.replace (/]*>/ig, ''); // var repl_i1 = /]*>/ig; // str = str.replace (repl_i1, ''); str = str.replace (/]*>/ig, ''); str = str.replace (/<\/DIV>/gi, ''); str = str.replace (/<[\/\w?]+:[^>]*>/ig, ''); str = str.replace (/( ){2,}/ig, ' '); str = str.replace (//ig, ''); str = str.replace (/<\/STRONG>/ig, ''); str = str.replace (//ig, ''); str = str.replace (/<\/TT>/ig, ''); str = str.replace (/]*>/ig, ''); str = str.replace (/<\/FONT>/ig, ''); str = str.replace (/STYLE=\"[^\"]*\"/ig, ''); str = str.replace(/<([\w]+) class=([^ |>]*)([^>]*)/gi, '<$1$3'); str = str.replace(/<([\w]+) style="([^"]*)"([^>]*)/gi, '<$1$3'); str = str.replace(/width=([^ |>]*)([^>]*)/gi, ''); str = str.replace(/classname=([^ |>]*)([^>]*)/gi, ''); str = str.replace(/align=([^ |>]*)([^>]*)/gi, ''); str = str.replace(/valign=([^ |>]*)([^>]*)/gi, ''); str = str.replace(/<\\?\??xml[^>]>/gi, ''); str = str.replace(/<\/?\w+:[^>]*>/gi, ''); str = str.replace(//gi, ''); str = str.replace(/o:/gi, ''); str = str.replace(//gi, ''); str = str.replace(/<\/--[^>]*>/gi, ''); doc.body.innerHTML = str; }, /** * Display an iframe instead of the textarea. * * @param n - ID of textarea to replace * @param settings - object which holds the settings */ _display: function(n, settings) { // Get the textarea element var textarea = $(n); // Validate if textarea exists if(textarea == null) { alert("No textarea found with the given identifier (ID: " + n + ")."); return; } // Validate browser compatiblity if(!WYSIWYG_Core.isBrowserCompatible()) { if(this.config[n].NoValidBrowserMessage != "") { alert(this.config[n].NoValidBrowserMessage); } return; } // Load settings in config array, use the textarea id as identifier if(typeof(settings) != "object") { this.config[n] = new this.Settings(); } else { this.config[n] = settings; } // Hide the textarea textarea.style.display = "none"; // Override the width and height of the editor with the // size given by the style attributes width and height if(textarea.style.width) { this.config[n].Width = textarea.style.width; } if(textarea.style.height) { this.config[n].Height = textarea.style.height } // determine the width + height var currentWidth = this.config[n].Width; var currentHeight = this.config[n].Height; // Calculate the width + height of the editor var ifrmWidth = "100%"; var ifrmHeight = "100%"; if(currentWidth.search(/%/) == -1) { ifrmWidth = currentWidth; ifrmHeight = currentHeight; } // Create iframe which will be used for rich text editing var iframe = '
\n' + '\n' + '
\n'; // Insert after the textArea both toolbar one and two textarea.insertAdjacentHTML("afterEnd", iframe); // Pass the textarea's existing text over to the content variable var content = textarea.value; var doc = this.getEditorWindow(n).document; // Replace all \n with
if(this.config[n].ReplaceLineBreaks) { content = content.replace(/(\r\n)|(\n)/ig, "
"); } // Write the textarea's content into the iframe doc.open(); doc.write(content); doc.close(); // Set default style of the editor window WYSIWYG_Core.setAttribute(doc.body, "style", this.config[n].DefaultStyle); }, /** * Replace the given textarea with wysiwyg editor * * @param n - ID of textarea to replace * @param settings - object which holds the settings */ _generate: function(n, settings) { // Get the textarea element var textarea = $(n); // Validate if textarea exists if(textarea == null) { alert("No textarea found with the given identifier (ID: " + n + ")."); return; } // Validate browser compatiblity if(!WYSIWYG_Core.isBrowserCompatible()) { if(this.config[n].NoValidBrowserMessage != "") { alert(this.config[n].NoValidBrowserMessage); } return; } // Hide the textarea textarea.style.display = 'none'; // Override the width and height of the editor with the // size given by the style attributes width and height if(textarea.style.width) { this.config[n].Width = textarea.style.width; } if(textarea.style.height) { this.config[n].Height = textarea.style.height } // determine the width + height var currentWidth = this.config[n].Width; var currentHeight = this.config[n].Height; // Calculate the width + height of the editor var toolbarWidth = currentWidth; var ifrmWidth = "100%"; var ifrmHeight = "100%"; if(currentWidth.search(/%/) == -1) { toolbarWidth = currentWidth.replace(/px/gi, ""); toolbarWidth = (parseFloat(toolbarWidth) + 2) + "px"; ifrmWidth = currentWidth; ifrmHeight = currentHeight; } // Generate the WYSIWYG Table // This table holds the toolbars and the iframe as the editor var editor = ""; editor += ''; editor += ''; // Status bar HTML code if(this.config[n].StatusBarEnabled) { editor += ''; } editor += '
'; // Output all command buttons that belong to toolbar one for (var j = 0; j < this.config[n].Toolbar.length;j++) { if(this.config[n].Toolbar[j] && this.config[n].Toolbar[j].length > 0) { var toolbar = this.config[n].Toolbar[j]; // Generate WYSIWYG toolbar one editor += ''; editor += ''; for (var i = 0; i < toolbar.length;i++) { if (toolbar[i]) { // Font selection if (toolbar[i] == "font"){ editor += ''; } // Font size selection else if (toolbar[i] == "fontsize"){ editor += ''; } // Button print out else { // Get the values of the Button from the global ToolbarList object var buttonObj = this.ToolbarList[toolbar[i]]; var buttonID = buttonObj[0]; var buttonTitle = buttonObj[1]; var buttonImage = this.config[n].ImagesDir + buttonObj[2]; var buttonImageRollover = this.config[n].ImagesDir + buttonObj[3]; var buttonImageDown = this.config[n].ImagesDir + buttonObj[4]; if (toolbar[i] == "seperator") { editor += ''; } else if (toolbar[i] == "return") { editor += ''; } // View Source button else if (toolbar[i] == "viewSource"){ editor += ''; } else { editor += ''; } } } } editor += '
'; editor += ''; editor += ''; editor += ''; editor += ''; editor += ''; editor += ''; editor += ''; editor += ''; editor += ' 
'; } } editor += '
\n'; // Create iframe which will be used for rich text editing editor += '\n' + '
 
\n'; // Insert the editor after the textarea textarea.insertAdjacentHTML("afterEnd", editor); // Insert the Font Type and Size drop downs into the toolbar // Hide the dynamic drop down lists for the Font Types and Sizes this.outputFontSelect(n); this.outputFontSizes(n); this.hideFonts(n); this.hideFontSizes(n); // Hide the "Text Mode" button // Validate if textMode Elements are prensent if($("textMode" + n)) { $("textMode" + n).style.display = 'none'; } // Pass the textarea's existing text over to the content variable var content = textarea.value; var doc = this.getEditorWindow(n).document; // Replace all \n with
if(this.config[n].ReplaceLineBreaks) { content = content.replace(/\n\r|\n/ig, "
"); } // Write the textarea's content into the iframe doc.open(); doc.write(content); doc.close(); // Make the iframe editable in both Mozilla and IE // Improve compatiblity for IE + Mozilla if (doc.body.contentEditable) { doc.body.contentEditable = true; } else { doc.designMode = "on"; } // Set default font style WYSIWYG_Core.setAttribute(doc.body, "style", this.config[n].DefaultStyle); // Event Handling // Update the textarea with content in WYSIWYG when user submits form for (var idx=0; idx < document.forms.length; idx++) { WYSIWYG_Core.addEvent(document.forms[idx], "submit", function xxx_aa() { WYSIWYG.updateTextArea(n); }); } // close font selection if mouse moves over the editor window WYSIWYG_Core.addEvent(doc, "mouseover", function xxx_bb() { WYSIWYG.hideFonts(n); WYSIWYG.hideFontSizes(n); }); // If it's true invert the line break capability of IE if(this.config[n].InvertIELineBreaks) { WYSIWYG_Core.addEvent(doc, "keypress", function xxx_cc() { WYSIWYG.invertIELineBreakCapability(n); }); } // status bar update if(this.config[n].StatusBarEnabled) { WYSIWYG_Core.addEvent(doc, "mouseup", function xxx_dd() { WYSIWYG.updateStatusBar(n); }); } // custom context menu if(this.config[n].ContextMenu) { WYSIWYG_ContextMenu.init(n); } // init viewTextMode var this.viewTextMode[n] = false; }, /* ---------------------------------------------------------------------- *\ Function : disable() Description : Disable the given WYSIWYG Editor Box Usage : WYSIWYG.disable(textareaID) Arguments : textareaID - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ disable: function(textareaID) { // set n to textareaID var n = textareaID; // get the editor window var editor = this.getEditorWindow(n); // Validate if editor exists if(editor == null) { alert("No editor found with the given identifier (ID: " + n + ")."); return; } if(editor) { // disable design mode or content editable feature if(editor.document.body.contentEditable) { editor.document.body.contentEditable = false; } else { editor.document.designMode = "Off"; } // change the style of the body WYSIWYG_Core.setAttribute(editor.document.body, "style", this.config[n].DisabledStyle); // hide the status bar this.hideStatusBar(n); // hide all toolbars this.hideToolbars(n); } }, /* ---------------------------------------------------------------------- *\ Function : enable() Description : Enables the given WYSIWYG Editor Box Usage : WYSIWYG.enable(textareaID) Arguments : textareaID - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ enable: function(textareaID) { // set n to textareaID var n = textareaID; // get the editor window var editor = this.getEditorWindow(n); // Validate if editor exists if(editor == null) { alert("No editor found with the given identifier (ID: " + n + ")."); return; } if(editor) { // disable design mode or content editable feature if(editor.document.body.contentEditable){ editor.document.body.contentEditable = true; } else { editor.document.designMode = "On"; } // change the style of the body WYSIWYG_Core.setAttribute(editor.document.body, "style", this.config[n].DefaultStyle); // hide the status bar this.showStatusBar(n); // hide all toolbars this.showToolbars(n); } }, /* ---------------------------------------------------------------------- *\ Function : getNodeTree() Description : Returns the node structure of the current selection as array Usage : WYSIWYG.getNodeTree(n); Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ getNodeTree: function(n) { var sel = this.getSelection(n); var range = this.getRange(sel); // get element of range var tag = this.getTag(range); if(tag == null) { return; } // get parent of element var node = this.getParent(tag); // init the tree as array with the current selected element var nodeTree = new Array(tag); // get all parent nodes var ii = 1; while(node != null && node.nodeName != "#document") { nodeTree[ii] = node; node = this.getParent(node); ii++; } return nodeTree; }, /** * Removes the current node of the selection * * @param {String} n The editor identifier (the textarea's ID) */ removeNode: function(n) { // get selection and range var sel = this.getSelection(n); var range = this.getRange(sel); // the current tag of range var tag = this.getTag(range); var parent = tag.parentNode; if(tag == null || parent == null) { return; } if(tag.nodeName == "HTML" || tag.nodeName == "BODY") { return; } // copy child elements of the node to the parent element before remove the node //var childNodes = new Array(); //for(var i=0; i < tag.childNodes.length;i++) // childNodes[i] = tag.childNodes[i]; //for(var i=0; i < childNodes.length;i++) // parent.insertBefore(childNodes[i], tag); // remove node parent.removeChild(tag); // validate if parent is a link and the node is only // surrounded by the link, then remove the link too if(parent.nodeName == "A" && !parent.hasChildNodes()) { if(parent.parentNode) { parent.parentNode.removeChild(parent); } } // update the status bar this.updateStatusBar(n); }, /** * Get the selection of the given editor * * @param n The editor identifier (the textarea's ID) */ getSelection: function(n) { var ifrm = this.getEditorWindow(n); var doc = ifrm.document; var sel = null; if(ifrm.getSelection){ sel = ifrm.getSelection(); } else if (doc.getSelection) { sel = doc.getSelection(); } else if (doc.selection) { sel = doc.selection; } return sel; }, /* ---------------------------------------------------------------------- *\ Function : updateStatusBar() Description : Updates the status bar with the current node tree Usage : WYSIWYG.updateStatusBar(n); Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ updateStatusBar: function(n) { // get the node structure var nodeTree = this.getNodeTree(n); if(nodeTree == null) { return; } // format the output var outputTree = ""; var max = nodeTree.length - 1; for(var i=max;i>=0;i--) { if(nodeTree[i].nodeName != "HTML" && nodeTree[i].nodeName != "BODY") { outputTree += '' + nodeTree[i].nodeName + ''; } else { outputTree += nodeTree[i].nodeName; } if(i > 0) { outputTree += " > "; } } // update the status bar var statusbar = $("wysiwyg_statusbar_" + n); if(statusbar){ statusbar.innerHTML = outputTree; } }, /* ---------------------------------------------------------------------- *\ Function : disableDesignMode() Description : Disable the design mode if right mouse button is pressed. It's needed for custom context menus on mozilla (firefox), because if design mode is on then you can`t diabled the browser context menu. Usage : WYSIWYG.disableDesignMode(e, n); Arguments : event - browser event (like which button pressed) n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ disableDesignMode: function(event, n) { var doc = this.getEditorWindow(n).document; if(event.which == 3) { doc.designMode = "off"; return false; } else if(event.which != 3 && doc.designMode == "off") { doc.designMode = "on"; return true; } }, /* ---------------------------------------------------------------------- *\ Function : formatText() (changed) Description : Format the content within the WYSIWYG Editor Usage : WYSIWYG.formatText(id, n, selected); Arguments : cmd - The execCommand (e.g. Bold) n - The editor identifier that the command affects (the textarea's ID) selected - The selected value when applicable (e.g. Arial) \* ---------------------------------------------------------------------- */ formatText: function(cmd, n, selected) { // When user clicks toolbar button make sure it always targets its respective WYSIWYG this.getEditorWindow(n).focus(); // When in Text Mode these execCommands are disabled var formatIDs = new Array("FontSize","FontName","Bold","Italic","Underline","Subscript","Superscript","Strikethrough","Justifyleft","Justifyright","Justifycenter","InsertUnorderedList","InsertOrderedList","Indent","Outdent","ForeColor","BackColor","InsertImage","InsertTable","CreateLink", "Preview", "RemoveFormat"); // Check if button clicked is in disabled list for (var i = 0; i < formatIDs.length; i++) { if (formatIDs[i] == cmd) { var disabled_id = 1; } } // rbg to hex convertion implementation dependents on browser var toHexColor = WYSIWYG_Core.isMSIE ? WYSIWYG_Core._dec_to_rgb : WYSIWYG_Core.toHexColor; // popup screen positions var popupPosition = {left: parseInt(window.screen.availWidth / 8), top: parseInt(window.screen.availHeight / 4)}; // Check if in Text Mode and disabled button was clicked if (this.viewTextMode[n] == true && disabled_id == 1) { alert("You are in TEXT Mode. This feature has been disabled."); return; } // Check the insert image popup implementation var imagePopupFile = this.config[n].PopupsDir + 'insert_image.html'; var imagePopupWidth = 400; var imagePopupHeight = 215; if(typeof this.config[n].ImagePopupFile != "undefined" && this.config[n].ImagePopupFile != "") { imagePopupFile = this.config[n].ImagePopupFile; } if(typeof this.config[n].ImagePopupWidth && this.config[n].ImagePopupWidth > 0) { imagePopupWidth = this.config[n].ImagePopupWidth; } if(typeof this.config[n].ImagePopupHeight && this.config[n].ImagePopupHeight > 0) { imagePopupHeight = this.config[n].ImagePopupHeight; } // switch which action have to do switch(cmd) { // Font size case "FontSize": this.getEditorWindow(n).document.execCommand("FontSize", false, selected); break; // FontName case "FontName": this.getEditorWindow(n).document.execCommand("FontName", false, selected); break; // ForeColor and case "ForeColor": var rgb = this.getEditorWindow(n).document.queryCommandValue(cmd); var currentColor = rgb != '' ? toHexColor(this.getEditorWindow(n).document.queryCommandValue(cmd)) : "000000"; window.open(this.config[n].PopupsDir + 'select_color.html?color=' + currentColor + '&command=' + cmd + '&wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,width=210,height=165,top=' + popupPosition.top + ',left=' + popupPosition.left).focus(); break; // BackColor case "BackColor": var currentColor = toHexColor(this.getEditorWindow(n).document.queryCommandValue(cmd)); window.open(this.config[n].PopupsDir + 'select_color.html?color=' + currentColor + '&command=' + cmd + '&wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,width=210,height=165,top=' + popupPosition.top + ',left=' + popupPosition.left).focus(); break; // InsertImage case "InsertImage": window.open(imagePopupFile + '?wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,resizable=0,width=' + imagePopupWidth + ',height=' + imagePopupHeight + ',top=' + popupPosition.top + ',left=' + popupPosition.left).focus(); break; // Remove Image case "RemoveImage": this.removeImage(n); break; // Remove Link case "RemoveLink": this.removeLink(n); break; // Remove a Node case "RemoveNode": this.removeNode(n); break; // Create Link case "CreateLink": window.open(this.config[n].PopupsDir + 'insert_hyperlink.html?wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,resizable=0,width=350,height=160,top=' + popupPosition.top + ',left=' + popupPosition.left).focus(); break; // InsertTable case "InsertTable": window.open(this.config[n].PopupsDir + 'create_table.html?wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,resizable=0,width=400,height=360,top=' + popupPosition.top + ',left=' + popupPosition.left).focus(); break; // ViewSource case "ViewSource": this.viewSource(n); break; // ViewText case "ViewText": this.viewText(n); break; // Help case "Help": window.open(this.config[n].PopupsDir + 'about.html?wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,resizable=0,width=400,height=350,top=' + popupPosition.top + ',left=' + popupPosition.left).focus(); break; // Strip any HTML added by word case "RemoveFormat": this.removeFormat(n); break; // Preview thx to Korvo case "Preview": window.open('http://www.brannsikker.com/default.asp?pageID=preview&wysiwyg=' + n + '&preview=' + this.config[n].Preview,'popup', 'location=0,status=0,scrollbars=1,resizable=1,width=' + this.config[n].PreviewWidth + ',height=' + this.config[n].PreviewHeight + ',top=' + popupPosition.top + ',left=' + popupPosition.left).focus(); break; // Print case "Print": this.print(n); break; // Save case "Save": WYSIWYG.updateTextArea(n); document.getElementById(this.config[n].FormName).submit(); break; // Save and close case "Saveclose": WYSIWYG.updateTextArea(n); document.getElementById(this.config[n].FormName).submit(); break; // Return case "Return": history.go(-1); break; default: WYSIWYG_Core.execCommand(n, cmd); } // hide node the font + font size selection this.hideFonts(n); this.hideFontSizes(n); }, /* ---------------------------------------------------------------------- *\ Function : insertHTML() Description : Insert HTML into WYSIWYG in rich text Usage : WYSIWYG.insertHTML("hello", "textareaID") Arguments : html - The HTML being inserted (e.g. hello) n - The editor identifier that the HTML will be inserted into (the textarea's ID) \* ---------------------------------------------------------------------- */ insertHTML: function(html, n) { if (WYSIWYG_Core.isMSIE) { this.getEditorWindow(n).document.selection.createRange().pasteHTML(html); } else { var span = this.getEditorWindow(n).document.createElement("span"); span.innerHTML = html; this.insertNodeAtSelection(span, n); } }, /* ---------------------------------------------------------------------- *\ Function : insertNodeAtSelection() Description : insert HTML into WYSIWYG in rich text (mozilla) Usage : WYSIWYG.insertNodeAtSelection(insertNode, n) Arguments : insertNode - The HTML being inserted (must be innerHTML inserted within a div element) n - The editor identifier that the HTML will be inserted into (the textarea's ID) \* ---------------------------------------------------------------------- */ insertNodeAtSelection: function(insertNode, n) { // get editor document var doc = this.getEditorWindow(n).document; // get current selection var sel = this.getSelection(n); // get the first range of the selection // (there's almost always only one range) var range = sel.getRangeAt(0); // deselect everything sel.removeAllRanges(); // remove content of current selection from document range.deleteContents(); // get location of current selection var container = range.startContainer; var pos = range.startOffset; // make a new range for the new selection range = doc.createRange(); if (container.nodeType==3 && insertNode.nodeType==3) { // if we insert text in a textnode, do optimized insertion container.insertData(pos, insertNode.data); // put cursor after inserted text range.setEnd(container, pos+insertNode.length); range.setStart(container, pos+insertNode.length); } else { var afterNode; var beforeNode; if (container.nodeType==3) { // when inserting into a textnode // we create 2 new textnodes // and put the insertNode in between var textNode = container; container = textNode.parentNode; var text = textNode.nodeValue; // text before the split var textBefore = text.substr(0,pos); // text after the split var textAfter = text.substr(pos); beforeNode = document.createTextNode(textBefore); afterNode = document.createTextNode(textAfter); // insert the 3 new nodes before the old one container.insertBefore(afterNode, textNode); container.insertBefore(insertNode, afterNode); container.insertBefore(beforeNode, insertNode); // remove the old node container.removeChild(textNode); } else { // else simply insert the node afterNode = container.childNodes[pos]; container.insertBefore(insertNode, afterNode); } range.setEnd(afterNode, 0); range.setStart(afterNode, 0); } sel.addRange(range); }, /* ---------------------------------------------------------------------- *\ Function : print() Description : Print out the content of the WYSIWYG editor area Usage : WYSIWYG.print(n) Arguments : n - The editor identifier (textarea ID) \* ---------------------------------------------------------------------- */ print: function(n) { if(document.all && navigator.appVersion.substring(22,23)==4) { var doc = this.getEditorWindow(n).document; doc.focus(); var OLECMDID_PRINT = 6; var OLECMDEXECOPT_DONTPROMPTUSER = 2; var OLECMDEXECOPT_PROMPTUSER = 1; var WebBrowser = ''; doc.body.insertAdjacentHTML('beforeEnd',WebBrowser); WebBrowser.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER); WebBrowser.outerHTML = ''; } else { this.getEditorWindow(n).print(); } }, /* ---------------------------------------------------------------------- *\ Function : outputFontSelect() Description : creates the Font Select drop down and inserts it into the toolbar Usage : WYSIWYG.outputFontSelect(n) Arguments : n - The editor identifier that the Font Select will update when making font changes (the textarea's ID) \* ---------------------------------------------------------------------- */ outputFontSelect: function(n) { var fontDiv = $('FontSelect' + n); if(fontDiv == null) { return; } var fonts = this.config[n].Fonts; var FontSelectObj = this.ToolbarList['selectfont']; var FontSelect = this.config[n].ImagesDir + FontSelectObj[2]; var FontSelectOn = this.config[n].ImagesDir + FontSelectObj[3]; fonts.sort(); var FontSelectDropDown = new Array; FontSelectDropDown[n] = '

'; FontSelectDropDown[n] += ''; for (var i = 0; i < fonts.length;i++) { if (fonts[i]) { FontSelectDropDown[n] += '
'; } } FontSelectDropDown[n] += '
'; fontDiv.insertAdjacentHTML("afterBegin", FontSelectDropDown[n]); }, /* ---------------------------------------------------------------------- *\ Function : outputFontSizes() Description : creates the Font Sizes drop down and inserts it into the toolbar Usage : WYSIWYG.outputFontSelect(n) Arguments : n - The editor identifier that the Font Sizes will update when making font changes (the textarea's ID) \* ---------------------------------------------------------------------- */ outputFontSizes: function(n) { var fontSizeDiv = $('FontSizes' + n); if(fontSizeDiv == null) { return; } var fontSize = this.config[n].Fontsizes; var FontSizeObj = this.ToolbarList['selectsize']; var FontSize = this.config[n].ImagesDir + FontSizeObj[2]; var FontSizeOn = this.config[n].ImagesDir + FontSizeObj[3]; fontSize.sort(); var FontSizesDropDown = new Array; FontSizesDropDown[n] = '

'; FontSizesDropDown[n] += ''; for (var i = 0; i < fontSize.length;i++) { if (fontSize[i]) { FontSizesDropDown[n] += '
'; } } FontSizesDropDown[n] += '
'; fontSizeDiv.insertAdjacentHTML("afterBegin", FontSizesDropDown[n]); }, /* ---------------------------------------------------------------------- *\ Function : hideFonts() Description : Hides the list of font names in the font select drop down Usage : WYSIWYG.hideFonts(n) Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ hideFonts: function(n) { if($('Fonts' + n)) { $('Fonts' + n).style.display = 'none'; } }, /* ---------------------------------------------------------------------- *\ Function : hideFontSizes() Description : Hides the list of font sizes in the font sizes drop down Usage : WYSIWYG.hideFontSizes(n) Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ hideFontSizes: function(n) { if($('Sizes' + n)) { $('Sizes' + n).style.display = 'none'; } }, /* ---------------------------------------------------------------------- *\ Function : showFonts() Description : Shows the list of font names in the font select drop down Usage : WYSIWYG.showFonts(n) Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ showFonts: function(n) { if($('Fonts' + n) == null) { return; } if ($('Fonts' + n).style.display == 'block') { $('Fonts' + n).style.display = 'none'; } else { $('Fonts' + n).style.display = 'block'; $('Fonts' + n).style.position = 'absolute'; } // hide font size selection this.hideFontSizes(n); }, /* ---------------------------------------------------------------------- *\ Function : showFontSizes() Description : Shows the list of font sizes in the font sizes drop down Usage : WYSIWYG.showFonts(n) Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ showFontSizes: function(n) { if($('Sizes' + n) == null) { return; } if ($('Sizes' + n).style.display == 'block') { $('Sizes' + n).style.display = 'none'; } else { $('Sizes' + n).style.display = 'block'; $('Sizes' + n).style.position = 'absolute'; } // hide font size selection this.hideFonts(n); }, /* ---------------------------------------------------------------------- *\ Function : viewSource() Description : Shows the HTML source code generated by the WYSIWYG editor Usage : WYSIWYG.showFonts(n) Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ viewSource: function(n) { // document var doc = this.getEditorWindow(n).document; // View Source for IE if (WYSIWYG_Core.isMSIE) { var iHTML = doc.body.innerHTML; // strip off the absolute urls iHTML = this.stripURLPath(n, iHTML); // replace all decimal color strings with hex decimal color strings iHTML = WYSIWYG_Core.replaceRGBWithHexColor(iHTML); doc.body.innerText = iHTML; } // View Source for Mozilla/Netscape else { // replace all decimal color strings with hex decimal color strings var html = WYSIWYG_Core.replaceRGBWithHexColor(doc.body.innerHTML); html = document.createTextNode(html); doc.body.innerHTML = ""; doc.body.appendChild(html); } // Hide the HTML Mode button and show the Text Mode button // Validate if Elements are present if($('HTMLMode' + n)) { $('HTMLMode' + n).style.display = 'none'; } if($('textMode' + n)) { $('textMode' + n).style.display = 'block'; } // set the font values for displaying HTML source doc.body.style.fontSize = "12px"; doc.body.style.fontFamily = "Courier New"; this.viewTextMode[n] = true; }, /* ---------------------------------------------------------------------- *\ Function : viewSource() Description : Shows the HTML source code generated by the WYSIWYG editor Usage : WYSIWYG.showFonts(n) Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ viewText: function(n) { // get document var doc = this.getEditorWindow(n).document; // View Text for IE if (WYSIWYG_Core.isMSIE) { var iText = doc.body.innerText; // strip off the absolute urls iText = this.stripURLPath(n, iText); // replace all decimal color strings with hex decimal color strings iText = WYSIWYG_Core.replaceRGBWithHexColor(iText); doc.body.innerHTML = iText; } // View Text for Mozilla/Netscape else { var html = doc.body.ownerDocument.createRange(); html.selectNodeContents(doc.body); // replace all decimal color strings with hex decimal color strings html = WYSIWYG_Core.replaceRGBWithHexColor(html.toString()); doc.body.innerHTML = html; } // Hide the Text Mode button and show the HTML Mode button // Validate if Elements are present if($('textMode' + n)) { $('textMode' + n).style.display = 'none'; } if($('HTMLMode' + n)) { $('HTMLMode' + n).style.display = 'block'; } // reset the font values (changed) WYSIWYG_Core.setAttribute(doc.body, "style", this.config[n].DefaultStyle); this.viewTextMode[n] = false; }, /* ---------------------------------------------------------------------- *\ Function : getDocumentPath() Description : Get the path of the given document Usage : WYSIWYG.getDocumentPath(doc) Arguments : doc - Document of which you get the the path \* ---------------------------------------------------------------------- */ getDocumentPathOfUrl: function(url) { var path = null; // if local file system, convert local url into web url url = url.replace(/file:\/\//gi, "file:///"); url = url.replace(/\\/gi, "\/"); var pos = url.lastIndexOf("/"); if(pos != -1) { path = url.substring(0, pos + 1); } return path; }, /* ---------------------------------------------------------------------- *\ Function : getDocumentUrl() Description : Get the documents url, convert local urls to web urls Usage : WYSIWYG.getDocumentUrl(doc) Arguments : doc - Document of which you get the the path \* ---------------------------------------------------------------------- */ getDocumentUrl: function(doc) { // if local file system, convert local url into web url var url = doc.URL; url = url.replace(/file:\/\//gi, "file:///"); url = url.replace(/\\/gi, "\/"); return url; }, /* ---------------------------------------------------------------------- *\ Function : stripURLPath() Description : Strips off the defined image and the anchor urls of the given content. It also can strip the document URL automatically if you define auto. Usage : WYSIWYG.stripURLPath(content) Arguments : content - Content on which the stripping applies \* ---------------------------------------------------------------------- */ stripURLPath: function(n, content, exact) { // parameter exact is optional if(typeof exact == "undefined") { exact = true; } var stripImgageUrl = null; var stripAnchorUrl = null; // add url to strip of anchors to array if(this.config[n].AnchorPathToStrip == "auto") { stripAnchorUrl = this.getDocumentUrl(document); } else if(this.config[n].AnchorPathToStrip != "") { stripAnchorUrl = this.config[n].AnchorPathToStrip; } // add strip url of images to array if(this.config[n].ImagePathToStrip == "auto") { stripImgageUrl = this.getDocumentUrl(document); } else if(this.config[n].ImagePathToStrip != "") { stripImgageUrl = this.config[n].ImagePathToStrip; } var url; var regex; var result; // strip url of image path if(stripImgageUrl) { // escape reserved characters to be a valid regex url = WYSIWYG_Core.stringToRegex(this.getDocumentPathOfUrl(stripImgageUrl)); // exact replacing of url. regex: src="" if(exact) { regex = eval("/(src=\")(" + url + ")([^\"]*)/gi"); content = content.replace(regex, "$1$3"); } // not exect replacing of url. regex: else { regex = eval("/(" + url + ")(.+)/gi"); content = content.replace(regex, "$2"); } // strip absolute urls without a heading slash ("images/print.gif") result = this.getDocumentPathOfUrl(stripImgageUrl).match(/.+[\/]{2,3}[^\/]*/,""); if(result) { url = WYSIWYG_Core.stringToRegex(result[0]); // exact replacing of url. regex: src="" if(exact) { regex = eval("/(src=\")(" + url + ")([^\"]*)/gi"); content = content.replace(regex, "$1$3"); } // not exect replacing of url. regex: else { regex = eval("/(" + url + ")(.+)/gi"); content = content.replace(regex, "$2"); } } } // strip url of image path if(stripAnchorUrl) { // escape reserved characters to be a valid regex url = WYSIWYG_Core.stringToRegex(this.getDocumentPathOfUrl(stripAnchorUrl)); // strip absolute urls with a heading slash ("/product/index.html") // exact replacing of url. regex: src="" if(exact) { regex = eval("/(href=\")(" + url + ")([^\"]*)/gi"); content = content.replace(regex, "$1$3"); } // not exect replacing of url. regex: else { regex = eval("/(" + url + ")(.+)/gi"); content = content.replace(regex, "$2"); } // strip absolute urls without a heading slash ("product/index.html") result = this.getDocumentPathOfUrl(stripAnchorUrl).match(/.+[\/]{2,3}[^\/]*/,""); if(result) { url = WYSIWYG_Core.stringToRegex(result[0]); // exact replacing of url. regex: src="" if(exact) { regex = eval("/(href=\")(" + url + ")([^\"]*)/gi"); content = content.replace(regex, "$1$3"); } // not exect replacing of url. regex: else { regex = eval("/(" + url + ")(.+)/gi"); content = content.replace(regex, "$2"); } } // stip off anchor links with #name url = WYSIWYG_Core.stringToRegex(stripAnchorUrl); // exact replacing of url. regex: src="" if(exact) { regex = eval("/(href=\")(" + url + ")(#[^\"]*)/gi"); content = content.replace(regex, "$1$3"); } // not exect replacing of url. regex: else { regex = eval("/(" + url + ")(.+)/gi"); content = content.replace(regex, "$2"); } // stip off anchor links with #name (only for local system) url = this.getDocumentUrl(document); var pos = url.lastIndexOf("/"); if(pos != -1) { url = url.substring(pos + 1, url.length); url = WYSIWYG_Core.stringToRegex(url); // exact replacing of url. regex: src="" if(exact) { regex = eval("/(href=\")(" + url + ")(#[^\"]*)/gi"); content = content.replace(regex, "$1$3"); } // not exect replacing of url. regex: else { regex = eval("/(" + url + ")(.+)/gi"); content = content.replace(regex, "$2"); } } } return content; }, /* ---------------------------------------------------------------------- *\ Function : updateTextArea() Description : Updates the text area value with the HTML source of the WYSIWYG Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ updateTextArea: function(n) { // on update switch editor back to html mode if(this.viewTextMode[n]) { this.viewText(n); } // get inner HTML var content = this.getEditorWindow(n).document.body.innerHTML; // strip off defined URLs on IE content = this.stripURLPath(n, content); // replace all decimal color strings with hex color strings content = WYSIWYG_Core.replaceRGBWithHexColor(content); // remove line breaks before content will be updated if(this.config[n].ReplaceLineBreaks) { content = content.replace(/(\r\n)|(\n)/ig, ""); } // set content back in textarea $(n).value = content; }, /* ---------------------------------------------------------------------- *\ Function : hideToolbars() Description : Hide all toolbars Usage : WYSIWYG.hideToolbars(n) Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ hideToolbars: function(n) { for(var i=0;i 0) { elmWorking = range.item(0); } else { elmWorking = range.parentElement(); } while (elmWorking.tagName != "HTML") { if (elmWorking.tagName == parentTagName){ return elmWorking; } else { elmWorking = elmWorking.parentElement; } } rangeWorking = range.duplicate(); rangeWorking.collapse(true); rangeWorking.moveEnd("character", 1); if (rangeWorking.text.length>0) { while (rangeWorking.compareEndPoints("EndToEnd", range) < 0){ rangeWorking.move("Character"); if (null != this.findParentTag(parentTagName, rangeWorking)){ return this.findParentTag(parentTagName, rangeWorking); } } } return null; } } catch(e) { return null; } }, /* ---------------------------------------------------------------------- *\ Function : getTag() Description : Get the acutally tag of the given range Usage : WYSIWYG.getTag(range) Arguments : range - Range \* ---------------------------------------------------------------------- */ getTag: function(range) { try { if(!WYSIWYG_Core.isMSIE) { var node = range.startContainer; var pos = range.startOffset; if(node.nodeType != 3) { node = node.childNodes[pos]; } if(node.nodeName && node.nodeName.search(/#/) != -1) { return node.parentNode; } return node; } else { if(range.length > 0) { return range.item(0); } else if(range.parentElement()) { return range.parentElement(); } } return null; } catch(e) { return null; } }, /* ---------------------------------------------------------------------- *\ Function : getParent() Description : Get the parent node of an node Usage : WYSIWYG.getParent(node) Arguments : element - Element which parent will be returned \* ---------------------------------------------------------------------- */ getParent: function(element) { if(element.parentNode) { return element.parentNode; } return null; }, /* ---------------------------------------------------------------------- *\ Function : getTextRange() Description : Get the text range object of the given element Usage : WYSIWYG.getTextRange(element) Arguments : element - An element of which you get the text range object \* ---------------------------------------------------------------------- */ getTextRange: function(element){ var range = element.parentTextEdit.createTextRange(); range.moveToElementText(element); return range; }, /* ---------------------------------------------------------------------- *\ Function : invertIELineBreakCapability() Description : Inverts the line break capability of IE (Thx to richyrich) Normal: ENTER =

, SHIFT + ENTER =
Inverted: ENTER =
, SHIFT + ENTER =

Usage : WYSIWYG.invertIELineBreakCapability(n) Arguments : n - The editor identifier (the textarea's ID) \* ---------------------------------------------------------------------- */ invertIELineBreakCapability: function(n) { var editor = this.getEditorWindow(n); var sel; // validate if the press key is the carriage return key if (editor.event.keyCode==13) { if (!editor.event.shiftKey) { sel = this.getRange(this.getSelection(n)); sel.pasteHTML("
"); editor.event.cancelBubble = true; editor.event.returnValue = false; sel.select(); sel.moveEnd("character", 1); sel.moveStart("character", 1); sel.collapse(false); return false; } else { sel = this.getRange(this.getSelection(n)); sel.pasteHTML("

"); editor.event.cancelBubble = true; editor.event.returnValue = false; sel.select(); sel.moveEnd("character", 1); sel.moveStart("character", 1); sel.collapse(false); return false; } } }, /* ---------------------------------------------------------------------- *\ Function : selectNode() Description : Select a node within the current editor Usage : WYSIWYG.selectNode(n, level) Arguments : n - The editor identifier (the textarea's ID) level - identifies the level of the element which will be selected \* ---------------------------------------------------------------------- */ selectNode: function(n, level) { var sel = this.getSelection(n); var range = this.getRange(sel); var parentnode = this.getTag(range); var i = 0; for (var node=parentnode; (node && (node.nodeType == 1)); node=node.parentNode) { if (i == level) { this.nodeSelection(n, node); } i++; } this.updateStatusBar(n); }, /* ---------------------------------------------------------------------- *\ Function : nodeSelection() Description : Do the node selection Usage : WYSIWYG.nodeSelection(n, node) Arguments : n - The editor identifier (the textarea's ID) node - The node which will be selected \* ---------------------------------------------------------------------- */ nodeSelection: function(n, node) { var doc = this.getEditorWindow(n).document; var sel = this.getSelection(n); var range = this.getRange(sel); if(!WYSIWYG_Core.isMSIE) { if (node.nodeName == "BODY") { range.selectNodeContents(node); } else { range.selectNode(node); } /* if (endNode) { try { range.setStart(node, startOffset); range.setEnd(endNode, endOffset); } catch(e) { } } */ if (sel) { sel.removeAllRanges(); } if (sel) { sel.addRange(range); } } else { // MSIE may not select everything when BODY is selected - // start may be set to first text node instead of first non-text node - // no known workaround if ((node.nodeName == "TABLE") || (node.nodeName == "IMG") || (node.nodeName == "INPUT") || (node.nodeName == "SELECT") || (node.nodeName == "TEXTAREA")) { try { range = doc.body.createControlRange(); range.addElement(node); range.select(); } catch(e) { } } else { range = doc.body.createTextRange(); if (range) { range.collapse(); if (range.moveToElementText) { try { range.moveToElementText(node); range.select(); } catch(e) { try { range = doc.body.createTextRange(); range.moveToElementText(node); range.select(); } catch(e) {} } } else { try { range = doc.body.createTextRange(); range.moveToElementText(node); range.select(); } catch(e) {} } } } } } } /******************************************************************** * openWYSIWYG core functions Copyright (c) 2006 openWebWare.com * Contact us at devs@openwebware.com * This copyright notice MUST stay intact for use. * * $Id: wysiwyg.js,v 1.10 2006/12/25 09:17:07 xhaggi Exp $ ********************************************************************/ var WYSIWYG_Core = { /** * Holds true if browser is MSIE, otherwise false */ isMSIE: navigator.appName == "Microsoft Internet Explorer" ? true : false, /** * Holds true if browser is Firefox (Mozilla) */ isFF: !document.all && document.getElementById && !this.isOpera, /** * Holds true if browser is Opera, otherwise false */ isOpera: navigator.appName == "Opera" ? true : false, /** * Trims whitespaces of the given string * * @param str String * @return Trimmed string */ trim: function(str) { return str.replace(/^\s*|\s*$/g,""); }, /** * Determine if the given parameter is defined * * @param p Parameter * @return true/false dependents on definition of the parameter */ defined: function(p) { return typeof p == "undefined" ? false : true; }, /** * Determine if the browser version is compatible * * @return true/false depending on compatiblity of the browser */ isBrowserCompatible: function() { // Validate browser and compatiblity if ((navigator.userAgent.indexOf('Safari') != -1 ) || !document.getElementById || !document.designMode){ //no designMode (Safari lies) return false; } return true; }, /** * Set the style attribute of the given element. * Private method to solve the IE bug while setting the style attribute. * * @param element The element on which the style attribute will affect * @param style Stylesheet which will be set */ _setStyleAttribute: function(element, style) { var styles = style.split(";"); var pos; for(var i=0;i>= 8; // drop low byte var nybble2 = myByte & 0x0F; // get low nybble (4 bits) var nybble1 = (myByte >> 4) & 0x0F; // get high nybble hex_string += nybble1.toString(16); // convert nybble to hex hex_string += nybble2.toString(16); // convert nybble to hex } return hex_string.toUpperCase(); }, /** * Replace RGB color strings with hex color strings within a string. * * @param {String} str RGB String * @param {String} Hex color string */ replaceRGBWithHexColor: function(str) { // find all decimal color strings var matcher = str.match(/rgb\([0-9 ]+,[0-9 ]+,[0-9 ]+\)/gi); if(matcher) { for(var j=0; j'; item += '' + title + ''; item += ''; } else { item += ''; item += ''; item += '' + title + ''; item += ''; } this.html += item; }, /** * Add seperator to context menu */ addSeperator: function() { var output = ''; output += ''; output += '


'; output += ''; this.html += output; } } /** * Get an element by it's identifier * * @param id Element identifier */ function $(id) { return document.getElementById(id); } /** * Emulates insertAdjacentHTML(), insertAdjacentText() and * insertAdjacentElement() three functions so they work with Netscape 6/Mozilla * by Thor Larholm me@jscript.dk */ if(typeof HTMLElement!="undefined" && !HTMLElement.prototype.insertAdjacentElement){ HTMLElement.prototype.insertAdjacentElement = function (where,parsedNode) { switch (where){ case 'beforeBegin': this.parentNode.insertBefore(parsedNode,this); break; case 'afterBegin': this.insertBefore(parsedNode,this.firstChild); break; case 'beforeEnd': this.appendChild(parsedNode); break; case 'afterEnd': if (this.nextSibling) { this.parentNode.insertBefore(parsedNode,this.nextSibling); } else { this.parentNode.appendChild(parsedNode); } break; } }; HTMLElement.prototype.insertAdjacentHTML = function (where,htmlStr) { var r = this.ownerDocument.createRange(); r.setStartBefore(this); var parsedHTML = r.createContextualFragment(htmlStr); this.insertAdjacentElement(where,parsedHTML); }; HTMLElement.prototype.insertAdjacentText = function (where,txtStr) { var parsedText = document.createTextNode(txtStr); this.insertAdjacentElement(where,parsedText); }; } var news = new WYSIWYG.Settings(); news.Width = "500px"; news.Height = "380px"; news.FormName = "article"; news.Preview = "news"; news.Toolbar[0] = new Array("bold", "italic", "underline", "strikethrough", "seperator", "forecolor", "backcolor", "seperator", "justifyleft", "justifycenter", "justifyright", "seperator", "unorderedlist", "orderedlist", "outdent", "indent"); news.Toolbar[1] = new Array("subscript", "superscript", "seperator", "cut", "copy", "paste", "removeformat", "seperator", "undo", "redo", "seperator", "inserttable", "insertimage", "createlink", "seperator", "preview", "print", "seperator", "viewSource"); var full = new WYSIWYG.Settings(); full.Width = "890px"; full.Height = "410px"; full.FormName = "edit";