<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  
  <title>Jérémi Joslin's blog</title>
  
    <updated>2010-11-21T20:30:11Z</updated>
  
  <id>http://blog.jeremi.info/</id>
  <link rel="alternate" href="http://blog.jeremi.info/" title="Jérémi Joslin's blog" type="text/html"/>
  <link rel="self" href="http://blog.jeremi.info/feed" title="Jérémi Joslin's blog" type="application/atom+xml"/>
  <link rel="license" type="application/rdf+xml" href="http://creativecommons.org/licenses/by/3.0/rdf"/>

  <author><name>Jérémi Joslin's blog</name></author>
  
    <entry>
      <id>http://blog.jeremi.info/entry/my-git-workflow-to-deploy-an-application-to-appengine</id>
      <title type="text">My git workflow to deploy an application to appengine</title>
      <link href="http://blog.jeremi.info/entry/my-git-workflow-to-deploy-an-application-to-appengine" rel="alternate" type="text/html"/>
      <updated>2010-11-21T20:30:11Z</updated>
      <published>2010-11-21T20:30:11Z</published>
      <category term="git" label="git" /><category term="appengine" label="appengine" /><category term="fabric" label="fabric" /><category term="workflow" label="workflow" /><category term="production" label="production" />
      <content type="xhtml" xml:base="http://blog.jeremi.info/">
	<div xmlns="http://www.w3.org/1999/xhtml"><p>my workflow to deploy an application to appengine using git</p>

<p>I've been using git for nearly 2 years. I love it. It's so extensible that you can easily map it to your own workflow.</p>

<p>I've recently been working on a contextual gadget for Gmail. The problem with contextual gadget is that it's not easy to test it outside of Gmail. So you need to have an easy and quick way to deploy your app. I wanted also to have a way to easily manage my staging and production environment. For this purpose I wrote a script using <a href="http://docs.fabfile.org/">fabric</a> that is making it easy to manage the different versions (staging, prod and their history). I'm now using it for all my appengine deployment.</p>

<p>For the staging environment, I'm just using a staging version of the application with <a href="http://code.google.com/appengine/docs/python/multitenancy/multitenancy.html">App Engine Mulitenancy</a>. In some case, you might want to use a totally different application, It's easy to change.</p>

<p>so here is a typical use :</p>

<pre class="prettyprint">
$ git commit -m "blah blah"
$ fab deploy # this is tagging the version and deploying to staging
$ fab last_tag # this give me the last tag deployed on staging
$ fab production last_tag # this give me the last tag deployed on production
$ fab production deploy:staging-2010-11-15.015 # this deploy the version tagged staging-2010-11-15.015 to production and tag this version with a production tag
</pre>

<p>If you want to play with it as well, check it out on github and fork it :</p>

<script src="https://gist.github.com/663181.js"> </script>
</div>
      </content>
    </entry>
  
    <entry>
      <id>http://blog.jeremi.info/entry/how-to-activate-groovy-rest-services-in-gatein-beta5</id>
      <title type="text">How to activate groovy REST services in GateIn Beta5</title>
      <link href="http://blog.jeremi.info/entry/how-to-activate-groovy-rest-services-in-gatein-beta5" rel="alternate" type="text/html"/>
      <updated>2010-04-29T09:38:07Z</updated>
      <published>2010-02-16T02:20:00Z</published>
      <category term="groovy" label="groovy" /><category term="REST" label="REST" /><category term="gatein" label="gatein" />
      <content type="xhtml" xml:base="http://blog.jeremi.info/">
	<div xmlns="http://www.w3.org/1999/xhtml"><p>By default GateIn come with an implementation of <a href="https://jsr311.dev.java.net/">JAX-RS(JSR-311)</a>. You can write your REST services in java using this spec, and deploy your jar in GateIn. But at eXo, system admins don't let us access to the filesystem of the GateIn servers in the cloud, so it's not an option. But we can write our services in groovy and deploy them in the portal without having to restart the portal or access to the filesystem, and this, admin sys let us do it.</p>

