woensdag 24 februari 2010

GWT Widget

Het grafische deel van een GWT applicatie bestaat uit Panels en Widgets. Een Panel is een container die andere Panels of Widgets kan bevatten. Verschillende panels rangschikken hun inhoud op verschillende manieren (links naar rechts, boven naar beneden, etc). Een Widget is een user-interface element. Standaard hebben we hier de TextBox, Button, Checkboxen etc. Daarnaast kunnen we ook zelf Widgets bouwen.

Stel nu dat we zo'n Widget hebben gebouwd en we willen die graag gebruiken op onze website, zonder alles om te bouwen naar GWT. Dit gaat als volgt. We voegen aan onze bestaande website een element toe:
<div id="mijnwidget"></div>
Dit is de placeholder waar onze widget gaat komen. Start nu een nieuw GWT project en implementeer de onModuleLoad() methode als volgt:
public void onModuleLoad() {
 Widget widget = new MijnWidget();
 RootPanel.get("mijnwidget").add(widget);
}
Compileer je project en zet de directory met daarin het resultaat naast je oorspronkelijke HTML bestand. Voeg tenslotte de volgende regel toe binnen de <head> en </head> tags:
<script type="text/javascript" language="javascript" src="mywidget/mywidget.nocache.js"></script>
waarin mywidget verwijst naar het door GWT gegenereerde JS bestand. Nu zou het moeten werken.

Op zich is dit nog niet zo spannend, dus we gaan een stap verder. In het volgende voorbeeld gebruiken we een uitgebreide versie van de RichTextArea, voorzien van een toolbar. Deze Widget willen we voortaan gebruiken als standaard textarea. We maken het volgende html bestand:
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="MyExample.css">
    <title>RichTextArea Demo</title>
    <script type="text/javascript" language="javascript" src="myexample/myexample.nocache.js"></script>
  </head>

  <body>
    <form action="myexample/print" method="post">
      <textarea name="mytext" class="rich"></textarea><br />
      <input type="submit" />
    </form>
  </body>
</html>
Nu moeten we nog een script maken dat onze Widget over de bovenstaande textarea heenplakt. Dit doen we als volgt. We gaan eerst op zoek naar de elementen waar onze Widget op geplakt moet worden. Deze elementen slaan we op. Vervolgens vervangen we deze elementen door placeholders. Vervolgens zetten we op de plaats van deze placeholder een kopie van onze Widget en een hidden input element waarin we de waarde van de textarea opslaan. Als de waarde in de textarea verandert, moet ook de waarde in onze hidden inputbox mee veranderen. En voila, onze eigen input widget.
public class MyExample implements EntryPoint {
 
 private Vector richTextAreas = new Vector();
 
 public void onModuleLoad() {
  Element body = RootPanel.getBodyElement();
  
  NodeList inputs = body.getElementsByTagName("textarea"); 
  
  for (int i = 0; i < inputs.getLength(); i++) {
   Element element = inputs.getItem(i);
   if (element instanceof TextAreaElement) {
    TextAreaElement textAreaElement = (TextAreaElement) element;
    if (textAreaElement.getClassName().startsWith("rich")) {
     richTextAreas.add(textAreaElement);
    }
   }
  }
   
  for (TextAreaElement element : richTextAreas) { 
   Element parent = element.getParentElement();
   String id = generateId(); 
   Element el = new Label().getElement();
   el.setId(id);
   parent.replaceChild(el, element);
   
   replaceTextArea(id, element.getName());
  }
  
  
 }
 
 private void replaceTextArea(String id, String name) {
  final Hidden hidden = new Hidden();
  hidden.setName(name);
  final RichTextArea textArea = 
   new RichTextArea();
  
  textArea.addRichTextHandler(new RichTextHandler() {

   @Override
   public void onChange(RichTextEvent event) {
    hidden.setValue(event.getHtml());
    
   }});
  RootPanel.get(id).clear();
  RootPanel.get(id).add(textArea);
  RootPanel.get(id).add(hidden);
 }
 
 private String generateId() {
  return UUID.uuid();
 }
}
An example can be found here.

woensdag 17 februari 2010

GWT 2.0

In het kader van persoonlijke ontwikkeling heb ik met mijn werkgever afgesproken om komend jaar één dag per week te besteden aan het leren van nieuwe (werk gerelateerde) vaardigheden. Tijdens het normale werk is er vaak geen tijd om ergens wat dieper in te duiken, of om een onbekende techniek, die wellicht heel handig zou kunnen zijn, te onderzoeken. Tijdens mijn nieuwe dag in de week neem ik de tijd om met deze onbekende technieken te experimenteren. In deze blog wil ik zo nu en dan kort vertellen wat ik geleerd of gemaakt heb.

Om die reden ben ik kort geleden weer eens aan de slag gegaan met Google Web Toolkit 2.0 (GWT). GWT is een Java-framework dat het mogelijk maakt om JavaScript-applicaties te ontwikkelen in een Java omgeving. Het maken van wat exotischere JavaScript-applicaties is vervelend omdat de verschillende webbrowsers eigen JavaScript engines (en HTML renderers hebben). De ene fabrikant volgt de JavaScript standaard stricter dan de andere, waardoor er kleine verschillen zijn ontstaan. Een JavaScript-applicatie kan zich daarom op verschillende manieren gedragen in verschillende browsers. De programmeur moet hier rekening mee houden door in sommige gevallen functionaliteit op verschillende manieren te programmeren. Daarnaast is het debuggen van een JavaScript applicatie een vervelende klus.

GWT geeft ons een omgeving waarin we op een hoger niveau een applicatie kunnen ontwikkelen. Gebruikmakend van libraries en tools van Google, kun je je webapplicatie helemaal in Java ontwikkelen, debuggen en testen. Wanneer je klaar bent kun je je code omzetten naar JavaScript-code. Tijdens deze stap wordt er rekening gehouden met de browser verschillen. De ontwikkelaar is daarom sneller klaar, of kan in dezelfde tijd een geliktere applicatie in elkaar zetten.

GWT had lang last van kinderziektes en onvolledigheden, maar inmiddels kunnen we bij versie 2.0 zeggen dat GWT volwassen is geworden. Ik kan daarom iedereen die bezig is met webapplicaties aanraden er eens naar te kijken.