Posting data from a popup back into TinyMCE

Recently I’ve spent a long time playing around with WYMeditor a jQuery based text editor for websites. Its really interesting and I’m glad I was able to devote quite a lot of time to playing about with it, but unfortunately at the end of the day we decided it just wasn’t mature enough for our needs, so looking around I settled on TinyMCE and have been working with that.

In some ways the main problem with something like TinyMCE is the shear number of options available, but once you strip it back there is a great tool there. The trick is to find that balance between giving users the a useful feature set but stopping short of giving them the power to destroy that carefully crafted website design and throw any measure of accessibility out of the window in the process.

TinyMCE has got quite straightforward plugin architecture that seems to work well and and is fairly easy to trace through and debug and hack about and the inline popups plugin is a real winner Рpopups in windows are just so pass̩e.

Of course being in a terrible rush I decided at against writing (or hacking) a full blown plugin and instead decided to just load a window (containing our custom file / image manager) and then return data and insert it back. My quick and dirty solution works well, but it does contain what I can only really describe as a bit of brute force cheating (and if somebody can suggest an alternative I would really appreciate it).

My TinyMCE setup is straight forward, I am using TinyMCE on its recommended path (/js/tiny_mce/tiny_mce.js) and I am also using jQuery.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<script type="text/javascript">
 
tinyMCE.init({
	mode : "textareas",
	theme : "advanced",
	editor_selector : "cms_editor",
	theme_advanced_toolbar_location : "top",
	plugins : "inlinepopups,safari",
	theme_advanced_buttons1 : "bold,italic,styleselect,formatselect,removeformat,link,unlink",
	theme_advanced_buttons2 : "",
	theme_advanced_buttons3 : "",
	theme_advanced_toolbar_align : "left",
	theme_advanced_statusbar_location : "bottom",
	content_css : "/css/editor.css",
	relative_urls : false,
	remove_script_host : true,
	document_base_url : "/",
});
 
 
</script>

Digging about I soon found the example of adding a custom button to the editor tool bar that inserts some HTML http://tinymce.moxiecode.com/examples/example_20.php and just modified this so my new init function now changes to:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
 
<script type="text/javascript">
 
var my_editor = null;
 
 
tinyMCE.init({
	mode : "textareas",
	theme : "advanced",
	editor_selector : "cms_editor",
	theme_advanced_toolbar_location : "top",
	plugins : "inlinepopups,safari",
	theme_advanced_buttons1 : "bold,italic,styleselect,formatselect,removeformat,link,unlink,image_button", 
        // image_button is my new button
	theme_advanced_buttons2 : "",
	theme_advanced_buttons3 : "",
	theme_advanced_toolbar_align : "left",
	theme_advanced_statusbar_location : "bottom",
	content_css : "/css/editor.css",
	relative_urls : false,
	remove_script_host : true,
	document_base_url : "/",
 
 
 
    setup : function(ed) {
 
        my_editor = ed;
 
        // Add a custom button
        ed.addButton('image_button', {
            title : 'Insert an Image',
            image : '/img/mce_image.gif', // icon for the button link
            class : 'mce_image', // add a class to the button link
            onclick : function() {
 
            tinyMCE.activeEditor.windowManager.open(
            		{file: '/admin/uploads/image_browser', width : 920, height : 560, inline : true}
 
            	); 
            }
        });
 
    }
});
</script>

The above function just adds a button image_button to the toolbar and adds a click event to this button. The click event just loads a page into (containing my custom browser) into an inline popup.

In the example on the moxiecode website, if you look at the source you will see that the onclick just adds some content at the cursor, ed being a reference to the editor instance.

1
2
 
ed.selection.setContent('<strong>Hello world!</strong>');

In my modified function the first thing I do is save a reference to the instance in a global variable my_editor, this is so we can refer to it latter and insert the data back.

As this whole escapade is just a quick and dirty way of getting data back into the editor without going through the proper plugin route, the my image_browser can just be considered as a black box. The important thing is that it returns a string of HTML for example <img src=”/uploads/images/image.xgh46.jpg” width=”200″ height=”100″ title=”some image” alt=”some-image” class=”float-right” />

The only thing of importance in my Image Browser is the following piece of code:

1
2
3
4
5
6
7
8
 
$(document).ready(function(){ 
 
	$('#submit-button').click(function(){
 
		parent.insert_data(str);
	});		
});

Simply adding a click event to a submit button and then calling the function insert_data() in the parent window (containing the editor) and passing my string of HTML to it.

The final piece of the puzzle is this simple function:

1
2
3
4
5
6
7
8
9
10
11
12
 
function insert_data(data){
 
 
	$('.clearlooks2').remove();
	$('#mceModalBlocker').remove();
 
	my_editor.selection.setContent(data);
 
 
 
}

We have access to the editor instance via the my_editor variable we created when we added the button to the toolbar and with this we can insert the data at the selection.

I had one problem, I can’t for the life of me figure out how to close / destroy the overlay. In the end I had to resort to brute force and just zapped it with a bit of jQuery magic, .clearlooks2 and #mceModalBlocker being the popup and the overlay respectively. If anybody knows a more elegant solution, please let me know.