<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/css" href="/stylesheets/rss.css"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Depth-First: Tag ajax</title>
    <link>http://depth-first.com/articles/tag/ajax</link>
    <language>en-us</language>
    <ttl>40</ttl>
    <description>Walking the Web of Chemical Informatics</description>
    <item>
      <title>Anatomy of a Cheminformatics Web Application: Structure Cleanup in Java Molecular Editor</title>
      <description>&lt;p&gt;&lt;a href="http://rubyonrails.org"&gt;&lt;img src="http://depth-first.com/files/rails_logo.png" align="right" border="0"&gt;&lt;/img&gt;&lt;/a&gt;A very useful feature of many 2-D structure editors is a "clean" function that tidies up bond lengths and angles. &lt;a href="http://www.molinspiration.com/jme/"&gt;Java Molecular Editor&lt;/a&gt; (JME) is a lightweight 2-D editor that lacks this functionality. In this article, I'll describe a small Web application called "Cleanup" that adds a "clean" function to JME through Ajax and server-side programming, rather than directly extending JME itself. The technique described here differs somewhat from that described in a previous article on &lt;a href="http://depth-first.com/articles/2006/12/15/anatomy-of-a-cheminformatics-web-application-inchimatic"&gt;adding InChI support to JME with Ajax&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Cleanup in Action&lt;/h4&gt;

&lt;p&gt;Let's say Bob needs to draw the structure of the H&lt;sub&gt;1&lt;/sub&gt; antagonist &lt;a href="http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi?cid=2725"&gt;chlorpheniramine&lt;/a&gt; with JME. He mistakenly creates irregular bond angles at several points, but continues drawing anyway. His finished molecule looks like that shown below:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061218/screenshot_1.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Rather than starting over to beautify his molecule, Bob, simply presses the &lt;strong&gt;Clean Molecule&lt;/strong&gt; button. This produces a structure with much more aesthetically-pleasing atom coordinates:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061218/screenshot_2.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;If Bob needs to continue drawing at this point he can. In fact, he can press &lt;strong&gt;Clean Molecule&lt;/strong&gt; as many times as he wants to clean his structure at any time. Each time he presses the button, his structure is retained within the JME window.&lt;/p&gt;

&lt;h4&gt;Download and Prerequisites&lt;/h4&gt;

&lt;p&gt;Cleanup requires &lt;a href="http://rubyonrails.org"&gt;Ruby on Rails&lt;/a&gt; and &lt;a href="http://depth-first.com/articles/2006/10/30/agile-chemical-informatics-development-with-cdk-and-ruby-rcdk-0-3-0"&gt;Ruby CDK&lt;/a&gt;. Both of these libraries can be installed using the &lt;a href="http://rubygems.org/"&gt;RubyGems&lt;/a&gt; packaging system.&lt;/p&gt;

&lt;p&gt;A recent article described the small amount of system configuration required for &lt;a href="http://depth-first.com/articles/2006/09/25/cdk-the-ruby-way-rcdk-0-2-0"&gt;Ruby CDK on Linux&lt;/a&gt;. Another article showed how to install &lt;a href="http://depth-first.com/articles/2006/10/12/running-ruby-java-bridge-on-windows"&gt;Ruby CDK on Windows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="http://rubyforge.org/frs/download.php/15687/jme-cleanup-0.0.1.tar.gz"&gt;complete Cleanup source package&lt;/a&gt; can be downloaded from RubyForge. For convenience, a copy of JME is included with the distribution. The author, Peter Ertl, has kindly given permission for the bundled JME applet to be used with Cleanup. For other uses, consult the &lt;a href="http://www.molinspiration.com/jme/"&gt;JME homepage&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;Running Cleanup&lt;/h4&gt;

&lt;p&gt;After inflating the Cleanup archive, the following commands will start the server:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ cd jme-cleanup-0.0.1
$ ruby script/server
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;AMD64 Linux users will need to prepend a &lt;tt&gt;LD_PRELOAD&lt;/tt&gt; assignment to the &lt;tt&gt;script/server&lt;/tt&gt; invocation. On my system, which uses Sun's JDK, this looks like:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ cd jme-cleanup-0.0.1
$ LD_PRELOAD=/usr/java/jdk1.5.0_09/jre/lib/amd64/libzip.so ruby script/server
&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;After starting the Cleanup server, pointing your browser to &lt;a href="http://localhost:3000/editor/cleanup"&gt;http://localhost:3000/editor/cleanup&lt;/a&gt; will run the application.&lt;/p&gt;

