Sunday, May 1, 2011

Mixing Google Closure with GWT

I’ve been happily using GWT for some time now, but I’ve wanted some widgets (just three**) that didn’t exist in GWT out of the box. While searching for widgets to fit my UI needs, I decided to try to mix the use Google’s Closure Library inside my GWT app. I’ve had some success and wanted to share how I got the two to work together.

**Namely I’ve needed tri-state checkboxes, a button with a dropdown menu (like the labels drop-down button in GMail), and I’ve also desired the look of buttons in a row (like the button bar in GMail that contains: Archive|Spam|Delete ).


The outline version of how to do this is:

  1. Write a static html page (non GWT) that isolates the desired closure widgets onto a page by themselves.
  2. Compile the closure javascript into a standalone .js file.
  3. Copy the standalone .js file and the some closure CSS files into your GWT project.
  4. Copy the static html bits into your uibinder xml file.
  5. Use JSNI to glue the Closure and GWT worlds.


1. Isolate the closure widgets you want.

You should follow the Closure Getting Started page to download the closure library, and to setup a simple static html page containing the Closure widgets you want to use. I wanted to use a CustomButton “button bar”, like the [Left|Center|Right] buttons shown in this demo page. (You can browse all the closure demos – click the Demos tab on the right side of this page.)

I already had a local apache httpd server running, so I just checked out the closure library directly into my apache document root, and created another directory called buttonbar where I could create my work.

cd /website/docroot
svn checkout closure-library
mkdir buttonbar


In the buttonbar directory I created a buttonbar.html file and buttonbar.js file. With Closure, I had a choice of “decorating” existing div tags, or generating all the items programmatically. I opted to “decorate” because this allowed me to still layout my page in a declarative style, i.e. supply my button names in the HTML, etc. This is also a good match with how I’ve already been using UIBinder in GWT to keep layout as declarative as possible. These two files looked like this:

    <script src="../closure-library/closure/goog/base.js"></script>
    <script src="buttonbar.js"></script>
    <link rel="stylesheet" href="../closure-library/closure/goog/css/common.css">
    <link rel="stylesheet" href="../closure-library/closure/goog/css/custombutton.css">
    <div style="font-size: 11px;">
        <div id="btn1" class="goog-custom-button goog-custom-button-collapse-right">
            <div style="padding: 0px 5px;">Dodge</div>
        </div><div id="btn2" class="goog-custom-button goog-custom-button-collapse-left goog-custom-button-collapse-right">
            <div style="padding: 0px 5px;">Parry</div>
        </div><div id="btn3" class="goog-custom-button goog-custom-button-collapse-left">
            <div style="padding: 0px 5px;">Spin</div>
    <script type="text/javascript">
        buttonbar.setup('btn1', function() {alert("Dodge")} );
        buttonbar.setup('btn2', function() {alert("Parry")} );
        buttonbar.setup('btn3', function() {alert("Spin")} );


 * onClickCallback will be passed an ActionEvent when the button is clicked.
buttonbar.setup = function(name, onClickCallback) {
    var button = goog.ui.decorate(goog.dom.getElement(name));
    button.setDispatchTransitionEvents(goog.ui.Component.State.ACTION, true);, goog.ui.Component.EventType.ACTION, onClickCallback);
goog.exportSymbol('buttonbar.setup', buttonbar.setup);


With respect to the event filtering in the above code, know that Closure does their own (browser-independent) implementation of events. You will simply have to read about Closure Events to decide the appropriate way you should handle them for your application. In my code above, I specifically only want events when a button is clicked, which is why you only see goog.ui.Component.State.ACTION and goog.ui.Component.EventType.ACTION. You will need to examine your application needs with respect to the event handing you specify here.

Finally, loading the html page in a browser yields a lovely button bar:


