Your Development & Design Resource

XPages-based Waterfall / Cascading Navigation Demo

XPages-based Waterfall / Cascading Navigation Demo Most NotesData navigation in XPages is done by way of Pagination, where the current NotesData contents are replaced with a new set by the user clicking on Next or Previous links that reside at the top or bottom of the contents.

In fact, the xp:pager Control gives us amazing flexibility and can be used to easily provide the pagination-style navigation.

But when your users go home, most of the Web 2.0-style apps and services they use don't rely on pagination, but rather waterfall or cascading navigation.

For example, let's consider Facebook News Feeds and Profile Walls. To see more information, you simply click an Older Posts link, and the older content is appended via an AJAX call to the bottom of the feed.

Another example can be found on Twitter, where they've adopted the Facebook News Feed... but in reverse. Clicking on the New Tweets link at the top of your current tweet-stream prepends the latest tweets to the stream.

I wanted to create a similar user experience for an XPage application, and did so rather successfully with some XPage markup and JavaScript.

To begin, I created a rather simple XPage - request.xsp - and a Repeat Control which will return the alldocs View from within the same NotesDatabase:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="" createForm="false">
        <xp:dominoView var="alldocsview" viewName="alldocs"></xp:dominoView>

    <xp:repeat styleClass="inline" id="content" var="thisview" value="#{alldocsview}"

        <xp:div styleClass="item">
            <xp:span styleClass="title">
                <xp:text value="#{thisview.title}"></xp:text>
            <xp:span styleClass="description">
                <xp:text value="#{thisview.description}"></xp:text>
            <xp:span styleClass="date_created">
                <xp:text value="#{thisview.date_created}"></xp:text>
            <xp:span styleClass="author">
                <xp:text value="#{}"></xp:text>
            <xp:span styleClass="categories">
                <xp:text value="#{thisview.categories}"



You'll see that I additionally wired the Starting Index and Count of the Repeat Control to read from QueryString Parameters.

With my request.xsp XPage and wired Repeat Control, I could now return the NotesData from my NotesDatabase with ease... and control what was returned via QueryString Parameters.

Next, my common.js Client Side JavaScript Library:

function more(targetObj, targURL){
    var xmlhttp;
    if (window.XMLHttpRequest){
        xmlhttp=new XMLHttpRequest();
    } else {
        xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
    xmlhttp.onreadystatechange=function() {
        if (xmlhttp.readyState==4 && xmlhttp.status==200){
            var newObj = document.createElement("span");
            newObj.className = "set";
            newObj.innerHTML = xmlhttp.responseText;
            cstart = cmore + cstart;
    targURL += "?start=" + cstart + "&count=" + cmore;"GET",targURL,true);

Above we have a fairly basic AJAX-call to the targURL, using two global JavaScript variables cstart and cmore which control my Start and Count (which is wired to the request.xsp Repeat Control).

Now, I needed the XPage that would actually surface my NotesData using the waterfall navigation technique.

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="" createForm="false"

        <xp:script src="/common.js" clientSide="true"></xp:script>
        <xp:styleSheet href="/screen.css"></xp:styleSheet>

    <script type="text/javascript">cstart = 0; cmore = 5;</script>

    <div id="container">


        href="javascript:more(document.getElementById('container'), 'request.xsp');">
        Click here for more...

    <script type="text/javascript">
        more(document.getElementById('container'), 'request.xsp')


The first Script Element sets my cstart and cmore JavaScript variables.

The container DIV Element is the target [wait for it...] container for my content, with a Click here for more... A Element which calls my more() JavaScript Function.

And the inline-JavaScript call to my more() JavaScript Function kicks off -- in this case -- the initial population of the first 5 elements returned from my requests.xsp Repeat Control.

So let's take a look at our live demo: .nsf/example.xsp

This is a simple [and quickly-developed] Proof of Concept. If I had the time/desire/need, I would instead return JSON and beef-up my more() JavaScript Function to handle the returned NotesData appropriately... or I would use an XAgent (non-rendered XPage) to write and return any data I desire, including using the SSJS to call a Java URLConnection to give me a cross-domain AJAX handler or grab contents directly via the Google Data API...

And the beauty of this is... the surfacing tech is not XPages-specific, so you could use traditional Domino Web Design Elements, or a static HTML File Resource or an HTML file in the NotesData\domino\html directory, or another technology that can initiate an HTTP Connection to your requests.xsp.

So yeah, you've got options...

About the author: Chris Toohey

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

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

More from 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, by Chris Toohey is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License.