Category Archives: Ephox

Inside TinyMCE plugins (and an introduction to plugin dependencies)

I’ve just been spending some time adding dependency resolution to TinyMCE plugins.

The concept is that a plugin can depend on other plugins. As a part of doing this work I’ve had some good opportunity to dive deep into how plugins in TinyMCE work. It’s been a good little trip that I’ll summarise briefly here. I’ll do this by first presenting the lifecycle, then explaining how plugin dependencies will work.

Plugin Loading Lifecycle

The TinyMCE plugin loading lifecycle there are three concepts that are important to understand:

  1. load
  2. add
  3. init

Load

The loading of a plugin will automatically download the javascript code, and run this. This is done by looking for a file, “editor_plugin.js”, in the “plugin short name” folder in the plugins folder. When running in development mode, the file “editor_plugin_src.js” will be used. It is expected that the source code in this js file will use the TinyMCE create function to create a class for the plugin, add the plugin to TinyMCE using PluginManager.add This code should typically try to remain outside of the global namespace, executing within an anonymous function block, as per the code in the example plugin.

Plugins specified in the plugins attribute of the settings object will be loaded if they have not previously been loaded. Historically TinyMCE has also included a – prefix to prevent autoloading of plugins. This is no longer required, as TinyMCE is smart enough to know if a plugin has been loaded, and won’t load it twice. So in effect, there is no reason to include the – prefix (so the only part to remember from this paragraph is that plugins specified in the plugins attribute of the settings object will be loaded if they have not previously been loaded).

Add

A plugin class can be added to TinyMCE using the PluginManager.add function, passing the short name of the plugin and the implementing class for the plugin. The short name should be a unique identifier for the plugin, and the plugin class provides the code that implements the plugin.

Importantly the class can provide an init method which will be called by TinyMCE when it is being initialised. The class should also provide a getInfo method which returns information about the plugin.

There are two ways of performing an add. It can either be done manually before loading TinyMCE, or it could be specified in the editor_plugin.js that gets loaded as a part of the load process above.

Init

The init function of the class for a plugin will be called after TinyMCE has created the plugin, as a part of the editor initialisation process. The plugin will be passed a reference to the editor as a part of the initialisation process.

Plugin Dependencies

Plugin dependencies can/will be specified in an array parameter to the PluginManager.add function call. There are two ways to specify a dependency.

  1. as a string. String dependencies will reference the short name of the dependency. If the dependency has not previously been loaded, TinyMCE will attempt to load the dependency.
  2. as a simple object. The object will have the form:
    {
    prefix: 'url_prefix/',
    resource:'name_of_plugin',
    suffix:'/path_to_file.js'
    }

    These will then be concatenated together to form a url. URLs will be resolved as relative to the TinyMCE installation. In the above object this would generate the url: “url_prefix/name_of_plugin/path_to_file.js”

When specifying a plugin dependency, there is a guarantee that the init method of the dependencies will be called before the init method of the plugin. There is no guarantee of the order in which the plugin “editor_plugin.js” is loaded. This can be seen in the test “plugin_dependency_init_call_order.html” which shows the order in which the init method is called. That the loading of plugins is not specified as a part of the new dependencies work is somewhat intuitive. It is only as a part of the load process that a plugin (and it’s list of dependencies) are made known to TinyMCE, which means that it is not possible to specify dependencies within the plugin before loading the plugin. The init of plugins is only performed after the plugins have all been loaded, making it possible for the dependencies to be init’ed before a plugin is init’ed

Swing Text APIs

At Ephox we are pretty heavy users of the Java text APIs. In some respects the EditLive! team probably knows more about them than anyone in the world. In a Creative Coding Afternoon recently, I was doing some work on a cool plugin for EditLive! (it might make it into a future release of Enterprise Edition), and after spending time getting angry with the Swing document (some of the anger was justified). I had an epiphany. I expect that the actual revelation will not matter to any outside of Ephox (ok so people who want to work for ephox might be interested), but I'm going to share it anyway.

The Swing Document model != the DOM. Don't expect it to look like the DOM. Don't expect it to be the HTML DOM. The subclass HTMLDocument is not the DOM. While you can access all the information in the DOM, you should not expect there to be a direct mapping between concepts in the DOM and in the Swing Document model. You can expect all the information in the DOM to be available in the Swing Document model, but it isn't going to look exactly like the DOM. The Swing Document model is a generic model for presenting a document for us in a rich text editor, which means the DOM is transformed to work with the Swing Document model.

