Wednesday, February 02, 2011

Embedding the Orion Editor

[Edit Jan 3, 2012: Orion has evolved significantly since this post was first written a year ago. Please see this post written by Felipe for an update.]

Yesterday I wrote a blog post which contains a few snippets of Ant code. If you have java-script enabled, those snippets should be nicely formatted with line numbers and some basic syntax highlighting.

Those code snippets are actually being shown using the Orion Editor embedded into my blog post. Granted, using the full editor here is a little over-kill since we aren't doing very much with it, but this was an interesting exercise.

Here is the javascript I wrote to do this:

/*******************************************************************************
 * Copyright (c) 2011 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *******************************************************************************/
function findOrionElements(tagName){
   var elements = [];
   var tags=document.getElementsByTagName(tagName);
   for(var i=0;i<tags.length;i++) {
      if(tags[i].getAttribute('name')==='orion') {
         elements.push(tags[i]);
      }
   }
   return elements;
}

function createEditors() {
   //find all pre elements named 'orion'
   var elements = findOrionElements('pre');

   
   for(var i=0; i < elements.length; i++) {
      var element = elements[i];

      //extract the text from inside the pre
      var text = "";
      for( var j=0; j < element.childNodes.length; j++ ) {
         var nodeName = element.childNodes[j].nodeName;
         if (nodeName === "#text")
            text += element.childNodes[j].nodeValue;
         else if (nodeName === "BR" )
          text += '\n';
      }
      
      /* Create the editor: 
          - parent is the containing div element
          - readonly by default, but can specify class="writable"
          - use the given stylesheet  */
      var parentNode = element.parentNode;      
      var elementClass = element.getAttribute('class');
      var editor = new eclipse.Editor({
         parent: parentNode, 
         readonly: !(elementClass && elementClass.indexOf('writable') > -1),
         stylesheet: "http://download.eclipse.org/e4/orion/js/org.eclipse.orion.client.editor/editor.css"
      });

      // use javascript styler for now, there is no html/xml syntax highlighting yet
      var styler = new eclipse.TextStyler(editor, "js");
      // add a ruler with line numbers to the left side
      var lines = new eclipse.LineNumberRuler("left", {styleClass: "ruler_lines"}, {styleClass: "ruler_lines_odd"}, {styleClass: "ruler_lines_even"});
      editor.setText(text);
      editor.addRuler(lines);

      //fix the height of the containing div
      parentNode.style.height = (editor.getLineHeight() * (editor.getModel().getLineCount() + 1)) + 2 + 'px';  
   }
}


This code is looking for all <pre name='orion'> elements and creating editors to replace them. These elements should generally be contained inside a <div> element. HTML for a replaceable section would look like this:

<div><pre name="orion" class="writable">
   var hello = "Hello World!";
   alert(hello);
</pre></div>

This example above was made writable by adding "class='writable'" to the <pre/> element. Inside the <pre> element, all '<' should be escaped as '&lt;' and all '>' as '&gt;'.

As a final step, to get this working on blogger.com, I combined my javascript together with:
org.eclipse.orion.client.editor/web/js/editor.js
org.eclipse.orion.client.editor/web/js/model.js
org.eclipse.orion.client.editor/web/samples/rulers.js
org.eclipse.orion.client.editor/web/samples/styler.js
and minified it all using the Google Closure compiler. I hosted the resulting .js file on download.eclipse.org and added the following lines to the bottom of my blog post:

<script type="text/javascript" src="http://download.eclipse.org/e4/orion/js/org.eclipse.orion.client.editor/orion-editor.js"></script>
<script type="text/javascript">document.onload=createEditors();</script>


If someone visits the post without javascript enabled, then they don't get the nice formatting on the code snippets, but at least they are still inside <pre> elements which give them some basic formatting.


7 comments:

Patrick Mueller said...

Very cool.

Some suggestions.

The code you wrote should be part of Orion. And it should work off of class, not name, for the pre's. And it should somehow include the language to parse the code. And your code in the pre's shouldn't include br's - pre already handles that for you :-)

Last suggestion, make this work like GitHub gists's "embed" feature. I should be able to include one line in my blog post, which points to the thing I want to view in the Orion editor, and it just works.

Patrick Mueller said...

I just noticed that if I "mouse scroll" while the mouse is over the orion editor, the page doesn't scroll. Please fix. This is on a Mac (but you already knew that!)

Not a big deal, but I've also noticed that I don't get a context menu over the editor - I've tried to do that to "inspect" (with Chrome devtools) the editor a few times now. A tiny bit frustrating.

Unknown said...

I raised bug 336276 about moving the code into Orion. Also, we noticed the scrolling problem which is being tracked by bug 336021. See also bug 336178 for problems with the line numbers not aligning quite right with the editor.

Felipe Heidrich said...

See Bug 334583 for the context menu.

Unknown said...

For embed editor with "writable" class, is there a way to save the code after it was edited? Same for undo and redo...

Unknown said...

Take a look at minimaleditor.html and minimaleditor.js. You can hook up key bindings for save and undo/redo. Things are being refactored a little in the current milestone M7, editorContainer.js will be the basis for reusing the editor with more complete keybindings and commands. See bug 337647 for some discussion about this.

Pradyut said...

Pretty cool blog...Was helpful to set up my own environment. I put up a post to contribute to the Orion Navigator http://pradyutsarma.blogspot.com/2011/06/extending-orion-navigator.html