function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Eric SantiagoEric Santiago 

WYSIWYG Editors for textarea fields

I've been experimenting with adding TinyMCE (http://tinymce.moxiecode.com/) to Sforce controls to add HTML formatting features to textareas in Salesforce.

Originally, I planned to add a pop-up window to the edit screen for my custom object and have the formatted text sent back to the parent window. Unfortunately, unless I'm mistaken, you can't add scontrols to the edit screen.

It seems then that the only option is to override the edit button. Ideally I'd like to run the TinyMCE javascript (see below) as the edit screen loads. Is there a way to do this?

Code:
<script type="text/javascript" src="http://wiki.moxiecode.com/examples/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>
<script language="javascript" type="text/javascript">
tinyMCE.init({
mode : "textareas",
theme : "advanced",
plugins : "table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,zoom,flash,searchreplace,print,contextmenu",
theme_advanced_buttons1_add_before : "save,separator",
theme_advanced_buttons1_add : "fontselect,fontsizeselect",
theme_advanced_buttons2_add : "separator,insertdate,inserttime,preview,zoom,separator,forecolor,backcolor",
theme_advanced_buttons2_add_before: "cut,copy,paste,separator,search,replace,separator",
theme_advanced_buttons3_add_before : "tablecontrols,separator",
theme_advanced_buttons3_add : "emotions,iespell,flash,advhr,separator,print",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_path_location : "bottom",
plugin_insertdate_dateFormat : "%Y-%m-%d",
plugin_insertdate_timeFormat : "%H:%M:%S",
extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
external_link_list_url : "example_data/example_link_list.js",
external_image_list_url : "example_data/example_image_list.js",
flash_external_list_url : "example_data/example_flash_list.js"
});
</script>

 If that's also not an option, I was thinking about using a Scontrol that ran the tinyMCE code and then took advantage of the DescribeLayoutResult call to build the normal edit page layout. Using a dynamic rather than static page layout seemed the best way to reuse the WYSIWYG editor for any number of custom objects. Unfortunately, I haven't seen anu ajax samples using this call and developing it from scratch is far beyond my own expertise. Perhaps some ingenious soul is willing to take on the challenge?

 


Eric SantiagoEric Santiago
I did hack together a scontrol that works as far as the html formatting is concerned. It dosen't save and is limited to a custom object that is part of my non-profit's implementation, but it should give some sense of the desired end result.

