/******************************************************************** * 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; font-size: 12px; background-color: #FFFFFF"; // Stylesheet if editor is disabled this.DisabledStyle = "font-family: Arial; font-size: 12px; background-color: #EEEEEE"; // Width + Height of the preview window this.PreviewWidth = 940; this.PreviewHeight = 400; // 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( "font", "fontsize", "bold", "italic", "underline", "strikethrough", "seperator", "forecolor", "backcolor", "seperator", "justifyleft", "justifycenter", "justifyright", "seperator", "unorderedlist", "orderedlist", "outdent", "indent" ); this.Toolbar[1] = new Array( "save", "seperator", "subscript", "superscript", "seperator", "cut", "copy", "paste", "removeformat", "seperator", "undo", "redo", "seperator", "inserttable", "insertimage", "createlink", "seperator", "preview", "print", "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(this.config[n].PopupsDir + 'preview.html?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("font", "fontsize", "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 = "475px"; full.FormName = "edit";