Using Embedded to show 3D structure of molecules

Hi,
I recently started to work with Vaadin. Actually I work on portlets for a portal used in chemical research. I want to create a UI element that is able to show the 3D structure of a molecule. Therefore I use
ChemDoodle
. ChemDoodle is a Javascript library which enables the 3D representation of molecules. An easy example for the usage of ChemDoodle would be:

<html>
<head>
<title>3D Interactive Model of DDT test 2</title>
<link rel="stylesheet" href="http://hub.chemdoodle.com/cwc/latest/ChemDoodleWeb.css" type="text/css">
<script type="text/javascript" src="http://hub.chemdoodle.com/cwc/latest/ChemDoodleWeb-libs.js"></script>
<script type="text/javascript" src="http://hub.chemdoodle.com/cwc/latest/ChemDoodleWeb.js"></script>
</head>

<body>
  <script type="text/javascript">
    var mol_DDT = '3036\n  CHEMDOOD12280913053D\n\n 28 29  0     0  0  0  0  0  0999 V2000\n    0.0456    1.0544   -1.9374 Cl  0  0  0  0  0  0  0  0  0  0  0  0\n   -0.7952   -1.7026   -1.7706 Cl  0  0  0  0  0  0  0  0  0  0  0  0\n    0.6447   -0.8006   -4.1065 Cl  0  0  0  0  0  0  0  0  0  0  0  0\n    1.8316   -0.9435    4.4004 Cl  0  0  0  0  0  0  0  0  0  0  0  0\n    6.9949    1.1239   -3.9007 Cl  0  0  0  0  0  0  0  0  0  0  0  0\n    1.9032   -1.0692   -1.6001 C   0  0  0  0  0  0  0  0  0  0  0  0\n    1.8846   -1.0376   -0.1090 C   0  0  0  0  0  0  0  0  0  0  0  0\n    3.2176   -0.5035   -2.1949 C   0  0  0  0  0  0  0  0  0  0  0  0\n    0.5585   -0.6223   -2.3126 C   0  0  0  0  0  0  0  0  0  0  0  0\n    2.2670    0.1198    0.5688 C   0  0  0  0  0  0  0  0  0  0  0  0\n    4.3480   -1.2638   -2.0859 C   0  0  0  0  0  0  0  0  0  0  0  0\n    1.4856   -2.1660    0.6075 C   0  0  0  0  0  0  0  0  0  0  0  0\n    3.1719    0.7242   -2.7939 C   0  0  0  0  0  0  0  0  0  0  0  0\n    2.2506    0.1490    1.9633 C   0  0  0  0  0  0  0  0  0  0  0  0\n    5.5313   -0.7541   -2.6203 C   0  0  0  0  0  0  0  0  0  0  0  0\n    1.4691   -2.1369    2.0020 C   0  0  0  0  0  0  0  0  0  0  0  0\n    4.3552    1.2340   -3.3284 C   0  0  0  0  0  0  0  0  0  0  0  0\n    1.8515   -0.9793    2.6800 C   0  0  0  0  0  0  0  0  0  0  0  0\n    5.5350    0.4948   -3.2417 C   0  0  0  0  0  0  0  0  0  0  0  0\n    1.9777   -2.1366   -1.8749 H   0  0  0  0  0  0  0  0  0  0  0  0\n    2.5727    1.0177    0.0401 H   0  0  0  0  0  0  0  0  0  0  0  0\n    4.3513   -2.2356   -1.6034 H   0  0  0  0  0  0  0  0  0  0  0  0\n    1.1951   -3.0814    0.0991 H   0  0  0  0  0  0  0  0  0  0  0  0\n    2.3077    1.3562   -2.8879 H   0  0  0  0  0  0  0  0  0  0  0  0\n    2.5491    1.0585    2.4783 H   0  0  0  0  0  0  0  0  0  0  0  0\n    6.4431   -1.3411   -2.5451 H   0  0  0  0  0  0  0  0  0  0  0  0\n    1.1584   -3.0244    2.5473 H   0  0  0  0  0  0  0  0  0  0  0  0\n    4.3449    2.2098   -3.8075 H   0  0  0  0  0  0  0  0  0  0  0  0\n  1  9  1  0  0  0  0\n  2  9  1  0  0  0  0\n  3  9  1  0  0  0  0\n  4 18  1  0  0  0  0\n  5 19  1  0  0  0  0\n  6  7  1  0  0  0  0\n  6  8  1  0  0  0  0\n  6  9  1  0  0  0  0\n  6 20  1  0  0  0  0\n  7 10  2  0  0  0  0\n  7 12  1  0  0  0  0\n  8 11  2  0  0  0  0\n  8 13  1  0  0  0  0\n 10 14  1  0  0  0  0\n 10 21  1  0  0  0  0\n 11 15  1  0  0  0  0\n 11 22  1  0  0  0  0\n 12 16  2  0  0  0  0\n 12 23  1  0  0  0  0\n 13 17  2  0  0  0  0\n 13 24  1  0  0  0  0\n 14 18  2  0  0  0  0\n 14 25  1  0  0  0  0\n 15 19  2  0  0  0  0\n 15 26  1  0  0  0  0\n 16 18  1  0  0  0  0\n 16 27  1  0  0  0  0\n 17 19  1  0  0  0  0\n 17 28  1  0  0  0  0\nM  END\n';
  </script>
  <script type="text/javascript">
	var view = new ChemDoodle.TransformCanvas3D('view', 640, 640);
	view.specs.set3DRepresentation('Ball and Stick');
	view.specs.backgroundColor = 'black';
	var molecule = ChemDoodle.readMOL(mol_DDT, 1);
	view.loadMolecule(molecule);
  </script>