&lt;h4&gt;How It Works: A Web Application in Two Parts&lt;/h4&gt;

&lt;p&gt;Cleanup is a Web application consisting of two main parts - one written for a Web server, and one written for a Browser client. These two components work together to achieve an effect that, to a user, is indistinguishable from extending the JME applet with Java.&lt;/p&gt;

&lt;p&gt;The first component consists of small Rails application that accepts a Molfile as input and produces a Molfile with re-assigned coordinates as output. A Rails Action, &lt;tt&gt;clean_structure&lt;/tt&gt; accepts a Molfile encoded as form data and produces a response Molfile with re-assigned coordinates.&lt;/p&gt;

&lt;p&gt;The second component of the Cleanup application is written in JavaScript and executed from within the Browser. Let's take a look:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;script language=&amp;quot;JavaScript&amp;quot;&amp;gt;

  /*
   * Returns the client-specific version of XMLHttpRequest
   */
  function createXHR()
  {
    var xhr;

    try
    {
      xhr = new ActiveXObject(&amp;quot;Msxml2.XMLHTTP&amp;quot;); // IE 5.0+
    }

    catch (e)
    {
      try
      {
        xhr = new ActiveXObject(&amp;quot;Microsoft.XMLHTTP&amp;quot;); // IE 5.0-
      }

      catch (E)
      {
        xhr = false;
      }
    }

    if (!xhr &amp;amp;&amp;amp; typeof XMLHttpRequest != 'undefined')
    {
      xhr = new XMLHttpRequest(); // every other browser
    }

    return xhr;  
  }

  function cleanStructure()
  {       
    var molfile = document.jme.molFile();
    var xhr = createXHR();

    xhr.open(&amp;quot;GET&amp;quot;, &amp;quot;clean_structure?molfile=&amp;quot; + encodeURIComponent(molfile));

    xhr.onreadystatechange=function()
    {
      if (xhr.readyState != 4) return;

      cleanMolfile = xhr.responseText;

      document.jme.readMolFile(cleanMolfile);
    }

    xhr.send(null);
  }
&amp;lt;/script&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/0976694085?ie=UTF8&amp;amp;tag=depthfirst-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0976694085"&gt;&lt;img border="0" src="http://depth-first.com/files/pragmatic_ajax.jpg" align="right" &gt;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=depthfirst-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0976694085" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;As you can see, the client side of Cleanup consists of two JavaScript functions, &lt;tt&gt;createXHR&lt;/tt&gt; and &lt;tt&gt;cleanStructure&lt;/tt&gt;.&lt;/p&gt;

&lt;p&gt;The purpose of &lt;tt&gt;createXHR&lt;/tt&gt; is to return a valid instance of the central Ajax JavaScript object, &lt;tt&gt;XMLHttpRequest&lt;/tt&gt;. This function is a standard idiom in Ajax programming, and many JavaScript toolkits eliminate the need to write it explicitly. The function is included here mainly for the purpose of illustration. Microsoft browsers define two different flavors of &lt;tt&gt;XMLHttpRequest&lt;/tt&gt;, and both differ from the flavor supported by every other browser. To take this browser-specific behavior into account, a series of try/catch blocks are used.&lt;/p&gt;

&lt;p&gt;The second function, &lt;tt&gt;cleanStructure&lt;/tt&gt; does all of the JME-specific work. After obtaining an instance of &lt;tt&gt;XMLHttpRequest&lt;/tt&gt;, a HTTP GET request is built from JME's molfile. Of course, the magic of this request is that it is &lt;em&gt;asynchronous&lt;/em&gt;; it will not block the browser while it is being processed. When the request is complete, the cleaned Molfile is read by JME.&lt;/p&gt;

&lt;p&gt;Through the coordinated action of both of Cleanup's components, the application gives the appearance that JME has cleaned its own structure.&lt;/p&gt;

&lt;h4&gt;So What?&lt;/h4&gt;

&lt;p&gt;Well-designed, rich functionality makes software interesting and useful. At the same time, users demand software that loads and responds quickly. Using the technique presented here, it's possible to satisfy both of these contradictory requirements. Delegating key tasks to a server obviates the need to transmit large Java libraries to clients. Instead, small Java libraries can be transmitted, and several small asynchronous requests will be processed along the way.&lt;/p&gt;