(Note: if you are loading the html page with a file:/// url, and you are using Chrome, you will have to set the security parameter --allow-file-access-from-files as an argument to Chrome upon startup.)

It is this dividing point between the html file and the js file where you must consider what code goes into the .js file, and what function(s) you will expose to the outside html world to call. You need to think about how your GWT app is going to interact with the closure widget and be sure to expose a function that allows to you stitch these two worlds together. In this case, I only need a callback to be called when a button is clicked. And I also want to keep the button declarations in the html side, and just have the javascript side “decorate” these elements. Therefore the only other argument is the ‘name’, which is the id of the div element that represents a button.

For your application, other closure widgets (or even multiple widgets combined ) will likely require exposing multiple setup functions.


2. Compile the javascript into a “standalone” script.

To compile, you use the Closure Builder. Using the Closure compiler will eliminate all the unused code, and given the right flags, it will reduce the code into a single compact javascript file.

The compiler itself is written in Java, and you have to download the latest compiler jar file separately. Unzip this archive and copy compiler.jar to the same directory that contains your closure-library directory that you checked out earlier.

cd /website/docroot
unzip compiler.jar


Run the compiler over the buttonbar.js file (requires python):

cd /website/docroot

closure-library/closure/bin/build/ \
  --root=closure-library/ \
  --root=buttonbar/ \
  --namespace="buttonbar.setup" \
  --output_mode=compiled \
  --compiler_jar=compiler.jar \
  --compiler_flags="--compilation_level=ADVANCED_OPTIMIZATIONS" \
  > buttonbar/buttonbar.x.js


It’s the compiler_flags option above that shrinks the output code into a nice single little file.

Now you can edit the <head> of your original html file, loading only your new single javascript file":

    <script src="buttonbar.x.js"></script>
    <link rel="stylesheet" href="../closure-library/closure/goog/css/common.css">
    <link rel="stylesheet" href="../closure-library/closure/goog/css/custombutton.css">


Again, loading the html page in a browser should yield:



3. Copy the standalone .js file .css files into your GWT project

At this point we depend only upon a single javascript file buttonbar.x.js, and two css files common.css and custombutton.css. Copy all three to appropriate subdirectories of the “war” directory in your GWT  project. In your html (or jsp, or whatever) be sure to load all three of these resources. E.g., your <head> should now also contain these three items:


<script src="/path/to/js/buttonbar.x.js"></script>

    <link rel="stylesheet" href="/path/to/css/common.css">
    <link rel="stylesheet" href="/path/to/css/custombutton.css">


4. Copy the static html bits into your UIBinder file, e.g. MyPage.ui.xml :

    <div style="font-size: 11px;">
        <div id="btn1" class="goog-custom-button goog-custom-button-collapse-right">
            <div style="padding: 0px 5px;">Dodge</div>
        </div><div id="btn2" class="goog-custom-button goog-custom-button-collapse-left goog-custom-button-collapse-right">
            <div style="padding: 0px 5px;">Parry</div>
        </div><div id="btn3" class="goog-custom-button goog-custom-button-collapse-left">
            <div style="padding: 0px 5px;">Spin</div>

(Note: the above .ui.xml file actually contains many more GWT widgets; just this bit of html is shown cut and paste into an HTMLPanel)


5. Use JSNI to glue the Closure and GWT worlds.

In our GWT code, we must setup our closure widgets. This requires the presence of two things: 1) the buttonbar.x.js script must be loaded, 2) the html that declares the widgets must be loaded. Some reading about GWT widgets reveals that we can override the onLoad() method which will be called after both of those items are ready.

Earlier, in our simple html file, we made a javascript call to buttonbar.setup() for each button. In GWT, we will wrap the same call using JSNI and use the $wnd prefix to access the global space where we will find our setup function. Look for the setup in the onLoad() method.

public class MyPage extends Composite {
    interface MyPageUiBinder extends UiBinder<Widget, MyPage> {}
    private static MyPageUiBinder uiBinder = GWT.create(MyPageUiBinder.class);
    public MyPage() {
        // etc...
    protected void onLoad() {
    private static native void setupGoogButtons(MyPage widget) /*-{
        $wnd.buttonbar.setup('btn1', function() { widget.@com.your.namespace.client.MyPage::btnDodgeClick()() });
        $wnd.buttonbar.setup('btn2', function() { widget.@com.your.namespace.client.MyPage::btnParryClick()() });
        $wnd.buttonbar.setup('btn3', function() { widget.@com.your.namespace.client.MyPage::btnSpinClick()() });
    public void btnDodgeClick() {
        GWT.log("btn dodge click");
    public void btnParryClick() {
        GWT.log("btn parry click");
    public void btnSpinClick() {
        GWT.log("btn spin click");


That’s it. Granted the above example just logs the button clicks. But it does demonstrate the use of closure widgets in a GWT app.



I have two thoughts after achieving this task:

1) I do not have a “clean” development environment to easily iterate development. Normally GWT work is completely self-contained in eclipse. But with closure, I need python (plus java) to compile, and I was using an existing apache server to test my html/javascript, and just using vi to edit files. Figuring out how I could integrate all this activity into my “normal” eclipse world does not seem worth the effort for a one-off use of closure widgets. I am just documenting how I did things so I may maintain it or repeat it in the future. But it is not a push-one-button “make all” solution.

2) One could wrap each individual closure library widget into a self standing GWT widget and be done with the “dirty work” for good. But that would defeat closure’s ability of reducing unnecessary code. Instead you have consider the whole content of a particular page load, and all the possible closure widgets you will need while on that GWT page. You need to consider your interface and export javascript functions for all of those widgets and compile them such that you GWT page will still only need to load one closure js file. This presents more “dirty work” for each GWT page that needs closure widgets, and will make me curse my disjointed development environment. But the end result is worthwhile, so the incongruent nature of it all will be okay by me.