Showing posts with label CSS3. Show all posts
Showing posts with label CSS3. Show all posts

Monday, 13 April 2015

Native GridLayout component in PrimeFaces 5.2 (panelGrid)

Introduction

A while ago, I blogged here about the GridLayout component for JSF 2.X which allow you to have the responsive layout using DIV structure with CSS classes from Bootstrap or PrimeFaces. 


In the recent PrimeFaces 5.2, the panelGrid component is improved so that you can have the same functionality. 

Improvements

With the new version, you can specify the CSS column class yourself, which allows you to have columns of different width.


So now it is possible to write something like this 

<p:panelGrid columns="2" columnClasses="ui-grid-col-8, ui-grid-col-4" style="width: 100%" layout="grid">

    <h:outputLabel value="First Column"/>

    <h:outputLabel value="Second Column"/>
</p:panelGrid>
And have 2 columns, the first twice as wide as the second one.

The old functionality is still available, so if you don't specify any columnClasses in the above example, both columns have the same width.

So if you are using PrimeFaces, there is no need anymore for my GridLayout component, unless you want to use twitter bootstrap CSS classes.

That is all for now about the new primeFaces 5.2. Enjoy it.

Monday, 19 January 2015

GridLayout component for JSF 2.X

Introduction

It is common practice to use a CSS Grid to define the layout of your web application page.  We shouldn’t use tables for that purpose.
Also in JSF we can use this CSS Grid but it requires quit a lot of DIV elements and thus boilerplate in your page. The good thing is that we can create a custom component which reduce the amount of html we need to put in dramatically.  The component got the name gridLayout.

PrimeFaces recently introduced in his version 5.1, also CSS Grid classes.  The following example comes from the user guide.
<div class="ui-grid">
    <div class="ui-grid-row">
        <div class="ui-grid-col-4">Col1</div>
        <div class="ui-grid-col-4">Col2</div>
        <div class="ui-grid-col-4">Col2</div>
    </div>
</div>

But also other CSS Grid systems can be used with the gridLayout custom component.  The component was first used in an application that used the Bootstrap CSS grid.  And in fact, all CSS grids can be used as you specify which CSS class will be used on the row DIV and which will be used on the column DIVs.

gridLayout

The gridLayout component has 3 attributes, which are
columns: This determines the number of columns which should be created.
rowClass: Determines the CSS class which will be used on the row DIV, in above example it is ui-grid-row.
columnClasses: A comma separated list of CSS classes which will be used on the column DIVs.

The needed steps to integrate the component are described further on in this text, I already give you an example usage:

<c4j:gridLayout columns="2" rowClass="ui-grid-row" columnClasses="ui-grid-col-2, ui-grid-col-4">
    <p:outputLabel for="firstName" value="First name"/>
    <p:inputText id="firstName"/>
    <p:outputLabel for="lastName" value="Last name"/>
    <p:inputText id="lastName"/>
    <h:panelGroup/>
    <p:commandButton value="save"/>
</c4j:gridLayout>
The above example creates a layout with 2 columns. The first column, with the labels, spans 2 ‘columns’, the other column takes 4 ‘columns’ of the CSS grid.  As you can see, we don’t need to take up the complete with available.  In this example, we are just using half of the screen.
On the last row, the button is aligned with the fields due to the .

Configure the project and usage of the component.

  • Download the code from GitHub.  It is a maven project but I didn’t deploy it to Maven Central.
  • Build it locally and add it to the dependencies of your project
<dependency>
     <groupId>be.rubus.web</groupId>
     <artifactId>gridLayout</artifactId>
     <version>1.0</version>
</dependency>
  • Define the namespace on top of your xhtml page, like 
xmlns:c4j="http://www.rubus.be/component"
  • Start using it, according to the info you saw already here.

