## How the button is created and how it acts

Due to specific design of the buttons in the Photo Album application, it's necessary to clarify some design and development points about the button. The button is visually represented by Facelets template stored in the button.xhtml file.

Please have a look at the content of the file:

            <ui:composition xmlns="http://www.w3.org/1999/xhtml" … >

                <richx:actionMapper>
                    <r:outputPanel layout="block" style="#{'#{'}style}" styleClass="photoalbumButton #{'#{'}styleClass}" lang="#{'#{'}lang}" dir="#{'#{'}dir}"
                        title="#{'#{'}title}" rendered="#{'#{'}empty rendered or rendered}" onmousedown="$(this).css('background-position', '0 28px');"
                        onmouseup="$(this).css('background-position', '0 0');" onmouseout="$(this).css('background-position', '0 0');">

                    <div>#{'#{'}value}</div>

                    <r:commandButton accesskey="#{'#{'}accesskey}" alt="#{'#{'}alt}" type="image" image="/img/shell/spacer.gif"
                        actionListener="#{'#{'}mappedActionListener}" action="#{'#{'}mappedAction}" bypassUpdates="#{'#{'}bypassUpdates}"
                        data="#{'#{'}data}" disabled="#{'#{'}disabled}" eventsQueue="#{'#{'}eventsQueue}" focus="#{'#{'}focus}" immediate="#{'#{'}immediate}"
                        limitRender="#{'#{'}limitRender}" onbeforedomupdate="#{'#{'}onbeforedomupdate}" tabindex="#{'#{'}tabindex}" render="#{'#{'}render}"
                        execute="#{'#{'}execute}" oncomplete="#{'#{'}oncomplete}" onblur="#{'#{'}onblur}" onclick="#{'#{'}onclick}"
                        ondblclick="#{'#{'}ondblclick}" onfocus="#{'#{'}onfocus}" onkeydown="#{'#{'}onkeydown}" onkeypress="#{'#{'}onkeypress}"
                        onkeyup="#{'#{'}onkeyup}" onmousedown="#{'#{'}onmousedown}" onmousemove="#{'#{'}onmousemove}" onmouseout="#{'#{'}onmouseout}"
                        onmouseover="#{'#{'}onmouseover}" onmouseup="#{'#{'}onmouseup}" />

                    </r:outputPanel>
                </richx:actionMapper>
            </ui:composition>

The <richx:actionMapper> tag is covered in more detail further in the text. In brief, it's a special tag developed deliberately to pass to the button a method expression of the action which must be performed when the button is clicked.

The button consists of several parts:

- 2 images (pressed and not pressed) - technically only one image that's being shifted

- <div> element that displays the button's text

- <r:commandButton> that sends Ajax request to the server

These elements are wrapped by <r:outputPanel> to adjust the look-and-feel.

In the application the button is used for example like this:

            …
            <richx:commandButton value="#{'#{'}messages['login.register']}" immediate="true"
                            actionListener="#{'#{'}authenticator.goToRegister()}" render="mainArea"
                            oncomplete="#{'#{'}r:component('loginPanel')}.hide();" execute="@this" />
            …

We can pass to the <richx:commandButton> all attributes or only some, in the example only actionListener, render, value, immediate, oncomplete and execute are passed.

<richx:commandButton> is a custom tag that is declared in the photoalbum-taglib.xml tag library:

                <?xml version="1.0"?>
                <facelet-taglib xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibary_2_0.xsd"
                    version="2.0">
                    <namespace>http://richfaces.orgx</namespace>
                    <tag>
                        <tag-name>commandButton</tag-name>
                        <source>templates/button.xhtml</source>
                    </tag>
                    <tag>
                        <tag-name>actionMapper</tag-name>
                        <handler-class>org.richfaces.photoalbum.util.ActionMapperTagHandler</handler-class>
                    </tag>
                </facelet-taglib>

In order to use the <richx:commandButton> on the page the namespace of the taglib must be declared:

            <ui:composition xmlns="http://www.w3.org/1999/xhtml"
                    …
                xmlns:richx="http://richfaces.orgx">
                    …

A more complex part of the button implementation, as we said earlier, is <richx:actionMapper> which is also described in tablib. But it is not just a simple tag-template since it has Facelets handler-class which specifies how it is handled when declared on the page. It is created because Facelets templates do not allow to make the MethodExpression a Facelets-template parameter. Please find below the code of the class(some irrelevant details are omitted):

            public class ActionMapperTagHandler extends TagHandler {

                private static final Class<?>[] ACTION_PARAM_TYPES = new Class[0];

    		    private static final Class<?>[] ACTION_LISTENER_PARAM_TYPES = new Class[] { ActionEvent.class };

                private static final String ACTION = "action";

                private static final String ACTION_LISTENER = "actionListener";

                private static final String MAPPED_ACTION = "mappedAction";

                private static final String MAPPED_ACTION_LISTENER = "mappedActionListener";

                public ActionMapperTagHandler(TagConfig config) {
                    super(config);
                }

                private MethodExpression remap(FaceletContext faceletContext, String varName, Class<?> expectedReturnType,
                    Class<?>[] expectedParamTypes) {

                    MethodExpression result = null;

                    VariableMapper mapper = faceletContext.getVariableMapper();
                    ValueExpression valueExpression = mapper.resolveVariable(varName);
                    if (valueExpression != null) {
                        ExpressionFactory ef = faceletContext.getExpressionFactory();
                        ELContext elContext = faceletContext.getFacesContext().getELContext();

                        result = ef.createMethodExpression(elContext, valueExpression.getExpressionString(), expectedReturnType,
                            expectedParamTypes);
                    }

                    return result;
                }

                public void apply(FaceletContext ctx, UIComponent parent) throws IOException, FacesException, FaceletException, ELException {

                    MethodExpression actionExpression = remap(ctx, ACTION, String.class, ACTION_PARAM_TYPES);
                    MethodExpression actionListenerExpression = remap(ctx, ACTION_LISTENER, null, ACTION_LISTENER_PARAM_TYPES);

                    VariableMapper initialVarMapper = ctx.getVariableMapper();
                    try {
                        if (actionExpression == null) {
                            actionExpression = NOOP_ACTION_EXPRESSION;
                        }

                        initialVarMapper.setVariable(MAPPED_ACTION,
                            ctx.getExpressionFactory().createValueExpression(actionExpression, MethodExpression.class));

                        if (actionListenerExpression == null) {
                            actionListenerExpression = NOOP_ACTION_LISTENER_EXPRESSION;
                        }

                        initialVarMapper.setVariable(MAPPED_ACTION_LISTENER,
                            ctx.getExpressionFactory().createValueExpression(actionListenerExpression, MethodExpression.class));

                        ctx.setVariableMapper(initialVarMapper);

                        nextHandler.apply(ctx, parent);

                    } finally {
                        ctx.setVariableMapper(initialVarMapper);
                    }
                }
            }

You can find more infromation about Facelets, custom tags, taglibs, Facelets tag handlers and Facelets templates here.