Heya all,

I am trying to revive this blog from a long period of sleep. Let's start today with a little Java trick I made to have a working TinyMCE implementation using Wicket (tested over 1.4.9 and 1.4.13 in my case but I think it should work for any 1.4.x at least, please report successful attempts under other releases).

For newcomers, TinyMCE is a really powerful WYSIWYG editor written entirely in Javascript, it features plugin and theme ability in order to be THE editor to use in your projects. Apache Wicket is a really powerful web framework based on Java EE specs (I think I'll talk a lot about Wicket in here...).

An implementation of TinyMCE for Wicket exists, it'll be the first result you get when you ask your old pal G***** a hand. But, this implementation is a bit tricky to find (outdated links everywhere) and not feature complete (or not fully complete), as I explain in the read more part...

You can checkout latest almost working release from there by using the following command line :

svn co https://wicket-stuff.svn.sourceforge.net/svnroot/wicket-stuff/releases/wicketstuff-core-1.4-rc7/tinymce-parent

Let me explain what problem I encountered, it happens only on isolated cases (ajax pushing the whole WYSIWYG shebang on a page without that mess). TinyMCE is then lost, and the only output you get when you try to call init() is tinyMCE is undefined on your Javascript console. My first thought was to replace the outdated version bundled (3.1.0.1), so I headed to TinyMCE's website , downloaded latest version so far (3.3.9.2) and replaced it in my workspace. A try later and no luck, the problem is still here.

What's happening, why on hell this working component don't want to work anymore ? By digging into TinyMCE's code, you'll find that it looks for its baseURL, for lazy loading stuffs (depending on what you use), but Wicket responds to Ajax  headers contribution in a special way : instead of appending regular <script type='text/javascript' src='myurltomyfile.js'></script> it appends <script type='text/javascript' src_='myurltomyfile.js'>[content of myurltomyfile.js]</script> to the body of the document.

This particular way of answering to browser is not well handled by TinyMCE, which looks up its baseURL by parsing script tags present in the DOM. The hack to circumvent this is really simple, make TinyMCE find its baseURL by reacting on src_ attributes. The following listing shows the patch in tiny_mce_src.js on the getBase(n)method :

 1 function getBase(n) {
 2     var src_ = n.getAttribute(&quot;src_&quot;);
 3     if (src_) {
 4         n.src = src_;
 5     }
 6    if (n.src &amp;&amp; /tiny_mce(|_gzip|_jquery|_prototype|_full)(_dev|_src)?.js/.test(n.src)) {
 7         if (/_(src|dev)\.js/g.test(n.src)) {
 8             t.suffix = '_src';
 9         }
10         if ((p = n.src.indexOf('?')) != -1) {
11             t.query = n.src.substring(p + 1);
12         }
13 
14         t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
15 
16         // If path to script is relative and a base href was found add that one infront
17         // the src property will always be an absolute one on non IE browsers and IE 8
18         // so this logic will basically only be executed on older IE versions
19         if (base &amp;&amp; t.baseURL.indexOf('://') == -1 &amp;&amp; t.baseURL.indexOf('/') !== 0) {
20             t.baseURL = base + t.baseURL;
21         }
22         return t.baseURL;
23   }
24   return null;
25 }

With this hack, console error yelling tinyMCE is undefined is gone. No more error but the editor still does not work, TinyMCE waits for the document to be ready before calling its render phase. Let's fake it by flagging when we're coming from a Wicket Ajax request. We simply add an attribute to tinyMCE object : in the _init() method

t.isAjax = false;

We flag in the getBase(n) when we come from Wicket Ajax (when we get something like <script src_=""></script>)

1 if (src_) {
2     t.isAjax = true;
3     n.src = src_;
4 }

and we set the domLoaded flag to the newly introduced attribute at the end of the JavaScript file :

tinymce.dom.Event.domLoaded = tinymce.isAjax;

This way, TinyMCE calls its render phase directly when we call init() on tinyMCE object. This call is done by Wicket when the dom is ready and then we finally got TinyMCE working even when coming from an ajax javascript inclusion. The only thing you need to do in order for this to work in deployment mode is to compress tiny_mce_src.js to tiny_mce.js with this patch.

You can find the resulting tiny_mce_src.js here

.
comments powered by Disqus