Thursday 14 February 2013

Client Behavior functionality with JSF 2.x (part 2)

Introduction

In the previous text, I described how you can create a button that ask for a confirmation.  It showed the basic functionality of creating reusable client side functionality.
The example was very simple, just requiring one javaScript command.
In this text, I'll show some more advanced usages where you need to include an external resource and have to respond on multiple events.
The example shows how you can create the hover functionality for an input field. And of course with most browsers you can specify it as a css selector
    .myHover:hover {
        background-color: red;
    }
Unfortunately, not all browsers supports this and it is a pity that IE9 fails to understand it. So lets write an universal hover functionality.

Specify the event

For the change of color when the mouse is over a field, we need to respond to 2 events.  The mouse that enters the field, mouseover event, to adjust the color and when the mouse leaves the field, mouseout event, to revert the color to his original one.
So we need a client behaviour tag, just like the confirmation tag we have created the last time, lets call it hover so that we can attach the functionality to a field.  We have 2 events but we don't need to create 2 different tags. We are able to retrieve the intended event in the getScript method.
So let start with the definition of the tag in the facelet tag library
    <tag>
        <tag-name>hover</tag-name>
        <behavior>
            <behavior-id>hover<behavior-id>
        </behavior>
    </tag>;
This is identical to the confirmation functionality.  And we can use it in the following way
        <h:inputText value="#{bean.prop}" >
            <custom:hover event="mouseover"/>
            <custom:hover event="mouseout"/>
        </h:inputText>
We now specify the events we like to intercept and based on the event name, we can code the required javaScript        
    @Override
    public String getScript(ClientBehaviorContext behaviorContext) {
        if (MOUSEOVER_EVENT.equals(behaviorContext.getEventName())) {
            return "this.className += ' hoverClass '";
        }
        if (MOUSEOUT_EVENT.equals(behaviorContext.getEventName())) {
            return "this.className = this.className.replace( /(?:^|\\s)hoverClass(?!\\S)/g , '' )";
        }
        return null;
    }
The event name is passed to the getScript method in the behaviorContext parameter. The code adds or removes a CSS class to the HTML element. So when the hoverclass is defined as a red background, the input text element becomes red when the mouse is over the field and returns to his 'normal' color when we move out of it.

A single tag

The above solution is from a developers perspective not an ideal situation. The first improvement we will make is that you only need to specify 1 tag, and not 2.
The hover tag we created earlier was explicitly linked to the client behaviour functionality.  You can also create a tag for other purposes like a converter or your new component.  But there is also the possibility to create a tag for which you must implement the functionality, like this
<tag>
        <tag-name>myHover</tag-name>
        <handler-class>be.rubus.web.jsf.tutorial.clientbehaviour.HoverHandler</handler-class>
    </tag>

Within the HoverHandler, you must program the behaviour that you want. Before you can start with it, you must know what the function of a handler class is.

This class will be used by the JSF system to convert the xhtml page to the component tree. Afterwards this component tree will be converted to the HTML which is sent to the browser in the Render Response phase of the JSF lifecycle.
With a handler class you can change the created component tree. You can manipulate the 'DOM tree' (or what will become the DOM tree) by adding, removing and rearranging nodes but also change the properties of the nodes in the component tree.
The HoverHandler looks like this
public class HoverHandler extends TagHandler {
    private HoverBehavior mouseOver = new HoverBehavior();
    private HoverBehavior mouseOut = new HoverBehavior();
    public HoverHandler(TagConfig config) {
        super(config);
    }
    @Override
    public void apply(FaceletContext ctx, UIComponent parent) throws IOException {
        if (parent instanceof ClientBehaviorHolder) {
            ClientBehaviorHolder comp = (ClientBehaviorHolder) parent;
            comp.addClientBehavior("mouseover", mouseOver);
            comp.addClientBehavior("mouseout", mouseOut);
        }
    }
}
If you want to create a tag handler class of your own, you should extend it from javax.faces.view.facelets.TagHandler and do your work in the apply method. The method has a parameter parent and it is the immediate parent of the tag. In our case, the inputText.
Since we now have a reference to the component we like to modify, we can call the addClientBehavior method twice, once for the mouseover event and once for the mouseout event.
The HoverBehaviour class we pass along with the event names, is the same class as we used in the previous section.  So it will generate the correct javaScript code for each event.
So now we have improved our hover functionality greatly from a developers standpoint.  He doesn't have to type the event names (strings where he can make mistakes) and has to type a lot less characters.

Resource dependency

The only thing that can go wrong now, is the definition of the CSS class.  If we define it in the CSS file of the application, we have it available on every page.