&lt;p&gt;Viewed from this perspective, the capabilities of a good Java applet take on a very different character from what many have become accustomed to. In particular, extensibility and a robust, text-based communication protocol become much more important than built-in features.&lt;/p&gt;

&lt;p&gt;For example, we could provide a much more consistent user experience if the &lt;strong&gt;Clean Molfile&lt;/strong&gt; button were contained inside the JME editor itself, instead of on the Web page. In a more general sense, we'd like JME to offer the option of defining custom buttons that can be assigned arbitrary actions. Because Java/JavaScript integration is very well-supported, these custom actions could actually be written in JavaScript.&lt;/p&gt;

&lt;h4&gt;Conclusions&lt;/h4&gt;

&lt;p&gt;Java applets have been much maligned of late, partly due to the realization that in many situations they can be replaced with Ajax. However, well-designed, small, and extensible Java applets can play a key role in certain kinds of Ajax applications such as the one described here. Future articles in this series will explore some more of the many possibilities.&lt;/p&gt;</description>
      <pubDate>Mon, 18 Dec 2006 15:15:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:9e354945-8529-4ef0-98ad-8cba4e1dfe0d</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/12/18/anatomy-of-a-cheminformatics-web-application-structure-cleanup-in-java-molecular-editor</link>
      <category>Web</category>
      <category>ajax</category>
      <category>java</category>
      <category>applet</category>
      <category>rails</category>
      <category>ruby</category>
      <category>2d</category>
      <category>cleanup</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Anatomy of a Cheminformatics Web Application: Ajaxifying Depict</title>
      <description>&lt;p&gt;&lt;a href="http://rubyonrails.org"&gt;&lt;img src="http://depth-first.com/files/rails_logo.png" align="right" border="0"&gt;&lt;/img&gt;&lt;/a&gt;The &lt;a href="http://depth-first.com/articles/2006/11/27/anatomy-of-a-cheminformatics-web-application-beautifying-depict"&gt;previous tutorial in this series&lt;/a&gt; showed some techniques for improving the appearance and usability of a simple cheminformatics Web application. That application, Depict, rendered color images of 2-D molecular structures when given a SMILES string. Still, something is missing. Wouldn't it be better if the application responded to individual keystrokes in the input field, rather than waiting for the user to hit the return key? In this tutorial, we'll see how to quickly accomplish this effect with a technology called "Ajax."&lt;/p&gt;

&lt;h4&gt;Downloads and Prerequisites&lt;/h4&gt;

&lt;p&gt;For this tutorial, you'll need &lt;a href="http://depth-first.com/articles/2006/10/30/agile-chemical-informatics-development-with-cdk-and-ruby-rcdk-0-3-0"&gt;Ruby CDK&lt;/a&gt; (RCDK). A recent article described the small amount of system configuration required for &lt;a href="http://depth-first.com/articles/2006/09/25/cdk-the-ruby-way-rcdk-0-2-0"&gt;RCDK on Linux&lt;/a&gt;. Another article showed how to install &lt;a href="http://depth-first.com/articles/2006/10/12/running-ruby-java-bridge-on-windows"&gt;RCDK on Windows&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In addition, you'll need to install &lt;a href="http://www.rubyonrails.org/down"&gt;Ruby on Rails&lt;/a&gt; - something that can be done through &lt;a href="http://docs.rubygems.org/"&gt;RubyGems&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The Rails application that this tutorial starts with can be downloaded from &lt;a href="http://depth-first.com/demo/20061127/depict-20061127.tar.gz"&gt;this link&lt;/a&gt;. If you'd rather start working directly with the version of Depict produced by applying the changes outlined in this tutorial, the full source code can be downloaded from &lt;a href="http://depth-first.com/demo/20061204/depict-20061204.tar.gz"&gt;this link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you'll be running Depict on an AMD64 Linux system, you'll need to prepend your invocation of &lt;tt&gt;script/server&lt;/tt&gt; with &lt;tt&gt;LD_PRELOAD&lt;/tt&gt;. For example, on my system running Sun's JVM, the full command looks like:&lt;/p&gt;

