Showtime
My Blackberry Enterprise Server Push Utility for the Lotus Notes Client, allows you to create Jobs for individual Channel, Message, and Browser Content Pushes, as well as allows you to delete Pushed Channel Icons from defined recipient devices.
Contact Information
Blogger, podcaster, writer, and geek Chris Toohey covers topics from application development to the latest must-have-gadgets.
Latest Updates

More on Mailer...
More on Junction Lite...
More on Remote Console...

More on Controller API Utility...
Products & Applications
Time Tracker
The idea is simple. At the start of your day - upon completion of your first task - create an entry highlighting what you did and whether you feel it was an efficient or inefficient use of your time. Based on several requests, you can also select the priority, apply categories, or even align your time against a project.
For Lotus Notes Client v8.0 and above, you can use the Time Tracker Widget to make this process even easier!
Zephyr
My Configuration-based Rich Text Mail Merge and Emailing Utility, Zephyr allows you to create rich, data-driven emails to support automated workflow - all via Microsoft Word Mail Merge-like architecture. Dear <firstname> allows you to personalize each email message not only to the individual recipient, but also to the individual application workflow event!
xCopy
xCopy is a simple configurable xCopy client for the Lotus Notes client. By creating and defining xCopy Profiles, you can batch process your file backup or remote upload jobs. With the addition of the xCopy sidebar widget, you can easily kick-off these jobs, and modify both the xCopy Profiles and xCopy itself.
Community & Resources
Lotus Technical Information & Education Community
The Lotus Technical Information & Education community is comprised of IBM, business partner, and customer subject matter experts who use product wikis, published articles, white papers, community blogs and the latest in social media to build and share high quality technical content.
OpenNTF.org - Open Source Community for Lotus Notes Domino
OpenNTF is devoted to enabling groups of individuals all over the world to collaborate on IBM Lotus Notes/Domino applications and release them as open source.
developerWorks Lotus : Wikis
Share your deployment experiences and best practices in our wikis and help IBM to create scenarios for successful deployments. Contribute to the community by collaborating on shared content and leverage the shared knowledge from that community.
IBM XPages Dojo borderContainer Layout Custom Control
07/31/2012 02:15:00 PM by Chris Toohey
Extending the Extension Library xe:djBorderContainer, this take on a "Lotus Notes Client frameset" for XPages shows how we can create a reusable layout-type Custom Control that provides an alternative to an OneUI application layout.
Now while I don't hate OneUI themeing for XPages applications, I think it's absolutely critical to the adoption of XPages as an application services platform that we show the ability to serve alternative application UIs lest people unfamiliar with the technologies at play think XPages is OneUI...
Let's kick things off with an overview of the desired end-result:
This wireframe/mockup of the Dojo borderContainer (seen below) shows off a headline layout configuration. Alternately, there's a sidebar option that gives us a more traditional Lotus Notes client frameset-layout.
There are also various configuration options (such as enabling liveSplitters, which allows the user to resize the "frames") which we'll want to support.
The basic setup of an xe:djBorderContainer layout looks like this:
<xe:djBorderContainer>
<xe:djContentPane>
top
</xe:djContentPane>
<xe:djContentPane>
leading
</xe:djContentPane>
<xe:djContentPane>
center
</xe:djContentPane>
<xe:djContentPane>
trailing
</xe:djContentPane>
<xe:djContentPane>
bottom
</xe:djContentPane>
</xe:djBorderContainer>
This is, of course, sans any functional properties. But it should give you an idea of the basic setup:
The xe:djBorderContainer uses xe:djContentPane children controls to act as a container for each "frame". The order I've used here - top, leading, center, trailing, bottom - is more for visual/logical flow and has absolutely nothing to do with function: position of a "frame" has nothing to do with position, but rather the "region" attribute on the generated HTML DIV (which the Dojo library runs with to create the frame/frameset layout).
To make our xc:layout Custom Control as dynamic and configuration-controlled as possible, we'll want to wire as many xe:djBorderContainer and xe:djContentPane properties to the Properties of the Custom Control.
The cool thing about an xe:djBorderContainer is that you can either use the xe:djContentPane as a standard xp:div-like "container" Control, or use the AJAX-driven "scraping" abilities to create an iframe-like container for any content from within the same domain (or cross-domain should you choose to employ an XAgent -- for example -- to interact with an external web service).
Let's take a look at a configured xc:layout first to get an idea of the various options you'll have for populating your "frameset" layout:
<xc:layout>
<xp:this.facets>
<xp:div
xp:key="contentPane_top_bodycontent">
<xp:text tagName="h1" styleClass="heading" value="#{javascript:@DbTitle();}" />
</xp:div>
</xp:this.facets>
<xc:this.borderContainer>
<xc:borderContainer
bC_gutters="true"
bC_liveSplitters="true"
bC_design="sidebar"
bC_parseOnLoad="true"
bC_persist="true">
</xc:borderContainer>
</xc:this.borderContainer>
<xc:this.contentPane_bottom>
<xc:contentPane_bottom
cP_region="bottom"
cP_splitter="true">
</xc:contentPane_bottom>
</xc:this.contentPane_bottom>
<xc:this.contentPane_center>
<xc:contentPane_center
cP_region="center"
cP_splitter="true">
</xc:contentPane_center>
</xc:this.contentPane_center>
<xc:this.contentPane_leading>
<xc:contentPane_leading
cP_region="leading"
cP_splitter="true"
cP_href="navigation.xsp"
cP_extractContent="false"
cP_loadingMessage="Loading application navigation controls..."
cP_maxSize="350"
cP_minSize="200"
cP_parseOnLoad="true">
</xc:contentPane_leading>
</xc:this.contentPane_leading>
<xc:this.contentPane_top>
<xc:contentPane_top
cP_region="top"
cP_splitter="false">
</xc:contentPane_top>
</xc:this.contentPane_top>
<xc:this.contentPane_trailing>
<xc:contentPane_trailing
cP_region="trailing"
cP_splitter="true"
cP_rendered="false">
</xc:contentPane_trailing>
</xc:this.contentPane_trailing>
</xc:layout>
Here we're using a combination of XPage markup (in the "top" xe:djContentPane), "scraped" XPages (in the "leading" and "center" xe:djContentPanes). We'll also be using a "scraped" download.html Page Design Element for the Demo download. We're also telling the "trailing" xe:djContentPane to not render, again all driven via the configuration of the xc:layout Custom Control.
Now let's take a look at the XPage markup for the xc:layout Custom Control:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view
xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xe="http://www.ibm.com/xsp/coreex"
dojoParseOnLoad="true"
dojoTheme="true">
<xp:this.resources>
<xp:styleSheet
href="/screen.css" />
<xp:script
src="/screen.js"
clientSide="true">
</xp:script>
</xp:this.resources>
<xe:djBorderContainer
id="djBorderContainer_layout"
design="#{compositeData.borderContainer.bC_design}"
dir="#{compositeData.borderContainer.bC_dir}"
gutters="#{compositeData.borderContainer.bC_gutters}"
liveSplitters="#{compositeData.borderContainer.bC_liveSplitters}"
persist="#{compositeData.borderContainer.bC_persist}"
rendered="#{compositeData.borderContainer.bC_rendered}"
styleClass="#{compositeData.borderContainer.bC_styleClass}"
themeId="${compositeData.borderContainer.bC_themeId}">
<xe:djContentPane
id="djContentPane_top"
dir="#{compositeData.contentPane_top.cP_dir}"
errorMessage="#{compositeData.contentPane_top.cP_errorMessage}"
extractContent="#{compositeData.contentPane_top.cP_extractContents}"
href="#{compositeData.contentPane_top.cP_href}"
loadingMessage="#{compositeData.contentPane_top.cP_loadingMessage}"
partialRefresh="#{compositeData.contentPane_top.cP_partialRefresh}"
preload="#{compositeData.contentPane_top.cP_preload}"
preventCache="#{compositeData.contentPane_top.cP_preventCache}"
refreshOnShow="#{compositeData.contentPane_top.cP_refreshOnShow}"
rendered="#{compositeData.contentPane_top.cP_rendered}"
parseOnLoad="#{compositeData.contentPane_top.cP_parseOnLoad}"
styleClass="#{compositeData.contentPane_top.cP_styleClass}"
themeId="${compositeData.contentPane_top.cP_themeId}">
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="region"
value="#{compositeData.contentPane_top.cP_region}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_top) {
if (compositeData.contentPane_top.cP_region !== null || compositeData.contentPane_top.cP_region !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="minSize"
value="#{compositeData.contentPane_top.cP_minSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_top) {
if (compositeData.contentPane_top.cP_minSize !== null || compositeData.contentPane_top.cP_minSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="maxSize"
value="#{compositeData.contentPane_top.cP_maxSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_top) {
if (compositeData.contentPane_top.cP_maxSize !== null || compositeData.contentPane_top.cP_maxSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="splitter">
<xp:this.loaded><![CDATA[${javascript:var r = false;
var arg = compositeData.contentPane_top;
if(arg) {
if(arg.cP_splitter !== null || arg.cP_splitter !== "") {
r = true;
};
};
return r;}]]></xp:this.loaded>
<xp:this.value><![CDATA[#{javascript:var arg = compositeData.contentPane_top.cP_splitter;
if(arg) {
arg.toString();
}}]]></xp:this.value>
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xp:callback
facetName="contentPane_top_bodycontent"
id="contentPane_top_bodycontent">
</xp:callback>
</xe:djContentPane>
<xe:djContentPane
id="djContentPane_leading"
dir="#{compositeData.contentPane_leading.cP_dir}"
errorMessage="#{compositeData.contentPane_leading.cP_errorMessage}"
extractContent="#{compositeData.contentPane_leading.cP_extractContents}"
href="#{compositeData.contentPane_leading.cP_href}"
loadingMessage="#{compositeData.contentPane_leading.cP_loadingMessage}"
partialRefresh="#{compositeData.contentPane_leading.cP_partialRefresh}"
preload="#{compositeData.contentPane_leading.cP_preload}"
preventCache="#{compositeData.contentPane_leading.cP_preventCache}"
refreshOnShow="#{compositeData.contentPane_leading.cP_refreshOnShow}"
rendered="#{compositeData.contentPane_leading.cP_rendered}"
parseOnLoad="#{compositeData.contentPane_leading.cP_parseOnLoad}"
styleClass="#{compositeData.contentPane_leading.cP_styleClass}"
themeId="${compositeData.contentPane_leading.cP_themeId}">
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="region"
value="#{compositeData.contentPane_leading.cP_region}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_leading) {
if (compositeData.contentPane_leading.cP_region !== null || compositeData.contentPane_leading.cP_region !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="minSize"
value="#{compositeData.contentPane_leading.cP_minSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_leading) {
if (compositeData.contentPane_leading.cP_minSize !== null || compositeData.contentPane_leading.cP_minSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="maxSize"
value="#{compositeData.contentPane_leading.cP_maxSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_leading) {
if (compositeData.contentPane_leading.cP_maxSize !== null || compositeData.contentPane_leading.cP_maxSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="splitter">
<xp:this.loaded><![CDATA[${javascript:var r = false;
var arg = compositeData.contentPane_leading;
if(arg) {
if(arg.cP_splitter !== null || arg.cP_splitter !== "") {
r = true;
};
};
return r;}]]></xp:this.loaded>
<xp:this.value><![CDATA[#{javascript:var arg = compositeData.contentPane_leading.cP_splitter;
if(arg) {
arg.toString();
}}]]></xp:this.value>
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xp:callback
facetName="contentPane_leading_bodycontent"
id="contentPane_leading_bodycontent">
</xp:callback>
</xe:djContentPane>
<xe:djContentPane
id="djContentPane_center"
dir="#{compositeData.contentPane_center.cP_dir}"
errorMessage="#{compositeData.contentPane_center.cP_errorMessage}"
extractContent="#{compositeData.contentPane_center.cP_extractContents}"
href="#{compositeData.contentPane_center.cP_href}"
loadingMessage="#{compositeData.contentPane_center.cP_loadingMessage}"
partialRefresh="#{compositeData.contentPane_center.cP_partialRefresh}"
preload="#{compositeData.contentPane_center.cP_preload}"
preventCache="#{compositeData.contentPane_center.cP_preventCache}"
refreshOnShow="#{compositeData.contentPane_center.cP_refreshOnShow}"
rendered="#{compositeData.contentPane_center.cP_rendered}"
parseOnLoad="#{compositeData.contentPane_center.cP_parseOnLoad}"
styleClass="#{compositeData.contentPane_center.cP_styleClass}"
themeId="${compositeData.contentPane_center.cP_themeId}">
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="region"
value="#{compositeData.contentPane_center.cP_region}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_center) {
if (compositeData.contentPane_center.cP_region !== null || compositeData.contentPane_center.cP_region !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="minSize"
value="#{compositeData.contentPane_center.cP_minSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_center) {
if (compositeData.contentPane_center.cP_minSize !== null || compositeData.contentPane_center.cP_minSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="maxSize"
value="#{compositeData.contentPane_center.cP_maxSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_center) {
if (compositeData.contentPane_center.cP_maxSize !== null || compositeData.contentPane_center.cP_maxSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="splitter">
<xp:this.loaded><![CDATA[${javascript:var r = false;
var arg = compositeData.contentPane_center;
if(arg) {
if(arg.cP_splitter !== null || arg.cP_splitter !== "") {
r = true;
};
};
return r;}]]></xp:this.loaded>
<xp:this.value><![CDATA[#{javascript:var arg = compositeData.contentPane_center.cP_splitter;
if(arg) {
arg.toString();
}}]]></xp:this.value>
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xp:callback
facetName="contentPane_center_bodycontent"
id="contentPane_center_bodycontent">
</xp:callback>
</xe:djContentPane>
<xe:djContentPane
id="djContentPane_trailing"
dir="#{compositeData.contentPane_trailing.cP_dir}"
errorMessage="#{compositeData.contentPane_trailing.cP_errorMessage}"
extractContent="#{compositeData.contentPane_trailing.cP_extractContents}"
href="#{compositeData.contentPane_trailing.cP_href}"
loadingMessage="#{compositeData.contentPane_trailing.cP_loadingMessage}"
partialRefresh="#{compositeData.contentPane_trailing.cP_partialRefresh}"
preload="#{compositeData.contentPane_trailing.cP_preload}"
preventCache="#{compositeData.contentPane_trailing.cP_preventCache}"
refreshOnShow="#{compositeData.contentPane_trailing.cP_refreshOnShow}"
rendered="#{compositeData.contentPane_trailing.cP_rendered}"
parseOnLoad="#{compositeData.contentPane_trailing.cP_parseOnLoad}"
styleClass="#{compositeData.contentPane_trailing.cP_styleClass}"
themeId="${compositeData.contentPane_trailing.cP_themeId}">
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="region"
value="#{compositeData.contentPane_trailing.cP_region}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_trailing) {
if (compositeData.contentPane_trailing.cP_region !== null || compositeData.contentPane_trailing.cP_region !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="minSize"
value="#{compositeData.contentPane_trailing.cP_minSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_trailing) {
if (compositeData.contentPane_trailing.cP_minSize !== null || compositeData.contentPane_trailing.cP_minSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="maxSize"
value="#{compositeData.contentPane_trailing.cP_maxSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_trailing) {
if (compositeData.contentPane_trailing.cP_maxSize !== null || compositeData.contentPane_trailing.cP_maxSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="splitter">
<xp:this.loaded><![CDATA[${javascript:var r = false;
var arg = compositeData.contentPane_trailing;
if(arg) {
if(arg.cP_splitter !== null || arg.cP_splitter !== "") {
r = true;
};
};
return r;}]]></xp:this.loaded>
<xp:this.value><![CDATA[#{javascript:var arg = compositeData.contentPane_trailing.cP_splitter;
if(arg) {
arg.toString();
}}]]></xp:this.value>
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xp:callback
facetName="contentPane_trailing_bodycontent"
id="contentPane_trailing_bodycontent">
</xp:callback>
</xe:djContentPane>
<xe:djContentPane
id="djContentPane_bottom"
dir="#{compositeData.contentPane_bottom.cP_dir}"
errorMessage="#{compositeData.contentPane_bottom.cP_errorMessage}"
extractContent="#{compositeData.contentPane_bottom.cP_extractContents}"
href="#{compositeData.contentPane_bottom.cP_href}"
loadingMessage="#{compositeData.contentPane_bottom.cP_loadingMessage}"
partialRefresh="#{compositeData.contentPane_bottom.cP_partialRefresh}"
preload="#{compositeData.contentPane_bottom.cP_preload}"
preventCache="#{compositeData.contentPane_bottom.cP_preventCache}"
refreshOnShow="#{compositeData.contentPane_bottom.cP_refreshOnShow}"
rendered="#{compositeData.contentPane_bottom.cP_rendered}"
parseOnLoad="#{compositeData.contentPane_bottom.cP_parseOnLoad}"
styleClass="#{compositeData.contentPane_bottom.cP_styleClass}"
themeId="${compositeData.contentPane_bottom.cP_themeId}">
<xe:this.dojoAttributes>
<xp:dojoAttribute
name="region"
value="#{compositeData.contentPane_bottom.cP_region}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_bottom) {
if (compositeData.contentPane_bottom.cP_region !== null || compositeData.contentPane_bottom.cP_region !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="minSize"
value="#{compositeData.contentPane_bottom.cP_minSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_bottom) {
if (compositeData.contentPane_bottom.cP_minSize !== null || compositeData.contentPane_bottom.cP_minSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="maxSize"
value="#{compositeData.contentPane_bottom.cP_maxSize}">
<xp:this.loaded><![CDATA[${javascript:var r = false;
if(compositeData.contentPane_bottom) {
if (compositeData.contentPane_bottom.cP_maxSize !== null || compositeData.contentPane_bottom.cP_maxSize !== "") {
r = true;
}};
return r;}]]></xp:this.loaded>
</xp:dojoAttribute>
<xp:dojoAttribute
name="splitter">
<xp:this.loaded><![CDATA[${javascript:var r = false;
var arg = compositeData.contentPane_bottom;
if(arg) {
if(arg.cP_splitter !== null || arg.cP_splitter !== "") {
r = true;
};
};
return r;}]]></xp:this.loaded>
<xp:this.value><![CDATA[#{javascript:var arg = compositeData.contentPane_bottom.cP_splitter;
if(arg) {
arg.toString();
}}]]></xp:this.value>
</xp:dojoAttribute>
</xe:this.dojoAttributes>
<xp:callback
facetName="contentPane_bottom_bodycontent"
id="contentPane_bottom_bodycontent">
</xp:callback>
</xe:djContentPane>
</xe:djBorderContainer>
<xp:scriptBlock>
<xp:this.value><![CDATA[var djBorderContainer_layout = '#{id:djBorderContainer_layout}';
var djContentPane_top = '#{id:djContentPane_top}';
var djContentPane_leading = '#{id:djContentPane_leading}';
var djContentPane_center = '#{id:djContentPane_center}';
var djContentPane_trailing = '#{id:djContentPane_trailing}';
var djContentPane_bottom = '#{id:djContentPane_bottom}';]]></xp:this.value>
</xp:scriptBlock>
</xp:view>
Really basic once you get your head around what's going on here:
The xe:djBorderContainer uses the xc:layout Custom Control "borderContainer" Properties group to wire the overall "settings" for the xe:djBorderContainer.
Each xe:djContentPane uses a specific xc:layotu Custom Control Properties group for both the native Control Properties and leverages dojoAttributes to add additional attributes required to make the xe:djContentPane completely xe:djBorderContainer-functional. Specifically, we're talking "region", "minSize", "maxSize", and "splitter".
Each xe:djContentPane contains an xp:callback -- which can conditionally be used -- to throw some XPage markup in there as needed as an alternative to the iframe/"scraping" technique.
We use some scriptBlock Artifacting to surface some global JavaScript variables to help with ClientSide JavaScript population of our xe:djContentPanes (should you opt for the iframe/"scrape" technique).
All we need now is some CSS and JavaScript to bring things home...
CSS:
html,
body {
padding: 0px !important;
margin: 0px !important;
height: 100%;
}
div[id*="djBorderContainer_layout"][dojotype="dijit.layout.BorderContainer"] {
height: 100%;
width: 100%;
}
div[dojotype="dijit.layout.ContentPane"][region="leading"] {
width: 250px;
}
JavaScript:
var setFrameHref = function(tfKey, tfHref) {
var t = dijit.byId(tfKey);
t.attr("onDownloadEnd", function() {
dojo.parser.parse();
});
t.attr("href", tfHref);
}
The CSS is used to make the xe:djBorderContainer Control goes 100% of the height of the browser while the JavaScript runs our iframe/"scrape" function and -- onDownloadEnd (when finished) -- calls the Dojo parser function.
One last thing to point out with this control: a functional Design Definition.
As mentioned, each xe:djContentPane has an xp:callback Control. We can do ourselves a huge favor here and surface those via a functional Design Definition:
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:table style="width:100%; vertical-align: top;">
<xp:tr>
<xp:td>
<xp:callback
facetName="contentPane_leading_bodycontent"
id="contentPane_leading_bodycontent">
</xp:callback>
</xp:td>
<xp:td>
<xp:table style="width:100%; vertical-align: top;">
<xp:tr>
<xp:td>
<xp:callback
facetName="contentPane_top_bodycontent"
id="contentPane_top_bodycontent">
</xp:callback>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td>
<xp:callback
facetName="contentPane_center_bodycontent"
id="contentPane_center_bodycontent">
</xp:callback>
</xp:td>
</xp:tr>
<xp:tr>
<xp:td>
<xp:callback
facetName="contentPane_bottom_bodycontent"
id="contentPane_bottom_bodycontent">
</xp:callback>
</xp:td>
</xp:tr>
</xp:table>
</xp:td>
<xp:td>
<xp:callback
facetName="contentPane_trailing_bodycontent"
id="contentPane_trailing_bodycontent">
</xp:callback>
</xp:td>
</xp:tr>
</xp:table>
</xp:view>
The above Design Definition turns this:
xc:layout Custom Control without Design Definition
-- into this:
xc:layout Custom Control with Design Definition
So now that we've covered everything that makes up this control, let's finally see this xc:layout Custom Control in action!
Demo and Download
Dojo borderContainer Layout Demo
This shockingly simple demo is downloadable and completely available to rip apart to meet your application user interface needs... or give you ideas on how you can create your own layout-type Custom Controls. Again, pretty simple once you can get your head around it!
Any requests for your own layout-type Custom Controls? I'm currently working on a Twitter Bootstrap Control, but always interested in hearing about new frameworks or "types" of layouts that XPages can deliver.



This is a very nice piece of code which I am definately using, thanks. Can you please also tell us how to employ the xAgent in order to allow cross-domain links in the centre container pane? Thanks
Is possible to open a url in djContentPane_bottom?
Thanks
Hi!! you layout is excelent and is that i need in order to apply in my app...
i just have some errors when installing in my domino server 8.5.2 server with com.ibm.xsp.extlib.library plugin...
Description Resource Path Location Type
The complex type tag (xp:dojoAttribute) must be within a property tag, like <this.something>. casas.xsp dbld.nsf/XPages line 45 com.ibm.designer.domino.ide.resources.designerproblem
this is the error
need i to install some other plugin or some thing more???
regards!!
MC
Hi!! you layout is excelent and is that i need in order to apply in my app...
i just have some errors when installing in my domino server 8.5.2 server with com.ibm.xsp.extlib.library plugin...
Description Resource Path Location Type
The complex type tag (xp:dojoAttribute) must be within a property tag, like <this.something>. casas.xsp dbld.nsf/XPages line 45 com.ibm.designer.domino.ide.resources.designerproblem
this is the error
need i to install some other plugin or some thing more???
regards!!
MC