Monday, March 11, 2013

Embedded ICE

‹prev | My Chain | next›

I would like to explore the possibility of embedding the ICE Code Editor inline in web pages. ICE is just the name that I give my fork of Mr.doob's code editor. I use it throughout 3D Game Programming for Kids, but it seems like the kind of thing that would be neat in blogs and other documentation.

ICE, and its progenitor from Mr.doob, consists of two main parts: the editor (I am using ACE code editor) and the preview. The editor is superimposed over the preview so that the programmer gets to see how her changes affect the visualization layer. On the face of it, this should not be too hard. Both are plain old <div> tags added to an otherwise empty page:
// preview

var preview = document.createElement( 'div' );
preview.id = "preview";
document.body.appendChild( preview );

// editor

var editor_el = document.createElement( 'div' );
editor_el.id = "editor";
document.body.appendChild( editor_el );
I might want to embed multiple ICE instances on a single page (e.g. one to demonstrate shapes, the other materials). So it is fairly clear that I will need to convert this to a JavaScript constructor at some point. But I will worry about that later. For now, I will settle for a proof of concept.

The whole page editor is done with the following HTML:
<!DOCTYPE html>
<html manifest="editor.appcache">
  <head>
    <title>code editor</title>
    <meta charset="utf-8">
    <link rel="stylesheet" href="editor.css">
    <script src="js/ace/ace.js" type="text/javascript" charset="utf-8"></script>
    <script src="js/ace/keybinding-emacs.js"></script>
    <script src="js/rawinflate.js"></script>
    <script src="js/rawdeflate.js"></script>
    <script src="js/appcache.js"></script>
  </head>
  <body>
  </body>
  <script src="js/editor.js">
  </script>
</html>
It is one thing to require that in an HTML5 application cache, but I would need to cut that down to a single <script> tag if I would even make it publicly available. Again, something for another day. For now, I copy that to a separate proof of concept page with with an id="ice" <div> tag already in place:
<body>
    <div id="content">
<p>Lebowski ipsum i'll ...</p>

    <div id="ice"></div>

<p>One a those days, ...</p>

<p>I'm not Mr. Lebowski ....</p>
    </div>
  </body>
<style>
#content { width: 600px }
</style>
Now that I think about it, maybe I do not need a new fork of the editor.js library. Instead of adding the editor and preview <div> tags to document.body, I can look for this id="ice" tag as the other possible parent for ICE:
var ice_parent = document.getElementById('ice') || document.body,
    embedded = !!document.getElementById('ice');
With that, I can then update the IDs and appendChild() calls to account for this alternative parent:
// preview

var preview = document.createElement( 'div' );
preview.id = embedded ? "preview_embed" : "preview";
ice_parent.appendChild( preview );

// editor

var editor_el = document.createElement( 'div' );
editor_el.id = embedded ? "editor_embed" : "editor";
ice_parent.appendChild( editor_el );

var editor = ace.edit(editor_el.id);
To get the editor and preview to overlap inline, I need the usual relative+absolute CSS chicanery:
#ice {
  position: relative;
  width: 100%;
  height: 350px;
}

#editor_embed, #preview_embed {
  position: absolute;
  width: 100%;
  height: 350px;
  top: 0;
}
And, just like that, I have ICE embedded in a web page:



That was easier that I had anticipated. There is still much to do to make this viable. I would dearly love a single <script> tag. I need some way to move between embedded and full-screen mode. But this is a very nice start.


Day #687

No comments:

Post a Comment