The first one concerns a bugbear I've had with the RichFaces color picker widget. The widget looks like this:
It's a cool component, but for me it lacks an important feature: once you've chosen a color there's no way to unchoose it - to clear the box. This is annoying because typically getColor is a nullable field, so we need a way to null it. One approach would be to extend HtmlColorPicker (or its Renderer) and try to add the extra functionality - but that can be a bit scary.
Metawidget affords us a different approach. We can write a small WidgetProcessor and it will process every ColorPicker (across our entire application) and add the extra button. Here's the code:
package com.myapp;
import java.util.Map;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlGraphicImage;
import javax.faces.context.FacesContext;
import org.metawidget.faces.component.UIMetawidget;
import org.metawidget.widgetprocessor.iface.WidgetProcessor;
import org.richfaces.component.html.HtmlColorPicker;
public class ColorPickerWidgetProcessor
implements WidgetProcessor<UIComponent, UIMetawidget> {
@Override
public UIComponent processWidget( UIComponent component, String elementName, Map<String, String> attributes,
UIMetawidget metawidget ) {
if ( !( component instanceof HtmlColorPicker ) ) {
return component;
}
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
UIComponent stubComponent = application.createComponent( "org.metawidget.Stub" );
stubComponent.getChildren().add( component );
HtmlGraphicImage graphicImage = (HtmlGraphicImage) application.createComponent( "javax.faces.HtmlGraphicImage" );
graphicImage.setStyle( "vertical-align: middle; margin-left: 2px; cursor: pointer" );
graphicImage.setValue( "/media/core.delete.gif" );
graphicImage.setTitle( "Remove colour" );
graphicImage.setOnclick( "if ( confirm( 'Okay to remove this colour?' )) { var picker = document.getElementById( '" + component.getClientId( context ) + "' ); picker.childNodes[0].value = ''; picker.childNodes[1].style.backgroundColor = '#ffffff'; }" );
stubComponent.getChildren().add( graphicImage );
return stubComponent;
}
}
import java.util.Map;
import javax.faces.application.Application;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlGraphicImage;
import javax.faces.context.FacesContext;
import org.metawidget.faces.component.UIMetawidget;
import org.metawidget.widgetprocessor.iface.WidgetProcessor;
import org.richfaces.component.html.HtmlColorPicker;
public class ColorPickerWidgetProcessor
implements WidgetProcessor<UIComponent, UIMetawidget> {
@Override
public UIComponent processWidget( UIComponent component, String elementName, Map<String, String> attributes,
UIMetawidget metawidget ) {
if ( !( component instanceof HtmlColorPicker ) ) {
return component;
}
FacesContext context = FacesContext.getCurrentInstance();
Application application = context.getApplication();
UIComponent stubComponent = application.createComponent( "org.metawidget.Stub" );
stubComponent.getChildren().add( component );
HtmlGraphicImage graphicImage = (HtmlGraphicImage) application.createComponent( "javax.faces.HtmlGraphicImage" );
graphicImage.setStyle( "vertical-align: middle; margin-left: 2px; cursor: pointer" );
graphicImage.setValue( "/media/core.delete.gif" );
graphicImage.setTitle( "Remove colour" );
graphicImage.setOnclick( "if ( confirm( 'Okay to remove this colour?' )) { var picker = document.getElementById( '" + component.getClientId( context ) + "' ); picker.childNodes[0].value = ''; picker.childNodes[1].style.backgroundColor = '#ffffff'; }" );
stubComponent.getChildren().add( graphicImage );
return stubComponent;
}
}
And here's what it produces:
Now you can click the red 'X' next to each ColorPicker, and it will use JavaScript to clear the box ready for POST back.
Feedback welcome!
0 comments:
Post a Comment