Two of my favorite javascript libraries, YUI and ExtJS, both have WYSIWYG editors. While the editor for ExtJS , in my opinion, has some more ways to go, I've heard raves about YUI's implementation at least from one other developer.
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>

26 comments:
Thanks, after couple frustrating hours i found your solution. Thanks.
Glad to help !
Thanks 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!
Nope I didn't have anything loaded when the page starts and I didn't use tinyMCE.init()
If 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?
Thanks,
archerid
I created a one page demo on my box
http://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 :)
archerid, I encountered your same troubles... But I don't want upgrade to a beta version!!
You might be able to get a clue from
http://extjs.com/forum/showthread.php?t=19101&highlight=tinymce
I hope this helps.
take a look: this worked for me
http://rorlach.de/mediawiki/index.php/Load_it_ondemand
Worked fine! Just one detail: you must disable flash tiny_mce plugin.
Thx!
Thanks 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!
Thank you very very much. You have saved my bacon and a project I'm working on.
Had 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
Hi,
I 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
Without 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,
I 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
Hi Ham,
I 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.
If 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!
To 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,
Great 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.
:)
Hi,
I 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.
we provide a power leveling and free wow gold wow power leveling|*|wow power leveling|*|http://www.wotlk-powerleveling.com|*|fdgf51
Post a Comment