dominoGuru.com

Your Development & Design Resource

Rendering Controls in XPages via User Agent

IBM Lotus Notes 
Domino XPages I have spoken in the past to a need for IBM Lotus Notes Domino Application Developers to embrace the need to develop (and maintain) separate Design Elements for multiple User Agent/Client applications. The pro with this technique is that you can create unique-to-the-client experiences... as quite frankly your Mobile Device Client experience should be more streamlined than your more feature-rich Web Browser or Lotus Notes Client. The con, of course, is the code and Design Element maintenance required. Using traditional IBM Lotus Notes Domino Application Development techniques, you could use Computed Subforms or complex HideWhen Formulas... but XPages allow us to control individual or grouped item rendering in a rather simple way.

Who is this target audience for this tutorial?

The technique discussed in this tutorial can be leveraged by IBM Lotus Notes Domino Application Developers using Release 8.5 (or greater) who need to create multiple-User Agent/Client applications.

What is the scope of this tutorial??

The tutorial specifically showcases support for Webkit (iPhone, iPad, Safari, Chrome, et al) vs. Gecko (Mozilla, Lotus Notes Client, et al), but can be adapted for any multi-User Agent need.

Why would you use the techniques discussed in this tutorial?

The techniques discussed in this tutorial can be applied to more traditional IBM Lotus Notes Domino Application Development (ie., Form, Subform, and View Design Elements), but doing so is horribly inefficient. XPage Development -- leveraging XPage Design Elements, SSJS and Java Script Libraries -- allows us to simplify our development maintenance while improving platform performance.

Tutorial Build

The helloworld.nsf NotesDatabase will consist of a very simple XPage (index.xsp) which will conditionally include HTML Markup and Stylesheets based on the User Agent access the IBM Lotus Notes Domino app.

index.xsp will render LINK and META Elements and include a specific Stylesheet resoruce for Webkit XUL-based User Agents. Alternately, it will render more generic Stylesheets for non-Webkit XUL-based User Agents (as well as not rendering the LINK and META Elements).

To start, I download the iWebkit CSS framework and import it into helloworld.nsf, renaming it webkit.css.

I then create two more Stylesheets named blackberry.css and screen.css for RIM BlackBerry Mobile Device User Agents and Gecko/Trinidad XUL-engine.

Since I'm planning to return the User Agent as part of the XPage (and will be using that to conditionally render various Controls, Resources, and content, I create a common.jss SSJS Library with the following Function:

  1. function getUA(){
  2.     if (!(sessionScope.containsKey("UA"))) {
  3.         sessionScope.put("UA",  facesContext.getExternalContext().getRequest().getHeader("User-Agent"));
  4.     }
  5.     return sessionScope.get("UA");
  6. }

This will allow me to use sessionScope.UA or sessionScope.get("UA") within my XPage.

I create the index.xsp XPage Design Element which consists of the following XPage XML markup:

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <xp:view xmlns:xp="http://www.ibm.com/xsp/core" pageTitle="Hello World"
  3.     xmlns:xc="http://www.ibm.com/xsp/custom">
  4.  
  5.     <xp:this.resources>
  6.         <xp:script src="/common.jss" clientSide="false"></xp:script>
  7.         <xp:styleSheet href="/iwebkit.css"></xp:styleSheet>
  8.     </xp:this.resources>
  9.  
  10.     <meta name="viewport"
  11.         content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" />
  12.     <meta name="apple-mobile-web-app-capable" content="yes" />
  13.     <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  14.     <link href="hw.png" rel="apple-touch-icon">
  15.         <link rel="apple-touch-startup-image" href="startup.png" />
  16.     </link>
  17.  
  18.     <div id="topbar">
  19.         <div id="leftnav">
  20.             <a href="index.xsp">
  21.                 <img alt="home" src="home.png" />
  22.             </a>
  23.         </div>
  24.         <div id="rightnav">
  25.             <a href="http://www.dominoguru.com">dominoGuru.com</a>
  26.         </div>
  27.     </div>
  28.     <div id="content">
  29.  
  30.         <xp:panel>
  31.             <span class="graytitle">Hello World</span>
  32.             <p>You are using the following User Agent:</p>
  33.             <p>
  34.                 <xp:text escape="true" id="useragent" value="#{sessionScope.UA}">
  35.                 </xp:text>
  36.             </p>
  37.         </xp:panel>
  38.     </div>
  39.     <div id="footer">
  40.         <xp:panel>
  41.             <a class="noeffect"
  42.                 href="http://iwebkit.net">
  43.                 Powered by iWebKit
  44.             </a>
  45.         </xp:panel>
  46.  
  47.     </div>
  48.  
  49. </xp:view>
  50.  