Things to know

  • It is released under the Apache V2 License.
  • It is compiled against Java 1.5
  • It is only dependent on JSF 2.0 (Java EE 6).
  • It is NOT dependent on any component library.
  • If you define less CSS classes in the columnClasses attribute, as you have defined in the columns attribute, columnClasses are reused from the beginning of the attribute value.
    So the example from the PrimeFaces user guide can be achieved by the following coding
    <c4j:gridLayout columns="3" rowClass="ui-grid-row" columnClasses="ui-grid-col-4">
  • The correct assignment of each JSF component to a certain column and row is only guaranteed if you use JSF components as children.  If you use html elements or plain text/EL expressions, the layout can be very surprising and not want you had in mind.
  • You can also put your custom CSS classes in the columnClasses attribute and even combine them.  So if you want to right align the label column, you can write something like this.
    <c4j:gridLayout columns="2" rowClass="ui-grid-row" columnClasses="ui-grid-col-2 alignRight, ui-grid-col-4">

Conclusion

The gridLayout component is a very small one but makes it easy to use the CSS Grid of your choice in your JSF Web pages.
Have fun coding.

Update

13/4/2015

With the new PrimeFaces 5.2 release, the panelGrid component is updated to have similar functionality as the GridLayout (but only for PrimeFaces CSS classes)

See http://jsfcorner.blogspot.co.at/2015/04/native-gridlayout-component-in.html.




Friday, 31 October 2014

Overriding defaults of PrimeFaces component properties

Introduction

The prime faces components can be customised with many options.  They can be specified by using the properties on the components.  For all these customisation possibilities, there are defaults active so that you don’t need to specify each option.

But what if that default value doesn’t fit for your project. What are your options?  I’ll show you how you can override the default in the case of the datable component.  but other components can be modified in the same way.

Paginator for dataTable.


The dataTable component can show the paginator bar to do navigation in a table with a lot of records.  By default, this bar is shown on top and at the bottom of the table.

But what can you do when you only want to show it at the bottom of the table?

Use the property


Of course, everywhere you place the table on a screen, you can specify the paginatorPosition property and set it to bottom.

    <p:dataTable value="#{personBean.persons}" var="person" paginator="true" rows="3" paginatorPosition="bottom"> 
        <p:column headerText="name"> #{person.name}

    </p:dataTable>

This will work of course but is more work and it can be forgotten by the developers. especially in larger scale applications.

And what happens if they decide that after all, they want to show it as it ways, on top and at the bottom? Change everything again?

CSS is everywhere

Since PrimeFaces relies heavily on CSS, a solution can be found in specifying some CSS style which hide the top paginator bar.

If you inspect the HTML in the browser, you can easily see that the top paginator has a style class with the name ui-paginator-top.

So the following CSS is able to hide the top paginator bar.

    <style type="text/css"> 
        .ui-paginator-top { 
            display: none; 
        } 
    </style>

But this solution is not ideal. The paginator is suppressed in a general way, so we don’t need to change the xhtml files individually.  But the server sends this information to the browser.  So the size of the response is too large because some parts aren’t shown anyway.

Change the defaults


There exists another way to achieve our goal.  You can alter the defaults of PrimeFaces quite easily since PrimeFaces is designed with extensibility in mind. 
The default values are coded in the class org.primefaces.component.datatable.DataTable.

There exists for example a method getPaginatorPosition() which retrieves the values specified in the xhtml file or, when not specified, returns the value “both” which is the default for this property.

So when you extend this class, you can overwrite this method and return, for instance always the value “bottom” and we now have override the default (well we basically ignore the property and always return the same value)

public class MyDataTable extends DataTable { 
    @Override 
    public String getPaginatorPosition() { 
        return "bottom"; 
    } 
}

Just overriding the method in the extended class is not enough.  You need to inform JSF that your version must be used as component class.

This can be done by specifying the following snippet in the faces-config.xml file.

    <component> 
        <component-type>org.primefaces.component.DataTable</component-type> 
        <component-class>be.rubus.web.primefaces.MyDataTable</component-class> 
    </component>

