However, there is one WYSIWYG editor that trumps them both and all the others I've seen, it's called TinyMCE.
So it's no wonder that many a developer would like to use it and/or integrate it into their javascript library of choice, including myself.
If you visit the TinyMCE wiki, you'll probably learn to initialize TinyMCE like this
tinyMCE.init({
theme : "advanced",
mode : "textarea",
language : "en",
theme_advanced_layout_manager : "SimpleLayout",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough"
});
This works great if :
- you want the editor to appear immediately after the page has loaded
- all the editors on your page share the same configuration
Store the configuration objects in an array.
var configArray = [{
theme : "advanced",
mode : "none",
language : "en",
height:"200",
width:"100%",
theme_advanced_layout_manager : "SimpleLayout",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2 : "",
theme_advanced_buttons3 : ""
},{
theme : "advanced",
mode : "none",
language : "en",
width:"100%",
theme_advanced_layout_manager : "SimpleLayout",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left"
}]
In a DOM event, like click or expand that reveals one of my TinyMCE instances (textarea1), I do ..
tinyMCE.settings = configArray[0];
tinyMCE.execCommand('mceAddControl', true, "textarea1");
When I want to reveal my second TinyMCE instance (textarea2), I do ..
tinyMCE.settings = configArray[1];
tinyMCE.execCommand('mceAddControl', true, "textarea2");
To clear the contents of the TinyMCE editor on textarea1, I do ...
tinyMCE.editors.textarea1.setContent(" ");
Here is an html page with the above in action. Remember to change the src of the tinymce javascript.
<html>
<head>
<title>TinyMCE </title>
<script type="text/javascript" src="tiny_mce/tiny_mce.js"></script>
<script>
var tinymceConfigs = [ {theme : "advanced",
mode : "none",
language : "en",
height:"200",
width:"100%",
theme_advanced_layout_manager : "SimpleLayout",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2 : "",
theme_advanced_buttons3 : "" },{ theme : "advanced",
mode : "none",
language : "en",
height:"200",
width:"100%",
theme_advanced_layout_manager : "SimpleLayout",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left"}];
function tinyfy(settingid,el_id) {
tinyMCE.settings = tinymceConfigs[settingid];
tinyMCE.execCommand('mceAddControl', true, el_id);
}
</script>
</head>
<body>
<h2>Editor 1</h2>
<a href="javascript:void(0)" onclick="tinyfy(0,'ed1')">show editor 1</a>
<br><textarea id="ed1"></textarea>
<h2>Editor 2</h2>
<a href="javascript:void(0)" onclick="tinyfy(1,'ed2')">show editor 2</a>
<br><textarea id="ed2"></textarea>
</body>
</html>
Thanks, after couple frustrating hours i found your solution. Thanks.
ReplyDeleteGlad to help !
ReplyDeleteThanks for your post! I had a quick question. Did you have to have anything be loaded when you start the page up? We're trying to do something similar, and we get an error such as 's.invalid_elements has no properties'. Where do you do the tinyMCE.init()? Thanks!
ReplyDeleteNope I didn't have anything loaded when the page starts and I didn't use tinyMCE.init()
ReplyDeleteIf you want to create the two instances on page load, I suggest executing execCommand with body onload.
You can create a function ....
function init() {
tinyMCE.settings = configArray[0];
tinyMCE.execCommand('mceAddControl', true, "textarea1");
tinyMCE.settings = configArray[1];
tinyMCE.execCommand('mceAddControl', true, "textarea2");
}
In the body tag call the function onload
body onload="init()"
Please see if that works for you.
Thanks for dropping by my blog.
This looks promising, but I'm having problems implementing it. Initially I had the 's.invalid_elements has no properties' error, but I added 'invalid_elements : ""' to the parameters list and that error was replaced with 'fn has no properties'. Do you have an example page that you can provide a link to?
ReplyDeleteThanks,
archerid
I created a one page demo on my box
ReplyDeletehttp://8tons.dyndns.biz/demos/tinymce/index.html
Please see if you can access it. If not , please take a look again at the blog post. I have added the html for that sample page there.
Hope this helps.
Thanks for posting the example. I was hoping that this method was compatible with prior versions of tinyMCE, but it looks like it has to be v3+. I see an upgrade in my future :)
ReplyDeletearcherid, I encountered your same troubles... But I don't want upgrade to a beta version!!
ReplyDeleteYou might be able to get a clue from
ReplyDeletehttp://extjs.com/forum/showthread.php?t=19101&highlight=tinymce
I hope this helps.
take a look: this worked for me
ReplyDeletehttp://rorlach.de/mediawiki/index.php/Load_it_ondemand
Worked fine! Just one detail: you must disable flash tiny_mce plugin.
ReplyDeleteThx!
ReplyDeleteThanks a LOT for this solution. It just works like a charm. I have had some frustrating hours this evening trying to make this work, and then I found your article! Thanks, realy!
ReplyDeleteThank you very very much. You have saved my bacon and a project I'm working on.
ReplyDeleteHad a very complicated AJAX application and just couldn't get tinyMCE working on AJAX recalls.
You are the man!
It is mentioned in the original post (and even the title), but I thought it was worth pointing out this only works on version 3 and not version 2. I tested with 2.1.2 originally and got error 's.invalid_elements has no properties' which is mentioned in an earlier comment
ReplyDeleteHi,
ReplyDeleteI am trying to use you method, those I have a function similar to tinyfy in a separate js file. I get an error on tinyMCE.get(id).. for the first instance, though the instances after that work perfectly fine... any ideas?
@umang
ReplyDeleteWithout looking at the code and based on your description, I have a feeling that it may be an issue with timing.
This means that your function call is executing before TinyMCE is initialized.
On what browser does it occur ? (e.g. Firefox or IE) Does it occur erratically ? Can you post the error message here ?
One suggestion I can make is to add a defer attribute to the js file when you declare it. A defer attribute signals the browser to load the whole page first before loading the js file.
Try googling for defer and javascript.
Thanks for visiting and do let me know if this fixed your problem.
Hi Ham,
ReplyDeleteI actually have a sort of a wrapper over tinymce. The html page only initializes the wrapper. The wrapper has a overlay which when clicked on opens the editor. So I populate the settings array onclick and call mceAddControl. Fot the first wrapper div I click on, the editor opens up but displays an error in a line that comes after the mceAddControl part. The error is
tinyMCE.get(id).getDoc() has no properties. I am trying to attach a keyup event to the doc.
This has worked for me when all instances use the same configs(using a init call).
Thanks in advance
Oh! and I encounter problems on both IE6 and FF2.. though FF2 does not display this error always...sometimes it seems to work fine
ReplyDeleteHi Ham,
ReplyDeleteI was able to solve the problem by having a default setting and init... and then overriding the setting if requires using your method.
Thanks a lot
This is wonderful works without a problem.
ReplyDeleteIf your are looking to reuse this code in multiple pages below script will help.
function HookMceEditorsByClass()
{
for(var i=0;i<mceSettingsArray.length;i++)
{
tinyMCE.settings = mceSettingsArray[i];
var elCssClass = mceSettingsArray[i].editor_selector;
//get all elements with that class
var textAreaArray = getElementsByClass(elCssClass,null,"textarea")
for(var j=0;j<textAreaArray.length;j++)
tinyMCE.execCommand('mceAddControl', true, textAreaArray[j].id );
}
}
function getElementsByClass(searchClass,node,tag) {
var classElements = new Array();
if ( node == null )
node = document;
if ( tag == null )
tag = '*';
var els = node.getElementsByTagName(tag);
var elsLen = els.length;
var pattern = new RegExp("(^|\\\\s)"+searchClass+"(\\\\s|$)");
for (i = 0, j = 0; i < elsLen; i++) {
if ( pattern.test(els[i].className) ) {
classElements[j] = els[i];
j++;
}
}
return classElements;
}
where mceSettingsArray is array of different configurations.
Now call the function HookMceEditorsByClass() in 'onload' event of the page with textarea decorated with target class.
-sm
Ham, you saved me tonight!
ReplyDeleteTo those having problems with waiting for the page to load... I am using scriptaculous througout my app, so I figured I'd use it here as well.
So, here is my config, which allows for multiple unique configs per page. It's in a ColdFusion Function, so mind the pound signs as variables...
//-------------------------
var configArray#arguments.element# = [{
mode : 'exact',
element: "#arguments.element#",
theme : '#theme#',
plugins : '#plugins#',
theme_advanced_disable : 'hr',
theme_advanced_buttons1_add : '#theme_advanced_buttons1_add#',
theme_advanced_buttons2_add_before: '#theme_advanced_buttons2_add_before#',
theme_advanced_buttons3_add_before : '#theme_advanced_buttons3_add_before#',
theme_advanced_buttons3_add : '#theme_advanced_buttons3_add#',
content_css : '#cssfile#',
paste_auto_cleanup_on_paste : true,
paste_convert_pageheaders_to_strong : false,
paste_strip_class_attributes : 'all',
paste_remove_spans : false,
paste_remove_styles : false,
force_br_newlines : true,
force_p_newlines : false,
relative_urls : false,
gecko_spellcheck : true,
convert_urls : true,
theme_advanced_resizing_use_cookie : true,
theme_advanced_resizing : #resizing#,
theme_advanced_resize_horizontal : false,
theme_advanced_toolbar_location : 'top',
theme_advanced_toolbar_align : 'left',
theme_advanced_statusbar_location : 'bottom',
extended_valid_elements : '#extended_valid_elements#',
file_browser_callback : 'ajaxfilemanager'
}];
Event.observe(window,'load', function(){
tinyMCE.settings = configArray#arguments.element#[0];
tinyMCE.execCommand('mceAddControl', false, '#arguments.element#');
});
//-------------------------
Thanks,
Jules
Hey Ham,
ReplyDeleteGreat code. My only problem is that if I add a plugin, like Plugin: "xxx", it doesn't work. How can I include plugins for TinyMCE with your code?
Thanks
Thank you very much! Solved all of my problems.
ReplyDelete:)
Hi,
ReplyDeleteI tried #Freelance Web Development# example... it gives me a javascript error...
It says "invalid_elements" is null or not an object.
Even if i give some invalid_elements in the configuration, it gives me another error... i am not able to fix it... could you please anyone help me on this.
Thanks Ham! Did you ever find out why it's not working if you have certain plugins, like George said (in my case: plugins : "preview,ezfilemanager,tinybrowser",)
ReplyDelete??
He Ham, nice one!
ReplyDeleteDid you ever find out why it's not working if you use plugins, like george said?(in my case: plugins: "preview,ezfilemanager,tinybrowser")???
Thanks.
Thanks and sorry, I haven't been able to figure it out either.
ReplyDeleteMen, you save my life! Thanks!!
ReplyDeletethanx
ReplyDeleteHi there
ReplyDeleteThis is strange as the example code does not work in IE7, it works in Firefox, but IE7 it brings up a javascript error saying:
--------------8<----------
Line: 2
Char: 9950
Error: Access is Denied
Code: 0
--------------8<----------
Please could you check this
@NRasool
ReplyDeleteI'm not getting any error when I load the example on IE7. Please make sure that you have a copy of tiny_mce.js and that you have changed the src attribute in the script tag to point to it.
I tested with IE v. 7.0.5730.11 not that it makes any difference.
Please take a look again and let me know.
Apologises Ham, I was using an old version of TinyMCE, downloaded the latest build and it runs for me :-)
ReplyDeleteSorry for wasting your time :-)
No worries. I'm glad it's fixed :-)
ReplyDeleteI used this solution in a work-in-progress project, but it stopped to work suddenly...
ReplyDeleteIf I try to pass any setting using tinyMCE.settings = mySettingsArray, TinyMCE does not render and also I get no error, also with firebug.
Any advice on what could cause this?
Thanks
THANK YOU! I've been trying to get a 2nd TinyMCE to work in a WordPress admin and I've been google for hours and *nobody* (I mean *nobody*) covers how to set configuration prior to using tinyMCE.execCommand("mceAddControl"). I was about to give up before I found this post. THANK YOU again!
ReplyDelete@ Mike Schinkel. Trying to add a custom secondary TinyMCE editor to custom fields myself as well. Have not been able to so far. I can load the standard TinyMCE editor, but not a custom one from an array as suggested here. Could you maybe share your implementation?
ReplyDelete@ Ham, maybe you could tell me how I can connect/load your array into my JQuery code? Here is the current code:
ReplyDeletevar tinymceConfigs = [ {theme : "advanced",
mode : "none",
language : "en",
height:"200",
width:"100%",
theme_advanced_layout_manager : "SimpleLayout",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left",
theme_advanced_buttons1 : "bold,italic,underline,strikethrough,|,justifyleft,justifycenter,justifyright,justifyfull",
theme_advanced_buttons2 : "",
theme_advanced_buttons3 : "" },{ theme : "advanced",
mode : "none",
language : "en",
height:"200",
width:"100%",
theme_advanced_layout_manager : "SimpleLayout",
theme_advanced_toolbar_location : "top",
theme_advanced_toolbar_align : "left"}];
function tinyfy(settingid,el_id) {
tinyMCE.settings = configArray[0];
}
jQuery(document).ready(function() {
jQuery("#'.$meta_box['name'].'_value").addClass("mceEditor");
if ( typeof( tinyMCE ) == "object" && typeof( tinyMCE.execCommand ) == "function" ) {
tinyMCE.execCommand("mceAddControl", false, "'.$meta_box['name'].'_value");
}
});
Thanks in advance for all your help!
Ham, I must say, this is some excellent work you have done! I really would like to thank & appreciate you for coming up with the solution as I am sure, it has already made life very easy for many of us & would even help others in future.
ReplyDeleteThank you for putting up the solution for us.
Thank you! Great work! I just wanted to point out to others what took me some time to figure out.... if you're using tinyMCE 4.0.xxx this will not work. They've replaced "mceAddControl" with "mceAddEditor". Swapping that out will get this working on the new version.
ReplyDelete