&lt;div class="console"&gt;
&lt;pre&gt;
$ LD_PRELOAD=/usr/java/jdk1.5.0_09/jre/lib/amd64/libzip.so ruby script/server
&lt;/pre&gt;
&lt;/div&gt;

&lt;h4&gt;A Brief Introduction to Ajax&lt;/h4&gt;

&lt;p&gt;When stripped down to its essentials, &lt;a href="http://ajaxian.com/"&gt;Ajax&lt;/a&gt; is nothing more than an asynchronous communication channel between Web browsers and Web servers. In the pre-Ajax model of client-server Web interactions, a browser would make a request to a server and then wait until getting a server response, which would take the form of a complete Web page. In the Ajax model, a browser makes a request to a server, continuing to function while the server generates a response, which takes the form of a small section of the page that gets replaced. For this reason, Ajax-enabled Web sites are far more application-like than the document-centric sites that preceded them.&lt;/p&gt;

&lt;h4&gt;Ajax Support in Rails&lt;/h4&gt;

&lt;p&gt;&lt;a href="http://www.amazon.com/gp/product/0977616630?ie=UTF8&amp;amp;tag=depthfirst-20&amp;amp;linkCode=as2&amp;amp;camp=1789&amp;amp;creative=9325&amp;amp;creativeASIN=0977616630"&gt;&lt;img border="0" src="http://depth-first.com/demo/20061127/0977616630.01._AA_SCMZZZZZZZ_V36350687_.jpg" align="right"&gt;&lt;/a&gt;&lt;img src="http://www.assoc-amazon.com/e/ir?t=depthfirst-20&amp;amp;l=as2&amp;amp;o=1&amp;amp;a=0977616630" width="1" height="1" border="0" alt="" style="border:none !important; margin:0px !important;" /&gt;Ajax is implemented in JavaScript using the &lt;tt&gt;HTMLHttpRequest&lt;/tt&gt; object, although working at this level can require a lot of code to do anything meaningful. Fortunately, Rails and other Web application frameworks provide high-level interfaces to Ajax. In Rails, Ajax support takes the form of a variety of helper methods, one of which we'll use in this tutorial: &lt;tt&gt;observe_field&lt;/tt&gt;. This method, an instance of the &lt;a href="http://en.wikipedia.org/wiki/Observer_pattern"&gt;Observer Pattern&lt;/a&gt;, assigns an Observer to monitor input activity in a text field.&lt;/p&gt;

&lt;h4&gt;The Problem at Hand&lt;/h4&gt;

&lt;p&gt;We'd like Depict to provide immediate feedback by rendering a SMILES string as it is keyed into the input field. If the partial SMILES string is valid, it will be rendered, otherwise, an error image will be rendered. At no point will the user need to press the return key to see an image of the SMILES string they are typing.&lt;/p&gt;

&lt;h4&gt;Step 1: Ajaxify the View&lt;/h4&gt;

&lt;p&gt;Let's start by adding an observer to Depict's input field. These changes will occur to the SMILES View, contained in &lt;strong&gt;depict/app/views/smiles/depict.rhtml&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;html&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;Depict&amp;lt;/title&amp;gt;
    &amp;lt;%= stylesheet_link_tag &amp;quot;default&amp;quot;, :media =&amp;gt; &amp;quot;all&amp;quot; %&amp;gt;

    &amp;lt;!-- Nothing works without this line. --&amp;gt;
    &amp;lt;%= javascript_include_tag :defaults %&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;h1&amp;gt;Depict a SMILES String&amp;lt;/h1&amp;gt;

    &amp;lt;!-- New id attribute needed by Ajax --&amp;gt;
    &amp;lt;div class=&amp;quot;image&amp;quot; id=&amp;quot;results&amp;quot; &amp;gt;
      &amp;lt;img src=&amp;quot;&amp;lt;%= image_for_smiles :smiles =&amp;gt; @smiles %&amp;gt;&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;br /&amp;gt;&amp;lt;br /&amp;gt;
      &amp;lt;div class=&amp;quot;smiles&amp;quot;&amp;gt;
      &amp;lt;%= form_tag :action=&amp;gt;'depict' %&amp;gt;
        &amp;lt;label&amp;gt;SMILES: &amp;lt;/label&amp;gt;

        &amp;lt;!-- Ajaxified text field. --&amp;gt;
        &amp;lt;!-- We turn off autocomplete to simplfify the interface. --&amp;gt;
        &amp;lt;%= text_field_tag :smiles, @smiles, {:autocomplete =&amp;gt; &amp;quot;off&amp;quot;} %&amp;gt;
        &amp;lt;%= observe_field( :smiles,
                           :frequency =&amp;gt; 0.5,
                           :update    =&amp;gt; :results,
                           :url       =&amp;gt; { :action =&amp;gt; :ajax_depict } ) %&amp;gt;
      &amp;lt;%= end_form_tag %&amp;gt;
      &amp;lt;/div&amp;gt;
  &amp;lt;/body&amp;gt;

  &amp;lt;div class=&amp;quot;about&amp;quot;&amp;gt;
    &amp;lt;!-- Update the URL to point to the new Depth-First article --&amp;gt;
    &amp;lt;a href=&amp;quot;http://depth-first.com/articles/2006/12/04/anatomy-of-a-cheminformatics-web-application-ajaxifying-depict&amp;quot;&amp;gt;About this Application&amp;lt;/a&amp;gt;
  &amp;lt;/div&amp;gt;
