//------------------------------------------------------------------------------ // IPS Cross-Browser Rich Text Editor //------------------------------------------------------------------------------ // Supports Mozilla 1.3+ (Firefox, etc) and IE 5.5+ // (c) 2005 Invision Power Services, Inc. // http://www.invisionpower.com //------------------------------------------------------------------------------ /*--------------------------------------------*/ // INIT variables /*--------------------------------------------*/ var i_am = 'rte'; //document.getElementById( 'debugmsg' ).value var DEBUG = 0; var isRichText = false; var css_off = false; var rng; var currentRTE; var allRTEs = ""; var rte = ""; // Defined in enable_design_mode var rtewindow; var rtedocument; var rteready; var isIE; var isGecko; var isSafari; var isKonqueror; var imagesPath; var includesPath; //------------------------------- // Set global scope //------------------------------- var g_buttons; var g_rte; var g_tablewidth; var g_width_unit; var g_imagesPath; var g_width; var g_height; var g_readOnly; var g_includesPath var g_html; var g_DEBUG; //------------------------------- // Font & size //------------------------------- var currentfont; var currentsize; var button_status = new Array(); //------------------------------- // Viewing HTML? //------------------------------- var viewingHTML = 0; //------------------------------- // Viewing Full screen? //------------------------------- var viewingFS = 0; //------------------------------- // Define which buttons change // when clicked //------------------------------- var buttons_update = new Array( "bold", "italic", "underline", "strikethrough", //"superscript", //"subscript", "justifyleft", "justifycenter", "justifyright", "insertorderedlist", "insertunorderedlist" ); var opentags = { 'bold' : 0, 'italic' : 0, 'strikethrough' : 0, 'underline' : 0, 'forecolor' : 0, 'fontname' : 0, 'fontsize' : 0 }; /*--------------------------------------------*/ // INIT RTE /*--------------------------------------------*/ function init_rte( imgPath, incPath ) { //------------------------------- // Set browser vars //------------------------------- var ua = navigator.userAgent.toLowerCase(); isIE = ((ua.indexOf("msie") != -1) && (ua.indexOf("opera") == -1) && (ua.indexOf("webtv") == -1)); isGecko = (ua.indexOf("gecko") != -1); isSafari = (ua.indexOf("safari") != -1); isKonqueror = (ua.indexOf("konqueror") != -1); //------------------------------- // Check to see if designMode mode // is available. Should be for: // IE5.5+ Mozilla 1.3+ // Safari 2+ //------------------------------- if ( document.getElementById && document.designMode && ! isSafari &&!isKonqueror ) { isRichText = true; } if ( isIE ) { document.onmouseover = ie_raise_button; document.onmouseout = ie_normal_button; document.onmousedown = ie_lower_button; document.onmouseup = ie_raise_button; } //------------------------------- // Set paths vars //------------------------------- imagesPath = imgPath; includesPath = incPath; //------------------------------- //for testing standard textarea, uncomment the following line //isRichText = false; //------------------------------- } /*--------------------------------------------*/ // Write Rich text to screen /*--------------------------------------------*/ function write_rte_editor(fieldname, html, width, height, buttons, readOnly) { rte = fieldname; if ( isRichText ) { if (allRTEs.length > 0) { allRTEs += ";"; } allRTEs += rte; write_rte(html, width, height, buttons, readOnly); } else { write_default(html, width, height, buttons, readOnly); } } /*--------------------------------------------*/ // Write the default info /*--------------------------------------------*/ function write_default(html, width, height, buttons, readOnly) { if ( ! readOnly ) { document.writeln(''); } else { document.writeln(''); } } /*--------------------------------------------*/ // Display RTE /*--------------------------------------------*/ function write_rte(html, width, height, buttons, readOnly) { if (readOnly) buttons = false; var o_width = width; var o_height = height; width = parseInt( width ); height = parseInt( height ); //------------------------------- // Adjust minimum table widths //------------------------------- if ( isIE ) { if ( ! o_width.match( /%/ ) ) { if ( buttons && (width < 400) ) { width = 400; } g_width_unit = 'px'; var tablewidth = width + 4; } else { g_width_unit = '%'; var tablewidth = width ; width = width; } } else { if ( ! o_width.match( /%/ ) ) { if ( buttons && (width < 400) ) { width = 400; } g_width_unit = 'px'; var tablewidth = width + 2; } else { g_width_unit = '%'; var tablewidth = width; width = width; } } //------------------------------- // Globalize //------------------------------- g_buttons = buttons; g_rte = rte; g_tablewidth = tablewidth; g_imagesPath = imagesPath; g_width = width; g_height = height; g_readOnly = readOnly; g_includesPath = includesPath; g_html = html; g_DEBUG = DEBUG; boo_to_int = isRichText == true ? 1 : 0; //------------------------------- // Use HTML from rte_html.js //------------------------------- document.writeln( "" ); write_rte_html(); document.getElementById('hdn_rte_content').value = html; enable_design_mode( make_newlines_safe(html), readOnly ); //------------------------------- // Make buttons unselectable //------------------------------- poss_images = document.getElementsByTagName('img'); if ( poss_images.length ) { for( var i in poss_images ) { if ( poss_images[i].className == 'rteimage' ) { poss_images[i].unselectable = true; } } } //----------------------------------------- // Make
into]*)>(.*)<\/p>/i, '$2');
if ( (sel.type == "Text" || sel.type == "None") )
{
ts.pasteHTML( "
" + t + "\n" );
}
else
{
rtewindow.document.body.innerHTML += "
\n";
}
rtewindow.event.returnValue = false;
ts.select();
rtewindow.focus();
return false ;
}
}
}
}
/*--------------------------------------------*/
// Enable Design Mode
/*--------------------------------------------*/
function enable_design_mode(html, readOnly)
{
//-------------------------------
// Got char set?
//-------------------------------
var use_charset = '';
try
{
use_charset = g_CHARSET;
}
catch(e)
{
}
use_charset = use_charset ? use_charset : 'iso-8859-1';
//-------------------------------
// Print...
//-------------------------------
var frameHtml = "\n";
frameHtml += "
]*)>(.*)<\/p>/i, '$2'); if ( (sel.type == "Text" || sel.type == "None") ) { ts.pasteHTML( t + "
\n" ); } else { rtewindow.document.body.innerHTML += ""; } rtewindow.focus(); rtewindow.document.execCommand( command, false, null ); rte_button_update( command ); rtewindow.focus(); } else { rtewindow.focus(); _gecko_kill_css(); rtewindow.document.execCommand(command, false, null); rte_button_update( command ); rtewindow.focus(); } } catch (e) { alert(e); } } /*--------------------------------------------*/ // Show smilies pop-up /*--------------------------------------------*/ function show_smilies() { //------------------------------- // Position and show color palette //------------------------------- buttonElement = document.getElementById('popsmilies'); var iLeftPos = getOffsetLeft(buttonElement); var iTopPos = getOffsetTop(buttonElement) + (buttonElement.offsetHeight + 30); document.getElementById('smiliestable').style.left = (iLeftPos) + "px"; document.getElementById('smiliestable').style.top = (iTopPos) + "px"; if (document.getElementById('smiliestable').style.visibility == "hidden") { document.getElementById('smiliestable').style.visibility = "visible"; document.getElementById('smiliestable').style.display = "inline"; } else { document.getElementById('smiliestable').style.visibility = "hidden"; document.getElementById('smiliestable').style.display = "none"; } } /*--------------------------------------------*/ // Function to set color /*--------------------------------------------*/ function setColor(color) { var parentCommand = parent.command; if ( isIE ) { //------------------------------- //retrieve selected range //------------------------------- var sel = rtewindow.document.selection; if (parentCommand == "hilitecolor") parentCommand = "backcolor"; if (sel != null) { var newRng = sel.createRange(); newRng = rng; newRng.select(); } } rtewindow.focus(); _gecko_kill_css(); rtewindow.document.execCommand(parentCommand, false, color); rtewindow.focus(); document.getElementById('cp').style.visibility = "hidden"; document.getElementById('cp').style.display = "none"; } /*--------------------------------------------*/ // Function to add email address /*--------------------------------------------*/ function add_email() { if ( isIE ) { //------------------------------- // Get current selected range //------------------------------- var selection = rtewindow.document.selection; if (selection != null) { rng = selection.createRange(); } var rng_len = rng.text.length; } else { //------------------------------- // Get currently selected range //------------------------------- var selection = rtewindow.getSelection(); rng = selection.getRangeAt(selection.rangeCount - 1).cloneRange(); } emailaddress = prompt( text_enter_email, ''); if ((emailaddress != null) && (emailaddress != "")) { if( isIE ) { if( rng_len != "undefined" && rng_len > 0 ) { rtewindow.focus(); _gecko_kill_css(); rtewindow.document.execCommand('createlink', false, 'mailto:' + emailaddress); rtewindow.focus(); } else { emailHTML = '' + emailaddress + ''; wrap_tags( "" + emailHTML, ""); rtewindow.focus(); } } else if( (rng != null) && (rng != "") ) { rtewindow.focus(); _gecko_kill_css(); rtewindow.document.execCommand('createlink', false, 'mailto:' + emailaddress); rtewindow.focus(); } else { emailHTML = '' + emailaddress + ''; wrap_tags( "" + emailHTML, ""); rtewindow.focus(); } } } /*--------------------------------------------*/ // Function to add image /*--------------------------------------------*/ function add_image() { if ( isIE ) { //------------------------------- // Get current selected range //------------------------------- var selection = rtewindow.document.selection; if (selection != null) { rng = selection.createRange(); } } else { //------------------------------- // Get currently selected range //------------------------------- var selection = rtewindow.getSelection(); rng = selection.getRangeAt(selection.rangeCount - 1).cloneRange(); } imagePath = prompt( text_enter_image, 'http://'); var pass_image = 0; if(imagePath.substring(0,7) == 'http://') { pass_image = 1; } if(imagePath.substring(0,8) == 'https://') { pass_image = 1; } if(imagePath.substring(0,6) == 'ftp://') { pass_image = 1; } if( pass_image == 0 ) { imagePath = null; } if ((imagePath != null) && (imagePath != "")) { rtewindow.focus(); _gecko_kill_css(); rtewindow.document.execCommand('InsertImage', false, imagePath); rtewindow.focus(); } } /*--------------------------------------------*/ //Function to perform spell check /*--------------------------------------------*/ function checkspell() { try { var tmpis = new ActiveXObject("ieSpell.ieSpellExtension"); tmpis.CheckAllLinkedDocuments(document); } catch(exception) { if(exception.number==-2146827859) { if (confirm( jsfile_erroriespell )) window.open("http://www.iespell.com/download.php","DownLoad"); } else { alert( jsfile_errorliespell + exception.number); } } } /*--------------------------------------------*/ // Add emoticon /*--------------------------------------------*/ function emoticon( scode, smid, surl ) { rtewindow.focus(); try { if ( ! surl ) { surl = document.getElementById(smid).src; } if ( ! isIE ) { rtewindow.focus(); _gecko_kill_css(); rtewindow.document.execCommand('InsertImage', false, surl); rtewindow.focus(); var images = rtewindow.document.getElementsByTagName('img'); //---------------------------------- // Sort through and fix emo //---------------------------------- for ( var i = 0 ; i <= images.length ; i++ ) { if ( images[i].src == surl ) { if ( ! images[i].getAttribute('emoid') ) { images[i].setAttribute( 'emoid', scode ); images[i].setAttribute( 'border', '0' ); images[i].style.verticalAlign = 'middle'; } } } } else { smilieHTML = ']*)>(.*)<\/p>/i, '$2');
if ( (sel.type == "Text" || sel.type == "None") )
{
has_closed = true;
ts.pasteHTML( opentag + t + closetag );
}
else
{
has_closed = true;
rtewindow.document.body.innerHTML += opentag + closetag;
}
}
else
{
//-------------------------------
// FRAGment, not a game of UT
//-------------------------------
var frag = rtewindow.document.createDocumentFragment();
var span = rtewindow.document.createElement("span");
//-------------------------------
// Apply tags...
//-------------------------------
sel_html = _gecko_get_html();
//-------------------------------
// Remove empty span tags
//-------------------------------
var my_contents;
var my_length;
if ( sel_html )
{
has_closed = true;
span.innerHTML = opentag + sel_html + closetag;
my_contents = opentag + sel_html + closetag;
}
else
{
span.innerHTML = opentag + closetag;
my_contents = opentag + closetag;
}
while ( span.firstChild )
{
frag.appendChild(span.firstChild);
}
my_length = my_contents.length ? my_contents.length : 0;
_gecko_insert_node_at_selection( frag, my_length );
}
//-------------------------------
// Add tag to stack
//-------------------------------
rtewindow.focus();
return has_closed;
}
/*--------------------------------------------*/
// Do fontsize, etc
/*--------------------------------------------*/
function do_select(selectname)
{
if ( isIE )
{
//-------------------------------
// Get current selected range
//-------------------------------
var selection = rtewindow.document.selection;
if (selection != null)
{
rng = selection.createRange();
}
}
else
{
//-------------------------------
// Get currently selected range
//-------------------------------
var selection = rtewindow.getSelection();
rng = selection.getRangeAt(selection.rangeCount - 1).cloneRange();
}
var idx = document.getElementById(selectname).selectedIndex;
var selected = document.getElementById(selectname).options[idx].value;
rtewindow.focus();
_gecko_kill_css();
rtewindow.document.execCommand(selectname, false, selected);
rte_button_update( selectname );
rtewindow.focus();
}
/*--------------------------------------------*/
// Launch fullscreen...
/*--------------------------------------------*/
function launch_rte_fs()
{
if ( viewingFS )
{
//return false;
}
//-------------------------------
// If viewing source, switch back
// to design view
//-------------------------------
if ( viewingHTML )
{
toggleHTMLSrc();
}
viewingFS = 1;
window.open( ipb_var_base_url + '&act=rtefs', 'RTEFS', 'width=640,height=480,resizable=yes,scrollbars=yes,location=no,directories=no,status=no,menubar=no,toolbar=no');
}
/*--------------------------------------------*/
// Launch div...
/*--------------------------------------------*/
function launch_div()
{
// Could do with sorting this mess out.
window.open( includesPath + 'insert_div.html', 'DIV', 'width=550,height=340,resizable=yes,scrollbars=yes,location=no,directories=no,status=no,menubar=no,toolbar=no');
}
/*--------------------------------------------*/
// Manage tables...
/*--------------------------------------------*/
function write_div( param, pwindow )
{
try
{
if ( pwindow )
{
pwindow.close();
}
}
catch (e)
{
}
if ( ! param )
{
return false;
}
//-------------------------------
// Build remap array
//-------------------------------
var remap_elements = {
"f_fontfamily" : "font-family" ,
"f_fontsize" : "font-size" ,
"f_color" : "color" ,
"f_backgroundimage" : "background-image" ,
"f_backgroundrepeat" : "background-repeat",
"f_backgroundcolor" : "background-color" ,
"f_border" : "border" ,
"f_padding" : "padding" ,
"f_margin" : "margin"
};
//-------------------------------
// Get tag type
//-------------------------------
var tagtype = param["f_type"];
var style = "";
if ( ! param["f_classes"] || param["f_classes"] == "__none" )
{
//-------------------------------
// Start building style
//-------------------------------
style += "style='";
for (var field in param)
{
var value = param[field];
if ( ! value || value == 'undefined' || field == 'undefined' || ! remap_elements[ field ] )
{
continue;
}
if ( remap_elements[ field ] && value )
{
style += remap_elements[ field ] + ":" + value + ";";
}
}
//-------------------------------
// Finish style
//-------------------------------
style += param["f_other"]+"'";
}
else
{
style += "class='" + param["f_classes"] + "'";
}
//-------------------------------
// Pass to handler
//-------------------------------
if ( style )
{
wrap_tags( "<"+tagtype+" " + style + ">", ""+tagtype+">" );
}
else
{
wrap_tags( "<"+tagtype+">", ""+tagtype+">" )
}
return true;
}
/*--------------------------------------------*/
// Launch tables...
/*--------------------------------------------*/
function launch_table()
{
// Could do with sorting this mess out.
window.open( includesPath + 'insert_table.html', 'TABLE', 'width=450,height=220,resizable=yes,scrollbars=yes,location=no,directories=no,status=no,menubar=no,toolbar=no');
}
/*--------------------------------------------*/
// Manage tables...
/*--------------------------------------------*/
function write_tables( param, pwindow )
{
try
{
if ( pwindow )
{
pwindow.close();
}
}
catch (e)
{
}
var sel = _my_getselection();
var range = _my_createrange(sel);
if ( ! param )
{
return false;
}
var doc = rtewindow.document;
//-------------------------------
// create the table element
//-------------------------------
var table = doc.createElement("table");
//-------------------------------
// assign the given arguments
//-------------------------------
for (var field in param)
{
var value = param[field];
if ( ! value )
{
continue;
}
switch (field)
{
case "f_width" : table.style.width = value + param["f_unit"]; break;
case "f_align" : table.align = value; break;
case "f_border" : table.border = parseInt(value); break;
case "f_spacing" : table.cellspacing = parseInt(value); break;
case "f_padding" : table.cellpadding = parseInt(value); break;
}
}
var tbody = doc.createElement("tbody");
table.appendChild(tbody);
for (var i = 0; i < param["f_rows"]; ++i)
{
var tr = doc.createElement("tr");
tbody.appendChild(tr);
for (var j = 0; j < param["f_cols"]; ++j)
{
var td = doc.createElement("td");
tr.appendChild(td);
//-------------------------------
// Mozilla likes to see something
// inside the cell.
//-------------------------------
if ( ! isIE )
{
td.appendChild(doc.createElement("br"));
}
}
}
if ( isIE )
{
range.pasteHTML(table.outerHTML);
}
else
{
//-------------------------------
// insert the table
//-------------------------------
_gecko_insert_node_at_selection(table);
}
return true;
}
/*--------------------------------------------*/
// KeyBoard Handler
/*--------------------------------------------*/
function kb_handler(evt)
{
var rte = evt.target.id;
if (evt.ctrlKey)
{
var key = String.fromCharCode(evt.charCode).toLowerCase();
var cmd = '';
switch (key)
{
case 'b': cmd = "bold"; break;
case 'i': cmd = "italic"; break;
case 'u': cmd = "underline"; break;
};
if (cmd)
{
format_text(cmd, true);
//-------------------------------
// evt.target.ownerDocument.execCommand(cmd, false, true);
// stop the event bubble
//-------------------------------
evt.preventDefault();
evt.stopPropagation();
}
}
}
function docChanged (evt)
{
alert('changed');
}
/*--------------------------------------------*/
// Get selection (MY)
/*--------------------------------------------*/
function _my_getselection()
{
if ( isIE )
{
return rtewindow.document.selection;
}
else
{
return rtewindow.getSelection();
}
}
/*--------------------------------------------*/
// Create Range (my)
/*--------------------------------------------*/
function _my_createrange( sel )
{
if ( isIE )
{
return sel.createRange();
}
else
{
rtewindow.focus();
return sel ? sel.getRangeAt(0) : rtewindow.document.createRange();
}
}
/*--------------------------------------------*/
// Gecko work around to get selection HTML
/*--------------------------------------------*/
function _gecko_get_html()
{
var sel = _my_getselection();
var range = _my_createrange(sel);
var root = range.cloneContents();
return _gecko_read_nodes(root, false);
}
/*--------------------------------------------*/
// Gecko read nodes (based on midas)
/*--------------------------------------------*/
function _gecko_read_nodes(root, toptag)
{
var html = "";
var moz_check = /_moz/i;
switch (root.nodeType)
{
case Node.ELEMENT_NODE:
case Node.DOCUMENT_FRAGMENT_NODE:
{
var closed;
if (toptag)
{
closed = !root.hasChildNodes();
html = '<' + root.tagName.toLowerCase();
var attr = root.attributes;
for (i = 0; i < attr.length; ++i)
{
var a = attr.item(i);
if (!a.specified || a.name.match(moz_check) || a.value.match(moz_check))
{
continue;
}
html += " " + a.name.toLowerCase() + '="' + a.value + '"';
}
html += closed ? " />" : ">";
}
for (var i = root.firstChild; i; i = i.nextSibling)
{
html += _gecko_read_nodes(i, true);
}
if (toptag && !closed)
{
html += "" + root.tagName.toLowerCase() + ">";
}
}
break;
case Node.TEXT_NODE:
{
html = htmlspecialchars(root.data);
}
break;
}
return html;
}
/*--------------------------------------------*/
// Gecko insert html mode at selection (midas)
/*--------------------------------------------*/
function _gecko_insert_node_at_selection(text, text_length)
{
var sel = _my_getselection();
var range = _my_createrange(sel);
var node = range.startContainer;
var pos = range.startOffset;
text_length = text_length ? text_length : 0;
sel.removeAllRanges();
range.deleteContents();
//===============================
// Suggested fix by Dean - thx!
// Have to switch node to body
// if it's currently at html tag
//===============================
if (node.nodeName == 'HTML')
{
node = _goto_parent_then_body(node);
}
switch (node.nodeType)
{
case 1://Node.ELEMENT_NODE:
{
if (text.nodeType == 11)//Node.DOCUMENT_FRAGMENT_NODE)
{
selNode = text.firstChild;
}
else
{
selNode = text;
}
node.insertBefore(text, node.childNodes[pos]);
_gecko_add_range(selNode, text_length);
}
break;
case 3://Node.TEXT_NODE:
{
if ( text.nodeType == 3)//Node.TEXT_NODE )
{
var text_length = pos + text.length;
node.insertData(pos, text.data);
range = rtewindow.document.createRange();
range.setEnd( node, text_length);
range.setStart(node, text_length);
sel.addRange(range);
}
else
{
node = node.splitText(pos);
var selNode;
if (text.nodeType == 11)//Node.DOCUMENT_FRAGMENT_NODE)
{
selNode = text.firstChild;
}
else
{
selNode = text;
}
node.parentNode.insertBefore(text, node);
_gecko_add_range(selNode, text_length);
}
}
break;
}
}
function _goto_parent_then_body(n)
{
var o = n;
while (n.parentNode != null && n.parentNode.nodeName == 'HTML')
{
n = n.parentNode;
}
if (n)
{
for (var c=0; c