Code:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head><title>Scorecard Task Edit: New Scorecard Task ~ Salesforce - Enterprise Edition</title><link  href="/sCSS/8.0/1171411121000/Theme2/default/elements.css" media="handheld,print,projection,screen,tty,tv" rel="stylesheet" type="text/css" /><link  href="/sCSS/8.0/1171411121000/Theme2/default/common.css" media="handheld,print,projection,screen,tty,tv" rel="stylesheet" type="text/css" /><link  href="/css/assistive.css" media="aural,braille,embossed" rel="stylesheet" type="text/css" /><link  href="/sCSS/8.0/1172004110000/Theme2/00D300000000dDf/00530000000f5K2/dCustom.css" media="handheld,print,projection,screen,tty,tv" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="http://wiki.moxiecode.com/examples/tinymce/jscripts/tiny_mce/tiny_mce.js"></script>
<script language="javascript" type="text/javascript">
tinyMCE.init({
 mode : "textareas",
 theme : "advanced",
 plugins : "table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,zoom,flash,searchreplace,print,contextmenu",
 theme_advanced_buttons1_add_before : "save,separator",
 theme_advanced_buttons1_add : "fontselect,fontsizeselect",
 theme_advanced_buttons2_add : "separator,insertdate,inserttime,preview,zoom,separator,forecolor,backcolor",
 theme_advanced_buttons2_add_before: "cut,copy,paste,separator,search,replace,separator",
 theme_advanced_buttons3_add_before : "tablecontrols,separator",
 theme_advanced_buttons3_add : "emotions,iespell,flash,advhr,separator,print",
 theme_advanced_toolbar_location : "top",
 theme_advanced_toolbar_align : "left",
 theme_advanced_path_location : "bottom",
 plugin_insertdate_dateFormat : "%Y-%m-%d",
 plugin_insertdate_timeFormat : "%H:%M:%S",
 extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
 external_link_list_url : "example_data/example_link_list.js",
 external_image_list_url : "example_data/example_image_list.js",
 flash_external_list_url : "example_data/example_flash_list.js"
});
</script>
<script type="text/javascript" src="/js/functions.js"></script>
<script  src="/dJS/en/1170289429000/library.js" type="text/javascript"></script><script type="text/javascript" src="/js/setup.js"></script>
<script type="text/javascript" src="/js/roletreenode.js"></script>
<script type="text/javascript" src="/desktop/desktopAjax.js"></script>
<script  type="text/javascript">window.sfdcPage = new EditPage();</script><link rel="shortcut icon" href="https://na1.salesforce.com/favicon.ico" />
</head><body onLoad="if (this.bodyOnLoad) bodyOnLoad();" onBeforeUnload="if (this.bodyOnBeforeUnload) bodyOnBeforeUnload();" onUnload="if (this.bodyOnUnload) bodyOnUnload();" onResize="if (this.bodyOnUnload) bodyOnUnload();" onFocus="if (this.bodyOnFocus) bodyOnFocus();" class="custom customTab35  editPage"><iframe title="blank - ignore" name="div_submit" id="div_submit" src="/s.gif" style="display:none;visibility:hidden;width:0px;height:0px" frameborder="0"></iframe>
<!-- Main Body Starts Here -->
  <!-- <table class="outer" width="100%" id="bodyTable" border="0" cellspacing="0" cellpadding="0"> -->
<table width="100%" id="bodyTable" border="0" cellspacing="0" cellpadding="0">
<!-- Start page content table -->
<tr><td class="oRight" id="bodyCell">
<!-- Start page content -->
<a name="skiplink"><img src="/s.gif" height='1' width='1' alt="Content Starts Here" class="skiplink" title="Content Starts Here"></a><div class="bPageTitle"><div class="ptBody secondaryPalette"><div class="content"><img src="/s.gif" alt="Scorecard Task"  class="pageTitleIcon" title="Scorecard Task"><h1 class="pageType">Scorecard Task Edit<span  class="titleSeparatingColon">:</span></h1><h2 class="pageDescription"> New Scorecard Task</h2><div class="blank">&nbsp;</div></div><div class="links"><a href="javascript&colon;openPopupFocusEscapePounds('/help/doc/user_ed.jsp—loc=help&target=co_edit.htm&section=CustomObjects', 'Help', 700, 600, 'width=700,height=600,resizable=yes,toolbar=yes,status=no,scrollbars=yes,menubar=yes,directories=no,location=no,dependant=no', false, false);" title="Help for this Page (New Window)"><span  class="helpLink">Help for this Page</span><img src="/s.gif" alt=""  class="helpImage" title=""></a></div></div><div class="ptBreadcrumb"></div></div><script type="text/javascript">
</script>
<script  src="/js/picklist.js" type="text/javascript"></script><script  src="/servlet/servlet.picklist–h=v8dt%2FM%2FqeljSZznkR%2BGou%2FgVozUMdUIEJHxLCUIJ5Pg%3D&v=1141632834000&layout=00h300000011UVZ&l=0&pr=1.23&t=0" type="text/javascript"></script><form  action="/a0D/e" id="editPage" method="post" name="editPage" onsubmit="if (window.ffInAlert) { return false; }" ><input type="hidden" name="cancelURL" id="cancelURL" value="/a0D/o" /><input type="hidden" name="retURL" id="retURL" value="/a0D/o" /><input type="hidden" name="save_new_url" id="save_new_url" value="/a0D/e˜retURL=%2Fa0D%2Fo" /><div class="bPageBlock bEditBlock secondaryPalette" id="ep"><div class="pbHeader"><table  border="0" cellpadding="0" cellspacing="0"><tr><td class="pbTitle"><img src="/s.gif" alt="" width="1" height="1" class="minWidth" title="" /><h2 class="mainTitle">Scorecard Task Edit</h2></td><td class="pbButton"><input value=" Save "  class="btn" type="submit" title="Save" name="save" /> <input value="Save & New"  class="btn" type="submit" title="Save &amp; New" name="save_new" /> <input value="Cancel"  class="btn" type="submit" title="Cancel" name="cancel" /></td></tr>
</table></div><div class="pbBody"><div class="pbSubheader first tertiaryPalette" id="head_1_ep"><span class="pbSubExtra"><span class="requiredLegend"><span class="requiredExampleOuter"><span class="requiredExample">&nbsp;</span></span><span  class="requiredText"> = Required Information</span></span></span><h3>Information<span  class="titleSeparatingColon">:</span></h3></div><div class="pbSubsection"><table  class="detailList" border="0" cellpadding="0" cellspacing="0"><tr><td class="labelCol requiredInput"><label for="Name"><span class="requiredMark">*</span>Task Label</label></td><td class="dataCol col02"><div class="requiredInput"><div class="requiredBlock"></div><input  id="Name" maxlength="80" name="Name" size="20" tabindex="1" type="text" /></div></td><td class="labelCol">Owner</td><td class="dataCol">Eric Santiago</td></tr>

