Friday, 23 September 2011

Fixing the dojox.mobile.TabBar to the bottom of the mobile screen

The Dojox.mobile API provides some great features, functions and themes to quickly code up web services for mobile platforms, and have them appear in a familiar, native style to the device, with intuitive and easy to use menus, navigation, and form features.

There is, however, one quirky issue (with dojo 1.6 at least) which took me a few minutes to figure out, and so I thought I'd write up a quick post to help anyone else who is having trouble getting the TabBar to "stick" to the bottom of the screen, whilst the rest of the content happily scrolls.


Using the dojox.mobile API, you will most likely have built up your panes with a collection of dojox.mobile.View, and dojox.mobile.ScrollableView elements, and these have a different affect on where the dojox.mobile.TabBar appears.

If you have used dojox.mobile.ScrollableView, this makes the TabBar float over the top of an otherwise scrolling main-content. You need to add a style of "margin-top: -49px;" to the TabBar node to raise it into the viewport, but it will then always be visible, like so:

dojox.mobile.ScrollableView


To navigate, on mobile devices you use a "stroking" finger gesture, and on computers/compat devices, you must use an equivalent click-and-drag movement. This can have shortfalls in some environments, such as Blackberrys, where there is no touch screen, or click-and-drag functionality.

If you opted for dojox.mobile.View then the dojox.mobile.TabBar will appear at the bottom of the page, and the user will have to scroll down to the bottom access it. A scrollbar is displayed on the right hand side to facilitate this movement.

dojox.mobile.View 

This is the most universal and reliable format for cross-platform services, because you can still invoke a scroll motion using a touch-screen swipe, but pointing and scrolling devices can still also be used for easy navigation.

You can mix and match your view types, even within the same navigational flow, and each pane will act accordingly as above, of course, if you do switch between them, it is going to give an inconsistent user experience.

Monday, 12 September 2011

Making dojo datagrid columns non-resizable and unsortable

When dealing with grids of data in dojo I often find myself wanting to manage the control of the individual columns quite specifically, disabling the user resize ability, or click-to-sort on headers.

Here are two ways these two functions can be achieved on a dojox.grid.EnhancedGrid in a _Templated widget.

Disabling resize is quite easy to manage, when you know how. The column headers of a datagrid can be passed a noresize flag, which when set to true, inhibits this ability.

Simply define your column header as so:

<th field="id" width="50" noresize=true width="200"> ID </th>

Setting the width is optional, but any column without it will default to be 6em wide.

Preventing sorting is a little trickier. To do this I added the following code to the postCreate function of my widget to disable sorting on the fifth and sixth columns of my table (indexing starts at 1):


postCreate: function() { 
    this.myGrid.canSort = function(col){ if(col === 5 || col === 6) { return false; } else { return true; }};
},



Thursday, 1 September 2011

Creating a custom filter in Spring

Adding a filter in spring is something that seems like it should be easy, but can be tricky if you get your configurations in a twist.

So here is how I added a really simple filter to my Spring application.

In my web.xml I added the following filter definition, alongside the other standard security and encoding ones:

 <filter>
  <filter-name>expiredPasswordFilter</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
  <init-param>
    <param-name>targetBeanName</param-name>
    <param-value>expiredPasswordFilterBean</param-value>
  </init-param>
</filter>



The org.springframework.web.filter.DelegatingFilterProxy is the relevant filter type that allows you to then declare a targetBeanName value... which corresponds to a declaration we add in our applicationContext.xml, as so:

<bean name="expiredPasswordFilterBean" class="com.companyname.webapp.filter.ExpiredPasswordFilter"/>

With that connection set up, we now head back to the web.xml to define the mapping for our filter... separately from the above filter definition. In my case, this was enough:

 <filter-mapping>
  <filter-name>expiredPasswordFilter</filter-name>
  <url-pattern>*.html</url-pattern>
 </filter-mapping>


the filter name connects to the previous web.xml definition, and the url-pattern in my case was for the filter to be run on every request for a HTML path.

With that all in place, all I needed to do was declare the actual filter control class. This is defined in the applicationContext above as being at com.companyname.webapp.filter.ExpiredPasswordFilter, and the class looks a little like this:

com.companyname.webapp.filter.ExpiredPasswordFilter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.filter.OncePerRequestFilter;

public class ExpiredPasswordFilter extends OncePerRequestFilter {

 protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain) throws ServletException, IOException {
  
  /*
   *  This is where I did my user flag checking
   */
  
                chain.doFilter(req, res);
 }
}


The actual logic of the filter can be almost anything you want! But just make sure you call chain.doFilter(req, res); to invoke the next filter in the chain. This can be at any point throughout your code, and control is passed straight back to your filter once the chain has been executed, which can be useful for ensuring other security/authentication filters have been run before you do anything additional yourself.