/******************************************************************** * openWYSIWYG v1.47 Copyright (c) 2006 openWebWare.com  * Contact us at devs@openwebware.com * This copyright notice MUST stay intact for use. * * $Id: wysiwyg.js,v 1.22 2007/09/08 21:45:57 xhaggi Exp $ * $Revision: 1.22 $ * * 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 = "images/";				// Popups Directory		this.PopupsDir = "popups/";				// CSS Directory File		this.CSSFile = "styles/wysiwyg.css";						// Default WYSIWYG width and height (use px or %)		this.Width = "500px";		this.Height = "200px";				// 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 = 500;		this.PreviewHeight = 400;				// 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 = <p> , SHIFT + ENTER = <br>		// Inverted: ENTER = <br>, SHIFT + ENTER = <p>		this.InvertIELineBreaks = false;				// Replace line breaks with <br> tags		this.ReplaceLineBreaks = false;      		// Page that opened the WYSIWYG (Used for the return command)		this.Opener = "admin.asp";				// 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",			"headings",				"bold", 			"italic", 			"underline", 			"strikethrough",			"seperator", 			"forecolor", 			"backcolor", 			"seperator",			"justifyfull", 			"justifyleft", 			"justifycenter", 			"justifyright", 			"seperator", 			"unorderedlist", 			"orderedlist",			"outdent", 			"indent"		);		this.Toolbar[1] = new Array(			"save",			// "return",  // return button disabled by default			"seperator", 			"subscript", 			"superscript", 			"seperator", 			"cut", 			"copy", 			"paste",			"removeformat",			"seperator", 			"undo", 			"redo", 			"seperator", 			"inserttable", 			"insertimage", 			"createlink", 			"seperator",  			"preview", 			"print",			"seperator", 			"viewSource",			"maximize", 			"seperator", 			"help"		);				// DropDowns		this.DropDowns = new Array();		// Fonts		this.DropDowns['font'] = {			id: "fonts",			command: "FontName",			label: "<font style=\"font-family:{value};font-size:12px;\">{value}</font>",			width: "90px",			elements: new Array(				"Arial", 				"Sans Serif", 				"Tahoma", 				"Verdana", 				"Courier New", 				"Georgia", 				"Times New Roman", 				"Impact", 				"Comic Sans MS"			)		};		// Font sizes		this.DropDowns['fontsize'] = {				id: "fontsizes",			command: "FontSize",			label: "<font size=\"{value}\">Size {value}</font>",			width: "54px",			elements: new Array(				"1", 				"2", 				"3", 				"4", 				"5", 				"6", 				"7"			)		};		// Headings		this.DropDowns['headings'] = {				id: "headings",			command: "FormatBlock",			label: "<{value} style=\"margin:0px;text-decoration:none;font-family:Arial\">{value}</{value}>",			width: "74px",			elements: new Array(				"H1", 				"H2", 				"H3", 				"H4", 				"H5", 				"H6"			)		};						// 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<this.Toolbar.length;i++) {				if(this.Toolbar[i]) {					var toolbar = this.Toolbar[i];					for(var j=0;j<toolbar.length;j++) {						if(toolbar[j] != null && toolbar[j] == element) {							this.Toolbar[i].splice(j,1);						}					}				}			}		};				// clear all or a given toolbar		this.clearToolbar = function(toolbar) {			if(typeof toolbar == "undefined") {				this.Toolbar = new Array();			}			else {				this.Toolbar[toolbar+1] = new Array();			}		};			},				/* ---------------------------------------------------------------------- *\		!! Do not change something below or you know what you are doning !!	\* ---------------------------------------------------------------------- */		// List of available block formats (not in use)	//BlockFormats: new Array("Address", "Bulleted List", "Definition", "Definition Term", "Directory List", "Formatted", "Heading 1", "Heading 2", "Heading 3", "Heading 4", "Heading 5", "Heading 6", "Menu List", "Normal", "Numbered List"),	// List of available actions and their respective ID and images	ToolbarList: {	//Name              buttonID               buttonTitle           	buttonImage               buttonImageRollover	"bold":           ['Bold',                 'Bold',               	'bold.gif',               'bold_on.gif'],	"italic":         ['Italic',               'Italic',             	'italics.gif',            'italics_on.gif'],	"underline":      ['Underline',            'Underline',          	'underline.gif',          'underline_on.gif'],	"strikethrough":  ['Strikethrough',        'Strikethrough',      	'strikethrough.gif',      'strikethrough_on.gif'],	"seperator":      ['',                     '',                   	'seperator.gif',          'seperator.gif'],	"subscript":      ['Subscript',            'Subscript',          	'subscript.gif',          'subscript_on.gif'],	"superscript":    ['Superscript',          'Superscript',        	'superscript.gif',        'superscript_on.gif'],	"justifyleft":    ['Justifyleft',          'Justifyleft',        	'justify_left.gif',       'justify_left_on.gif'],	"justifycenter":  ['Justifycenter',        'Justifycenter',      	'justify_center.gif',     'justify_center_on.gif'],	"justifyright":   ['Justifyright',         'Justifyright',       	'justify_right.gif',      'justify_right_on.gif'],	"justifyfull": 	  ['Justifyfull', 		   'Justifyfull', 			'justify_justify.gif', 	  'justify_justify_on.gif'], 	"unorderedlist":  ['InsertUnorderedList',  'Insert Unordered List',	'list_unordered.gif',     'list_unordered_on.gif'],	"orderedlist":    ['InsertOrderedList',    'Insert Ordered List',  	'list_ordered.gif',       'list_ordered_on.gif'],	"outdent":        ['Outdent',              'Outdent',            	'indent_left.gif',        'indent_left_on.gif'],	"indent":         ['Indent',               'Indent',             	'indent_right.gif',       'indent_right_on.gif'],	"cut":            ['Cut',                  'Cut',                	'cut.gif',                'cut_on.gif'],	"copy":           ['Copy',                 'Copy',               	'copy.gif',               'copy_on.gif'],	"paste":          ['Paste',                'Paste',              	'paste.gif',              'paste_on.gif'],	"forecolor":      ['ForeColor',            'Fore Color',          	'forecolor.gif',          'forecolor_on.gif'],	"backcolor":      ['BackColor',            'Back Color',          	'backcolor.gif',          'backcolor_on.gif'],	"undo":           ['Undo',                 'Undo',               	'undo.gif',               'undo_on.gif'],	"redo":           ['Redo',                 'Redo',               	'redo.gif',               'redo_on.gif'],	"inserttable":    ['InsertTable',          'Insert Table',        	'insert_table.gif',       'insert_table_on.gif'],	"insertimage":    ['InsertImage',          'Insert Image',        	'insert_picture.gif',     'insert_picture_on.gif'],	"createlink":     ['CreateLink',           'Create Link',         	'insert_hyperlink.gif',   'insert_hyperlink_on.gif'],	"viewSource":     ['ViewSource',           'View Source',         	'view_source.gif',        'view_source_on.gif'],	"viewText":       ['ViewText',             'View Text',           	'view_text.gif',          'view_text_on.gif'],	"help":           ['Help',                 'Help',               	'help.gif',               'help_on.gif'],	"fonts":     	  ['Fonts',           	   'Select Font',        	'select_font.gif',        'select_font_on.gif'],	"fontsizes":      ['Fontsizes',            'Select Size',        	'select_size.gif',        'select_size_on.gif'],	"headings":       ['Headings',             'Select Size',        	'select_heading.gif',     'select_heading_on.gif'],	"preview":		  ['Preview', 			   'Preview',       	 	'preview.gif',			  'preview_on.gif'],	"print":		  ['Print', 			   'Print',       	 	 	'print.gif',			  'print_on.gif'],	"removeformat":   ['RemoveFormat',         'Strip Word HTML',    	'remove_format.gif',      'remove_format_on.gif'],	"delete":         ['Delete',               'Delete',             	'delete.gif',     		  'delete_on.gif'],	"save": 		  ['Save', 				   'Save document',         'save.gif', 			  'save_on.gif'],	"return": 		  ['Return', 			   'Return without saving', 'return.gif', 			  'return_on.gif'],	"maximize": 	  ['Maximize', 			   'Maximize the editor',   'maximize.gif', 		  'maximize_on.gif']	},		// stores the different settings for each textarea	// the textarea identifier is used to store the settings object	config: new Array(),	// Create viewTextMode global variable and set to 0	// enabling all toolbar commands while in HTML mode	viewTextMode: new Array(),	// maximized	maximized: new Array(),		/**	 * Get the range of the given selection	 *	 * @param {Selection} sel Selection object	 * @return {Range} Range object	 */	getRange: function(sel) {		return sel.createRange ? sel.createRange() : sel.getRangeAt(0);	},		/**	 * Return the editor div element	 *	 * @param {String} n Editor identifier 	 * @return {HtmlDivElement} Iframe object	 */	getEditorDiv: function(n) {		return $("wysiwyg_div_" + n);	},		/**	 * Return the editor table element	 *	 * @param {String} n Editor identifier 	 * @return {HtmlTableElement} Iframe object	 */	getEditorTable: function(n) {		return $("wysiwyg_table_" + n);	},		/**	 * Get the iframe object of the WYSIWYG editor	 * 	 * @param {String} n Editor identifier 	 * @return {HtmlIframeElement} Iframe object	 */	getEditor: function(n) {		return $("wysiwyg" + n);	},		/**	 * Get editors window element	 *	 * @param {String} n Editor identifier 	 * @return {HtmlWindowElement} Html window object	 */	getEditorWindow: function(n) {		return this.getEditor(n).contentWindow;	},		/**	 * Attach the WYSIWYG editor to the given textarea element	 *	 * @param {String} id Textarea identifier (all = all textareas)	 * @param {Settings} settings the settings which will be applied to the textarea	 */	attach: function(id, settings) {			if(id != "all") {				this.setSettings(id, settings);			WYSIWYG_Core.includeCSS(this.config[id].CSSFile);			WYSIWYG_Core.addEvent(window, "load", function generateEditor() {WYSIWYG._generate(id, settings);});		}		else {			WYSIWYG_Core.addEvent(window, "load", function generateEditor() {WYSIWYG.attachAll(settings);});		}	},		/**	 * Attach the WYSIWYG editor to all textarea elements	 *	 * @param {Settings} settings Settings to customize the look and feel	 */	attachAll: function(settings) {		var areas = document.getElementsByTagName("textarea");		for(var i=0;i<areas.length;i++) {			var id = areas[i].getAttribute("id");			if(id == null || id == "") continue;			this.setSettings(id, settings);			WYSIWYG_Core.includeCSS(this.config[id].CSSFile);			WYSIWYG._generate(id, settings);		}	},		/**	 * Display an iframe instead of the textarea. 	 * It's used as textarea replacement to display HTML.	 *	 * @param id Textarea identifier (all = all textareas)	 * @param settings the settings which will be applied to the textarea	 */	display: function(id, settings) {			if(id != "all") {				this.setSettings(id, settings);			WYSIWYG_Core.includeCSS(this.config[id].CSSFile);			WYSIWYG_Core.addEvent(window, "load", function displayIframe() {WYSIWYG._display(id, settings);});		}		else {			WYSIWYG_Core.addEvent(window, "load", function displayIframe() {WYSIWYG.displayAll(settings);});		}	},		/**	 * Display an iframe instead of the textarea. 	 * It's apply the iframe to all textareas found in the current document.	 *	 * @param settings Settings to customize the look and feel	 */	displayAll: function(settings) {		var areas = document.getElementsByTagName("textarea");		for(var i=0;i<areas.length;i++) {			var id = areas[i].getAttribute("id");			if(id == null || id == "") continue;			this.setSettings(id, settings);			WYSIWYG_Core.includeCSS(this.config[id].CSSFile);			WYSIWYG._display(id, settings);		}	},			/**	 * Set settings in config array, use the textarea id as identifier	 * 	 * @param n Textarea identifier (all = all textareas)	 * @param settings the settings which will be applied to the textarea	 */	setSettings: function(n, settings) {		if(typeof(settings) != "object") {			this.config[n] = new this.Settings();		}		else {			this.config[n] = settings;		}	},		/**	 * Insert or modify an image	 * 	 * @param {String} src Source of the image	 * @param {Integer} width Width	 * @param {Integer} height Height	 * @param {String} align Alignment of the image	 * @param {String} border Border size	 * @param {String} alt Alternativ Text	 * @param {Integer} hspace Horizontal Space	 * @param {Integer} vspace Vertical Space	 * @param {String} n The editor identifier (the textarea's ID)	 */	insertImage: function(src, width, height, align, border, alt, hspace, vspace, n) {			// get editor		var doc = this.getEditorWindow(n).document;		// get selection and range		var sel = this.getSelection(n);		var range = this.getRange(sel);				// the current tag of range		var img = this.findParent("img", range);				// element is not a link		var update = (img == null) ? false : true;		if(!update) {			img = doc.createElement("img");		}				// set the attributes		WYSIWYG_Core.setAttribute(img, "src", src);		WYSIWYG_Core.setAttribute(img, "style", "width:" + width + ";height:" + height);		if(align != "") { WYSIWYG_Core.setAttribute(img, "align", align); } else { img.removeAttribute("align"); }		WYSIWYG_Core.setAttribute(img, "border", border);		WYSIWYG_Core.setAttribute(img, "alt", alt);		WYSIWYG_Core.setAttribute(img, "hspace", hspace);		WYSIWYG_Core.setAttribute(img, "vspace", vspace);		img.removeAttribute("width");		img.removeAttribute("height");				// on update exit here		if(update) { return; }   				// Check if IE or Mozilla (other)		if (WYSIWYG_Core.isMSIE) {			range.pasteHTML(img.outerHTML);   		}		else {			this.insertNodeAtSelection(img, n);		}	},		/**	 * Insert or modify a link	 * 	 * @param {String} href The url of the link	 * @param {String} target Target of the link	 * @param {String} style Stylesheet of the link	 * @param {String} styleClass Stylesheet class of the link	 * @param {String} name Name attribute of the link	 * @param {String} n The editor identifier (the textarea's ID)	 */	insertLink: function(href, target, style, styleClass, name, n) {			// get editor		var doc = this.getEditorWindow(n).document;		// get selection and range		var sel = this.getSelection(n);		var range = this.getRange(sel);		var lin = null;				// get element from selection		if(WYSIWYG_Core.isMSIE) {			if(sel.type == "Control" && range.length == 1) {					range = this.getTextRange(range(0));				range.select();			}		}		// find a as parent element		lin = this.findParent("a", range);						// check if parent is found		var update = (lin == null) ? false : true;		if(!update) {			lin = doc.createElement("a");		}				// set the attributes		WYSIWYG_Core.setAttribute(lin, "href", href);		WYSIWYG_Core.setAttribute(lin, "class", styleClass);		WYSIWYG_Core.setAttribute(lin, "className", styleClass);		WYSIWYG_Core.setAttribute(lin, "target", target);		WYSIWYG_Core.setAttribute(lin, "name", name);		WYSIWYG_Core.setAttribute(lin, "style", style);				// on update exit here		if(update) { return; }			// Check if IE or Mozilla (other)		if (WYSIWYG_Core.isMSIE) {				range.select();			lin.innerHTML = range.htmlText;			range.pasteHTML(lin.outerHTML);   		} 		else {						var node = range.startContainer;				var pos = range.startOffset;			if(node.nodeType != 3) { node = node.childNodes[pos]; }			if(node.tagName)				lin.appendChild(node);			else				lin.innerHTML = sel;			this.insertNodeAtSelection(lin, n);		}	},		/**	 * Strips any HTML added by word	 *     * @param {String} n The editor identifier (the textarea's ID)	 */	removeFormat: function(n) {				if ( !confirm(this.config[n].RemoveFormatConfMessage) ) { return; }		var doc = this.getEditorWindow(n).document;		var str = doc.body.innerHTML;				str = str.replace(/<span([^>])*>(&nbsp;)*\s*<\/span>/gi, '');	    str = str.replace(/<span[^>]*>/gi, '');	    str = str.replace(/<\/span[^>]*>/gi, '');	    str = str.replace(/<p([^>])*>(&nbsp;)*\s*<\/p>/gi, '');	    str = str.replace(/<p[^>]*>/gi, '');	    str = str.replace(/<\/p[^>]*>/gi, '');	    str = str.replace(/<h([^>])[0-9]>(&nbsp;)*\s*<\/h>/gi, '');	    str = str.replace(/<h[^>][0-9]>/gi, '');	    str = str.replace(/<\/h[^>][0-9]>/gi, ''); 		str = str.replace (/<B [^>]*>/ig, '<b>');				// var repl_i1 = /<I[^>]*>/ig;		// str = str.replace (repl_i1, '<i>');				str = str.replace (/<DIV[^>]*>/ig, '');		str = str.replace (/<\/DIV>/gi, '');		str = str.replace (/<[\/\w?]+:[^>]*>/ig, '');		str = str.replace (/(&nbsp;){2,}/ig, '&nbsp;');		str = str.replace (/<STRONG>/ig, '');		str = str.replace (/<\/STRONG>/ig, '');		str = str.replace (/<TT>/ig, '');		str = str.replace (/<\/TT>/ig, '');		str = str.replace (/<FONT [^>]*>/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(/<st1:.*?>/gi, '');	    str = str.replace(/o:/gi, ''); 	    	    str = str.replace(/<!--([^>])*>(&nbsp;)*\s*<\/-->/gi, '');   		str = str.replace(/<!--[^>]*>/gi, '');   		str = str.replace(/<\/--[^>]*>/gi, '');				doc.body.innerHTML = str;	},		/**	 * Display an iframe instead of the textarea.	 * 	 * @private	 * @param {String} n The editor identifier (the textarea's ID)	 * @param {Object} 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 = '<table cellpadding="0" cellspacing="0" border="0" style="width:' + currentWidth + '; height:' + currentHeight + ';" class="tableTextareaEditor"><tr><td valign="top">\n'	    + '<iframe frameborder="0" id="wysiwyg' + n + '" class="iframeText" style="width:' + ifrmWidth + ';height:' + ifrmHeight + ';"></iframe>\n'	    + '</td></tr></table>\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 <br> 		if(this.config[n].ReplaceLineBreaks) {			content = content.replace(/(\r\n)|(\n)/ig, "<br>");		}					// 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	 * 	 * @private	 * @param {String} n The editor identifier (the textarea's ID)	 * @param {Object} 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 += '<div id="wysiwyg_div_' + n + '" style="width:' + currentWidth  +';">';	    editor += '<table border="0" cellpadding="0" cellspacing="0" class="tableTextareaEditor" id="wysiwyg_table_' + n + '" style="width:' + currentWidth  + '; height:' + currentHeight + ';">';	    editor += '<tr><td style="height:22px;vertical-align:top;">';	    	  		// 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 += '<table border="0" cellpadding="0" cellspacing="0" class="toolbar1" style="width:100%;" id="toolbar' + j + '_' + n + '">';	    		editor += '<tr><td style="width:6px;"><img src="' + this.config[n].ImagesDir + 'seperator2.gif" alt="" hspace="3"></td>';								// Interate over the toolbar element				for (var i = 0; i < toolbar.length;i++) { 					var id = toolbar[i];				    if (toolbar[i]) {				    	if(typeof (this.config[n].DropDowns[id]) != "undefined") {				    		var dropdown = this.config[n].DropDowns[id];				    		editor += '<td style="width: ' + dropdown.width + ';">';				    		// write the drop down content				    		editor += this.writeDropDown(n, id);				    		editor += '</td>';				    	}				    	else {				    							    		// Get the values of the Button from the global ToolbarList object							var buttonObj = this.ToolbarList[toolbar[i]];							if(buttonObj) {								var buttonID = buttonObj[0];								var buttonTitle = buttonObj[1];								var buttonImage = this.config[n].ImagesDir + buttonObj[2];								var buttonImageRollover  = this.config[n].ImagesDir + buttonObj[3];								    								if (toolbar[i] == "seperator") {									editor += '<td style="width: 12px;" align="center">';									editor += '<img src="' + buttonImage + '" border=0 unselectable="on" width="2" height="18" hspace="2" unselectable="on">';									editor += '</td>';								}								// View Source button								else if (toolbar[i] == "viewSource"){								    editor += '<td style="width: 22px;">';									editor += '<span id="HTMLMode' + n + '"><img src="' + buttonImage +  '" border="0" unselectable="on" title="' + buttonTitle + '" id="' + buttonID + '" class="buttonEditor" onmouseover="this.className=\'buttonEditorOver\'; this.src=\'' + buttonImageRollover + '\';" onmouseout="this.className=\'buttonEditor\'; this.src=\'' + buttonImage + '\';" onclick="WYSIWYG.execCommand(\'' + n + '\', \'' + buttonID + '\');" unselectable="on" width="20" height="20"></span>';									editor += '<span id="textMode' + n + '"><img src="' + this.config[n].ImagesDir + 'view_text.gif" border="0" unselectable="on" title="viewText" id="ViewText" class="buttonEditor" onmouseover="this.className=\'buttonEditorOver\'; this.src=\'' + this.config[n].ImagesDir + 'view_text_on.gif\';" onmouseout="this.className=\'buttonEditor\'; this.src=\'' + this.config[n].ImagesDir + 'view_text.gif\';" onclick="WYSIWYG.execCommand(\'' + n + '\',\'ViewText\');" unselectable="on"  width="20" height="20"></span>';							        editor += '</td>';						        }								else {									editor += '<td style="width: 22px;">';									editor += '<img src="' + buttonImage + '" border=0 unselectable="on" title="' + buttonTitle + '" id="' + buttonID + '" class="buttonEditor" onmouseover="this.className=\'buttonEditorOver\'; this.src=\'' + buttonImageRollover + '\';" onmouseout="this.className=\'buttonEditor\'; this.src=\'' + buttonImage + '\';" onclick="WYSIWYG.execCommand(\'' + n + '\', \'' + buttonID + '\');" unselectable="on" width="20" height="20">';									editor += '</td>';								}							}						}			  		}			  	}			  	editor += '<td>&nbsp;</td></tr></table>';			}		}			 	editor += '</td></tr><tr><td valign="top">\n';		// Create iframe which will be used for rich text editing		editor += '<iframe frameborder="0" id="wysiwyg' + n + '" class="iframeText" style="width:100%;height:' + currentHeight + ';"></iframe>\n'	    + '</td></tr>';	    // Status bar HTML code	    if(this.config[n].StatusBarEnabled) {		    editor += '<tr><td class="wysiwyg-statusbar" style="height:10px;" id="wysiwyg_statusbar_' + n + '">&nbsp;</td></tr>';    		}	    editor += '</table>';	    editor += '</div>';	    	    // Insert the editor after the textarea	    	    textarea.insertAdjacentHTML("afterEnd", editor);	    							// 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 <br> 		if(this.config[n].ReplaceLineBreaks) {			content = content.replace(/\n\r|\n/ig, "<br>");		}						// 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);				// Enable table highlighting		WYSIWYG_Table.refreshHighlighting(n);	    	    // 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.closeDropDowns(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;				},		/**	 * Disable the given WYSIWYG Editor Box	 * 	 * @param {String} n The editor identifier (the textarea's ID)	 */ 	disable: function(n) {				// 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);		}	},		/**	 * Enables the given WYSIWYG Editor Box	 * 	 * @param {String} n The editor identifier (the textarea's ID)	 */	enable: function(n) {					// 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);		}	},		/**	 * Returns the node structure of the current selection as array	 * 	 * @param {String} 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 {String} 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;	},		/**	 * Updates the status bar with the current node tree	 *	 * @param {String} 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 += '<a class="wysiwyg-statusbar" href="javascript:WYSIWYG.selectNode(\'' + n + '\',' + i + ');">' + nodeTree[i].nodeName + '</a>';				}			else {				outputTree += nodeTree[i].nodeName;			}			if(i > 0) { outputTree += " > "; }		}					// update the status bar 			var statusbar = $("wysiwyg_statusbar_" + n);		if(statusbar){ 			statusbar.innerHTML = outputTree; 		}	},		/**	 * Execute a command on the editor document	 * 	 * @param {String} command The execCommand (e.g. Bold)	 * @param {String} n The editor identifier	 * @param {String} value The value when applicable	 */	execCommand: function(n, cmd, value) {						// When user clicks toolbar button make sure it always targets its respective WYSIWYG		this.getEditorWindow(n).focus();				// When in Text Mode these execCommands are enabled		var textModeCommands = new Array("ViewText", "Print");	  	  	// Check if in Text mode and a disabled command execute		var cmdValid = false;		for (var i = 0; i < textModeCommands.length; i++) {			if (textModeCommands[i] == cmd) {				cmdValid = true;			}		}		if(this.viewTextMode[n] && !cmdValid) {			alert("You are in TEXT Mode. This feature has been disabled.");		  	return;		} 				// 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 / 3), top: parseInt(window.screen.availHeight / 3)};						// Check the insert image popup implementation		var imagePopupFile = this.config[n].PopupsDir + 'insert_image.html';		var imagePopupWidth = 400;		var imagePopupHeight = 210;		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) {			case "Maximize":				this.maximize(n);			break;			case "FormatBlock":				WYSIWYG_Core.execCommand(n, cmd, "<" + value + ">");			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=500,height=260,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,'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);			    var form = WYSIWYG_Core.findParentNode("FORM", this.getEditor(n));			    if(form == null) {			    	alert("Can not submit the content, because no form element found.");			    	return;			    }			    form.submit();			break;			         			// Return			case "Return":			   location.replace(this.config[n].Opener);			break;									default: 				WYSIWYG_Core.execCommand(n, cmd, value);						}	 				// hide node the font + font size selection		this.closeDropDowns(n);	},			/**	 * Maximize the editor instance	 * 	 * @param {String} n The editor identifier	 */	maximize: function(n) {				var divElm = this.getEditorDiv(n);		var tableElm = this.getEditorTable(n);		var editor = this.getEditor(n);		var setting = this.config[n];		var size = WYSIWYG_Core.windowSize();		size.width -= 5;		if(this.maximized[n]) {			WYSIWYG_Core.setAttribute(divElm, "style", "position:static;z-index:9998;top:0px;left:0px;width:" + setting.Width + ";height:100%;");			WYSIWYG_Core.setAttribute(tableElm, "style", "width:" + setting.Width + ";height:" + setting.Height + ";");			WYSIWYG_Core.setAttribute(editor, "style", "width:100%;height:" + setting.Height + ";");			this.maximized[n] = false;		}		else {			WYSIWYG_Core.setAttribute(divElm, "style", "position:absolute;z-index:9998;top:0px;left:0px;width:" + size.width + "px;height:" + size.height + "px;");			WYSIWYG_Core.setAttribute(tableElm, "style", "width:100%;height:100%;");			WYSIWYG_Core.setAttribute(editor, "style", "width:100%;height:100%;");			this.maximized[n] = true;		}	},					/**	 * Insert HTML into WYSIWYG in rich text	 *	 * @param {String} html The HTML being inserted (e.g. <b>hello</b>)	 * @param {String} n The editor identifier	 */	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);			}						try {				range.setEnd(afterNode, 0);				range.setStart(afterNode, 0);			}			catch(e) {				alert(e);			}		}				sel.addRange(range);	},		/**	 * Prints the content of the WYSIWYG editor area	 * 	 * @param {String} 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 = '<object id="WebBrowser1" width="0" height="0" classid="CLSID:8856F961-340A-11D0-A96B-00C04FD705A2"></object>';			doc.body.insertAdjacentHTML('beforeEnd',WebBrowser);			WebBrowser.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER);			WebBrowser.outerHTML = '';		} else {			this.getEditorWindow(n).print();		}	},		/**	 * Writes the content of an drop down	 *	 * @param {String} n The editor identifier (textarea ID)	 * @param {String} id Drop down identifier	 * @return {String} Drop down HTML	 */	writeDropDown: function(n, id) {			var dropdown = this.config[n].DropDowns[id];		var toolbarObj = this.ToolbarList[dropdown.id];		var image = this.config[n].ImagesDir  + toolbarObj[2];		var imageOn  = this.config[n].ImagesDir + toolbarObj[3];		dropdown.elements.sort();				var output = "";		output += '<table border="0" cellpadding="0" cellspacing="0"><tr>';		output += '<td onMouseOver="$(\'img_' + dropdown.id + '_' + n + '\').src=\'' + imageOn + '\';" onMouseOut="$(\'img_' + dropdown.id + '_' + n + '\').src=\'' + image + '\';">';		output += '<img src="' + image + '" id="img_' + dropdown.id + '_' + n + '" height="20" onClick="WYSIWYG.openDropDown(\'' + n + '\',\'' + dropdown.id + '\');" unselectable="on" border="0"><br>';		output += '<span id="elm_' + dropdown.id + '_' + n + '" class="dropdown" style="width: 145px;display:none;">';		for (var i = 0; i < dropdown.elements.length;i++) {			if (dropdown.elements[i]) {				var value = dropdown.elements[i];				var label = dropdown.label.replace(/{value}/gi, value);				// output		  		output += '<button type="button" onClick="WYSIWYG.execCommand(\'' + n + '\',\'' + dropdown.command + '\',\'' + value + '\')\;" onMouseOver="this.className=\'mouseOver\'" onMouseOut="this.className=\'mouseOut\'" class="mouseOut" style="width: 120px;">';		  		output += '<table cellpadding="0" cellspacing="0" border="0"><tr>';		  		output += '<td align="left">' + label + '</td>';		  		output += '</tr></table></button><br>';			  	}	  	}  		output += '</span></td></tr></table>';	  				return output;	},		/**	 * Close all drop downs. You can define a exclude dropdown id	 * 	 * @param {String} n The editor identifier (textarea ID)     * @param {String} exid Excluded drop down identifier	 */	closeDropDowns: function(n, exid) {		if(typeof(exid) == "undefined") exid = "";		var dropdowns = this.config[n].DropDowns;		for(var id in dropdowns) {			var dropdown = dropdowns[id];			if(dropdown.id != exid) {				var divId = "elm_" + dropdown.id + "_" + n;				if($(divId)) $(divId).style.display = 'none';			}		}				},		/**	 * Open a defined drop down	 *      * @param {String} n The editor identifier (textarea ID)	 * @param {String} id Drop down identifier	 */	openDropDown: function(n, id) {		var divId = "elm_" + id + "_" + n;		if($(divId).style.display == "none") {				$(divId).style.display = "block"; 		}		else {			$(divId).style.display = "none"; 		}		$(divId).style.position = "absolute";		this.closeDropDowns(n, id);	},		/**	 * Shows the HTML source code generated by the WYSIWYG editor	 * 	 * @param {String} n The editor identifier (textarea ID)	 */	viewSource: function(n) {				// document		var doc = this.getEditorWindow(n).document;				// Enable table highlighting		WYSIWYG_Table.disableHighlighting(n);					// 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;	},			/**	 * Shows the HTML source code generated by the WYSIWYG editor	 * 	 * @param {String} n The editor identifier (textarea 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;		}				// Enable table highlighting		WYSIWYG_Table.refreshHighlighting(n);					  		// 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    : 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 = WYSIWYG_Core.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 = WYSIWYG_Core.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(WYSIWYG_Core.getDocumentPathOfUrl(stripImgageUrl));							// exact replacing of url. regex: src="<url>"			if(exact) {				regex = eval("/(src=\")(" + url + ")([^\"]*)/gi");				content = content.replace(regex, "$1$3");				}			// not exect replacing of url. regex: <url>			else {				regex = eval("/(" + url + ")(.+)/gi");				content = content.replace(regex, "$2");				}						// strip absolute urls without a heading slash ("images/print.gif")				result = WYSIWYG_Core.getDocumentPathOfUrl(stripImgageUrl).match(/.+[\/]{2,3}[^\/]*/,"");			if(result) {				url = WYSIWYG_Core.stringToRegex(result[0]);								// exact replacing of url. regex: src="<url>"				if(exact) {					regex = eval("/(src=\")(" + url + ")([^\"]*)/gi");					content = content.replace(regex, "$1$3");				}				// not exect replacing of url. regex: <url>				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(WYSIWYG_Core.getDocumentPathOfUrl(stripAnchorUrl));						// strip absolute urls with a heading slash ("/product/index.html")			// exact replacing of url. regex: src="<url>"			if(exact) {				regex = eval("/(href=\")(" + url + ")([^\"]*)/gi");				content = content.replace(regex, "$1$3");				}			// not exect replacing of url. regex: <url>			else {				regex = eval("/(" + url + ")(.+)/gi");				content = content.replace(regex, "$2");				}						// strip absolute urls without a heading slash ("product/index.html")				result = WYSIWYG_Core.getDocumentPathOfUrl(stripAnchorUrl).match(/.+[\/]{2,3}[^\/]*/,"");			if(result) {				url = WYSIWYG_Core.stringToRegex(result[0]);				// exact replacing of url. regex: src="<url>"				if(exact) {					regex = eval("/(href=\")(" + url + ")([^\"]*)/gi");					content = content.replace(regex, "$1$3");					}				// not exect replacing of url. regex: <url>				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="<url>"			if(exact) {				regex = eval("/(href=\")(" + url + ")(#[^\"]*)/gi");				content = content.replace(regex, "$1$3");			}			// not exect replacing of url. regex: <url>			else {				regex = eval("/(" + url + ")(.+)/gi");				content = content.replace(regex, "$2");				}									// stip off anchor links with #name (only for local system)			url = WYSIWYG_Core.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="<url>"				if(exact) {					regex = eval("/(href=\")(" + url + ")(#[^\"]*)/gi");					content = content.replace(regex, "$1$3");				}				// not exect replacing of url. regex: <url>				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<this.config[n].Toolbar.length;i++) {			var toolbar = $("toolbar" + i + "_" + n);			if(toolbar) { toolbar.style.display = "none"; }		}		},		/* ---------------------------------------------------------------------- *\	  Function    : showToolbars()	  Description : Display all toolbars	  Usage       : WYSIWYG.showToolbars(n)	  Arguments   : n - The editor identifier (the textarea's ID)	\* ---------------------------------------------------------------------- */	showToolbars: function(n) {		for(var i=0;i<this.config[n].Toolbar.length;i++) {			var toolbar = $("toolbar" + i + "_" + n);			if(toolbar) { toolbar.style.display = ""; }		}		},		/* ---------------------------------------------------------------------- *\	  Function    : hideStatusBar()	  Description : Hide the status bar	  Usage       : WYSIWYG.hideStatusBar(n)	  Arguments   : n - The editor identifier (the textarea's ID)	\* ---------------------------------------------------------------------- */	hideStatusBar: function(n) {		var statusbar = $('wysiwyg_statusbar_' + n);		if(statusbar) {	statusbar.style.display = "none"; }	},		/* ---------------------------------------------------------------------- *\	  Function    : showStatusBar()	  Description : Display the status bar	  Usage       : WYSIWYG.showStatusBar(n)	  Arguments   : n - The editor identifier (the textarea's ID)	\* ---------------------------------------------------------------------- */	showStatusBar: function(n) {		var statusbar = $('wysiwyg_statusbar_' + n);		if(statusbar) { statusbar.style.display = ""; }	},		/**	 * Finds the node with the given tag name in the given range	 * 	 * @param {String} tagName Parent tag to find	 * @param {Range} range Current range	 */	findParent: function(parentTagName, range){		parentTagName = parentTagName.toUpperCase();		var rangeWorking;		var elmWorking = null;		try {			if(!WYSIWYG_Core.isMSIE) {				var node = range.startContainer;					var pos = range.startOffset;				if(node.nodeType != 3) { node = node.childNodes[pos]; }				return WYSIWYG_Core.findParentNode(parentTagName, node);			}			else {				elmWorking = (range.length > 0) ? range.item(0): range.parentElement();									elmWorking = WYSIWYG_Core.findParentNode(parentTagName, elmWorking);				if(elmWorking != null) return elmWorking;								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;		}	},			/**	 * Get the acutally tag of the given range	 *	 * @param {Range} range Current 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;		}	},		/**	 * Get the parent node of the given node	 * 	 * @param {DOMElement} 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 = <p> , SHIFT + ENTER = <br>	  				Inverted: ENTER = <br>, SHIFT + ENTER = <p>	  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("<br>");	            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("<p>");	            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.22 2007/09/08 21:45:57 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 {DOMElement} node The element on which the style attribute will affect	 * @param {String} style Stylesheet which will be set	 */	_setStyleAttribute: function(node, style) {		if(style == null) return;		var styles = style.split(";");		var pos;		for(var i=0;i<styles.length;i++) {			var attributes = styles[i].split(":");			if(attributes.length == 2) {				try {					var attr = WYSIWYG_Core.trim(attributes[0]);					while((pos = attr.search(/-/)) != -1) {						var strBefore = attr.substring(0, pos);						var strToUpperCase = attr.substring(pos + 1, pos + 2);						var strAfter = attr.substring(pos + 2, attr.length);						attr = strBefore + strToUpperCase.toUpperCase() + strAfter;					}					var value = WYSIWYG_Core.trim(attributes[1]).toLowerCase();					node.style[attr] = value;				}				catch (e) {					alert(e);				}			}		}	},		/**	 * Fix's the issue while getting the attribute style on IE	 * It's return an object but we need the style string	 *	 * @private	 * @param {DOMElement} node Node element	 * @return {String} Stylesheet	 */	_getStyleAttribute: function(node) {		if(this.isMSIE) {			return node.style['cssText'].toLowerCase();				}			else {			return node.getAttribute("style");		}	},		/**	 * Set an attribute's value on the given node element.	 *	 * @param {DOMElement} node Node element	 * @param {String} attr Attribute which is set	 * @param {String} value Value of the attribute	 */	setAttribute: function(node, attr, value) {		if(value == null || node == null || attr == null) return;		if(attr.toLowerCase() == "style") {			this._setStyleAttribute(node, value);		}		else {			node.setAttribute(attr, value);		}	},		/**	 * Removes an attribute on the given node	 * 	 * @param {DOMElement} node Node element	 * @param {String} attr Attribute which will be removed	 */ 	removeAttribute: function(node, attr) {		node.removeAttribute(attr, false);	},		/**	 * Get the vale of the attribute on the given node	 * 	 * @param {DOMElement} node Node element	 * @param {String} attr Attribute which value will be returned	 */	getAttribute: function(node, attr) {		if(node == null || attr == null) return;		if(attr.toLowerCase() == "style") {			return this._getStyleAttribute(node);		}		else {			return node.getAttribute(attr);		}	},		/**	 * Get the path out of an given url	 * 	 * @param {String} url The url with is used to get 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;	},		/**	 * Get the documents url, convert local urls to web urls	 * 	 * @param {DOMElement} doc Document which is used to get the url	 */	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;	},		/**	 * Find a parent node with the given name, of the given start node	 * 	 * @param {String} tagName - Tag name of the node to find	 * @param {DOMElement} node - Node element	 */	findParentNode: function(tagName, node) {		while (node.tagName != "HTML") {	  		if (node.tagName == tagName){	  			return node;	  		} 	  		node = node.parentNode;	 	}	 	return null;	},		/**	 * Cancel the given event.	 *	 * @param e Event which will be canceled	 */	cancelEvent: function(e) {		if (!e) return false;		if (this.isMSIE) {			e.returnValue = false;			e.cancelBubble = true;		} else {			e.preventDefault();			e.stopPropagation && e.stopPropagation();		}		return false;		},		/**	 * Converts a RGB color string to hex color string.	 *	 * @param color RGB color string	 * @param Hex color string	 */	toHexColor: function(color) {		color = color.replace(/^rgb/g,'');		color = color.replace(/\(/g,'');		color = color.replace(/\)/g,'');		color = color.replace(/ /g,'');		color = color.split(',');		var r = parseFloat(color[0]).toString(16).toUpperCase();		var g = parseFloat(color[1]).toString(16).toUpperCase();		var b = parseFloat(color[2]).toString(16).toUpperCase();		if (r.length<2) { r='0'+r; }		if (g.length<2) { g='0'+g; }		if (b.length<2) { b='0'+b; }		return r + g + b;	},		/**	 * Converts a decimal color to hex color string.	 *	 * @param Decimal color	 * @param Hex color string	 */	_dec_to_rgb: function(value) {		var hex_string = "";		for (var hexpair = 0; hexpair < 3; hexpair++) {			var myByte = value & 0xFF;            // get low byte			value >>= 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) {		if(str == null) return "";		// find all decimal color strings		var matcher = str.match(/rgb\([0-9 ]+,[0-9 ]+,[0-9 ]+\)/gi);		if(matcher) {			for(var j=0; j<matcher.length;j++) {				var regex = eval("/" + WYSIWYG_Core.stringToRegex(matcher[j]) + "/gi");				// replace the decimal color strings with hex color strings				str = str.replace(regex, "#" + this.toHexColor(matcher[j]));			}		}		return str;	},		/**	 * Execute the given command on the given editor	 * 	 * @param n The editor's identifier	 * @param cmd Command which is execute	 */	execCommand: function(n, cmd, value) {		if(typeof(value) == "undefined") value = null;				// firefox BackColor problem fixed		if(cmd == 'BackColor' && WYSIWYG_Core.isFF) cmd = 'HiliteColor';				// firefox cut, paste and copy		if(WYSIWYG_Core.isFF && (cmd == "Cut" || cmd == "Paste" || cmd == "Copy")) {			try {				WYSIWYG.getEditorWindow(n).document.execCommand(cmd, false, value);			}			catch(e) {				if(confirm("Copy/Cut/Paste is not available in Mozilla and Firefox\nDo you want more information about this issue?")) {					window.open('http://www.mozilla.org/editor/midasdemo/securityprefs.html');				}			}		}				else {			WYSIWYG.getEditorWindow(n).document.execCommand(cmd, false, value);		}	},		/**	 * Parse a given string to a valid regular expression	 * 	 * @param {String} string String to be parsed	 * @return {RegEx} Valid regular expression	 */	stringToRegex: function(string) {				string = string.replace(/\//gi, "\\/");		string = string.replace(/\(/gi, "\\(");		string = string.replace(/\)/gi, "\\)");		string = string.replace(/\[/gi, "\\[");		string = string.replace(/\]/gi, "\\]");		string = string.replace(/\+/gi, "\\+");		string = string.replace(/\$/gi, "\\$");		string = string.replace(/\*/gi, "\\*");		string = string.replace(/\?/gi, "\\?");		string = string.replace(/\^/gi, "\\^");		string = string.replace(/\\b/gi, "\\\\b");		string = string.replace(/\\B/gi, "\\\\B");		string = string.replace(/\\d/gi, "\\\\d");		string = string.replace(/\\B/gi, "\\\\B");		string = string.replace(/\\D/gi, "\\\\D");		string = string.replace(/\\f/gi, "\\\\f");		string = string.replace(/\\n/gi, "\\\\n");		string = string.replace(/\\r/gi, "\\\\r");		string = string.replace(/\\t/gi, "\\\\t");		string = string.replace(/\\v/gi, "\\\\v");		string = string.replace(/\\s/gi, "\\\\s");		string = string.replace(/\\S/gi, "\\\\S");		string = string.replace(/\\w/gi, "\\\\w");		string = string.replace(/\\W/gi, "\\\\W");				return string;				},		/**	 * Add an event listener	 *	 * @param obj Object on which the event will be attached	 * @param ev Kind of event	 * @param fu Function which is execute on the event	 */	addEvent: function(obj, ev, fu) {		if (obj.attachEvent)			obj.attachEvent("on" + ev, fu);		else			obj.addEventListener(ev, fu, false);	},		/**	 * Remove an event listener	 *	 * @param obj Object on which the event will be attached	 * @param ev Kind of event	 * @param fu Function which is execute on the event	 */	removeEvent:  function(obj, ev, fu) {		if (obj.attachEvent)			obj.detachEvent("on" + ev, fu);		else			obj.removeEventListener(ev, fu, false);	},		/**	 * Includes a javascript file	 *	 * @param file Javascript file path and name	 */	includeJS: function(file) {		var script = document.createElement("script");		this.setAttribute(script, "type", "text/javascript");		this.setAttribute(script, "src", file);		var heads = document.getElementsByTagName("head");		for(var i=0;i<heads.length;i++) {			heads[i].appendChild(script);				}	},		/**	 * Includes a stylesheet file	 *	 * @param file Stylesheet file path and name	 */	includeCSS: function(path) {		var link = document.createElement("link");		this.setAttribute(link, "rel", "stylesheet");		this.setAttribute(link, "type", "text/css");		this.setAttribute(link, "href", path);		var heads = document.getElementsByTagName("head");		for(var i=0;i<heads.length;i++) {			heads[i].appendChild(link);				}	},		/**	 * Get the screen position of the given element.	 * 	 * @param {HTMLObject} elm1 Element which position will be calculate	 * @param {HTMLObject} elm2 Element which is the last one before calculation stops	 * @param {Object} Left and top position of the given element	 */	getElementPosition: function(elm1, elm2) {		var top = 0, left = 0; 			while (elm1 && elm1 != elm2) {			left += elm1.offsetLeft;			top += elm1.offsetTop;			elm1 = elm1.offsetParent;		}		return {left : left, top : top};	},		/**	 * Get the window size	 * @private	 */	windowSize: function() {		if (window.innerWidth) {	  		return {width: window.innerWidth, height: window.innerHeight};	  	} 		else if (document.body && document.body.offsetWidth) {	  		return {width: document.body.offsetWidth, height: document.body.offsetHeight};	  	} 		else {	  		return {width: 0, height: 0};	  	}	}}/** * Context menu object */var WYSIWYG_ContextMenu = {		html: "",	contextMenuDiv: null,		/**	 * Init function	 *	 * @param {String} n Editor identifier	 */	init: function(n) {		var doc = WYSIWYG.getEditorWindow(n).document;					// create context menu div		this.contextMenuDiv = document.createElement("div");		this.contextMenuDiv.className = "wysiwyg-context-menu-div";		this.contextMenuDiv.setAttribute("class", "wysiwyg-context-menu-div");		this.contextMenuDiv.style.display = "none";		this.contextMenuDiv.style.position = "absolute";		this.contextMenuDiv.style.zIndex = 9999;		this.contextMenuDiv.style.left = "0";		this.contextMenuDiv.style.top = "0";		this.contextMenuDiv.unselectable = "on";				document.body.insertBefore(this.contextMenuDiv, document.body.firstChild);				// bind event listeners		WYSIWYG_Core.addEvent(doc, "contextmenu", function context(e) { WYSIWYG_ContextMenu.show(e, n); });		WYSIWYG_Core.addEvent(doc, "click", function context(e) { WYSIWYG_ContextMenu.close(); });		WYSIWYG_Core.addEvent(doc, "keydown", function context(e) { WYSIWYG_ContextMenu.close(); });		WYSIWYG_Core.addEvent(document, "click", function context(e) { WYSIWYG_ContextMenu.close(); });	},		/**	 * Show the context menu	 *	 * @param e Event	 * @param n Editor identifier	 */	show: function(e, n) {		if(this.contextMenuDiv == null) return false;				var ifrm = WYSIWYG.getEditor(n);		var doc = WYSIWYG.getEditorWindow(n).document;			// set the context menu position		var pos = WYSIWYG_Core.getElementPosition(ifrm);				var x = WYSIWYG_Core.isMSIE ? pos.left + e.clientX : pos.left + (e.pageX - doc.body.scrollLeft);		var y = WYSIWYG_Core.isMSIE ? pos.top + e.clientY : pos.top + (e.pageY - doc.body.scrollTop);							this.contextMenuDiv.style.left = x + "px"; 		this.contextMenuDiv.style.top = y + "px";		this.contextMenuDiv.style.visibility = "visible";		this.contextMenuDiv.style.display = "block";					// call the context menu, mozilla needs some time		window.setTimeout("WYSIWYG_ContextMenu.output('" + n + "')", 10);					WYSIWYG_Core.cancelEvent(e);		return false;	},		/**	 * Output the context menu items	 *	 * @param n Editor identifier	 */	output: function (n) {														// get selection		var sel = WYSIWYG.getSelection(n);		var range = WYSIWYG.getRange(sel);			// get current selected node							var tag = WYSIWYG.getTag(range);		if(tag == null) { return; }				// clear context menu		this.clear();				// Determine kind of nodes		var isImg = (tag.nodeName == "IMG") ? true : false;		var isLink = (tag.nodeName == "A") ? true : false;				// Selection is an image or selection is a text with length greater 0		var len = 0;		if(WYSIWYG_Core.isMSIE)			len = (document.selection && range.text) ? range.text.length : 0;		else			len = range.toString().length;		var sel = len != 0 || isImg;				// Icons		var iconLink = { enabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["createlink"][3], disabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["createlink"][2]};		var iconImage = { enabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["insertimage"][3], disabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["insertimage"][2]};		var iconDelete = { enabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["delete"][3], disabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["delete"][2]};		var iconCopy = { enabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["copy"][3], disabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["copy"][2]};		var iconCut = { enabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["cut"][3], disabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["cut"][2]};		var iconPaste = { enabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["paste"][3], disabled: WYSIWYG.config[n].ImagesDir + WYSIWYG.ToolbarList["paste"][2]};				// Create context menu html		this.html += '<table class="wysiwyg-context-menu" border="0" cellpadding="0" cellspacing="0">';				// Add items		this.addItem(n, 'Copy', iconCopy, 'Copy', sel);		this.addItem(n, 'Cut', iconCut, 'Cut', sel);		this.addItem(n, 'Paste', iconPaste, 'Paste', true);		this.addSeperator();		this.addItem(n, 'InsertImage', iconImage, 'Modify Image Properties...', isImg);		this.addItem(n, 'CreateLink', iconLink, 'Create or Modify Link...', sel || isLink);		this.addItem(n, 'RemoveNode', iconDelete, 'Remove', true);				this.html += '</table>';		this.contextMenuDiv.innerHTML = this.html;	},		/**	 * Close the context menu	 */	close: function() {		this.contextMenuDiv.style.visibility = "hidden";		this.contextMenuDiv.style.display = "none";	},		/**	 * Clear context menu	 */	clear: function() {		this.contextMenuDiv.innerHTML = "";		this.html = "";		},			/**	 * Add context menu item 	 * 	 * @param n editor identifier	 * @param cmd Command	 * @param icon Icon which is diabled	 * @param title Title of the item	 * @param disabled If item is diabled	 */	addItem: function(n, cmd, icon, title, disabled) {		var item = '';				if(disabled) {			item += '<tr>';			item += '<td class="icon"><a href="javascript:WYSIWYG.execCommand(\'' + n + '\',\'' + cmd + '\', null);"><img src="' + icon.enabled + '" border="0"></a></td>';			item += '<td onmouseover="this.className=\'mouseover\'" onmouseout="this.className=\'\'" onclick="WYSIWYG.execCommand(\'' + n + '\', \'' + cmd + '\', null);WYSIWYG_ContextMenu.close();"><a href="javascript:void(0);">' + title + '</a></td>';			item += '</tr>';		}		else {			item += '<tr>';			item += '<td class="icon"><img src="' + icon.disabled + '" border="0"></td>';			item += '<td onmouseover="this.className=\'mouseover\'" onmouseout="this.className=\'\'"><span class="disabled">' + title + '</span></td>';			item += '</tr>';		}				this.html += item;	},		/**	 * Add seperator to context menu	 */	addSeperator: function() {		var output = '';		output += '<tr>';		output += '<td colspan="2" style="text-align:center;"><hr size="1" color="#C9C9C9" width="95%"></td>';		output += '</tr>';		this.html += output;	}}/** * Table object */var WYSIWYG_Table = {	/**	 * 	 */	create: function(n, tbl) {				// get editor		var doc = WYSIWYG.getEditorWindow(n).document;		// get selection and range		var sel = WYSIWYG.getSelection(n);		var range = WYSIWYG.getRange(sel);		var table = null;						// get element from selection		if(WYSIWYG_Core.isMSIE) {			if(sel.type == "Control" && range.length == 1) {					range = WYSIWYG.getTextRange(range(0));				range.select();			}		}		// find a parent TABLE element		//table = WYSIWYG.findParent("table", range);						// check if parent is found		//var update = (table == null) ? false : true;		//if(!update) table = tbl;		table = tbl;				// add rows and cols		var rows = WYSIWYG_Core.getAttribute(tbl, "tmprows");		var cols = WYSIWYG_Core.getAttribute(tbl, "tmpcols");		WYSIWYG_Core.removeAttribute(tbl, "tmprows");		WYSIWYG_Core.removeAttribute(tbl, "tmpcols");		for(var i=0;i<rows;i++) {			var tr = doc.createElement("tr");			for(var j=0;j<cols;j++){				var td = createTD();				tr.appendChild(td);				}			table.appendChild(tr);		}				// on update exit here		//if(update) { return; }			// Check if IE or Mozilla (other)		if (WYSIWYG_Core.isMSIE) {			range.pasteHTML(table.outerHTML);   		}		else {			WYSIWYG.insertNodeAtSelection(table, n);		}				// refresh table highlighting		this.refreshHighlighting(n);									 	// functions		function createTD() {			var td = doc.createElement("td");			td.innerHTML = "&nbsp;";			return td;		}	 		},	/**	 * Enables the table highlighting	 * 	 * @param {String} n The editor identifier (the textarea's ID)	 */	refreshHighlighting: function(n) {		var doc = WYSIWYG.getEditorWindow(n).document;		var tables = doc.getElementsByTagName("table");			for(var i=0;i<tables.length;i++) {			this._enableHighlighting(tables[i]);		}		var tds = doc.getElementsByTagName("td");			for(var i=0;i<tds.length;i++) {			this._enableHighlighting(tds[i]);		}	},		/**	 * Enables the table highlighting	 * 	 * @param {String} n The editor identifier (the textarea's ID)	 */	disableHighlighting: function(n) {		var doc = WYSIWYG.getEditorWindow(n).document;		var tables = doc.getElementsByTagName("table");			for(var i=0;i<tables.length;i++) {			this._disableHighlighting(tables[i]);		}		var tds = doc.getElementsByTagName("td");			for(var i=0;i<tds.length;i++) {			this._disableHighlighting(tds[i]);		}		},		/**	 * @private	 */	_enableHighlighting: function(node) {		var style = WYSIWYG_Core.getAttribute(node, "style");			if(style == null) style = " ";		//alert("ENABLE: ELM = " + node.tagName + "; STYLE = " + style);		WYSIWYG_Core.removeAttribute(node, "prevstyle");		WYSIWYG_Core.setAttribute(node, "prevstyle", style);		WYSIWYG_Core.setAttribute(node, "style", "border:1px dashed #AAAAAA;");	},		/**	 * @private	 */	_disableHighlighting: function(node) {		var style = WYSIWYG_Core.getAttribute(node, "prevstyle");		//alert("DISABLE: ELM = " + node.tagName + "; STYLE = " + style);		// if no prevstyle is defined, the table is not in highlighting mode		if(style == null || style == "") { 			this._enableHighlighting(node); 			return; 		}					WYSIWYG_Core.removeAttribute(node, "prevstyle");		WYSIWYG_Core.removeAttribute(node, "style");		WYSIWYG_Core.setAttribute(node, "style", style);	}}/** * 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);	};}