<tr><td class="labelCol"><label for="00N3000000160GA">Active™</label></td><td class="dataCol col02"><input  id="00N3000000160GA" name="00N3000000160GA" tabindex="2" type="checkbox" value="1" /></td><td class="labelCol"><label for="00N3000000160GK">Rank</label></td><td class="dataCol"><input  id="00N3000000160GK" name="00N3000000160GK" size="20" tabindex="5" type="text" /></td></tr>
<tr><td class="labelCol"><label for="00N3000000160Fg">Category</label></td><td class="dataCol col02"><span><select  id="00N3000000160Fg" name="00N3000000160Fg" tabindex="3">
<option value="" selected>--None--</option>
</select></span><script>new picklist('00N3000000160Fg','00N3000000160Fg',null,['',''],' id="00N3000000160Fg" name="00N3000000160Fg" tabindex="3"',true,true);</script>
</td><td class="labelCol"><label for="00N3000000160Fq">Subcategory</label></td><td class="dataCol"><span><select  id="00N3000000160Fq" name="00N3000000160Fq" tabindex="6">
<option value="" selected>--None--</option>
</select></span><script>new picklist('00N3000000160Fq','00N3000000160Fq',null,['',''],' id="00N3000000160Fq" name="00N3000000160Fq" tabindex="6"',true,true);</script>
</td></tr>
<tr><td class="labelCol requiredInput last"><label for="00N3000000160FD"><span class="requiredMark">*</span>Type</label></td><td class="dataCol col02 last"><div class="requiredInput"><div class="requiredBlock"></div><span><select  id="00N3000000160FD" name="00N3000000160FD" tabindex="4">

