At Red Pill Development we're pushing the envelope a bit on XPages Mobile, we're certainly pushing the mobile controls to their limits. Because of this sometimes we need to take matters into our own hands and override the XPages Mobile controls and kind-of take over how they operate or create our own.
One of the things you're going to encounter when you delve into XPages Mobile development is trying to put a Tab Bar at the bottom of the screen that actually stays at the bottom of the screen. We were able to incorporate this by implementing the Dojo ScrollablePane as a custom dijit. We needed to pursue this route as it had to work with Domino 8.5.3. If you're using Domino 9.0 presumably you can just change the dojoType of a div to "dojox.mobile.ScrollablePane", add the dojo resource and voila you're done. However, the ScrollablePane didn't come around until Dojo 1.8 and Domino 8.5.3 uses Dojo 1.6.
So, to incorporate this I followed a post I did a while back on adding a custom dijit to an NSF. So once that was setup, I needed to hijack the Dojo 1.8 version of dojox.mobile.ScrollablePane. To do this you'll need to copy the files needed directly into the nsf. The files you'll need are:
-
dojox\mobile\Pane.js
-
dojox\mobile\ScrollablePane.js
-
dojox\mobile\_ScrollableMixin.js
-
dojox\mobile\scrollable.js
-
dojox\mobile\sniff.js
I copied all of those files including the directory structure into a folder I created in the WebContent folder called redpill. So we ended up with a directory structure of WebContent\redpill\dojox\mobile\*.js. We need all of those files because following what ScrollablePane.js extends that would be all of it's recursive dependencies. All of those particular files didn't show up until Dojo 1.8. The dependencies that were part of Dojo 1.6 you don't need to include here. You'll also need to go through all of those files and add redpill to the path and declared class to make it read redpill.dojox.mobile.* or redpill/dojox/mobile/*.
Theoretically all you should have to do now is create a div that will hold the content that you want within the ScrollablePane and give it a dojoType of "redpill.dojox.mobile.ScrollablePane". However you will run into some weirdness, as in nothing is displayed. So you'll have to extend the startup method from _ScrollableMixin.js inside the ScrollablePane.js file.
startup: function() {
this.inherited(arguments);
//Added by Red Pill Development to ensure that the control is actually created
this.resize();
//END RPD
}
Once that's done, you should get data within the scrollable pane. Now, to get the header and footer to stay where they should there are some properties of the ScrollablePane you can set that will lock the location of those elements. Those properties are:
-
fixedHeader - The client side ID of the header
-
fixedFooter - The client side ID of the footer
-
fixedHeaderHeight - The height in pixels of the header
-
fixedFooterHeight - The height in pixels of the footer
So, for your header and footer you should add those outside the div you gave the dojoType of redpill.dojox.mobile.ScrollablePane and you should end up with XSP markup something like the following:
<xe:appPage
id="appPage1"
pageName="firstpage">
<xe:djxmHeading
id="djxmHeading1"
label="Scrollable Pane Demo">
</xe:djxmHeading>
<xp:div
id="scrollableContent"
dojoType="redpill.dojox.mobile.ScrollablePane">
<xp:this.dojoAttributes>
<xp:dojoAttribute name="fixedFooter">
<xp:this.value><![CDATA[#{javascript:var mobFooter = getComponent("tabBar1");
return mobFooter.getClientId(facesContext);}]]></xp:this.value>
</xp:dojoAttribute>
<xp:dojoAttribute name="fixedHeader">
<xp:this.value><![CDATA[#{javascript:var mobHeader = getComponent("djxmHeading1");
return mobHeader.getClientId(facesContext);}]]></xp:this.value>
</xp:dojoAttribute>
<xp:dojoAttribute
name="scrollDir"
value="v">
</xp:dojoAttribute>
<xp:dojoAttribute
name="roundCornerMask"
value="true">
</xp:dojoAttribute>
<xp:dojoAttribute
name="radius"
value="5">
</xp:dojoAttribute>
<xp:dojoAttribute
name="fixedHeaderHeight"
value="54">
</xp:dojoAttribute>
<xp:dojoAttribute
name="fixedFooterHeight"
value="54">
</xp:dojoAttribute>
</xp:this.dojoAttributes>
<xe:dataView
id="dataView1"
pageName="secondpage"
openDocAsReadonly="true"
rows="30">
<xe:this.data>
<xp:dominoView
var="defaultView"
viewName="Default">
</xp:dominoView>
</xe:this.data>
<xe:this.summaryColumn>
<xe:viewSummaryColumn
columnName="Title"
columnTitle="Title"
contentType="text">
</xe:viewSummaryColumn>
</xe:this.summaryColumn>
<xe:this.extraColumns>
<xe:viewExtraColumn
columnName="UNID"
columnTitle="UNID"
contentType="text"
style="font-size: 0.7em;">
</xe:viewExtraColumn>
</xe:this.extraColumns>
</xe:dataView>
</xp:div>
<xe:tabBar
id="tabBar1"
barType="segmentedControl">
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="center"
value="true">
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xe:tabBarButton
id="tabBarButton1"
label="Button 1">
</xe:tabBarButton>
<xe:tabBarButton
id="tabBarButton2"
label="Button 2">
</xe:tabBarButton>
</xe:tabBar>
</xp:appPage>
I've created a demo db for this which you can find here. The demo db is also attached to this post but isn't quite the same, it's missing the "Short View" that only shows a few documents. This view shows that by using the Scrollable Pane forces your footer to be at the bottom. But you should be able to get the idea from the attached demo db. There is a bonus in the attached demo however and that's the infinite scroll custom control which the Javascript that actually fires the scroll is incorporated into Scrollable.js in the adjustDestination function. Enjoy.