And if you now run the application, you will see that there is no top paginator bar and it isn’t even present in the generated HTML.

How can you know which value you need to use for component-type?  Look in the PrimeFaces faces-config.xml file (you can find it in the META-INF directory of the PrimeFaces jar) and look for the component class you override.  That is the value you need to use.

Conclusion


You can easily override the default values for the PrimeFaces component properties.  Just extend the PrimeFaces component class and put any value you like in the overriding method.  You just have to specify then your component class in the  faces-config.xml file.

Sunday, 21 September 2014

Input in uppercase with JSF inputText, a TagHandler example

Introduction

Recently there was a requirement from a client to be able to input data all in uppercase within a JSF web application.

When you write a simple JSF converter and add a CSS style class to the component to uppercase all input client side, you’re done. You can find various posts on the internet where this solution is described.

This blog shows how you can improve the solution.  You can create a JSF tagHandler which allows you to combine the adding of the converter and CSS style class, by defining your custom tag.
It is convenient and typesafe.  Typesafe Because it is a tag, so you have IDE autocompletion.  Within the name of the converter and the CSS style class name, you can make some typos which leads to an incorrect behaviour.

TagHandler

What is a JSF TagHandler? The tagHandler is some piece of code executed when JSF encounters your custom tag that you have placed in the xhtml page.  This code runs during the creation of the JSF component tree and thus ideal to tweak some components as we like to do for the uppercase scenario.

Your tagHandler should extend from the javax.faces.view.facelets.TagHandler JSF class.  And all your work should go into the apply method.  This method is called in response to the identification of your custom tag in the xhtml file.

This method has a UIComponent typed parameter representing the parent component your custom tag belongs to.  So adding a converter and style class to your inputText component is very straightforward:

public class UppercaseHandler extends TagHandler { 
 
    public UppercaseHandler(TagConfig config) { 
        super(config); 
    } 
 
    @Override 
    public void apply(FaceletContext ctx, UIComponent parent) throws IOException { 
        if (parent instanceof HtmlInputText) { 
            HtmlInputText inputText = (HtmlInputText) parent; 
            inputText.setConverter(new UppercaseConverter()); 
 
            String styleClass = inputText.getStyleClass(); 
            if (styleClass == null) { 
                styleClass = ""; 
            } 
            if (!styleClass.contains("uppercase")) { 
                inputText.setStyleClass(styleClass + " uppercase"); 
            } 
        } 
    } 
} 

Configuration

The next step we have to do, is define the name of our custom tag and link the tagHandler class to it. This is done in the Facelets configuration file. Here you can define your new tag name and the tagHandler class name which is associated with it.

<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-facelettaglibrary_2_0.xsd" 
                version="2.0"> 
    <namespace>http://www.c4j.be/rubus</namespace> 
 
    <tag> 
        <tag-name>uppercase</tag-name> 
        <handler-class>be.sezz.handler.UppercaseHandler</handler-class> 
    </tag> 
 
</facelet-taglib>

In other scenarios, you can assign tags to converters, custom defined components or user defined EL functions.

Example