<option value="" selected>--None--</option>
</select></span><script>new picklist('00N3000000160FD','00N3000000160FD',null,['',''],' id="00N3000000160FD" name="00N3000000160FD" tabindex="4"',false,true);</script>
</div></td><td class="labelCol last"><label for="00N3000000162II">Archive?</label></td><td class="dataCol last"><input  id="00N3000000162II" name="00N3000000162II" tabindex="7" type="checkbox" value="1" /></td></tr>
</table></div><div class="pbSubheader tertiaryPalette" id="head_2_ep"><h3>Program & Year<span  class="titleSeparatingColon">:</span></h3></div><div class="pbSubsection"><table  class="detailList" border="0" cellpadding="0" cellspacing="0"><tr><td class="labelCol"><label for="00N300000016Car"><font color=red>Note 2:</label></td><td class="data2Col" colspan="3"><span><select  id="00N300000016Car" name="00N300000016Car" tabindex="8">
<option value="Academic Year is valid only for 4XL Program." selected>Academic Year is valid only for 4XL Program.</option>
</select></span><script>new picklist('00N300000016Car','00N300000016Car',null,['Academic Year is valid only for 4XL Program.','Academic Year is valid only for 4XL Program.'],' id="00N300000016Car" name="00N300000016Car" tabindex="8"',true,true);</script>
</td></tr>
<tr><td class="labelCol requiredInput"><label for="CF00N300000016Cdp"><span class="requiredMark">*</span>MLT Program</label></td><td class="data2Col" colspan="3"><div class="requiredInput"><div class="requiredBlock"></div><input type="hidden" name="CF00N300000016Cdp_lkid" id="CF00N300000016Cdp_lkid" value="000000000000000" /><input type="hidden" name="CF00N300000016Cdp_lkold" id="CF00N300000016Cdp_lkold" value="null" /><input type="hidden" name="CF00N300000016Cdp_lktp" id="CF00N300000016Cdp_lktp" value="a0C" /><input type="hidden" name="CF00N300000016Cdp_lspf" id="CF00N300000016Cdp_lspf" value="0" /><input type="hidden" name="CF00N300000016Cdp_mod" id="CF00N300000016Cdp_mod" value="0" /><span class="lookupInput"><input  id="CF00N300000016Cdp" maxlength="80" name="CF00N300000016Cdp" onchange="document.getElementById('CF00N300000016Cdp_lkid').value='';document.getElementById('CF00N300000016Cdp_mod').value='1';" size="75" tabindex="9" type="text" /><a href="JavaScript&colon; openLookup('/_ui/common/data/LookupPage?lkfm=editPage&lknm=CF00N300000016Cdp&lktp=' + document.getElementById('CF00N300000016Cdp_lktp').value,670,document.getElementById('CF00N300000016Cdp_mod').value,'&lksrch=' + escapeUTF(document.getElementById('CF00N300000016Cdp').value),'maxw')" id="CF00N300000016Cdp_lkwgt" onclick="setLastMousePosition(event)" tabindex="9" title="MLT Program Lookup (New Window)"><img src="/s.gif" alt="MLT Program Lookup (New Window)"  class="lookupPopup" title="MLT Program Lookup (New Window)"></a></span></div></td></tr>