</body>

</html>

The ChemDoodle libraries are loaded in the head element. In the body element, the first script tag defines the molecule, the second creates a canvas in which it is shown. (Just run it by yourself to see how it looks like)

In a first test I added this html document as resource to my portlet and used the Embedded component to show it (Used the resource in Embedded constructor). This works just fine! The problem now is of course that I also want to display other molecules than that defined in the html document :wink: i.e. I would like to exchange the first script element during runtime. For this purpose I created my own Widget which is extended from Embedded and VEmbedded respectively (creating own simple widgets worked just fine in some tests). I tried to exchange the script tag in the client side component in the ‘updateFromUIDL’ method like:


public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
  super.updateFromUIDL(uidl, client);
  Element browserElement = DOM.getFirstChild(getElement()); //this is the way VEmbedded gets the browser Element
  Element bodyElement = browserElement.getElementsByTagName("body").getItem(0); //get the body of html document
  bodyElement.getFirstChildElement().setInnerText(....define new molecule here...); //this should return the first script element. I want to define a new molecule here
}

The new molecule definition shall later be obtained from the uidl of course. By now I just hardcoded the new definition in ‘setInnerText()’ to see if this works in general. However, this does not work and I really don’t know why? Is this dynamic injection not allowed in general? I know the Embedded component creates an IFrame and sets the src attribute to the defined html document. Maybe i can’t change the script element because it would then be a kind of disagreement to the defined src?

By now I worked on three different solutions:

  1. Create own widget not extended from Embedded. Used a div element and added the corresponding script tags to load the libraries and create the canvas. This did not work at all…
  2. If the molecule is set once, it will not change in this canvas anymore. So just read in the given html document resource and overwrite first script tag in file (where molecule is defined) with the definition of a new molecule. Then load this new file as resource and use the normal Embedded component. I have not tried this but it should work… nevertheless it’s not a good solution in my opinion.
  3. Create widget extended from Embedded and replace first script element at runtime (as discussed above)

I would be very happy if some of you would like to discuss this problem with me. I’m stuck at this point :frowning:

Thanks,
Andi

I believe the most common way of using existing javascript libraries with Vaadin or GWT is through
JSNI calls
. It’s basically a workaround for GWT, that enables you to write raw JavaScript, instead of Java which is then cross compiled to JavaScript. It’s very powerful, but you need to be watchful of all kinds of things (most prominently browser incompatibilities).

So, you might want to even start a completely new component, instead of forking VEmbedded. Or you can always strip away all the unnecessary code that you don’t need for your molecule showing component

There are a lot of Add-ons on the Directory that just wrap around a javascript library. The one that comes first into mind is Risto’s impressive
MathQuill integration
that indeed uses JSNI. (Make sure to check out the source code, link on the right side)

Hope that helps you get some ideas and inspiration.

I don’t think JSNI will work for me because of some reasons but maybe I’ll try. But thank you for the hint about the Add-Ons! I hope I’ll find something usefull there and maybe see how it’s done.

Edit: I think the problem is the following: The executed chemdoodle javascript creates an html5 canvas element and puts it under the script element. This insertion/creation of the canvas element seems not to work (only in an iframe element like in Embedded). By now I’m able to call methods from the ChemDoodle lib (e.g. ChemDoodle.getVersion()) which works fine. But as I said the created canvas element just won’t be inserted in the DOM-tree.

I finally had time to work on this problem and figured it out. The solution is actually quite simple. The problem really was the dynamic injection/creation of the html5 canvas element.

My client-side widget now extends com.google.gwt.user.client.ui.HTML (which is nothing else than a div-element) and implements com.vaadin.terminal.gwt.client.Paintable of course. The trick is: I create and add a canvas element with
id
and
class
in the constructor


canvasElement = DOM.createElement("canvas");
canvasElement.setAttribute("id", "view");
canvasElement.setAttribute("class", "ChemDoodleWebComponent");
getElement().appendChild(canvasElement);

This canvas element can then be accessed by its
id
and gets manipulated with javascript calls. For example a simple JSNI call to initialize the canvase looks like:


public static native void createCanvas(float width, float height) /*-{
		$wnd.view = new $wnd.ChemDoodle.TransformCanvas3D('view', width,height);									
													}-*/;

These JSNI methods are then called from the updateFromUIDL. The ChemDoodle libs are inserted by declaring them in my widgetset.xml.