Once you can get your head around this, the Swing Text APIs can begin to make more sense (although I'm still grumpy about the lack of working with the java.util.collections properly).

Fun in Boston

I’m sitting typing this from my hotel room in Boston looking out over MIT, having just finished my morning conversation with my wife (skype is great), and thinking back over the past couple of days. I’ve had a great time in Boston, really enjoying the city. It’s a nice old town with an enjoyable skyline, and the rivers are beautiful.

For the interested, I ran a workshop at the CMPros workshop held on the Monday. It was titled “Open Standards and the Convergence of Wikis and Content Management Systems” (slides), and after a brief introduction the workshop focused on discussion around wikis and content management systems. We had some good discussions with people sharing their experiences with both content management systems and wikis. I’ll be running a webinar with Ephox talking about this, and soem of the coming directions in Content Collaboration in the next week. Drop me a line if you are interested.

cocktail-party-sign.jpg

The Gilbane Boston conference itself has started in earnest now. Tuesday night was the big kick-off for us at Ephox, as we were the proud hosts of a cocktail party, held in the hotel (picture taken by Marco). It was a good night with some really great conversations with some interesting people. Conversations ranging from geography to business (even touching on WYSIWYG editors and content management systems), to obscure technical jokes about metadata and tags.

Yesterday and today have been spent in a combination of manning the Ephox booth, and talking to some of the other vendors ont he floor. My focus has been looking for opportunities for future collaboration, and there looks like some great opportunities.

It has also been great meeting some of the San Mateo based Ephox team face-to-face, getting to know Antony and Marco as more than a voice at the other end of a phone line. They are great guys to work with, and have been doing a great job at helping to make sure that people get to see and know the great products that Ephox has.

An AJAX Iteration

I'm currently unwinding after only just managing to see all the cards1 move from the "this iteration" column2 to the "done" column3 on our XP storyboard.  While the estimates had us coming in at the same spot as earlier iterations, it ended up being quite a bit tighter than the earlier ones had been.  

There are a few reasons why, but the biggest cause would be the fact that we were moving from the comfortable world of Java actions into world of some heavy ajax ui.  I spent some time working with libraries and researching how to do things like JSON in Java, and AJAX popups.  It was a fun and stretching iteration, with plenty of prettiness to show for the work.

I learnt a lot including:

 AJAX with Prototype is great.  Prototype provides all the methods you want in the library.  I would consistently find the methods I would want in the library such as $('id') (to find an element with an id), and the serialize methods for forms are really nice. Kudos to the prototype team for a great library.

Scriptaculous provides nice effects that build on prototype.  The Autocompleter is worth the price of admission.

The popup library by Stuart Rackham works really nicely.  He doesn't have access to Safari so hasn't tested it there, but now I have, and while not all the features work, it is possible to produce nice popups that work in Safari with this library.  He has built this on top of Scriptaculous and prototype and he has done a great job.

JSON for passing around data is cool.  The whole eval on the client thing is a bit scary, but (almost as I expect now) at least prototype provides a nice evalJSON method to help alleviate a little my security paranoia. Of the millions of JSON libraries available, the standard java one works ok. (what's not to like about a library with a license that includes the text "The Software shall be used for Good, not Evil."  Mightier JSON libraries exist that do all kinds of magic, but the simple approach is working to start us off.

 

The biggest missing piece in my JavaScript Development is the fact that it isn't TDD. There seem to be bits and pieces out there, but nothing that is jumping out and saying "use me I just work.". The main reasons I am wanting to do Test Driven Javascript are for quality and pleasure. Doug spent some time researching options for acceptance testing of E2 front to back (including the javascript), which will definately help out the quality, but it still would be great to have a viable TDD option.

I never would have expected to say this, but it has been fun doing the JavaScript and AJAX in the past iteration. It really is much better than in the past, and I can see it only getting better.

1 – The card contains a unit of work

2 – The list of cards we are planning on getting done in the iteration, but haven't started working on yet

3 – The list of things we have finished this iteration.

Eight Months at Ephox

Given that it's been a while since I last posted about life at Ephox, and a bit has changed since then I thought I'd go ahead and do an update.

First of all, as well noted elsewhere, I've moved from product management back into development.  I made the move back into development a few months ago, and I've been loving it.  The foray into product management was an interesting trip, educational, and helped me to better realise where my strengths and passions are.  I love building software that meets peoples needs, and I particularly love doing this in a web environment (J2EE/Rails/whatever).

So for the past couple of months I've been really enjoying working on E2.  It's pretty cool, and I can really see where it will fit in with Ephox and how it can make peoples lives better.  I'm really excited about E2, and I'm looking forward to when it gets released to the wild.  We've started dogfooding some of the initial features internally, and it is shaping up to be a great product.

Another bit of news in the past while is that I'll be presenting at the CMPros summit in Boston.  I'm looking forward to presenting a talk that is loosely related to some of the ideas I've been thinking about lately.

It's been a fun and challenging period of time, being able to work with cool technologies, cool people, and cool toys.

A Somewhat Questionable Pair of Commit Messages

Andrew recently mentioned that I'm working on E2 currently.  We dog food all our products, and automatically deploy updates to our internal systems.  While doing some work on E2 I discovered that it isn't currently automatically updating.  In troubleshooting this I noticed that the line saying to do this was commented out.  The svn log had the following messages:

commit xxx: ADDED: Automatic deployment for E2
commit xxx+1: REMOVED: Automatic deployment for E2

Less than fully helpful when trying to work out why the automatic deployment was removed.

Good Management

Warning: if you are looking for an angry rant you won't find it here, instead this is a article about a truly good manager.

Like most people who have been in IT for as long as me, I’ve worked with some pretty dodgy management over the years. There have been times where I was sure Scott Adams was sitting in my cube farm, stealing ideas for dilbert.

I came to Ephox knowing that this wouldn’t be the case. I came knowing that I was going to be working for a good manager, Brett. Brett takes management, leadership and people seriously, as you can see in his recent blog post about a leadership course he is attending. Here he talks about what he has been learning about management and leadership, and how much he already understands and implements. You may read it, and think that he is perhaps self-deluded, but as someone who has been working for Brett, I can vouch for the fact that this isn't the case. Brett really does get people management. He understands the importance of putting people over process, and it makes a huge difference. It is his valuing of people that played a key part of my wanting to come to Ephox in the first place, and makes being a part of his team great.

Another thing that Brett does well is keeping commitments. In a recent InfoQ article on agile, there was the quote: ”…one of the quickest ways to take the wind out of a person’s sails is to break a commitment…”

I can’t think of a single commitment that Brett hasn't worked really hard to keep. He does well at making the right commitments, and sticking by them. One real instance of this that really sticks out in my mind was when I was nearing the end of my time in support. I could see that there might be value in me holding off transitioning (and I was willing to do so), but Brett stuck with his word, and made sure that I was able to transfer to development. It was great that Brett put in the work to ensure that this happened, and this commitment help keep my motivation high.

Brett spent time working on his management skills, and I really think this investment has paid off. Brett does really well at leading his team of developers, and creating an environment where we want to be. Having a good engineering manager is going to be a key part of helping Ephox to grow, enabling us to hire and keep good engineers.

Three Months at Ephox

 I've been at Ephox for three months now, and the ride is continuing to be a good experience. I've had the pleasure of spending most of the past month in development. It was quite strange finishing up the support, with me actually being sad to leave.  I was really getting into the customer interaction, and being able to help people come to some good positive solutions.

Moving out from support to development was a happy transition to make.  I went as far as to move desks getting closer to poking Doug and AJ.  I had a blissful first week of development, getting into the swing of things before Andrew (the CEO) came to visit.  I was really getting into the swing of being a happy code monkey, and Just a programmer, when Andrew shook things up, and we heard of plans for a restructure introducing more product managers, with the goal of better working as a company.  I am now going to join AJ, and Damien, and be a product manager.  AJ and Andrew have already started talking about what this might involve, and I'm really looking forward to what the new role has to offer.  Given the fact that I came to Ephox to code, it is ironic that I will have spent more time in support than coding, and I'm going to be a manager.  That said, I am definitely looking forward to the new role, and to the opportunity to be the customer voice (or as Dan North used to put it, "The Truth").  I've always been keen on delivering software that meets peoples needs, and one of my key responsibilities in this role will be guiding the development of EditLive! to ensure that we continue to meet expectations.  There is plenty to learn, and I'm excited about the new opportunities to grow.  

The month of coding has been fun.  I've learnt some things about JavaScript, and we got to add some nice features to EditLive.  I also got to learn more than I ever wanted to know about IWWCM.  My respect for Jack (our resident IWWCM expert) has gone up immensely (not that I didn't respect him before).  It has been nice to loosely be a part of the work that has been put into improving the stability, startup experience, and performance of the Editor, and I look forward to continuing to be able to influence the direction of EditLive!

Migrating to FreeMarker

… or Adding the red button

AJ mentioned that we have automated the build and release process. After spending much of the morning hearing everyone talking about wanting to push the “big red button” for a release, and hearing how it was “too hard”, to update the html, I decided to go ahead and work out what needed to happen. What an interesting world I discovered.

The webapp in need of the red button is basically a servlet which calls out to the various parts of the world (our various build ). This works fine, but sometimes gets a bit hard to maintain (ok so some things are very hard to maintain). So (rather than doing a huge change), I figured that I could drop in a templating engine, and use the servlet to merge the template. I knew that Velocity is a bit old hat now, so went for a bit of a google, and (after a short diversion into another non-maintained option), I found FreeMarker. Having heard of it in the past, and knowing that it was the tool of choice for WebWork, I thought I’d give it a go.

My first test was to create a hello world web app from scratch.

I ended up with a very basic servlet that I’ve attached.

Basically it creates a configuration:

configuration = new Configuration();

tells the config that templates are found in the templates sub directory of the current class. configuration.setClassForTemplateLoading(this.getClass(), "templates");

retrieves the template:

 template = configuration.getTemplate("start.html");

creates a map of data to merge with the template: 

Map freeMarkerData = new HashMap();

freeMarkerData.put("user", "Mr Man");

 and finally merges the data with the template: 

 template.process(freeMarkerData, response.getWriter());

The hello world spike done (at home), all I needed to do was repeat the process at work with the real servlet. Replacing the html from the magic servlet, one template at a time.

Of course the first template to be created on our deployment applet was the one with the Big Red button.