<tr><td class="labelCol"><label for="CF00N3000000160HS">Academic Year</label></td><td class="data2Col" colspan="3"><input type="hidden" name="CF00N3000000160HS_lkid" id="CF00N3000000160HS_lkid" value="000000000000000" /><input type="hidden" name="CF00N3000000160HS_lkold" id="CF00N3000000160HS_lkold" value="null" /><input type="hidden" name="CF00N3000000160HS_lktp" id="CF00N3000000160HS_lktp" value="a0G" /><input type="hidden" name="CF00N3000000160HS_lspf" id="CF00N3000000160HS_lspf" value="0" /><input type="hidden" name="CF00N3000000160HS_mod" id="CF00N3000000160HS_mod" value="0" /><span class="lookupInput"><input  id="CF00N3000000160HS" maxlength="80" name="CF00N3000000160HS" onchange="document.getElementById('CF00N3000000160HS_lkid').value='';document.getElementById('CF00N3000000160HS_mod').value='1';" size="75" tabindex="10" type="text" /><a href="JavaScript&colon; openLookup('/_ui/common/data/LookupPage?lkfm=editPage&lknm=CF00N3000000160HS&lktp=' + document.getElementById('CF00N3000000160HS_lktp').value,670,document.getElementById('CF00N3000000160HS_mod').value,'&lksrch=' + escapeUTF(document.getElementById('CF00N3000000160HS').value),'maxw')" id="CF00N3000000160HS_lkwgt" onclick="setLastMousePosition(event)" tabindex="10" title="Academic Year Lookup (New Window)"><img src="/s.gif" alt="Academic Year Lookup (New Window)"  class="lookupPopup" title="Academic Year Lookup (New Window)"></a></span></td></tr>
<tr><td class="labelCol requiredInput last"><label for="00N3000000160FR"><span class="requiredMark">*</span>Task</label><div class="textCounterOuter"><div class=""><div class="textCounter" id="00N3000000160FR_counter">32000 remaining</div></div></div></td><td class="data2Col last" colspan="3"><div class="requiredInput"><div class="requiredBlock"></div><textarea  cols="75" id="00N3000000160FR" maxlength="32000" name="00N3000000160FR" onchange="handleTextAreaElementChange('00N3000000160FR', 32000, 'remaining', 'over limit');" onclick="handleTextAreaElementChange('00N3000000160FR', 32000, 'remaining', 'over limit');" onkeydown="handleTextAreaElementChange('00N3000000160FR', 32000, 'remaining', 'over limit');" onkeyup="handleTextAreaElementChange('00N3000000160FR', 32000, 'remaining', 'over limit');" onmousedown="handleTextAreaElementChange('00N3000000160FR', 32000, 'remaining', 'over limit');" rows="10" tabindex="11" type="text" wrap="soft"></textarea></div></td></tr>
</table></div><div class="pbSubheader tertiaryPalette" id="head_3_ep"><h3>Answer<span  class="titleSeparatingColon">:</span></h3></div><div class="pbSubsection"><table  class="detailList" border="0" cellpadding="0" cellspacing="0"><tr><td class="labelCol"><label for="00N3000000160H8"><font color=red>Note 1:</label></td><td class="data2Col" colspan="3"><span><select  id="00N3000000160H8" name="00N3000000160H8" tabindex="12">
<option value="In the field below - Answers must be separated with either comma,semi-colon,colon" selected>In the field below - Answers must be separated with either comma,semi-colon,colon</option>
</select></span><script>new picklist('00N3000000160H8','00N3000000160H8',null,['In the field below - Answers must be separated with either comma,semi-colon,colon','In the field below - Answers must be separated with either comma,semi-colon,colon'],' id="00N3000000160H8" name="00N3000000160H8" tabindex="12"',true,true);</script>
</td></tr>
<tr><td class="labelCol last"><label for="00N3000000160Gy">Answers <font color=red>, : ; separated</label><div class="textCounterOuter"><div class="textCounterMiddle"><div class="textCounter" id="00N3000000160Gy_counter">32000 remaining</div></div></div></td><td class="data2Col last" colspan="3"><textarea  cols="75" id="00N3000000160Gy" maxlength="32000" name="00N3000000160Gy" onchange="handleTextAreaElementChange('00N3000000160Gy', 32000, 'remaining', 'over limit');" onclick="handleTextAreaElementChange('00N3000000160Gy', 32000, 'remaining', 'over limit');" onkeydown="handleTextAreaElementChange('00N3000000160Gy', 32000, 'remaining', 'over limit');" onkeyup="handleTextAreaElementChange('00N3000000160Gy', 32000, 'remaining', 'over limit');" onmousedown="handleTextAreaElementChange('00N3000000160Gy', 32000, 'remaining', 'over limit');" rows="6" tabindex="13" type="text" wrap="soft"></textarea></td></tr>

</table></div></div><div class="pbBottomButtons"><table  border="0" cellpadding="0" cellspacing="0"><tr><td class="pbTitle"><img src="/s.gif" alt="" width="1" height="1" class="minWidth" title="" />&nbsp;</td><td class="pbButtonb"><input value=" Save "  class="btn" name="save" tabindex="14" title="Save" type="submit" /> <input value="Save & New"  class="btn" name="save_new" tabindex="15" title="Save &amp; New" type="submit" /> <input value="Cancel"  class="btn" name="cancel" tabindex="16" title="Cancel" type="submit" /></td></tr>
</table></div><div class="pbFooter secondaryPalette"><div class="bg"></div></div></div></form><script  type="text/javascript">picklist.initAll()</script>


<!-- End page content -->
</td>
</tr>
</table>
</body></html>