<p><b>UPDATE: This is no more needed since  GateIn 3.0-GA</b></p>

<p>In it's Beta5 version, GateIn doesn't come with the needed configuration to be able to deploy groovy REST services.</p>

<ul>
    <li>Download <a href="http://www.jboss.org/gatein/downloads.html">GateIn</a> (I'm going to use the tomcat version on this article)</li>
    <li>Start it a first time to decompress the war and stop it (<em>./bin/gatein.sh run</em>)</li>
    <li>Add the jar <a href="http://repository.jboss.com/maven2/org/exoplatform/core/exo.core.component.script.groovy/2.3.0-Beta05/exo.core.component.script.groovy-2.3.0-Beta05.jar">exo.core.component.script.groovy-2.3.0-Beta05.jar</a> to the lib directory of your tomcat</li>
    <li>Edit repository-configuration.xml (webapps/portal/WEB-INF/conf/jcr/repository-configuration.xml) to add a JCR Workspace to store the files  and name it "groovy-rest" (if you don't want to do it yourself, copy this file: <a href="http://dl.dropbox.com/u/760234/blog.jeremi.info/how-to-activate-groovy-rest-services-in-gatein-beta5/repository-configuration.xml">repository-configuration.xml</a>)</li>
    <li>In the file "webapps/portal/WEB-INF/conf/jcr/jcr-configuration.xml", at the end of the file after the tag "" insert(if you don't want to do it yourself, copy this file: <a href="http://dl.dropbox.com/u/760234/blog.jeremi.info/how-to-activate-groovy-rest-services-in-gatein-beta5/jcr-configuration.xml">jcr-configuration.xml</a>):
<pre class="prettyprint lang-xml">&lt;component&gt;
  &lt;type&gt;org.exoplatform.services.jcr.ext.script.groovy.GroovyScript2RestLoader&lt;/type&gt;
  &lt;init-params&gt;
    &lt;object-param&gt;
      &lt;name&gt;observation.config&lt;/name&gt;
      &lt;object type="org.exoplatform.services.jcr.ext.script.groovy.ObservationListenerConfiguration"&gt;
        &lt;field name="repository"&gt;
          &lt;string&gt;repository&lt;/string&gt;
        &lt;/field&gt;
        &lt;field name="workspaces"&gt;
          &lt;collection type="java.util.ArrayList"&gt;
            &lt;value&gt;
              &lt;string&gt;groovy-rest&lt;/string&gt;
            &lt;/value&gt;
          &lt;/collection&gt;
        &lt;/field&gt;
      &lt;/object&gt;
    &lt;/object-param&gt;
  &lt;/init-params&gt;
&lt;/component&gt;</pre>
</li>
    <li>Remove the directory temp to force the creation of the new workspace: rm -rf temp/</li>
</ul>

<p><strong>Your GateIn is now ready to deploy groovy REST service.</strong></p>

<p>Let's write our first REST service called test.groovy:</p>

<pre class="prettyprint lang-java">// simple groovy script
import javax.ws.rs.Path
import javax.ws.rs.GET
import javax.ws.rs.PathParam

@Path("pub")
public class HelloWorld {
  @GET
  @Path("helloworld/{name}")
  public String hello(@PathParam("name") String name) {
    return "Hello $name\n"
  }
}</pre>

<p>To push this script, we simply have to do a POST on our server. We want our script to be loaded automatically so we add "autoload=true". Here is how to do with <a href="http://curl.haxx.se/">CURL</a>:</p>

<pre>$ curl -u root:gtn -X POST -F "file=@test.groovy;name=test" -F "autoload=true" http://localhost:8080/rest/private/script/groovy/add/repository/groovy-rest/test.groovy
$</pre>

<p>the URL is composed as :</p>

<ul>
    <li>http://localhost:8080: The url of our server</li>
    <li>/rest/private/: The private access of the REST API</li>
    <li>script/groovy/add: The name of the webservice we acces</li>
    <li>repository/groovy-rest/: our repository name followed by the workspace name</li>
    <li>test.groovy: The path to our groovy service</li>
</ul>

<p>You can test your service:</p>

<pre>$ curl http://localhost:8080/rest/pub/helloworld/jeremiHello jeremi
$</pre>

<p>the URL is composed as :</p>

<ul>
    <li>http://localhost:8080: The url of our server</li>
    <li>rest: The public access of the REST API</li>
    <li>pub: The @Path of our class</li>
    <li>helloworld: the @Path of our function</li>
    <li>jeremi: the parameter of our function</li>
</ul>

<p>To undeploy your service:</p>

<pre>$ curl -u root:gtn -X POST http://localhost:8080/rest/private/script/groovy/load/repository/groovy-rest/test.groovy?state=false</pre>

<p>If you want to make it easier to manage your groovy files I wrote a simple wrapper around the REST API used here: <a href="http://github.com/jeremi/gatein-groovy-tools">gatein-groovy-tools</a>.
To update your code:</p>

<pre>$ exo.groovy update
PUSHING: test.groovy
$</pre>

<p>Resources:</p>

<ul>
        <li><a href="http://www.jboss.org/gatein/downloads.html">Download GateIn</a></li>
    <li><a href="http://github.com/jeremi/gatein-groovy-tools">gatein-groovy-tools</a> (<a href="http://github.com/jeremi/gatein-groovy-tools/archives/master">Download</a>)</li>
    <li><a href="http://wiki.exoplatform.org/xwiki/bin/view/WS/Groovy+Scripts+as+REST+Services">Groovy Scripts as REST Services</a></li>
    <li><a href="http://curl.haxx.se/download.html">Download CURL</a></li>
</ul>
</div>
      </content>
    </entry>
  
    <entry>
      <id>http://blog.jeremi.info/entry/jax-rs-service-to-proxy-an-http-request-in-groovy</id>
      <title type="text">JAX-RS service to proxy an HTTP request in groovy</title>
      <link href="http://blog.jeremi.info/entry/jax-rs-service-to-proxy-an-http-request-in-groovy" rel="alternate" type="text/html"/>
      <updated>2010-01-26T14:24:32Z</updated>
      <published>2010-01-26T08:49:05Z</published>
      <category term="groovy" label="groovy" /><category term="REST" label="REST" /><category term="eXo IDE" label="eXo IDE" /><category term="code" label="code" />
      <content type="xhtml" xml:base="http://blog.jeremi.info/">
	<div xmlns="http://www.w3.org/1999/xhtml"><p>I needed a simple way to proxy an HTTP request and add an authorization header to it, so I created a REST service using <a href="https://jsr311.dev.java.net/">JAX-RS</a> and using groovy to call the server. I put the code on our eXo server thanks to eXo IDE, and click deploy and that's it :)</p>

<p>If you need something similar, here is the code:</p>

<pre class="prettyprint lang-java">
import javax.ws.rs.Path
import javax.ws.rs.POST
import javax.ws.rs.FormParam

@Path("proxy")
public class Proxy {
  @POST
  @Path("basic_auth")
  public String basic_auth(@FormParam("url") String url, @FormParam("login") String login,
                      @FormParam("password") String password) {
    def encoded = "$login:$password".getBytes().encodeBase64().toString()
    def c= new URL(url).openConnection()
    c.setRequestProperty("Authorization", "Basic $encoded")
    return c.content.text
  }
}
</pre>

<p>To test it:</p>

<pre>
curl -d "url=http://TheUrl.com/test&amp;login=my_login&amp;password=my_pwd" \
http://YourDomain.com/rest/proxy/basic_auth/
</pre>
</div>
      </content>
    </entry>
  
    <entry>
      <id>http://blog.jeremi.info/entry/open-source-sonar-gadget-for-the-enterprise-portal-gatein</id>
      <title type="text">Open source Sonar Gadget for the Enterprise Portal GateIn</title>
      <link href="http://blog.jeremi.info/entry/open-source-sonar-gadget-for-the-enterprise-portal-gatein" rel="alternate" type="text/html"/>
      <updated>2010-01-26T13:26:03Z</updated>
      <published>2010-01-25T03:32:37Z</published>
      <category term="sonar" label="sonar" /><category term="gadget" label="gadget" /><category term="code" label="code" /><category term="gatein" label="gatein" />
      <content type="xhtml" xml:base="http://blog.jeremi.info/">
	<div xmlns="http://www.w3.org/1999/xhtml"><p>I published a new set of gadgets for Sonar on Github. You can add them to your GateIn or Jira Dashboard. This gadget does not need you to deploy anything else to work. You can directly install them from <a href="http://exogadgets.appspot.com/">Google AppSpot</a>.</p>

<p>Technically, nothing complex so it's a good example to look at the code to learn how to integrate third party application. Sonar has a simple <a href="http://docs.codehaus.org/display/SONAR/Web+Service+API">webservice API</a> that made it easy to reuse the code between the gadgets.  The only thing I did not find how to do is how to know when the tendency of a metric should be red or green.</p>

<p>I created a file called sonar.js that is reused among all the gadgets. The sonar object simplifies the call to the API. It sends a request to the API of sonar through the gadget proxy to get the data:</p>

<pre class="prettyprint lang-js">
sonar.GetMetrics = function(metrics, callback, extras) {
    var prefs = new gadgets.Prefs(), params = {}, url, key;
    url = prefs.getString("sonar_url") + "api/resources?format=json&amp;resource=" + prefs.getString("sonar_project") + "&amp;metrics=" + metrics + "&amp;time=" + new Date().getTime();

    //if there is any extra parameters, we add them to the URL
    for (key in extras) {
        url = url + "&amp;" + key + "=" + extras[key];
    }

    //We want to get the result as a JSON object
    params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON;
    //We send the request
    // It will call the function callback when the data will be loaded with the result in parameter
    gadgets.io.makeRequest(url, callback, params);
};
</pre>

<p>After, the callback fill-in an html template with the data:</p>

<pre class="prettyprint lang-js">
function update_metrics() {
    sonar.GetMetrics("ncloc,lines,classes,packages,functions,accessors", function(res) {
        var resource = res.data[0];

        //Add the information about the project in the template
        $("#resource_name").text(resource.name);
        $("#resource_description").text(resource.description);

        for (var i = 0; i &lt; resource.msr.length; i++) {
            var metric = resource.msr[i];
            //update the values in the template
            $("#m_" + metric.key).text(metric.frmt_val);
        }
        gadgets.window.adjustHeight($(document).height());
    }, {includetrends: "true"});
}
</pre>

<p>I did not implement all the possible gadgets for sonar, I invite you to take the code, and create your own. You can reuse sonar.js that handle the request to the sonar server and the preferences. Have a look at the gadget of the <a href="http://github.com/jeremi/sonar-gadget/blob/master/gadget-code-overview.xml">code overview</a>, it's the easiest one.</p>

<p>Sonar Gadget in GateIn Dashboard:<br />
<a href="http://www.flickr.com/photos/jeremi/4291994637/" title="sonar Gadget in GateIn Dashboard"><img src="http://farm5.static.flickr.com/4034/4291994637_6a8c85c2e7.jpg" width="500" height="278" alt="sonar Gadget in GateIn Dashboard" /></a></p>

<p>Sonar Gadget in Jira4:<br />
<a href="http://www.flickr.com/photos/jeremi/4292736424/" title="sonar Gadget in Jira4"><img src="http://farm5.static.flickr.com/4028/4292736424_179f11e88f.jpg" width="500" height="259" alt="sonar Gadget in Jira4 Dashboard" /></a></p>

<p>Links:</p>

<ul>
<li><a href="http://exogadgets.appspot.com/">test the gadgets</a></li>
<li><a href="http://github.com/jeremi/sonar-gadget/archives/master">Download</a></li>
<li><a href="http://github.com/jeremi/sonar-gadget">Fork the code on github</a> (and send me pull request to integrate your updates)</li>
<li><a href="http://www.opensocial.org/Technical-Resources/opensocial-spec-v09/Gadgets-API-Specification.html">Gadget specs</a></li>
</ul>
</div>
      </content>
    </entry>
  
    <entry>
      <id>http://blog.jeremi.info/entry/notes-about-build-the-enterprise-portal-gatein</id>
      <title type="text">Notes about building the enterprise portal GateIn from source</title>
      <link href="http://blog.jeremi.info/entry/notes-about-build-the-enterprise-portal-gatein" rel="alternate" type="text/html"/>
      <updated>2010-01-26T13:27:18Z</updated>
      <published>2010-01-16T11:08:29Z</published>
      <category term="build" label="build" /><category term="gatein" label="gatein" />
      <content type="xhtml" xml:base="http://blog.jeremi.info/">
	<div xmlns="http://www.w3.org/1999/xhtml"><p>I's been nearly a year since the last time I build <strong>eXo Portal (now GateIn)</strong>. The Building process is way easier now!</p>

<p>Get the sources:</p>

<pre class="prettyprint lang-sh">
$ svn co http://anonsvn.jboss.org/repos/gatein/portal/trunk/ portal
</pre>

<p>Follow the instructions of  the README.txt.</p>

<p>You will need to :</p>

<ul>
<li>download <a href="http://tomcat.apache.org/download-60.cgi">tomcat</a></li>
<li>install <a href="http://www.apache.org/dyn/closer.cgi/maven/binaries/apache-maven-2.2.1-bin.tar.gz">maven 2.2.1</a></li>
</ul>

<p>I had error during the build:</p>

<pre>
 Embedded error: Error while executing the compiler.
 Java heap space
 </pre>

<p>Just increase the memory to 512 (or 1024):</p>

<pre class="prettyprint lang-sh">
$ set MAVEN_OPTS=-Xmx512m
 </pre>

<p>Go grab a coffee (or multiple), the build is long, very long (specially with my Chinese connection).</p>

<p>when the build is finish, the tomcat is in "packaging/pkg/target/tomcat/"</p>

<p>just type :</p>

<pre class="prettyprint lang-sh">
$ cd packaging/pkg/target/tomcat/
$ ./bin/gatein.sh run
 </pre>

<p>and go to <a href="http://localhost:8080/portal/">http://localhost:8080/portal/</a>.</p>
</div>
      </content>
    </entry>
  
    <entry>
      <id>http://blog.jeremi.info/entry/storing-data-in-cookies-in-a-secure-manner</id>
      <title type="text">Storing data in cookies in a secure manner</title>
      <link href="http://blog.jeremi.info/entry/storing-data-in-cookies-in-a-secure-manner" rel="alternate" type="text/html"/>
      <updated>2010-01-26T13:28:01Z</updated>
      <published>2010-01-12T20:34:16Z</published>
      <category term="python" label="python" /><category term="code" label="code" /><category term="tornado" label="tornado" />
      <content type="xhtml" xml:base="http://blog.jeremi.info/">
	<div xmlns="http://www.w3.org/1999/xhtml"><p>Having an hour to kill at starbucks without internet, I'm giving a look at the code of <a href="http://www.tornadoweb.org/">Tornado</a> (framework made by the guys of friendfeed). I discovered something quite interesting: the secure cookie.</p>

<p>The concept of the secure cookie is instead of storing data in the session (usually stored in a database as by default in Django) storing the data in a cookie. But, you will tell me it's not secure, anyone can change the value and, for example, see the website with the id of another user. So to make sure the user can't change (or if he does, we can detect it), they sign the request with a secret key. Every time we want to get the value, they check if the signature is valid. The value is stored in clear, so don't store anything a user should not view.</p>

<p>The cookie will look like this:</p>

<pre>
uid=1234|1234567890|d32b9e9c67274fa062e2599fd659cc14
</pre>

<p>Parts:</p>

<ol>
<li>uid is the name of the key</li>
<li>1234 is your value in clear</li>
<li>1234567890 is the timestamp</li>
<li>d32b9e9c67274fa062e2599fd659cc14 is the signature made from the value and the timestamp</li>
</ol>

<p>The interesting code (from Tornado's web.py):</p>

<pre class="prettyprint lang-py">
def set_secure_cookie(self, name, value, expires_days=30, **kwargs):
    """Signs and timestamps a cookie so it cannot be forged.

    You must specify the 'cookie_secret' setting in your Application
    to use this method. It should be a long, random sequence of bytes
    to be used as the HMAC secret for the signature.

    To read a cookie set with this method, use get_secure_cookie().
    """
    timestamp = str(int(time.time()))
    value = base64.b64encode(value)
    signature = self._cookie_signature(value, timestamp)
    value = "|".join([value, timestamp, signature])
    self.set_cookie(name, value, expires_days=expires_days, **kwargs)

def get_secure_cookie(self, name):
    """Returns the given signed cookie if it validates, or None."""
    value = self.get_cookie(name)
    if not value: return None
    parts = value.split("|")
    if len(parts) != 3: return None
    if self._cookie_signature(parts[0], parts[1]) != parts[2]:
        logging.warning("Invalid cookie signature %r", value)
        return None
    timestamp = int(parts[1])
    if timestamp &lt; time.time() - 31 * 86400:
        logging.warning("Expired cookie %r", value)
        return None
    try:
        return base64.b64decode(parts[0])
    except:
        return None

def _cookie_signature(self, *parts):
    self.require_setting("cookie_secret", "secure cookies")
    hash = hmac.new(self.application.settings["cookie_secret"],
                    digestmod=hashlib.sha1)
    for part in parts: hash.update(part)
    return hash.hexdigest()
</pre>

<p>The main use I see for this is to scale. if you don't need to store a lot of things in your session, you can store it in a cookie, so you have one request less to the session store (database or server). Also, you can add easily new server without problem of session replication.</p>

<p><strong>What do you think about this?</strong></p>
</div>
      </content>
    </entry>
  
    <entry>
      <id>http://blog.jeremi.info/entry/creating-a-chart-with-raphael-js-from-a-google-spreadsheet</id>
      <title type="text">Creating a chart with raphael.js from a google spreadsheet</title>
      <link href="http://blog.jeremi.info/entry/creating-a-chart-with-raphael-js-from-a-google-spreadsheet" rel="alternate" type="text/html"/>
      <updated>2010-01-26T13:28:55Z</updated>
      <published>2010-01-05T18:10:34Z</published>
      <category term="raphael.js" label="raphael.js" /><category term="code" label="code" /><category term="google" label="google" /><category term="spreadsheet" label="spreadsheet" /><category term="atom" label="atom" />
      <content type="xhtml" xml:base="http://blog.jeremi.info/">
	<div xmlns="http://www.w3.org/1999/xhtml"><p>We want to get data from a google spreadsheet and display it as a chart using <a href="http://g.raphaeljs.com/">gRaphaël</a>. We are going to transform the following spreadsheet into a bar graph.</p>

<p><img src="http://farm5.static.flickr.com/4069/4248489126_51229eb137_o.jpg" alt="example of graph made with graphael" /></p>

<iframe width='600' height='250' frameborder='0' src='http://spreadsheets.google.com/pub?key=tiRm6cBSE3AZJnyLC6Wlysw&amp;output=html&amp;widget=true'></iframe>

<p>gRaphaël’s goal is to help you create stunning charts on your website. gRaphaël is based on <a href="http://www.raphaeljs.com/">raphael.js</a>. Raphael.js is a small JavaScript library that should simplify your work with vector graphics on the web. It currently supports Firefox 3.0+, Safari 3.0+, Opera 9.5+ and Internet Explorer 6.0+.</p>

<p>You can download the code of the sample at the end of this article.</p>

<h2>1. Loading data from a Google Spreadsheet in javascript</h2>

<p><a href="http://spreadsheets.google.com/">Google spreadsheet</a> offers to serve its data thanks to the <a href="http://code.google.com/apis/gdata/">Google Data Protocol</a>. The Gdata format that suite to our needs is <a href="http://en.wikipedia.org/wiki/JSON#JSONP">JSONP</a>. They call it <a href="http://code.google.com/apis/gdata/docs/json.html#Request"><em>JSON in script</em></a>. Basically, what we are going to do, is include a script tag in the page that point to the spreadsheet data and when the data is loaded, it will call a function with this data in parameter.</p>

<p><strong>1.1 Preparing our spreadsheet</strong></p>

<ul>
<li>Create a spreadsheet that look like <a href="http://spreadsheets.google.com/pub?key=tiRm6cBSE3AZJnyLC6Wlysw&amp;output=html">our</a> (2 columns: the first one contain the label, and the second one the data)</li>
<li>Save and publish the spreadsheet (Warning! Don't publish private data!)</li>
<li>Click on "More Publishing Options," change file format to ATOM &amp; generate URL</li>
<li>The URL should look something like 'http://spreadsheets.google.com/feeds/list/[spreadsheet<em>id]/[worksheet</em>id]/public/values.'</li>
<li>Find the parts of the URL that match the example below and keep them for the second part.</li>
</ul>

<p><strong>1.2 Loading the spreadsheet data</strong></p>

<pre class="prettyprint lang-js">
/*
 * Specify the information about our spreadsheet
 */
var spreadsheet_id = "tiRm6cBSE3AZJnyLC6Wlysw",
worksheet_id = "od6";

/*
 * Creates a script tag in the page that loads in the 
 * JSON feed for the specified spreadsheet_id/worksheet_id. 
 * Once loaded, it calls loadGraphJSON.
 */
function getJSON() {
  var script = document.createElement('script');

  script.setAttribute('src', 'http://spreadsheets.google.com/feeds/list'
                         + '/' + spreadsheet_id + '/' + worksheet_id + '/public/values' +
                        '?alt=json-in-script&amp;callback=loadGraphJSON');
  // insert the script tag into the header
  document.documentElement.firstChild.appendChild(script);
}

/*
 * Extract the information we need into 2 lists (data and labels)
 * We iterate over the rows (json.feed.entry)
 * and extract our day and distance columns int 2 lists.
 * Once this list created, we call drawChart to draw the graph.
 */
function loadGraphJSON(json) {
    var data = [];
    var labels = [];
    for (var i = 0; i &lt; json.feed.entry.length; i++) {
        var entry = json.feed.entry[i];
        //this is our first column
        labels.push(entry["gsx$day"].$t);
        // this is our second column
        // We need to convert it to float because we get the data as string
        data.push(parseFloat(entry["gsx$distance"].$t));
    }
    drawChart(labels, data);
}
</pre>

<p>Now that we have loaded the data from the google spreadsheet, we can pass to the second part of this article: displaying the data with raphael.js.</p>

<h2>2. Displaying the data with raphael.js</h2>

<p>We are going to need some javascript library. insert them at the beginning of your page in the header tag. you can find them on the raphael.js website, or at the end of this article in the downloads.</p>

<pre class="prettyprint lang-html">
&lt;script src="raphael.js"&gt;&lt;/script&gt;
&lt;script src="g.raphael.js"&gt;&lt;/script&gt;
&lt;script src="g.bar.js"&gt;&lt;/script&gt;
</pre>

<p>We can now pass at the interesting part: <strong>drawing the chart with raphael.js</strong>.</p>

<pre class="prettyprint lang-js">
function drawChart(labels, data) {
    /* 
     * Create an instance of raphael and specify:
     * the ID of the div where to insert the graph
     * the width
     * the height
     * Tip: Remember that the reference point (0, 0) is at the top left position.
     */
    var r = Raphael("holder", 600, 300);

    /*
     * Create the chart at the position with the parameters:
     * * pos on the x axis where the drawing start
     * * pos on the y axis where is drawing start
     * * width
     * * height
     * * the values: it needs to be a list of list since you can have multiple data
     * * extra parameters:
     *      stacked: Putting stacked to false seems to create a problem with the labels
     *      type: the end of the bar, it can be: round sharp soft
     */
    var chart = r.g.barchart(10, 10, 580, 280, [data], {stacked: true, type: "soft"});

    /*
     * Create an hover effect to display the value when the mouse is over the graph.
     */
    chart.hover(function() {
        // Create a popup element on top of the bar
        this.flag = r.g.popup(this.bar.x, this.bar.y, (this.bar.value || "0") + " km").insertBefore(this);
    }, function() {
        // hide the popup element with an animation and remove the popup element at the end
        this.flag.animate({opacity: 0}, 300, function () {this.remove();});
    });

    /*
     * Define the default text attributes before writing the labels
     * you can find pore information about the available attributes at:
     *   http://raphaeljs.com/reference.html#attr
     * and in the SVG specification:
     *   http://www.w3.org/TR/SVG/
     */ 
    r.g.txtattr = {font:"12px Fontin-Sans, Arial, sans-serif", fill:"#000", "font-weight": "bold"};

    /*
     * We write the labels.
     * There is a bug not fixed at the time of writing this article. We added a patch to 
     * g.bar.js : http://github.com/DmitryBaranovskiy/g.raphael/issues#issue/11
     */
    chart.label(labels);

    /*
     * Set all the bar greater or equals than 15 to red
     */
    // iterate over all the bar
    for (var i = 0; i &lt; chart.bars[0].length; i++) {
        var bar = chart.bars[0][i];
        // if the value of the bar is greater or equals to 15 we change the color to red
        if (bar.value >= 15) {
            bar.attr("fill", "#bf2f2f");
            bar.attr("stroke", "#bf2f2f");
        }
    }
}
</pre>

<p>You have now a beautiful Graph. see the <strong><a href="http://blog.jeremi.info/static/examples/docs-raphael/index.html">result</a></strong></p>

<h2>Download</h2>

<p>The code of this howto is available on github:
<a href="http://github.com/jeremi/raphael-graph-demo">http://github.com/jeremi/raphael-graph-demo</a>.</p>

<p><strong><a href="http://github.com/jeremi/raphael-graph-demo">Download the source</a></strong></p>

<h2>Links</h2>

<ul>
<li><a href="http://github.com/jeremi/raphael-graph-demo">Source code</a></li>
<li><a href="http://www.raphaeljs.com/">raphael.js</a></li>
<li><a href="http://g.raphaeljs.com/">gRaphaël</a></li>
<li><a href="http://github.com/DmitryBaranovskiy/g.raphael/issues#issue/11">graph label bugfix</a> (applied to g.bar.js in the source)</li>
<li><a href="http://gmaps-samples.googlecode.com/svn/trunk/spreadsheetsmapwizard/makecustommap.htm">another sample for loading data from a spreadsheet to a google maps</a> (I reused their text for preparing the spreadsheet)</li>
</ul>
</div>
      </content>
    </entry>
  
    <entry>
      <id>http://blog.jeremi.info/entry/starting-to-blog-again</id>
      <title type="text">Starting to blog again</title>
      <link href="http://blog.jeremi.info/entry/starting-to-blog-again" rel="alternate" type="text/html"/>
      <updated>2010-01-03T18:30:00Z</updated>
      <published>2010-01-03T18:30:00Z</published>
      
      <content type="xhtml" xml:base="http://blog.jeremi.info/">
	<div xmlns="http://www.w3.org/1999/xhtml"><p>It's been 2 years that I've stopped blogging on my personal blog. I'm doing more and more experiments, so I'm going to start again. I'm going to talk about my experiments in development.</p>
</div>
      </content>
    </entry>
  
</feed>