This looks great on a WebKit-based User Agent (see screen cap from Google Chrome below), but horribly on everything else. Additionally, I have META and LINK markup that I don't really want to render to a User Agent that's not WebKit-based (Lines 10-16), and if I'm not using iWebkit for that specific User Agent rendering then there's really no reason to include the footer link.

Hello World on WebKit UXL-based User Agent

Now I'll make this thing cross-User Agent-friendly!

First, I'll conditionally load my 3 stylesheets based on the User Agent:

  1. <xp:this.resources>
  2.     <xp:script src="/common.jss" clientSide="false"></xp:script>
  3.     <xp:styleSheet>
  4.         <xp:this.href>
  5.             <![CDATA[#{javascript:var css = "/screen.css";
  6.             var UA = getUA();
  7.             if (UA.toLowerCase().indexOf("webkit") != -1) { var css = "/iwebkit.css"; }
  8.             if (UA.toLowerCase().indexOf("blackberry") != -1) { var css = "/blackberry.css"; }
  9.             return css;}]]>
  10.         </xp:this.href>
  11.     </xp:styleSheet>
  12. </xp:this.resources>

While the default Stylesheet is screen.css, I will load iwebkit.css or blackberry.css based on the results of looking for "webkit" and "blackberry" in the reported User Agent String respectively.

I will move the META and LINK Element markup into a Custom Control named meta_webkit. Now, I'll use my getUA(); SSJS Function to conditionally render/include the Custom Control with the following XPage XML:

  1. <xc:meta_webkit>
  2.     <xc:this.rendered>
  3.         <![CDATA[#{javascript:var UA = getUA();
  4.         if (UA.toLowerCase().indexOf("webkit") != -1) {
  5.             return true;
  6.         } else {
  7.             return false;
  8.         }}]]>
  9.     </xc:this.rendered>
  10. </xc:meta_webkit>

The last piece to this puzzle is the iWebKit footer promo, which I handle by conditionally rendering the Panel Control based on -- you guessed it -- the User Agent:

  1. <xp:panel>
  2.     <xp:this.rendered>
  3.         <![CDATA[#{javascript:var UA = getUA();
  4.         if (UA.toLowerCase().indexOf("webkit") != -1) {
  5.             return true;
  6.         } else {
  7.             return false;
  8.         }}]]>
  9.     </xp:this.rendered>
  10.     <a class="noeffect" href="http://iwebkit.net">Powered by iWebKit</a>
  11. </xp:panel>

The resulting XPage, when rendered via a non-Webkit rendering engine, will look like this:

Hello World on Gecko UXL-based User Agent

Conclusion & Example / Demo Download

In this example, I am able to control what is rendered based on the User Agent. Taking this technique a step further, I could completely control what is rendered to a user - based on their User Agent, their access to a particular app, their access to that particular NotesDocument, and countless other variable immediately available to me within the session.

XPages give IBM Lotus Notes Domino Application Developers complete control over what is rendered to a given User Agent - be it an iPad or the Lotus Notes Client. Most of this options are immediately available via the rendered Property on a given Control (see below):

rendered Property on XPage Controls - IBM Lotus 
Notes Domino Application Development

... most you can control with a little bit of forethought as seen with the inclusion of User Agent-specific Stylesheets. At the end of the day, XPages are about giving you - the IBM Lotus Notes Domino Application Developer - more control.

Click here to download the example / demo NotesDatabase app discussed in this tutorial:

Rendering Controls in XPages via User Agent Example / Demo 
Application Download

If you have any questions -- or requests -- comment to this post or contact me at ctoohey@dominoguru.com.


About the author: Chris Toohey

Thought Leadership, Web & Mobile Application Development, Solutions Integration, Technical Writing & Mentoring

A published developer and webmaster of dominoGuru.com, Chris Toohey specializes in platform application development, solutions integration, and evangelism of platform capabilities and best practices.



More from dominoGuru.com


dominoGuru.com is powered by IBM Notes Domino XPages & hosted by Prominic.NET

Contact Us

Use our Contact / Feedback form or one of these email addresses:

Creative Commons License

Except where otherwise noted, dominoGuru.com by Chris Toohey is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.