&amp;lt;/html&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The above code introduces three key elements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The &lt;tt&gt;javascript_include_tag&lt;/tt&gt; method is called, which is surprisingly easy to forget to do.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The original &lt;tt&gt;text_field&lt;/tt&gt; method call is replaced by &lt;tt&gt;text_field_tag&lt;/tt&gt; to simplify coding. We disable browser-based autocompletion by setting the &lt;tt&gt;autocomplete&lt;/tt&gt; attribute to &lt;tt&gt;off&lt;/tt&gt;. This removes a feature unlikely to ever be used, and leads to a more streamlined interface.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;tt&gt;observe_field&lt;/tt&gt; method is called, linking activity in the text field to an Ajax action, &lt;tt&gt;ajax_depict&lt;/tt&gt;, that will update the image area. To accomplish this, we assign the &lt;tt&gt;div&lt;/tt&gt; containing our image the id "results."&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Making these changes and refreshing the browser window gives a screen like the one below:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061204/step_1_1.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;Although the client side of the Ajax communication channel is working, the server side is not. Let's fix that.&lt;/p&gt;

&lt;h4&gt;Step 2: Ajaxify the Server&lt;/h4&gt;

&lt;p&gt;Depict needs an Action and View that will be invoked in response to keyboard events in the SMILES input box. To do this, first add a new &lt;tt&gt;ajax_depict&lt;/tt&gt; method to &lt;tt&gt;SmilesController&lt;/tt&gt;, the source for which is found in &lt;strong&gt;depict/app/controllers/smiles_controller.rb&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;class &lt;/span&gt;&lt;span class="class"&gt;SmilesController&lt;/span&gt; &lt;span class="punct"&gt;&amp;lt;&lt;/span&gt; &lt;span class="constant"&gt;ApplicationController&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;depict&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:smiles&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
      &lt;span class="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:smiles&lt;/span&gt;&lt;span class="punct"&gt;][&lt;/span&gt;&lt;span class="symbol"&gt;:value&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="keyword"&gt;else&lt;/span&gt;
      &lt;span class="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;image_for&lt;/span&gt;
    &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:bytes&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
      &lt;span class="ident"&gt;send_data&lt;/span&gt;&lt;span class="punct"&gt;(&lt;/span&gt;&lt;span class="ident"&gt;flash&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:bytes&lt;/span&gt;&lt;span class="punct"&gt;],&lt;/span&gt; &lt;span class="symbol"&gt;:type&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;image/png&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="symbol"&gt;:disposition&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;inline&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;,&lt;/span&gt; &lt;span class="symbol"&gt;:filename&lt;/span&gt; &lt;span class="punct"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="punct"&gt;&amp;quot;&lt;/span&gt;&lt;span class="string"&gt;&lt;span class="expr"&gt;#{flash[:smiles]}&lt;/span&gt;.png&lt;/span&gt;&lt;span class="punct"&gt;&amp;quot;)&lt;/span&gt;
    &lt;span class="keyword"&gt;end&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;

  &lt;span class="comment"&gt;# The new ajax_depict method.&lt;/span&gt;
  &lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;ajax_depict&lt;/span&gt;
    &lt;span class="attribute"&gt;@smiles&lt;/span&gt;&lt;span class="punct"&gt;=&lt;/span&gt;&lt;span class="ident"&gt;request&lt;/span&gt;&lt;span class="punct"&gt;.&lt;/span&gt;&lt;span class="ident"&gt;raw_post&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Making the above changes and refreshing your browser should give an error message:&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061204/step_2_1.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The new &lt;tt&gt;ajax_depict&lt;/tt&gt; method is being called, but no associated template exits. This template contains the HTML that will be inserted into the &lt;tt&gt;div&lt;/tt&gt; with the &lt;tt&gt;results&lt;/tt&gt; id attribute that we set up in Step 1. We can resolve the error we're getting by simply creating a new file (&lt;strong&gt;depict/app/views/smiles/ajax_depict.rhtml&lt;/strong&gt;) containing the following partial template:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;&amp;lt;img src=&amp;quot;&amp;lt;%= image_for_smiles :smiles =&amp;gt; @smiles %&amp;gt;&amp;quot;&amp;gt;&amp;lt;/img&amp;gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, refreshing your browser should produce a screen like that shown below. We have now Ajaxified Depict, but we're not quite done yet.&lt;/p&gt;

