Saturday, February 18, 2012

Radio buttons and jQuery Mobile

APEX 4.2 is supposed to put mobile front and center in APEX. But some developers aren't waiting. If you're in that small group of folks that is pushing forward with mobile development using jQuery Mobile prior to version 4.2, you may have found an issue with radio buttons.

jQuery Mobile does a fantastic job of enhancing the look and feel of elements in the DOM so that they look and work better in mobile browsers. For various reasons, including accessibly and proper alignment of elements, jQuery Mobile expects some specific HTML. In most cases, satisfying these requirements in APEX is as simple as wrapping the label and the element with a wrapper div. Even in 4.1 this can now be done from the label.

Radio buttons, on the other hand, are a good example of where APEX will need to be enhanced even more to work properly with jQuery Mobile. For now we just have to do a little extra work. Here's the standard HTML output for a single column radio button in APEX:

The markup produces the following when rendered in a browser:

When we go into "mobile mode" the table is gone and the elements are wrapped with a div so we get the following HTML output:

Once jQuery Mobile applies it's enhancements to the markup, we get the following rendering:

It may not be noticeable at first, seeing as how it's so different from the standard rending, but the look is not quite optimal. The reason is that jQuery Mobile is expecting output more like this:

The differences, while subtle, are important. Some are easy to spot while others are not. Here's a brief list:
  1. The fieldset that jQuery Mobile is expecting has some important attributes (data-role and data-type) 
  2. APEX uses a label for the fieldset while jQuery Mobile wants a legend (inside the fieldset)
  3. The fieldset in APEX has the CSS display property set to block via apex_4_1.min.css
  4. Each label in the fieldset in APEX is followed with a br element
  5. APEX adds the tabindex attribute (causes jQuery Mobile to "focus" incorrectly)
While we can't control everything that APEX outputs, we can modify the output after it makes it to the browser and before jQuery Mobile goes to work enhancing it. Here's some jQuery code that does just that:

Since most of use are not using the Ajax based page loading that jQuery Mobile like to use be default, putting the code in the Execute when Page Loads portion of the page attributes will work fine. Once jQuery Mobile is finished enhancing the new markup the radio buttons will render as follows:

Or, if you prefer, you can remove the optional .attr('data-type', 'horizontal') line from the JavaScript to get the following rendering:

If you haven't already gotten started with mobile development in APEX, check out Marc Sewtz's blog for details and downloads that can get you up and running quickly and easily. I'm really looking forward to seeing what Marc and the rest of the team has planned for the 4.2 release!