But what if we decide to create some kind of reusable library so that we can use it for all the applications of the company. Or what if the javaScript code is large and we have placed it in an external file?
Maybe you know already that with a JSF renderer, you can specify the external resources the renderer depends on. Resources like javascript files and CSS files, just as we also need for the client behaviour functionality.
The good news is that there exists a special renderer for client behaviour, called ClientBehaviorRenderer.  It has also a getScript method that we need to implement and we can specify the resources we need with the ResourceDependency annotation.  This is the renderer version of the hover functionality
@FacesBehaviorRenderer(rendererType="hover")
@ResourceDependency(name = "hover.css")
public class HoverBehaviorRenderer extends ClientBehaviorRenderer {
    private static final String MOUSEOVER_EVENT = "mouseover";
    private static final String MOUSEOUT_EVENT = "mouseout";
    @Override
    public String getScript(ClientBehaviorContext behaviorContext, ClientBehavior behavior) {
        if (MOUSEOVER_EVENT.equals(behaviorContext.getEventName())) {
            return "this.className += ' hoverCls '";
        }
        if (MOUSEOUT_EVENT.equals(behaviorContext.getEventName())) {
            return "this.className = this.className.replace( /(?:^|\\s)hoverCls(?!\\S)/g , '' )";
        }
        return null;
    }
}
It is a straight copy, only the base class is different and has other annotations.
The client behavior itself becomes now empty, except for the definition of the renderer that must be used.
@FacesBehavior(value = "hover")
public class HoverBehavior extends ClientBehaviorBase {
    @Override
    public String getRendererType() {
        return "hover";
    }
}

Wrap up

We now have created a custom tag which allows us to have the 'hover' functionality using javascript functionalities. We only need a single tag and due to the renderer approach, we can package it in a jar file. When the file is in the classpath and we use the template, the correct coloring is applied to the 'hovered' field.

Conclusion

With the client side behavior of JSF 2, you have the possibilities to further enhance the components in a component library with some client side features in a reusable way. JSF remains mainly a server side framework but the client side representation can now greatly enhanced by the developer.
With these possibilities available, JSF can go along with the recent HTML5 and JavaScript frameworks raise in interest in the application development business.

You can find the code for this tutorial here.




Sunday 3 February 2013

Client Behavior functionality with JSF 2.x (part 1)

Introduction

One of the lesser know new features of JSF 2, is the ability to define some client behavior for a component in a reusable way. We all know the possibility to enhance a component with ajax, using the tag.  It is also based on the Client Behavior functionality but we can define our custom functionality.

Just as you can define a validator for an input field, you can define a behavior which results in some JavaScript code which can be executed in the browser.

These features shows that, although JSF is still mainly a server side framework, the importance and the popularity of the client side is acknowledged.

Confirm button

We start with a simple example where we like to make a button that first asks for a confirmation before it performs its action.  A classic example is the button that deletes some information but first we ask the user for a confirmation if he is sure to execute this irreversible action.

The key Java class for the Client Behavior is ClientBehaviorBase. It implements the ClientBehavior interface, common to all functionality related to client side behavior, and by implementing the getScript method, half of the work is already done.
For our confirm functionality, we have a method like this

    @Override
    public String getScript(ClientBehaviorContext behaviorContext) {
        return "return confirm('Are you sure ?');";
    }

The return string is the JavaScript we like to execute in the browser, here it is the confirm method which pops-up a javascript ‘window’ with an OK and Cancel button.

When the class is annotated with @FacesBehavior, The JSF system add our class to the list of implemented client behaviors.

@FacesBehavior(value = "confirmation")
public class ConfirmBehavior extends ClientBehaviorBase {

The content of the value member is the, unique, name we can use to refer to our custom client behavior.  This is needed when we define a tag for the behavior.

A tag is needed so that we can specify in the xhtml files which components receive our javascript. In the facelet tag library we can define it as follows.

    <namespace>http://www.rubus.be/jsf/tutorial</namespace>

    <tag>
        <tag-name>confirmation</tag-name>
        <behavior>
            <behavior-id>confirmation</behavior-id>
        </behavior>
    </tag>



The behavior-id must match the value member of the FacesBehaviour annotation.  The tag name can be freely chosen but here it happens to be the same as the behavior id.

Assigning to a commandButton is not different than using any other custom tag that you have defined in a facelet tag library.

<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:r="http://www.rubus.be/jsf/tutorial"
        >
<h:head>
    ...
</h:head>
<h:body>
    ...
    <h:form>
        ...
        <h:commandButton value="with confirmation" actionListener="#{bean.performAction}">
            <r:confirmation/>
        </h:commandButton>
        ...
    >/h:form>
    ...
</h:body>
</html>

When the user clicks now on the button, a confirmation is asked with the text ‘Are you sure?’. And when he clicks on the cancel button, the action listener method isn’t performed. In the case he has pressed on the OK button, the post to the server is executed as usual.

Which components


To what components can we attach a custom client behaviour? This is determined by the ClientBehaviourHolder interface.  It has a few methods to handle the addition and retrieval of registered client behaviors and event names. More on event names in the next section.

Well almost all components implement that interface.  The most useful ones are of course all the input fields and the buttons. But also on the html body component we can attach a behaviour. More specifically, the load event can be used to attach some additional code to the page when rendered in the browser.

How to specify the event?


In our example with the confirmation question, the javascript method is attached to the onClick method of the button.  This is because the click event is the default event for the commandButton component. If we like to attach the code to some other event, then we have to specify the event name with the event attribute of the tag. We will see an example of it in the second part of this blog.

What are all the events which are supported? This differs from component to component. But the rule is that when you have the onXXX attribute on a component to attach some behaviour, the event XXX is available for creating a reusable client behaviour with the technique explained above.

Conclusion


It is very easy to specify some client behavior in a repeatable manner with JSF 2. And in the second part of this text I’ll explain some more advanced topics of the client behavior functionality.