/********************************************************************
* openWYSIWYG v1.46c Copyright (c) 2006 openWebWare.com
* Contact us at devs@openwebware.com
* This copyright notice MUST stay intact for use.
*
* $Id: wysiwyg.js,v 1.10 2006/12/25 09:17:07 xhaggi Exp $
*
* An open source WYSIWYG editor for use in web based applications.
* For full source code and docs, visit http://www.openwebware.com
*
* This library is free software; you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along
* with this library; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
********************************************************************/
var WYSIWYG = {
/**
* Settings class, holds all customizeable properties
*/
Settings: function() {
// Images Directory
this.ImagesDir = "popups/images/";
// Popups Directory
this.PopupsDir = "popups/";
// CSS Directory File
this.CSSFile = "styles/wysiwyg.css";
// Default WYSIWYG width and height (use px or %)
this.Width = "900px";
this.Height = "360px";
// Form name where WYSIWYG is attached to textarea
this.FormName = "edit";
// Page that opened the WYSIWYG (Used for the return command)
this.Opener = "admin.asp";
// Default stylesheet of the WYSIWYG editor window
this.DefaultStyle = "font-family: arial, verdana, helvetica; font-size: 10pt;";
// Stylesheet if editor is disabled
this.DisabledStyle = "font-family: Arial; font-size: 10pt; background-color: #EEEEEE";
// Width + Height of the preview window
this.PreviewWidth = 980;
this.PreviewHeight = 700;
// Action of the preview window
this.Preview = ""
// Confirmation message if you strip any HTML added by word
this.RemoveFormatConfMessage = "Clean HTML inserted by MS Word ?";
// Nofication if browser is not supported by openWYSIWYG, leave it blank for no message output.
this.NoValidBrowserMessage = "openWYSIWYG does not support your browser.";
// Anchor path to strip, leave it blank to ignore
// or define auto to strip the path where the editor is placed
// (only IE)
this.AnchorPathToStrip = "auto";
// Image path to strip, leave it blank to ignore
// or define auto to strip the path where the editor is placed
// (only IE)
this.ImagePathToStrip = "auto";
// Enable / Disable the custom context menu
this.ContextMenu = true;
// Enabled the status bar update. Within the status bar
// node tree of the actually selected element will build
this.StatusBarEnabled = true;
// If enabled than the capability of the IE inserting line breaks will be inverted.
// Normal: ENTER =
, SHIFT + ENTER =
// Inverted: ENTER = , SHIFT + ENTER =
this.InvertIELineBreaks = false;
// Replace line breaks with tags
this.ReplaceLineBreaks = false;
// Insert image implementation
this.ImagePopupFile = "";
this.ImagePopupWidth = 0;
this.ImagePopupHeight = 0;
// Holds the available buttons displayed
// on the toolbar of the editor
this.Toolbar = new Array();
this.Toolbar[0] = new Array(
"bold",
"italic",
"underline",
"strikethrough",
"seperator",
"forecolor",
"backcolor",
"seperator",
"justifyleft",
"justifycenter",
"justifyright",
"seperator",
"unorderedlist",
"orderedlist",
"outdent",
"indent",
"seperator",
"subscript",
"superscript",
"seperator",
"cut",
"copy",
"paste",
"removeformat",
"seperator",
"undo",
"redo",
"seperator",
"inserttable",
"insertimage",
"createlink",
"seperator",
"viewSource"
);
// List of available font types
this.Fonts = new Array(
"Arial",
"Sans Serif",
"Tahoma",
"Verdana",
"Courier New",
"Georgia",
"Times New Roman",
"Impact",
"Comic Sans MS"
);
// List of available font sizes
this.Fontsizes = new Array(
"1",
"2",
"3",
"4",
"5",
"6",
"7"
);
// Add the given element to the defined toolbar
// on the defined position
this.addToolbarElement = function(element, toolbar, position) {
if(element != "seperator") {this.removeToolbarElement(element);}
if(this.Toolbar[toolbar-1] == null) {
this.Toolbar[toolbar-1] = new Array();
}
this.Toolbar[toolbar-1].splice(position+1, 1, element);
};
// Remove an element from the toolbar
this.removeToolbarElement = function(element) {
if(element == "seperator") {return;} // do not remove seperators
for(var i=0;i])*>( )*\s*<\/span>/gi, '');
str = str.replace(/]*>/gi, '');
str = str.replace(/<\/span[^>]*>/gi, '');
str = str.replace(/
]*>/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 += '
';
// 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 += '
\n';
// Create iframe which will be used for rich text editing
editor += '\n'
+ '
';
// Status bar HTML code
if(this.config[n].StatusBarEnabled) {
editor += '
';
}
editor += '
\n';
// Insert the editor after the textarea
textarea.insertAdjacentHTML("afterEnd", editor);
// Insert the Font Type and Size drop downs into the toolbar
// Hide the dynamic drop down lists for the Font Types and Sizes
this.outputFontSelect(n);
this.outputFontSizes(n);
this.hideFonts(n);
this.hideFontSizes(n);
// Hide the "Text Mode" button
// Validate if textMode Elements are prensent
if($("textMode" + n)) {
$("textMode" + n).style.display = 'none';
}
// Pass the textarea's existing text over to the content variable
var content = textarea.value;
var doc = this.getEditorWindow(n).document;
// Replace all \n with
if(this.config[n].ReplaceLineBreaks) {
content = content.replace(/\n\r|\n/ig, " ");
}
// Write the textarea's content into the iframe
doc.open();
doc.write(content);
doc.close();
// Make the iframe editable in both Mozilla and IE
// Improve compatiblity for IE + Mozilla
if (doc.body.contentEditable) {
doc.body.contentEditable = true;
}
else {
doc.designMode = "on";
}
// Set default font style
WYSIWYG_Core.setAttribute(doc.body, "style", this.config[n].DefaultStyle);
// Event Handling
// Update the textarea with content in WYSIWYG when user submits form
for (var idx=0; idx < document.forms.length; idx++) {
WYSIWYG_Core.addEvent(document.forms[idx], "submit", function xxx_aa() { WYSIWYG.updateTextArea(n); });
}
// close font selection if mouse moves over the editor window
WYSIWYG_Core.addEvent(doc, "mouseover", function xxx_bb() { WYSIWYG.hideFonts(n); WYSIWYG.hideFontSizes(n); });
// If it's true invert the line break capability of IE
if(this.config[n].InvertIELineBreaks) {
WYSIWYG_Core.addEvent(doc, "keypress", function xxx_cc() { WYSIWYG.invertIELineBreakCapability(n); });
}
// status bar update
if(this.config[n].StatusBarEnabled) {
WYSIWYG_Core.addEvent(doc, "mouseup", function xxx_dd() { WYSIWYG.updateStatusBar(n); });
}
// custom context menu
if(this.config[n].ContextMenu) {
WYSIWYG_ContextMenu.init(n);
}
// init viewTextMode var
this.viewTextMode[n] = false;
},
/* ---------------------------------------------------------------------- *\
Function : disable()
Description : Disable the given WYSIWYG Editor Box
Usage : WYSIWYG.disable(textareaID)
Arguments : textareaID - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
disable: function(textareaID) {
// set n to textareaID
var n = textareaID;
// get the editor window
var editor = this.getEditorWindow(n);
// Validate if editor exists
if(editor == null) {
alert("No editor found with the given identifier (ID: " + n + ").");
return;
}
if(editor) {
// disable design mode or content editable feature
if(editor.document.body.contentEditable) {
editor.document.body.contentEditable = false;
}
else {
editor.document.designMode = "Off";
}
// change the style of the body
WYSIWYG_Core.setAttribute(editor.document.body, "style", this.config[n].DisabledStyle);
// hide the status bar
this.hideStatusBar(n);
// hide all toolbars
this.hideToolbars(n);
}
},
/* ---------------------------------------------------------------------- *\
Function : enable()
Description : Enables the given WYSIWYG Editor Box
Usage : WYSIWYG.enable(textareaID)
Arguments : textareaID - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
enable: function(textareaID) {
// set n to textareaID
var n = textareaID;
// get the editor window
var editor = this.getEditorWindow(n);
// Validate if editor exists
if(editor == null) {
alert("No editor found with the given identifier (ID: " + n + ").");
return;
}
if(editor) {
// disable design mode or content editable feature
if(editor.document.body.contentEditable){
editor.document.body.contentEditable = true;
}
else {
editor.document.designMode = "On";
}
// change the style of the body
WYSIWYG_Core.setAttribute(editor.document.body, "style", this.config[n].DefaultStyle);
// hide the status bar
this.showStatusBar(n);
// hide all toolbars
this.showToolbars(n);
}
},
/* ---------------------------------------------------------------------- *\
Function : getNodeTree()
Description : Returns the node structure of the current selection as array
Usage : WYSIWYG.getNodeTree(n);
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
getNodeTree: function(n) {
var sel = this.getSelection(n);
var range = this.getRange(sel);
// get element of range
var tag = this.getTag(range);
if(tag == null) { return; }
// get parent of element
var node = this.getParent(tag);
// init the tree as array with the current selected element
var nodeTree = new Array(tag);
// get all parent nodes
var ii = 1;
while(node != null && node.nodeName != "#document") {
nodeTree[ii] = node;
node = this.getParent(node);
ii++;
}
return nodeTree;
},
/**
* Removes the current node of the selection
*
* @param {String} n The editor identifier (the textarea's ID)
*/
removeNode: function(n) {
// get selection and range
var sel = this.getSelection(n);
var range = this.getRange(sel);
// the current tag of range
var tag = this.getTag(range);
var parent = tag.parentNode;
if(tag == null || parent == null) { return; }
if(tag.nodeName == "HTML" || tag.nodeName == "BODY") { return; }
// copy child elements of the node to the parent element before remove the node
//var childNodes = new Array();
//for(var i=0; i < tag.childNodes.length;i++)
// childNodes[i] = tag.childNodes[i];
//for(var i=0; i < childNodes.length;i++)
// parent.insertBefore(childNodes[i], tag);
// remove node
parent.removeChild(tag);
// validate if parent is a link and the node is only
// surrounded by the link, then remove the link too
if(parent.nodeName == "A" && !parent.hasChildNodes()) {
if(parent.parentNode) { parent.parentNode.removeChild(parent); }
}
// update the status bar
this.updateStatusBar(n);
},
/**
* Get the selection of the given editor
*
* @param n The editor identifier (the textarea's ID)
*/
getSelection: function(n) {
var ifrm = this.getEditorWindow(n);
var doc = ifrm.document;
var sel = null;
if(ifrm.getSelection){
sel = ifrm.getSelection();
}
else if (doc.getSelection) {
sel = doc.getSelection();
}
else if (doc.selection) {
sel = doc.selection;
}
return sel;
},
/* ---------------------------------------------------------------------- *\
Function : updateStatusBar()
Description : Updates the status bar with the current node tree
Usage : WYSIWYG.updateStatusBar(n);
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
updateStatusBar: function(n) {
// get the node structure
var nodeTree = this.getNodeTree(n);
if(nodeTree == null) { return; }
// format the output
var outputTree = "";
var max = nodeTree.length - 1;
for(var i=max;i>=0;i--) {
if(nodeTree[i].nodeName != "HTML" && nodeTree[i].nodeName != "BODY") {
outputTree += '' + nodeTree[i].nodeName + '';
}
else {
outputTree += nodeTree[i].nodeName;
}
if(i > 0) { outputTree += " > "; }
}
// update the status bar
var statusbar = $("wysiwyg_statusbar_" + n);
if(statusbar){
statusbar.innerHTML = outputTree;
}
},
/* ---------------------------------------------------------------------- *\
Function : disableDesignMode()
Description : Disable the design mode if right mouse button is pressed.
It's needed for custom context menus on mozilla (firefox),
because if design mode is on then you can`t diabled the browser
context menu.
Usage : WYSIWYG.disableDesignMode(e, n);
Arguments : event - browser event (like which button pressed)
n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
disableDesignMode: function(event, n) {
var doc = this.getEditorWindow(n).document;
if(event.which == 3) {
doc.designMode = "off";
return false;
}
else if(event.which != 3 && doc.designMode == "off") {
doc.designMode = "on";
return true;
}
},
/* ---------------------------------------------------------------------- *\
Function : formatText() (changed)
Description : Format the content within the WYSIWYG Editor
Usage : WYSIWYG.formatText(id, n, selected);
Arguments : cmd - The execCommand (e.g. Bold)
n - The editor identifier that the command affects (the textarea's ID)
selected - The selected value when applicable (e.g. Arial)
\* ---------------------------------------------------------------------- */
formatText: function(cmd, n, selected) {
// When user clicks toolbar button make sure it always targets its respective WYSIWYG
this.getEditorWindow(n).focus();
// When in Text Mode these execCommands are disabled
var formatIDs = new Array("FontSize","FontName","Bold","Italic","Underline","Subscript","Superscript","Strikethrough","Justifyleft","Justifyright","Justifycenter","InsertUnorderedList","InsertOrderedList","Indent","Outdent","ForeColor","BackColor","InsertImage","InsertTable","CreateLink", "Preview", "RemoveFormat");
// Check if button clicked is in disabled list
for (var i = 0; i < formatIDs.length; i++) {
if (formatIDs[i] == cmd) {
var disabled_id = 1;
}
}
// rbg to hex convertion implementation dependents on browser
var toHexColor = WYSIWYG_Core.isMSIE ? WYSIWYG_Core._dec_to_rgb : WYSIWYG_Core.toHexColor;
// popup screen positions
var popupPosition = {left: parseInt(window.screen.availWidth / 8), top: parseInt(window.screen.availHeight / 4)};
// Check if in Text Mode and disabled button was clicked
if (this.viewTextMode[n] == true && disabled_id == 1) {
alert("You are in TEXT Mode. This feature has been disabled.");
return;
}
// Check the insert image popup implementation
var imagePopupFile = this.config[n].PopupsDir + 'insert_image.html';
var imagePopupWidth = 400;
var imagePopupHeight = 215;
if(typeof this.config[n].ImagePopupFile != "undefined" && this.config[n].ImagePopupFile != "") {
imagePopupFile = this.config[n].ImagePopupFile;
}
if(typeof this.config[n].ImagePopupWidth && this.config[n].ImagePopupWidth > 0) {
imagePopupWidth = this.config[n].ImagePopupWidth;
}
if(typeof this.config[n].ImagePopupHeight && this.config[n].ImagePopupHeight > 0) {
imagePopupHeight = this.config[n].ImagePopupHeight;
}
// switch which action have to do
switch(cmd) {
// Font size
case "FontSize":
this.getEditorWindow(n).document.execCommand("FontSize", false, selected);
break;
// FontName
case "FontName":
this.getEditorWindow(n).document.execCommand("FontName", false, selected);
break;
// ForeColor and
case "ForeColor":
var rgb = this.getEditorWindow(n).document.queryCommandValue(cmd);
var currentColor = rgb != '' ? toHexColor(this.getEditorWindow(n).document.queryCommandValue(cmd)) : "000000";
window.open(this.config[n].PopupsDir + 'select_color.html?color=' + currentColor + '&command=' + cmd + '&wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,width=210,height=165,top=' + popupPosition.top + ',left=' + popupPosition.left).focus();
break;
// BackColor
case "BackColor":
var currentColor = toHexColor(this.getEditorWindow(n).document.queryCommandValue(cmd));
window.open(this.config[n].PopupsDir + 'select_color.html?color=' + currentColor + '&command=' + cmd + '&wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,width=210,height=165,top=' + popupPosition.top + ',left=' + popupPosition.left).focus();
break;
// InsertImage
case "InsertImage":
window.open(imagePopupFile + '?wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,resizable=0,width=' + imagePopupWidth + ',height=' + imagePopupHeight + ',top=' + popupPosition.top + ',left=' + popupPosition.left).focus();
break;
// Remove Image
case "RemoveImage":
this.removeImage(n);
break;
// Remove Link
case "RemoveLink":
this.removeLink(n);
break;
// Remove a Node
case "RemoveNode":
this.removeNode(n);
break;
// Create Link
case "CreateLink":
window.open(this.config[n].PopupsDir + 'insert_hyperlink.html?wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,resizable=0,width=350,height=160,top=' + popupPosition.top + ',left=' + popupPosition.left).focus();
break;
// InsertTable
case "InsertTable":
window.open(this.config[n].PopupsDir + 'create_table.html?wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,resizable=0,width=400,height=360,top=' + popupPosition.top + ',left=' + popupPosition.left).focus();
break;
// ViewSource
case "ViewSource":
this.viewSource(n);
break;
// ViewText
case "ViewText":
this.viewText(n);
break;
// Help
case "Help":
window.open(this.config[n].PopupsDir + 'about.html?wysiwyg=' + n, 'popup', 'location=0,status=0,scrollbars=0,resizable=0,width=400,height=350,top=' + popupPosition.top + ',left=' + popupPosition.left).focus();
break;
// Strip any HTML added by word
case "RemoveFormat":
this.removeFormat(n);
break;
// Preview thx to Korvo
case "Preview":
window.open('http://www.brannsikker.com/default.asp?pageID=preview&wysiwyg=' + n + '&preview=' + this.config[n].Preview,'popup', 'location=0,status=0,scrollbars=1,resizable=1,width=' + this.config[n].PreviewWidth + ',height=' + this.config[n].PreviewHeight + ',top=' + popupPosition.top + ',left=' + popupPosition.left).focus();
break;
// Print
case "Print":
this.print(n);
break;
// Save
case "Save":
WYSIWYG.updateTextArea(n);
document.getElementById(this.config[n].FormName).submit();
break;
// Save and close
case "Saveclose":
WYSIWYG.updateTextArea(n);
document.getElementById(this.config[n].FormName).submit();
break;
// Return
case "Return":
history.go(-1);
break;
default:
WYSIWYG_Core.execCommand(n, cmd);
}
// hide node the font + font size selection
this.hideFonts(n);
this.hideFontSizes(n);
},
/* ---------------------------------------------------------------------- *\
Function : insertHTML()
Description : Insert HTML into WYSIWYG in rich text
Usage : WYSIWYG.insertHTML("hello", "textareaID")
Arguments : html - The HTML being inserted (e.g. hello)
n - The editor identifier that the HTML
will be inserted into (the textarea's ID)
\* ---------------------------------------------------------------------- */
insertHTML: function(html, n) {
if (WYSIWYG_Core.isMSIE) {
this.getEditorWindow(n).document.selection.createRange().pasteHTML(html);
}
else {
var span = this.getEditorWindow(n).document.createElement("span");
span.innerHTML = html;
this.insertNodeAtSelection(span, n);
}
},
/* ---------------------------------------------------------------------- *\
Function : insertNodeAtSelection()
Description : insert HTML into WYSIWYG in rich text (mozilla)
Usage : WYSIWYG.insertNodeAtSelection(insertNode, n)
Arguments : insertNode - The HTML being inserted (must be innerHTML inserted within a div element)
n - The editor identifier that the HTML will be inserted into (the textarea's ID)
\* ---------------------------------------------------------------------- */
insertNodeAtSelection: function(insertNode, n) {
// get editor document
var doc = this.getEditorWindow(n).document;
// get current selection
var sel = this.getSelection(n);
// get the first range of the selection
// (there's almost always only one range)
var range = sel.getRangeAt(0);
// deselect everything
sel.removeAllRanges();
// remove content of current selection from document
range.deleteContents();
// get location of current selection
var container = range.startContainer;
var pos = range.startOffset;
// make a new range for the new selection
range = doc.createRange();
if (container.nodeType==3 && insertNode.nodeType==3) {
// if we insert text in a textnode, do optimized insertion
container.insertData(pos, insertNode.data);
// put cursor after inserted text
range.setEnd(container, pos+insertNode.length);
range.setStart(container, pos+insertNode.length);
}
else {
var afterNode;
var beforeNode;
if (container.nodeType==3) {
// when inserting into a textnode
// we create 2 new textnodes
// and put the insertNode in between
var textNode = container;
container = textNode.parentNode;
var text = textNode.nodeValue;
// text before the split
var textBefore = text.substr(0,pos);
// text after the split
var textAfter = text.substr(pos);
beforeNode = document.createTextNode(textBefore);
afterNode = document.createTextNode(textAfter);
// insert the 3 new nodes before the old one
container.insertBefore(afterNode, textNode);
container.insertBefore(insertNode, afterNode);
container.insertBefore(beforeNode, insertNode);
// remove the old node
container.removeChild(textNode);
}
else {
// else simply insert the node
afterNode = container.childNodes[pos];
container.insertBefore(insertNode, afterNode);
}
range.setEnd(afterNode, 0);
range.setStart(afterNode, 0);
}
sel.addRange(range);
},
/* ---------------------------------------------------------------------- *\
Function : print()
Description : Print out the content of the WYSIWYG editor area
Usage : WYSIWYG.print(n)
Arguments : n - The editor identifier (textarea ID)
\* ---------------------------------------------------------------------- */
print: function(n) {
if(document.all && navigator.appVersion.substring(22,23)==4) {
var doc = this.getEditorWindow(n).document;
doc.focus();
var OLECMDID_PRINT = 6;
var OLECMDEXECOPT_DONTPROMPTUSER = 2;
var OLECMDEXECOPT_PROMPTUSER = 1;
var WebBrowser = '';
doc.body.insertAdjacentHTML('beforeEnd',WebBrowser);
WebBrowser.ExecWB(OLECMDID_PRINT, OLECMDEXECOPT_DONTPROMPTUSER);
WebBrowser.outerHTML = '';
} else {
this.getEditorWindow(n).print();
}
},
/* ---------------------------------------------------------------------- *\
Function : outputFontSelect()
Description : creates the Font Select drop down and inserts it into the toolbar
Usage : WYSIWYG.outputFontSelect(n)
Arguments : n - The editor identifier that the Font Select will update
when making font changes (the textarea's ID)
\* ---------------------------------------------------------------------- */
outputFontSelect: function(n) {
var fontDiv = $('FontSelect' + n);
if(fontDiv == null) { return; }
var fonts = this.config[n].Fonts;
var FontSelectObj = this.ToolbarList['selectfont'];
var FontSelect = this.config[n].ImagesDir + FontSelectObj[2];
var FontSelectOn = this.config[n].ImagesDir + FontSelectObj[3];
fonts.sort();
var FontSelectDropDown = new Array;
FontSelectDropDown[n] = '
';
FontSelectDropDown[n] += '';
for (var i = 0; i < fonts.length;i++) {
if (fonts[i]) {
FontSelectDropDown[n] += ' ';
}
}
FontSelectDropDown[n] += '
';
fontDiv.insertAdjacentHTML("afterBegin", FontSelectDropDown[n]);
},
/* ---------------------------------------------------------------------- *\
Function : outputFontSizes()
Description : creates the Font Sizes drop down and inserts it into the toolbar
Usage : WYSIWYG.outputFontSelect(n)
Arguments : n - The editor identifier that the Font Sizes will update
when making font changes (the textarea's ID)
\* ---------------------------------------------------------------------- */
outputFontSizes: function(n) {
var fontSizeDiv = $('FontSizes' + n);
if(fontSizeDiv == null) { return; }
var fontSize = this.config[n].Fontsizes;
var FontSizeObj = this.ToolbarList['selectsize'];
var FontSize = this.config[n].ImagesDir + FontSizeObj[2];
var FontSizeOn = this.config[n].ImagesDir + FontSizeObj[3];
fontSize.sort();
var FontSizesDropDown = new Array;
FontSizesDropDown[n] = '
';
FontSizesDropDown[n] += '';
for (var i = 0; i < fontSize.length;i++) {
if (fontSize[i]) {
FontSizesDropDown[n] += ' ';
}
}
FontSizesDropDown[n] += '
';
fontSizeDiv.insertAdjacentHTML("afterBegin", FontSizesDropDown[n]);
},
/* ---------------------------------------------------------------------- *\
Function : hideFonts()
Description : Hides the list of font names in the font select drop down
Usage : WYSIWYG.hideFonts(n)
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
hideFonts: function(n) {
if($('Fonts' + n)) { $('Fonts' + n).style.display = 'none'; }
},
/* ---------------------------------------------------------------------- *\
Function : hideFontSizes()
Description : Hides the list of font sizes in the font sizes drop down
Usage : WYSIWYG.hideFontSizes(n)
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
hideFontSizes: function(n) {
if($('Sizes' + n)) { $('Sizes' + n).style.display = 'none'; }
},
/* ---------------------------------------------------------------------- *\
Function : showFonts()
Description : Shows the list of font names in the font select drop down
Usage : WYSIWYG.showFonts(n)
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
showFonts: function(n) {
if($('Fonts' + n) == null) { return; }
if ($('Fonts' + n).style.display == 'block') {
$('Fonts' + n).style.display = 'none';
}
else {
$('Fonts' + n).style.display = 'block';
$('Fonts' + n).style.position = 'absolute';
}
// hide font size selection
this.hideFontSizes(n);
},
/* ---------------------------------------------------------------------- *\
Function : showFontSizes()
Description : Shows the list of font sizes in the font sizes drop down
Usage : WYSIWYG.showFonts(n)
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
showFontSizes: function(n) {
if($('Sizes' + n) == null) { return; }
if ($('Sizes' + n).style.display == 'block') {
$('Sizes' + n).style.display = 'none';
}
else {
$('Sizes' + n).style.display = 'block';
$('Sizes' + n).style.position = 'absolute';
}
// hide font size selection
this.hideFonts(n);
},
/* ---------------------------------------------------------------------- *\
Function : viewSource()
Description : Shows the HTML source code generated by the WYSIWYG editor
Usage : WYSIWYG.showFonts(n)
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
viewSource: function(n) {
// document
var doc = this.getEditorWindow(n).document;
// View Source for IE
if (WYSIWYG_Core.isMSIE) {
var iHTML = doc.body.innerHTML;
// strip off the absolute urls
iHTML = this.stripURLPath(n, iHTML);
// replace all decimal color strings with hex decimal color strings
iHTML = WYSIWYG_Core.replaceRGBWithHexColor(iHTML);
doc.body.innerText = iHTML;
}
// View Source for Mozilla/Netscape
else {
// replace all decimal color strings with hex decimal color strings
var html = WYSIWYG_Core.replaceRGBWithHexColor(doc.body.innerHTML);
html = document.createTextNode(html);
doc.body.innerHTML = "";
doc.body.appendChild(html);
}
// Hide the HTML Mode button and show the Text Mode button
// Validate if Elements are present
if($('HTMLMode' + n)) {
$('HTMLMode' + n).style.display = 'none';
}
if($('textMode' + n)) {
$('textMode' + n).style.display = 'block';
}
// set the font values for displaying HTML source
doc.body.style.fontSize = "12px";
doc.body.style.fontFamily = "Courier New";
this.viewTextMode[n] = true;
},
/* ---------------------------------------------------------------------- *\
Function : viewSource()
Description : Shows the HTML source code generated by the WYSIWYG editor
Usage : WYSIWYG.showFonts(n)
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
viewText: function(n) {
// get document
var doc = this.getEditorWindow(n).document;
// View Text for IE
if (WYSIWYG_Core.isMSIE) {
var iText = doc.body.innerText;
// strip off the absolute urls
iText = this.stripURLPath(n, iText);
// replace all decimal color strings with hex decimal color strings
iText = WYSIWYG_Core.replaceRGBWithHexColor(iText);
doc.body.innerHTML = iText;
}
// View Text for Mozilla/Netscape
else {
var html = doc.body.ownerDocument.createRange();
html.selectNodeContents(doc.body);
// replace all decimal color strings with hex decimal color strings
html = WYSIWYG_Core.replaceRGBWithHexColor(html.toString());
doc.body.innerHTML = html;
}
// Hide the Text Mode button and show the HTML Mode button
// Validate if Elements are present
if($('textMode' + n)) {
$('textMode' + n).style.display = 'none';
}
if($('HTMLMode' + n)) {
$('HTMLMode' + n).style.display = 'block';
}
// reset the font values (changed)
WYSIWYG_Core.setAttribute(doc.body, "style", this.config[n].DefaultStyle);
this.viewTextMode[n] = false;
},
/* ---------------------------------------------------------------------- *\
Function : getDocumentPath()
Description : Get the path of the given document
Usage : WYSIWYG.getDocumentPath(doc)
Arguments : doc - Document of which you get the the path
\* ---------------------------------------------------------------------- */
getDocumentPathOfUrl: function(url) {
var path = null;
// if local file system, convert local url into web url
url = url.replace(/file:\/\//gi, "file:///");
url = url.replace(/\\/gi, "\/");
var pos = url.lastIndexOf("/");
if(pos != -1) {
path = url.substring(0, pos + 1);
}
return path;
},
/* ---------------------------------------------------------------------- *\
Function : getDocumentUrl()
Description : Get the documents url, convert local urls to web urls
Usage : WYSIWYG.getDocumentUrl(doc)
Arguments : doc - Document of which you get the the path
\* ---------------------------------------------------------------------- */
getDocumentUrl: function(doc) {
// if local file system, convert local url into web url
var url = doc.URL;
url = url.replace(/file:\/\//gi, "file:///");
url = url.replace(/\\/gi, "\/");
return url;
},
/* ---------------------------------------------------------------------- *\
Function : stripURLPath()
Description : Strips off the defined image and the anchor urls of the given content.
It also can strip the document URL automatically if you define auto.
Usage : WYSIWYG.stripURLPath(content)
Arguments : content - Content on which the stripping applies
\* ---------------------------------------------------------------------- */
stripURLPath: function(n, content, exact) {
// parameter exact is optional
if(typeof exact == "undefined") {
exact = true;
}
var stripImgageUrl = null;
var stripAnchorUrl = null;
// add url to strip of anchors to array
if(this.config[n].AnchorPathToStrip == "auto") {
stripAnchorUrl = this.getDocumentUrl(document);
}
else if(this.config[n].AnchorPathToStrip != "") {
stripAnchorUrl = this.config[n].AnchorPathToStrip;
}
// add strip url of images to array
if(this.config[n].ImagePathToStrip == "auto") {
stripImgageUrl = this.getDocumentUrl(document);
}
else if(this.config[n].ImagePathToStrip != "") {
stripImgageUrl = this.config[n].ImagePathToStrip;
}
var url;
var regex;
var result;
// strip url of image path
if(stripImgageUrl) {
// escape reserved characters to be a valid regex
url = WYSIWYG_Core.stringToRegex(this.getDocumentPathOfUrl(stripImgageUrl));
// exact replacing of url. regex: src=""
if(exact) {
regex = eval("/(src=\")(" + url + ")([^\"]*)/gi");
content = content.replace(regex, "$1$3");
}
// not exect replacing of url. regex:
else {
regex = eval("/(" + url + ")(.+)/gi");
content = content.replace(regex, "$2");
}
// strip absolute urls without a heading slash ("images/print.gif")
result = this.getDocumentPathOfUrl(stripImgageUrl).match(/.+[\/]{2,3}[^\/]*/,"");
if(result) {
url = WYSIWYG_Core.stringToRegex(result[0]);
// exact replacing of url. regex: src=""
if(exact) {
regex = eval("/(src=\")(" + url + ")([^\"]*)/gi");
content = content.replace(regex, "$1$3");
}
// not exect replacing of url. regex:
else {
regex = eval("/(" + url + ")(.+)/gi");
content = content.replace(regex, "$2");
}
}
}
// strip url of image path
if(stripAnchorUrl) {
// escape reserved characters to be a valid regex
url = WYSIWYG_Core.stringToRegex(this.getDocumentPathOfUrl(stripAnchorUrl));
// strip absolute urls with a heading slash ("/product/index.html")
// exact replacing of url. regex: src=""
if(exact) {
regex = eval("/(href=\")(" + url + ")([^\"]*)/gi");
content = content.replace(regex, "$1$3");
}
// not exect replacing of url. regex:
else {
regex = eval("/(" + url + ")(.+)/gi");
content = content.replace(regex, "$2");
}
// strip absolute urls without a heading slash ("product/index.html")
result = this.getDocumentPathOfUrl(stripAnchorUrl).match(/.+[\/]{2,3}[^\/]*/,"");
if(result) {
url = WYSIWYG_Core.stringToRegex(result[0]);
// exact replacing of url. regex: src=""
if(exact) {
regex = eval("/(href=\")(" + url + ")([^\"]*)/gi");
content = content.replace(regex, "$1$3");
}
// not exect replacing of url. regex:
else {
regex = eval("/(" + url + ")(.+)/gi");
content = content.replace(regex, "$2");
}
}
// stip off anchor links with #name
url = WYSIWYG_Core.stringToRegex(stripAnchorUrl);
// exact replacing of url. regex: src=""
if(exact) {
regex = eval("/(href=\")(" + url + ")(#[^\"]*)/gi");
content = content.replace(regex, "$1$3");
}
// not exect replacing of url. regex:
else {
regex = eval("/(" + url + ")(.+)/gi");
content = content.replace(regex, "$2");
}
// stip off anchor links with #name (only for local system)
url = this.getDocumentUrl(document);
var pos = url.lastIndexOf("/");
if(pos != -1) {
url = url.substring(pos + 1, url.length);
url = WYSIWYG_Core.stringToRegex(url);
// exact replacing of url. regex: src=""
if(exact) {
regex = eval("/(href=\")(" + url + ")(#[^\"]*)/gi");
content = content.replace(regex, "$1$3");
}
// not exect replacing of url. regex:
else {
regex = eval("/(" + url + ")(.+)/gi");
content = content.replace(regex, "$2");
}
}
}
return content;
},
/* ---------------------------------------------------------------------- *\
Function : updateTextArea()
Description : Updates the text area value with the HTML source of the WYSIWYG
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
updateTextArea: function(n) {
// on update switch editor back to html mode
if(this.viewTextMode[n]) { this.viewText(n); }
// get inner HTML
var content = this.getEditorWindow(n).document.body.innerHTML;
// strip off defined URLs on IE
content = this.stripURLPath(n, content);
// replace all decimal color strings with hex color strings
content = WYSIWYG_Core.replaceRGBWithHexColor(content);
// remove line breaks before content will be updated
if(this.config[n].ReplaceLineBreaks) { content = content.replace(/(\r\n)|(\n)/ig, ""); }
// set content back in textarea
$(n).value = content;
},
/* ---------------------------------------------------------------------- *\
Function : hideToolbars()
Description : Hide all toolbars
Usage : WYSIWYG.hideToolbars(n)
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
hideToolbars: function(n) {
for(var i=0;i 0) {
elmWorking = range.item(0);
}
else {
elmWorking = range.parentElement();
}
while (elmWorking.tagName != "HTML") {
if (elmWorking.tagName == parentTagName){
return elmWorking;
} else {
elmWorking = elmWorking.parentElement;
}
}
rangeWorking = range.duplicate();
rangeWorking.collapse(true);
rangeWorking.moveEnd("character", 1);
if (rangeWorking.text.length>0) {
while (rangeWorking.compareEndPoints("EndToEnd", range) < 0){
rangeWorking.move("Character");
if (null != this.findParentTag(parentTagName, rangeWorking)){
return this.findParentTag(parentTagName, rangeWorking);
}
}
}
return null;
}
}
catch(e) {
return null;
}
},
/* ---------------------------------------------------------------------- *\
Function : getTag()
Description : Get the acutally tag of the given range
Usage : WYSIWYG.getTag(range)
Arguments : range - Range
\* ---------------------------------------------------------------------- */
getTag: function(range) {
try {
if(!WYSIWYG_Core.isMSIE) {
var node = range.startContainer;
var pos = range.startOffset;
if(node.nodeType != 3) { node = node.childNodes[pos]; }
if(node.nodeName && node.nodeName.search(/#/) != -1) {
return node.parentNode;
}
return node;
}
else {
if(range.length > 0) {
return range.item(0);
}
else if(range.parentElement()) {
return range.parentElement();
}
}
return null;
}
catch(e) {
return null;
}
},
/* ---------------------------------------------------------------------- *\
Function : getParent()
Description : Get the parent node of an node
Usage : WYSIWYG.getParent(node)
Arguments : element - Element which parent will be returned
\* ---------------------------------------------------------------------- */
getParent: function(element) {
if(element.parentNode) {
return element.parentNode;
}
return null;
},
/* ---------------------------------------------------------------------- *\
Function : getTextRange()
Description : Get the text range object of the given element
Usage : WYSIWYG.getTextRange(element)
Arguments : element - An element of which you get the text range object
\* ---------------------------------------------------------------------- */
getTextRange: function(element){
var range = element.parentTextEdit.createTextRange();
range.moveToElementText(element);
return range;
},
/* ---------------------------------------------------------------------- *\
Function : invertIELineBreakCapability()
Description : Inverts the line break capability of IE (Thx to richyrich)
Normal: ENTER =
, SHIFT + ENTER =
Inverted: ENTER = , SHIFT + ENTER =
Usage : WYSIWYG.invertIELineBreakCapability(n)
Arguments : n - The editor identifier (the textarea's ID)
\* ---------------------------------------------------------------------- */
invertIELineBreakCapability: function(n) {
var editor = this.getEditorWindow(n);
var sel;
// validate if the press key is the carriage return key
if (editor.event.keyCode==13) {
if (!editor.event.shiftKey) {
sel = this.getRange(this.getSelection(n));
sel.pasteHTML(" ");
editor.event.cancelBubble = true;
editor.event.returnValue = false;
sel.select();
sel.moveEnd("character", 1);
sel.moveStart("character", 1);
sel.collapse(false);
return false;
}
else {
sel = this.getRange(this.getSelection(n));
sel.pasteHTML("
");
editor.event.cancelBubble = true;
editor.event.returnValue = false;
sel.select();
sel.moveEnd("character", 1);
sel.moveStart("character", 1);
sel.collapse(false);
return false;
}
}
},
/* ---------------------------------------------------------------------- *\
Function : selectNode()
Description : Select a node within the current editor
Usage : WYSIWYG.selectNode(n, level)
Arguments : n - The editor identifier (the textarea's ID)
level - identifies the level of the element which will be selected
\* ---------------------------------------------------------------------- */
selectNode: function(n, level) {
var sel = this.getSelection(n);
var range = this.getRange(sel);
var parentnode = this.getTag(range);
var i = 0;
for (var node=parentnode; (node && (node.nodeType == 1)); node=node.parentNode) {
if (i == level) {
this.nodeSelection(n, node);
}
i++;
}
this.updateStatusBar(n);
},
/* ---------------------------------------------------------------------- *\
Function : nodeSelection()
Description : Do the node selection
Usage : WYSIWYG.nodeSelection(n, node)
Arguments : n - The editor identifier (the textarea's ID)
node - The node which will be selected
\* ---------------------------------------------------------------------- */
nodeSelection: function(n, node) {
var doc = this.getEditorWindow(n).document;
var sel = this.getSelection(n);
var range = this.getRange(sel);
if(!WYSIWYG_Core.isMSIE) {
if (node.nodeName == "BODY") {
range.selectNodeContents(node);
} else {
range.selectNode(node);
}
/*
if (endNode) {
try {
range.setStart(node, startOffset);
range.setEnd(endNode, endOffset);
} catch(e) {
}
}
*/
if (sel) { sel.removeAllRanges(); }
if (sel) { sel.addRange(range); }
}
else {
// MSIE may not select everything when BODY is selected -
// start may be set to first text node instead of first non-text node -
// no known workaround
if ((node.nodeName == "TABLE") || (node.nodeName == "IMG") || (node.nodeName == "INPUT") || (node.nodeName == "SELECT") || (node.nodeName == "TEXTAREA")) {
try {
range = doc.body.createControlRange();
range.addElement(node);
range.select();
}
catch(e) { }
}
else {
range = doc.body.createTextRange();
if (range) {
range.collapse();
if (range.moveToElementText) {
try {
range.moveToElementText(node);
range.select();
} catch(e) {
try {
range = doc.body.createTextRange();
range.moveToElementText(node);
range.select();
}
catch(e) {}
}
} else {
try {
range = doc.body.createTextRange();
range.moveToElementText(node);
range.select();
}
catch(e) {}
}
}
}
}
}
}
/********************************************************************
* openWYSIWYG core functions Copyright (c) 2006 openWebWare.com
* Contact us at devs@openwebware.com
* This copyright notice MUST stay intact for use.
*
* $Id: wysiwyg.js,v 1.10 2006/12/25 09:17:07 xhaggi Exp $
********************************************************************/
var WYSIWYG_Core = {
/**
* Holds true if browser is MSIE, otherwise false
*/
isMSIE: navigator.appName == "Microsoft Internet Explorer" ? true : false,
/**
* Holds true if browser is Firefox (Mozilla)
*/
isFF: !document.all && document.getElementById && !this.isOpera,
/**
* Holds true if browser is Opera, otherwise false
*/
isOpera: navigator.appName == "Opera" ? true : false,
/**
* Trims whitespaces of the given string
*
* @param str String
* @return Trimmed string
*/
trim: function(str) {
return str.replace(/^\s*|\s*$/g,"");
},
/**
* Determine if the given parameter is defined
*
* @param p Parameter
* @return true/false dependents on definition of the parameter
*/
defined: function(p) {
return typeof p == "undefined" ? false : true;
},
/**
* Determine if the browser version is compatible
*
* @return true/false depending on compatiblity of the browser
*/
isBrowserCompatible: function() {
// Validate browser and compatiblity
if ((navigator.userAgent.indexOf('Safari') != -1 ) || !document.getElementById || !document.designMode){
//no designMode (Safari lies)
return false;
}
return true;
},
/**
* Set the style attribute of the given element.
* Private method to solve the IE bug while setting the style attribute.
*
* @param element The element on which the style attribute will affect
* @param style Stylesheet which will be set
*/
_setStyleAttribute: function(element, style) {
var styles = style.split(";");
var pos;
for(var i=0;i>= 8; // drop low byte
var nybble2 = myByte & 0x0F; // get low nybble (4 bits)
var nybble1 = (myByte >> 4) & 0x0F; // get high nybble
hex_string += nybble1.toString(16); // convert nybble to hex
hex_string += nybble2.toString(16); // convert nybble to hex
}
return hex_string.toUpperCase();
},
/**
* Replace RGB color strings with hex color strings within a string.
*
* @param {String} str RGB String
* @param {String} Hex color string
*/
replaceRGBWithHexColor: function(str) {
// find all decimal color strings
var matcher = str.match(/rgb\([0-9 ]+,[0-9 ]+,[0-9 ]+\)/gi);
if(matcher) {
for(var j=0; j';
// 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 += '';
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 += '