&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061204/step_2_2.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;h4&gt;Step 3: Update the Cascading Style Sheet&lt;/h4&gt;

&lt;p&gt;As you type a SMILES string into the input window, you may have noticed the input box being repositioned toward the top of the application window just prior to the display of a new image. This is due to the image area being resized to zero height as the new image is generated.&lt;/p&gt;

&lt;p&gt;Fortunately, the fix is simple; we'll just specify that the image area must be 400 pixels high, whether an image is being displayed or not. This is done by editing the &lt;tt&gt;image&lt;/tt&gt; selector in the CSS file at &lt;strong&gt;depict/public/stylesheets/default.css&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_default "&gt;.image {
    margin-left: auto;
    margin-right: auto;
    width: 400px;
    /* Keeps the input box from moving during image refresh.*/
    height: 400px;
}&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Refreshing the Depict window should now give a statically-positioned SMILES input field.&lt;/p&gt;

&lt;h4&gt;Step 4: Backward Compatibility&lt;/h4&gt;

&lt;p&gt;As it stands, if the user presses the return key, they will see the "Enter SMILES Below" message. This is due to the change in the way SMILES strings are transmitted into the application. To fix this problem, we simply change the way that &lt;tt&gt;SmilesController&lt;/tt&gt; assigns the &lt;tt&gt;smiles&lt;/tt&gt; instance variable (&lt;strong&gt;depict/app/controllers/smiles_controller.rb&lt;/strong&gt;):&lt;/p&gt;

&lt;div class="typocode"&gt;&lt;pre&gt;&lt;code class="typocode_ruby "&gt;&lt;span class="keyword"&gt;def &lt;/span&gt;&lt;span class="method"&gt;depict&lt;/span&gt;
  &lt;span class="comment"&gt;# Uses new input method.&lt;/span&gt;
  &lt;span class="keyword"&gt;if&lt;/span&gt; &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:smiles&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
    &lt;span class="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="ident"&gt;params&lt;/span&gt;&lt;span class="punct"&gt;[&lt;/span&gt;&lt;span class="symbol"&gt;:smiles&lt;/span&gt;&lt;span class="punct"&gt;]&lt;/span&gt;
  &lt;span class="keyword"&gt;else&lt;/span&gt;
    &lt;span class="attribute"&gt;@smiles&lt;/span&gt; &lt;span class="punct"&gt;=&lt;/span&gt; &lt;span class="punct"&gt;'&lt;/span&gt;&lt;span class="string"&gt;&lt;/span&gt;&lt;span class="punct"&gt;'&lt;/span&gt;
  &lt;span class="keyword"&gt;end&lt;/span&gt;
&lt;span class="keyword"&gt;end&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Making this change produces an interface that will render the correct image whether the return key is typed or not. If JavaScript is disabled, Depict will work exactly the same way as it did in the non-Ajax version.&lt;/p&gt;

&lt;h4&gt;Conclusions&lt;/h4&gt;

