2010/01/14

Alpha release of Write Area

I've uploaded a beta version of Write Area to AMO as a little preview of what's next.

New plugin

It includes the Syntax Highlighter plugin by Darren James. Remember that you must configure your page with the SyntaxHighlighter by Alex Gorbatchev

With this feature you can include code in your pages like this:

  var script =  writearea.injectScript(this.parentWindow.document, command);
  var info = script.getUserData('editorInfo');
  script.parentNode.removeChild(script);
  // undetected framework
  if (!info)
   info = {
    type:"undetected",
    data:element.ownerDocument.body.innerHTML
   };

In the editor you click the "code" button and in that dialog you paste the contents and select the programming language that must be used to highlight it. In the editor it will be shown like other <pre> code (currently in blue, but I might change that), and in the final page it will show the code as you see above if you have properly installed the js and css files as explained by Alex Gorbatchev.

Not just textareas

The second feature is the ability to use the editor even on top of other editors. It tries to detect correctly some editors, but it should be able to handle any system where a WYSIWYG editor is used. Just right click on the content and click the Write Area entry, and the rest is just the same.

I'll explain this a little better: there are lots of places where some kind of rich editor is used: CMS, Forums, WebMail... The problem is that some of those places use old versions or editors that have very few features, so trying to use them can be a little painful.

My first motivation for writing this extension was that kind of situation where I had to deal for example with the editor here at blogspot. Fortunately for me I was able to disable it and use a plain textarea and easily work with it in my extension, but not all the editors have the ability to be switched off or to show the current source in a textarea, and one day I had a simple idea to detect this situation (check if the document has designMode == 'on') and work with the innerHTML of the body.

This works as long as the editor doesn't use special elements (like the icons shown here for anchors) as that means that the innerHTML isn't really the HTML output of the editor, to get that info (or to properly change the content so it shows any special elements) the API of each editor must be used. That means that there's a set of editors that I'm detecting and in the rest of cases the body.innerHTML is used for read/write.

The current sets of editors that I've coded to detect is as follows:

  •     CKEditor
  •     FCKeditor
  •     TinyMCE 2 & 3
  •     CuteEditor
  •     YUI Editor
  •     Xinha
  •     EssentialObjects
  •     HTMLArea

I could go on adding support for any other editor out there, but I think that this is enough to test the mechanism and verify that I could increase it in the future. I'm realizing right now that the detection could be extended even with a configuration option to add the required script, this is for example the part that detects CKEditor:

 if (window.CKEDITOR)
 {
  match = nodeId.match(/cke_contents_(.*)$/);
  if (match)
  {
   return {
    type: "CKEDITOR",
    data: CKEDITOR.instances[ match[1] ].getData(),
    setDataTemplate: "CKEDITOR.instances['" + match[1] + "'].setData(##DATA##)"
   };
  }
 }

The important trick here is that the code inside the extension can't call any method or access any custom javascript object of the web page, this is done in order to protect the browser from any external attack that tries to run code with Chrome privileges.

So by default the if (window.CKEDITOR) check always fails because as I said, the code in the extension can use the window of the document, and standard properties like window.document, but won't return anything that has been set by a script.

As a test phase I used the real window as returned by window.wrappedJSObject and I was able to verify that the ideas worked, and kept on that way for a little while, but finally today I have changed all the detection code so that it's done in a single place (previously the code looked quite different) and it's merged into a big string that it's added to the web document  as a script. That script executes a function that includes all the detection parts and returns an object that it's set as a property of the script DOM node, and then in the other side of the fence, the extension gets back that object with the detected data.

Isn't a little strange that I can't get an element added normally to an object like window, but it's possible to pass an object using node.setUserData?

So back to what's important:
Now you can use this extension almost anywhere, it doesn't matter if it's your blog, your CMS or a WebMail app like Hotmail, GMail or Yahoo, if you want to overcome some limitation of the editor, or a "silly" restriction set by whoever added that editor leaving only a few features, you can right click on it and launch the WriteArea extension to work as you please. Note that you might need to disable the option in the preferences of Firefox to allow the pages to replace the default context menu, and you should be aware that dueto bug 486990 if you are using Firefox 3.5 the page might be able to ignore that restriction (but Firefox 3.6 works nicely).

I plan to do some other enhancements before releasing this as a full new version, but I think that it's worth publishing it as a beta to let people test it.

I might edit this post to explain better how to use each of those two features and why they are useful, but I would like to hear your comments about them meanwhile.

Edit 17th January: I've added an example of the output of the Syntax Highlighter plugin and an explanation of how the detection of other editors work.

No comments: