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.

Geen opmerkingen: