2008/05/11
Last changed: Mai 11, 2008 09:20 by Uwe Schaefer Labels: wicket, gem, java
it happens quite often that, while browsing the Wicket mailing list, i stumble upon gems, that i fail to find or even remember when i could use them.
this really has to stop 
the problem is: there is of course no commen theme about these hacks, components, behaviours etc, so it is very hard to find a good name for a project like that.
i thought of wicket-contrib-kitchensink, but maybe i should give it another try.
until then, i´ll grab these gems and republish them here (after maybe adding a few things and polishing a little) just to make sure, that i wont forget them.
here is the first:
How would one implement "hint text" on a text field in Wicket? By hint text
I mean an empty TextField has greyed out text in it to indicate its purpose,
and gets cleared onFocus?)
the answer & code is from mighty igor vaynberg:
/**
* Adds hint-text to texfield, that will be erased onFocus
* @author igor vaynberg
*/
public class TextFieldHintBehaviour extends AbstractBehavior
{
private String pseudoUniqueJavascriptVariableName = this.getClass().getSimpleName()
+ String.valueOf(System.nanoTime());
public TextFieldHintBehaviour(final IModel hintTextModel)
{
this.hint = hintTextModel;
}
private final IModel hint;
private Component c;
private String hintColor = "gray";
private String textColor = "black";
@Override
public void bind(final Component component)
{
super.bind(component);
this.c = component;
this.c.setOutputMarkupId(true);
}
@Override
public void renderHead(final IHeaderResponse response)
{
response.renderOnDomReadyJavascript("var " + this.pseudoUniqueJavascriptVariableName
+ "=document.getElementById('" + this.c.getMarkupId() + "');" + this.pseudoUniqueJavascriptVariableName
+ ".value='" + this.hint.getObject() + "';" + this.pseudoUniqueJavascriptVariableName
+ ".style['color']='" + this.hintColor + "';");
}
@Override
public void onComponentTag(final Component component, final ComponentTag tag)
{
super.onComponentTag(component, tag);
tag.put("onfocus", "if (this.value=='" + this.hint.getObject() + "') {this.value=''; this.style['color']='"
+ this.textColor + ";'}");
}
public String getHintColor()
{
return this.hintColor;
}
public void setHintColor(final String hintColor)
{
this.hintColor = hintColor;
}
public String getTextColor()
{
return this.textColor;
}
public void setTextColor(final String textColor)
{
this.textColor = textColor;
}
}
Last changed: Mai 11, 2008 11:42 by Uwe Schaefer Labels: resin, glassfish, java, appserver
while this blog happily ran on glassfish v1 for quite some time now, i have to admit switching back to caucho resin. the reason for this is simple: i will be using resin at work soon again, so any detailed experience with glassfish (at least with anything <v3) will be void.
i worked with resin2 for about 8 years and was quite happy with it (apart from being pissed by its failure to implement the standards). looking at resin3 was quite impressive because of its advanced clustering, watchdog and automatic-restart capabilities as well as its embeddability, which makes wicket-development a breeze.
see for yourselves at http://caucho.com
Another very simple, yet incredibly helpful snippet:
/**
* Simple Link that renders its Model as a textual body
* @author Al Maw
*/
abstract class TextLink extends Link
{
public TextLink(final String id, final IModel model)
{
super(id, model);
}
@Override
protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)
{
if (!isLinkEnabled() && (getBeforeDisabledLink() != null))
{
getResponse().write(getBeforeDisabledLink());
}
replaceComponentTagBody(markupStream, openTag, getModelObjectAsString());
if (!isLinkEnabled() && (getAfterDisabledLink() != null))
{
getResponse().write(getAfterDisabledLink());
}
}
}
Another little gem:
/**
* Form that divides submit-events to inital and resubmit.
* @author igor vaynberg
*/
abstract class ResubmitSafeForm extends Form
{
private boolean submitted;
private static final long serialVersionUID = 1L;
public ResubmitSafeForm(final String id)
{
super(id);
}
public ResubmitSafeForm(final String id, final IModel model)
{
super(id, model);
}
protected abstract void onInitialSubmit();
protected abstract void onResubmit();
protected final void onSubmitted()
{
if (!this.submitted)
{
onInitialSubmit();
this.submitted = true;
}
else
{
onResubmit();
}
}
}
This one is all about id <-> object mapping when using DropDowns:
/**
* @author igor vaynberg
*/
public class DropDownIdChoice extends DropDownChoice
{
public DropDownIdChoice(String id, IModel model, IModel choices, IChoiceRenderer renderer, Class<?> type)
{
super(id, model, choices, renderer);
setType(type);
}
@Override
public String getModelValue()
{
final Object id = getModelObject();
if (id != null)
{
return getConverter(getType()).convertToString(id, getLocale());
}
else
{
return NO_SELECTION_VALUE;
}
}
}
This template for using a Breadcrumb-like Navigation really shows the beauty of stateful pages that separate wicket from those countless template-based frameworks.
/**
* Provides a list of Breadcrumbs. THIS IS ONLY A TEMPLATE. DO NOT USE UNMODIFIED
* @author igor vaynberg
*/
public abstract class BreadcrumbPage extends Page
{
private List<BreadcrumbPage> history = new ArrayList<BreadcrumbPage>();
public BreadcrumbPage()
{
add(new ListView("history", new PropertyModel(this, "history"))
{
@Override
protected void populateItem(final ListItem item)
{
final Link link = new Link("link", item.getModel())
{
@Override
protected void onClick()
{
getRequestCycle().setResponsePage((BreadcrumbPage) getModelObject());
}
};
link.add(new Label("title", ((BreadcrumbPage) item.getModelObject()).getTitle()));
}
});
}
public BreadcrumbPage(final BreadcrumbPage crumb)
{
this();
this.history.add(crumb); }
protected abstract IModel getTitle();
}
damn. the more i read, the more i find, the more i have to polish, test and copy over 
Here is a simple demonstration of how to prevent "Cross-Site Request Forgery"
/**
* Form that uses a random uuid token in order to prevent nasty people from messing around (also known as cross site request forgery) ;)
* @author igor vaynberg
*/
class SecureForm extends Form
{
public SecureForm(final String id)
{
super(id);
}
private static final long serialVersionUID = 1L;
private static final String TOKEN_NAME = "SECURE_FORM_TOKEN";
private String token;
@Override
protected void onBeforeRender()
{
super.onBeforeRender();
this.token = UUID.randomUUID().toString();
}
@Override
protected void onComponentTagBody(final MarkupStream markupStream, final ComponentTag openTag)
{
super.onComponentTagBody(markupStream, openTag);
getResponse().write("<input type='hidden' name='" + this.TOKEN_NAME + "' value='" + this.token + "'/>");
}
@Override
public boolean process()
{
if (!this.token.equals(getRequest().getParameter(this.TOKEN_NAME)))
{
throw new IllegalStateException("token mismatch");
}
return super.process();
}
}
thinking twice, ajax-indicators are not at all eye-candy, but useful from an usablity perspective.
/**
* Adds an AJAX-Indicator to DropDownChoice
* @author Eyal Golan
*/
class DropDownChoiceWithAjaxIndicator extends DropDownChoice implements IAjaxIndicatorAware
{
private static final long serialVersionUID = 1365817942506006686L;
private final WicketAjaxIndicatorAppender indicatorAppender = new WicketAjaxIndicatorAppender();
public DropDownChoiceWithAjaxIndicator(final String id, final IModel choices, final IChoiceRenderer renderer,
final MarkupContainer markupContainer)
{
super(id, choices, renderer);
init(markupContainer);
}
public DropDownChoiceWithAjaxIndicator(final String id, final IModel model, final IModel choices,
final IChoiceRenderer renderer, final MarkupContainer markupContainer)
{
super(id, model, choices, renderer);
init(markupContainer);
}
public DropDownChoiceWithAjaxIndicator(final String id, final IModel model, final IModel choices,
final MarkupContainer markupContainer)
{
super(id, model, choices);
init(markupContainer);
}
public DropDownChoiceWithAjaxIndicator(final String id, final IModel model, final List<Serializable> data,
final IChoiceRenderer renderer, final MarkupContainer markupContainer)
{
super(id, model, data, renderer);
init(markupContainer);
}
public DropDownChoiceWithAjaxIndicator(final String id, final IModel model, final List<Serializable> choices,
final MarkupContainer markupContainer)
{
super(id, model, choices);
init(markupContainer);
}
public DropDownChoiceWithAjaxIndicator(final String id, final IModel choices, final MarkupContainer markupContainer)
{
super(id, choices);
init(markupContainer);
}
public DropDownChoiceWithAjaxIndicator(final String id, final List<Serializable> data,
final IChoiceRenderer renderer, final MarkupContainer markupContainer)
{
super(id, data, renderer);
init(markupContainer);
}
public DropDownChoiceWithAjaxIndicator(final String id, final List<Serializable> choices,
final MarkupContainer markupContainer)
{
super(id, choices);
init(markupContainer);
}
public DropDownChoiceWithAjaxIndicator(final String id, final MarkupContainer markupContainer)
{
super(id);
init(markupContainer);
}
public String getAjaxIndicatorMarkupId()
{
return this.indicatorAppender.getMarkupId();
}
private void init(final MarkupContainer markupContainer)
{
add(this.indicatorAppender);
}
}
|
|
Mai 2008 |
|
| Sun |
Mon |
Tue |
Wed |
Thu |
Fri |
Sat |
|
|
|
|
|
1
|
2
|
3
|
|
4
|
5
|
6
|
7
|
8
|
9
|
10
|
|
11
|
12
|
13
|
14
|
15
|
16
|
17
|
|
18
|
19
|
20
|
21
|
22
|
23
|
24
|
|
25
|
26
|
27
|
28
|
29
|
30
|
31
|
|
|
|
|
|
|
|
|
Mai 18, 2008
Mai 04, 2008
|