In the Facelets Configuration file, we have defined a namespace(http://www.c4j.be/rubus in the example above)  This namespace we can be used in the xhtml file and our custom tag can be used. An example could be.

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
      xmlns:h="http://java.sun.com/jsf/html" 
      xmlns:r="http://www.c4j.be/rubus"> 
 
... 
 
<h:body> 
    <h:form id="mainForm"> 
        <h:inputText id="field" value="#{someBean.value}"> 
            <r:uppercase/> 
        </h:inputText> 
    </h:form> 
</h:body> 
</html> 

Conclusion

The JSF TagHandler is a very convenient way of assigning a tag name to some custom functionality you have created.  Better because it is ‘typesafe’ and thus you get warned when you should make a typo.
In the example above, you saw how you can assign in a few lines a custom converter and CSS style class to a JSF inputText component.




Sunday, 6 July 2014

Mavenize your Custom PrimeFaces Theme

Introduction

PrimeFaces relies on the ThemeRoller themes for the look of the components.  There are more then 35 already available. But it is also possible to create your own custom ones.  This blog not only describes the creation of such a new theme, which is already quit good documented, but also how you can wrap it in a maven project and add some further customisations.

Create custom theme

ThemeRoller has an online visual tool to design your custom theme.  You can specify Font and colour for various types of content like header, highlights, buttons and so on.

Once you are more or less comfortable with how the examples on the site looks, you are ready to download the theme.
On the download page, it is very important to exclude all the components, you only need the skinning style. You have a convenient ‘toggle all’ checkbox to remove all the components. Also the 1.11 version of jQuery is NOT supported, so take one of the other 2 versions noted on the page.

This zip needs a few modifications before it can be used as custom theme for PrimeFaces. Luckily this is automated and can be done on this page. 

Here you can specify the custom name for your theme and after you upload the zip to the site, you are able to get a jar file which can be used directly in your application.

Mavenize 

Most of the time you want to perform some modifications on the theme. Some of the modifications I made recently are described further on.
So it can be very convenient to turn the jar file into a maven project where the maven package goal generates a valid PrimeFaces Theme.
This is very easy to accomplish.

Just create a minimal POM file, you just need the groupId, artifactId and version info, nothing else, and extract the contents of the  jar into the src/main/resources directory.


The directory structure should look like the image above. The contents of the downloaded jar file is extracted in the resources directory as indicated in the image.

From now on, you can generate the PrimeFaces theme with a simple mvm clean package command.

Customizations

In this section, I want to share you a few of the customisations I made in my recent project.

Font

One of the common questions on the PrimeFaces forum is how you can change the size of the text within PrimeFaces Components.  This can be done by specifying a value for the .ui-widget, .ui-widget .ui-widget  CSS selector.

Instead of putting it into the css file of your application, you can also put this value in the theme and use it in all your applications.

Put the same font information also in the body selector as some components of your application are not from PrimeFaces (for example the h:outputText) and should look the same.

Table record selection

If you look closely to a selected record in a data table component, you see that the upper border isn’t highlighted like the 3 other borders. (look at the showcase with a theme like Blitzer, there you can see it easily).

You can ‘fix’ this in your theme CSS, look for the ui-state-highlight selector.

.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {
   border: 1px double "yourColor"
   ...
}

Replace the solid with double and you wil see that all 4 borders are identical now.

Other then these 2 customisations, you can put anything you need in that theme file. Examples are
- A different colour for the cancel type of buttons
- A different colour for the default button
- Error indication on a field with a validation error
and so on.

Conclusion

Creating a custom PrimeFaces theme can be done quite easily.  Starting from the ThemeRoller visual designer, you can convert it to a maven project which allows you to customise the theme even further.


Friday, 31 August 2012

CSS3 ellipsis functionality with PrimeFaces (Client side and server side)

Introduction

If you have a certain user UI requirement, you have basically 2 options when using JSF.
Since the output of the JSF system is in most cases just plain HTML, you can mixing the required CSS and javaScript to have your UI feature. Or you can have some server component that does most of the work and generates the required HTML from their renderers.
An example makes this situation clear.  In a project I had the requirement that on a screen there were a lot of long descriptions of codes that needed to be displayed.
In fact there were so much of them that the screen was very crowded when the full description of all codes was shown. The solution was that only a part of it was shown on the screen and when the mouse hoovered over, the complete description was shown

Server side solution

As I'm much more experienced in writing Custom JSF components, I created a new PrimeFaces component that is capable of showing some truncated text. It is almost identical to the outputText component and has only one additional attribute called truncateAt.
You can define with it the maximum number of characters it shows before three dots are generated.  In the case the text has more characters then specified in the truncateAt attribute, the complete text is placed in the title property of the span element surrounding the shortened text.
This custom PrimeFaces component is quit easy and the important parts of the code responsible for the rendering is shown below:

        writer.startElement("span", null);
        writer.writeAttribute("id", clientId, null);
        String value = outputText.getValue().toString();
        Integer truncateAt = outputText.getTruncateAt();
        if (truncateAt != null && value.length() > truncateAt) {
            writer.writeAttribute("title", value, null);
            value = value.substring(0, truncateAt-1)+"...";
        }

        writer.writeText(value, null);
        writer.endElement("span");
You can improve the above code by searching the words in the description and not slash words in two.

After creating a simple POJO for the component itself (extending HtmlOutputText) and registering your work in the faces-config.xml
<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-facelettaglibrary_2_0.xsd"
                version="2.0">
    <namespace>http://www.c4j.be/primefaces</namespace>

    <tag>
        <tag-name>outputText</tag-name>
        <component>
            <component-type>be.c4j.jsf.primefaces.outputtext.OutputText</component-type>
            <renderer-type>be.c4j.jsf.primefaces.outputtext.OutputTextRenderer</renderer-type>
        </component>
        <attribute>
        ....
    </tag>


You have your required functionality.

Cient side solution


Afterwards, some people pointed me to the CSS3 ellipsis (text-overflow attribute) as an alternative solution.  With some standard PrimeFaces components and the use of a proper css style definition, you can achieve the same effect.

The css style class looks like this
.ellipsis {
    display: inline-block;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    width: 400px;
    vertical-align: bottom;
}


where the width property can be varied to your convenience.  The central element here is the text-overflow: ellipsis line.  Since you can only specify the size of a html element in block mode, you have to specify the display: inline-block to allow more information on the same 'line'

Within the JSF view we can use the tooltip PrimeFaces component to show us the long description when we hoover over the truncated area.
<h:panelGroup styleClass="ellipsis" id="longText">${bean.text}</h:panelGroup>
<p:tooltip for="longText" value="#{bean.text}"></p:tooltip>

Differences of solutions


Both solutions are resulting in more or less the same visual and functional result in the browser but there are a few small differences.
  • With the client side solution, the truncation of the description is performed based on the size it takes on the screen.  When the user changes the font size, there are a different number of characters displayed. With the server side solution, the number of characters is always the same, despite of the user font settings.
  • The tooltip is only shown when some truncation of the description occurs in the server side solution in contract to always for the client side solution.  This can be changed by adapting the rendering code and always add the description to the title property.  However showing the same text in the tooltip isn't common practice.

Comparison of solution


As said, both solutions are resulting in more or less the same visual and functional result in the browser but each has his pro and contra. An overview of them

pro server side
  • Works on all browsers, no CSS3 support required
  • No CSS required, good for CSS/JavaScript newbies (I'm one of them)
  • Advanced algorithm determining the ... position easy to implement.

contra server side
  • Custom JSF component required (you need to use another tag in the JSF view if you want the functionality)
  • Less skinnable (look and feel changes by just changing CSS and JavaScript)

For the client side solution, the pro and contras are basically switched.

pro client side
  • No special/custom JSF component required, only the tooltip component of PrimeFaces
  • Skinnable
  • Screen layout is better preserved when user changes font size in browser.

contra client side
  • CSS3 browser support required.  This time Firefox was very late to include support for it and it is only available since version 7.
  • Positioning of the ... is difficult to align with the word boundaries.

Conclusion


I still prefer the server side solution, the one I used in the project.  I find it easy to create a simple JSF custom component where I'm in control of the result in Java and don't need any CSS3 or other client side solution to have the functionality that I need.
But for all the other people that like playing with those things, you can see how easy it is to do it with PrimeFaces.

You can find an example demo here.

Friday, 13 January 2012

PrimeFaces 3 on non CSS3 compliant browsers

PrimeFaces 3

PrimeFaces 3, final release at the beginning of this year, is using CSS3 features to have some nice features and functionality.  And although there is a fair amount of CSS3 in the latest versions of the browser, also in IE9, their are a lot of people that uses a browser which isn’t capable of handling these nice things like rounded corners.
And for most of the widgets, like input field, it is no problem for the end user that he doesn’t have a rounded corner.  But for some, like a radio button, it is confusing that the user sees a rectangular shape instead of the, for him familiar, circle.
As an example, go to the showcase of PrimeFaces and look how the radio buttons are displayed.  Do you see a circle, then you have a CSS3 compliant (at least for the rounded corners feature) browser.  For those that have Internet Explorer 9, they can see how it is displayed for users having IE7 or IE8.  Go to the developers tools (or press F12) and select there the option ‘Browser mode: IE7’. The radio buttons become squared and I can understand the reaction of the end user that filed an issue on my last project.

Find a solution

On the internet, there are plenty solutions that provide you the possibility to have something like rounded corners in Internet Explorer 8 or older. You can split them up in 2 groups.

JavaScript

Here you have to include a JavaScript on your page and in the windows.onload function you have to pass the id’s of the elements that you like to decorate with a rounded corner. The problem with this approach, in combination with PrimeFaces, is that the DOM elements that are responsible for the presentation don’t contain an id attribute.  (Yes, there isn’t any input tag for the radio button so that it can be made styleable)

<div class="ui-radiobutton-box ui-widget ui-corner-all ui-radiobutton-relative ui-state-default">
   <span class="ui-radiobutton-icon"></span>
</div>

VML


The other solution is based on Vector Markup Language (or VML in short), a specification of Microsoft and others that lost the battle against SVG.  However, it was integrated in some of Microsoft products, like the browser.  With VML, it is possible to have rounded corners and a good site where everything is explained, with the inevitable pitfalls, is here.

So I added the script and updated the css file of the project to include the property behaviour in the style classes .ui-radiobutton .ui-radiobutton-box.  It worked like a charm on my computer (emulating IE7 with the help of the developer tools) and on a lot of the computers of other testers. But on another machine it crashed IE completely. Since it isn’t a reliable solution for a public website, I had to find something else.

Adapt skinning


Since PrimeFaces is using themes, there had to be a solution to fix the problem that way.  If I can just place the image of radio button on the area where the user expects it, there couldn’t be any problem like the VML not supported or browser incompatibilities.

And after trying a few scenarios, I’m not a css expert you know, I came to a solution which is quit simple.  I even didn’t need two images, one for the selected and one for the deselected situation.  This is what I added to the css file of the project.

.ui-radiobutton-box {
    background: url("../javax.faces.resource/radio_button.png.jsf?ln=images") no-repeat !important;
    border-style: none !important;
}

.ui-radiobutton .ui-radiobutton-box {
    width: 18px !important;
    height: 18px !important;
}

Some words of explanation:
  • All the properties need the !important marker to overrule the values that comes from the theme css file.

  • The background property defines the image that needs to be displayed.  I’m using the JSF resource notation to reference the image.

  • The border style is there to remove the square of the div element.

  • The size is maybe strange at first glance. The original size of the div element is 16 and then you have to add the border size (1 pixel) to it.  The image contains the complete radio button and needs to be 18 pixels wide.

And to my surprise, the default behaviour of PrimeFaces was providing me a dot in the center of the circle when the radio button is selected.

The easiest way to create the image is to take a snapshot of the screen area in a browser that is capable of rendering CSS3 rounded corners.

Disadvantage


The solution described above has a one major disadvantage, it isn’t compatible with the theme support.  To formulate it maybe a bit more correct, whenever you change the theme, you have to change the image that is used for the radio button whenever you want the background colour to match with the rest of the colours in the PrimeFaces theme.

Conclusion


Since the PrimeFaces 3 JSF component library uses CSS3 features, the representation on browsers that doesn’t support it, like IE7 and IE8, can be a little bit awkward.  A solution for the squared representation of radio buttons can be found in this text.  I uploaded also a test project on Google code for those that want to play with it.