&lt;p&gt;Ajax makes the Web more attractive than ever as an application development platform. In this tutorial, we've seen how using Rails made it very easy to give Depict the feel of an interactive SMILES depiction tool using Ajax. But a few details remain before we're ready to deploy this application on a Web server for the public to use. For example, we need to take server load and network latency into account, and we need to make sure Depict works well on all major browsers. The next articles in this series will address these issues.&lt;/p&gt;</description>
      <pubDate>Mon, 04 Dec 2006 15:06:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:04460726-dd5b-40ce-aeb8-1b8f055932a8</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/12/04/anatomy-of-a-cheminformatics-web-application-ajaxifying-depict</link>
      <category>Tools</category>
      <category>depict</category>
      <category>rails</category>
      <category>cheminformatics</category>
      <category>2d</category>
      <category>integration</category>
      <category>ajax</category>
    </item>
    <item>
      <title>Look Ma, No Applets!</title>
      <description>&lt;p&gt;&lt;center&gt;&lt;img src="http://depth-first.com/demo/20061109/webme.png"&gt;&lt;/img&gt;&lt;/center&gt;&lt;/p&gt;

&lt;p&gt;The state of the art in structure editors for chemical Web services is Java applets. Although closed editors have long dominated this field, &lt;a href="http://depth-first.com/articles/2006/08/21/four-free-2-d-structure-editors-for-web-applications"&gt;Open Source editors&lt;/a&gt; are a possibly viable option. Java applets are great from a developer's perspective. But applets are avoided by some end users and IT support for their underlying need to install a Java plug-in of some kind and long startup times.&lt;/p&gt;

&lt;p&gt;Through David Bradly's &lt;a href="http://www.sciencebase.com/science-blog/chemists-escape-browser-lock-down.html"&gt;sciencebase&lt;/a&gt;, I came across a non-Java solution to the structure editor problem. The software is called &lt;a href="http://www.molinspiration.com/products/webme/"&gt;WebME&lt;/a&gt;. WebME looks and feels similar to &lt;a href="http://www.molinspiration.com/jme/"&gt;Java Molecular Editor&lt;/a&gt;. It loads quickly and provides a clean, inviting user interface. It should work in any modern browser. Most interesting of all, WebME works without a browser plugin of any kind.&lt;/p&gt;

&lt;p&gt;The magic behind WebME is AJAX, which has been summarized by Paul Graham as &lt;a href="http://paulgraham.com/web20.html"&gt;"Javascript now works"&lt;/a&gt;. By asynchronously interacting with a Web server as user interface events occur, WebME is able to cram a lot of functionality into a relatively small deployment package. The user interface is written in a mixture of HTML and JavaScript, thus eliminating the need for Java.&lt;/p&gt;

&lt;p&gt;Although WebME's use of AJAX is innovative, other non-Java solutions to the structure editor problem have also been implemented. For example, &lt;a href="http://pubchem.ncbi.nlm.nih.gov/"&gt;PubChem&lt;/a&gt; have developed an editor in JavaScript/HTML for use with their popular service.&lt;/p&gt;

&lt;p&gt;Despite its advantages, the AJAX approach does involve some trade-offs. For example, WebME is not nearly as responsive as, say, JME. I would imagine that unusually high network latency could further erode WebME's responsiveness. Furthermore, the subtle visual cues that make JME a productive tool, such as highlighting the node or edge the cursor is about to edit, are non-existent. It's unclear if this is a limitation of this particular version of WebME I used or the underlying technology.&lt;/p&gt;

&lt;p&gt;AJAX is a promising new technology that may well have a place in producing ergonomic user interfaces for chemistry Web services. On the other hand, it wasn't too long ago that JavaScript "didn't work", was loathed, or simply ignored altogether. It may well be that Java applets undergo a revival similar to that of JavaScript, perhaps triggered by built-in support for applets made possible through an &lt;a href="http://java.sun.com/developer/technicalArticles/Interviews/gosling_os1_qa.html"&gt;open source Java implementation&lt;/a&gt;. Regardless of how Java applet technology evolves, WebME's approach is worth serious consideration.&lt;/p&gt;</description>
      <pubDate>Thu, 09 Nov 2006 14:28:00 +0000</pubDate>
      <guid isPermaLink="false">urn:uuid:35a9ed1c-b1db-4538-ad05-6736318ec237</guid>
      <author>Rich Apodaca</author>
      <link>http://depth-first.com/articles/2006/11/09/look-ma-no-applets</link>
      <category>Tools</category>
      <category>webme</category>
      <category>ajax</category>
      <category>javascript</category>
      <category>applets</category>
      <category>editor</category>
    </item>
  </channel>
</rss>
