dominoGuru.com

Latest Updates

Products & Applications

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.

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.

More Nested IBM XPage Panels + viewPanel Controls in viewColumns (with an online demo: XBook)

10/28/2011 02:08:00 PM by Chris Toohey

More Nested IBM XPage Panels + viewPanel Controls in viewColumns (with an online demo: XBook)

Sometimes I like to play with a given technique to see how far I can take it.

Thus said, I thought I'd mess around with the techniques discussed in Inline Buttons for XPage View Controls, Nested XPage viewPanels in viewColumns (with meme-themed demo), and IBM XPages + Google Maps Mashup (or Surfacing traditional Views as NotesViewEntryCollections with a viewPanel Control), and see just how far I could take them.

I'll admit, I didn't go that far - mostly because it got to the point where I confirmed my theories: it works, and works really well.

My playground was a simple NotesDatabase that contains no Form Design Elements, only 2 View Design Elements (used for NotesViewEntryCollection sorting more than anything...), and uses only core XPage controls.

(I originally used the OpenNTF.org Extension Library dialog Control for the Status Update form -- in fact, you can see it in the banner image in this article -- but decided just now [midway through writing this article] that it's a better showcase using only the core XPage controls.)

Since each panel Control can have it's own unqiue data source, and a viewColumn control can house literally anything -- including, of course, a panel Control -- I thought that I'd create a Facebook-esque demo application that showed off the technique.

Here's a quick visual overview of what the architecture of the "XBooks" demo:

XBooks Demo XPage Application architecture wireframe XBooks Demo XPage Application architecture wireframe

I have a simple inline form panel Control ("newupdate") that allows me to submit a new update, then a viewPanel Control ("updates") that displays all of my previous updates - whose data source is set to pull the "documents" from the documents_bytype_descending View Design Element.

The first (and only) viewColumn of the "updates" viewPanel contains an "update" pane Control.

The "update" panel Control contains the "comments" viewPanel Control -- which loads all of the response NotesDocuments based on the @Text($Ref) category of the documents_bytype_ascending View Design Element.

The "update" panel Control also contains the "newcomment" pane Control, which allows you to submit a new comment to an update (and uses the UniversalID of the viewPanel entry NotesDocument to populate the "$Ref" NotesItem of the new comment).

It's all pretty simple, really.

Here's the Home.xsp XPage markup, where all of this exists:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view
    xmlns:xp="http://www.ibm.com/xsp/core"
    pageTitle="#{javascript:@DbTitle()}">

    <xp:this.resources>
        <xp:styleSheet
            href="/screen.css" />
    </xp:this.resources>

    <xp:this.beforePageLoad><![CDATA[#{javascript:sessionScope.remote_addr = facesContext.getExternalContext().getRequest().getRemoteAddr();}]]></xp:this.beforePageLoad>

    <xp:div
        styleClass="container_main"
        id="container_main">
        <xp:div
            styleClass="container_header">
            <xp:div
                styleClass="blueBar">
                <xp:div
                    styleClass="container_content">
                    <ul
                        class="navigation">
                        <li>
                            <xp:link
                                escape="true"
                                text="#{javascript:@DbTitle()}"
                                id="link1"
                                styleClass="h1"
                                value="/Home.xsp">
                            </xp:link>
                            <xp:link
                                escape="true"
                                text=""
                                id="link2"
                                styleClass="icon icon1"
                                value="/Home.xsp">
                            </xp:link>
                            <xp:link
                                escape="true"
                                text=""
                                id="link3"
                                styleClass="icon icon2"
                                value="/Home.xsp">
                            </xp:link>
                            <xp:link
                                escape="true"
                                text=""
                                id="link4"
                                styleClass="icon icon3"
                                value="/Home.xsp">
                            </xp:link>
                        </li>
                    </ul>
                    <input
                        type="text"
                        id="query"
                        name="query"
                        placeholder="Search" />
                    <button
                        id="runsearch"
                        type="submit" />
                </xp:div>
            </xp:div>
        </xp:div>
        <xp:div
            styleClass="container_body">
            <xp:div
                styleClass="container_content">
                <xp:div
                    styleClass="col0 column">
                    <xp:image
                        url="/batman_facebook.jpg"
                        id="image1"
                        style="width:175px">
                    </xp:image>
                    <xp:div
                        styleClass="buildinfo">
                        <xp:paragraph
                            id="paragraph1">
                            This application is designed to be as simple
                            as possible while
                            illustrating several
                            extremely powerful techniques that any
                            XPages
                            Developer can employ.
                        </xp:paragraph>
                        <xp:paragraph
                            id="paragraph2">
                            Here's an overview of the app:
                        </xp:paragraph>
                        <h3>Design Elements</h3>
                        <xp:paragraph>
                            <xp:table>
                                <xp:tr>
                                    <xp:td
                                        styleClass="col0">
                                        Views
                                    </xp:td>
                                    <xp:td
                                        styleClass="col1">2</xp:td>
                                </xp:tr>
                                <xp:tr>
                                    <xp:td
                                        styleClass="col0">
                                        XPages
                                    </xp:td>
                                    <xp:td
                                        styleClass="col1">1</xp:td>
                                </xp:tr>
                                <xp:tr>
                                    <xp:td
                                        styleClass="col0">
                                        Image Resources
                                    </xp:td>
                                    <xp:td
                                        styleClass="col1">2</xp:td>
                                </xp:tr>
                                <xp:tr>
                                    <xp:td
                                        styleClass="col0">
                                        Stylesheets
                                    </xp:td>
                                    <xp:td
                                        styleClass="col1">1</xp:td>
                                </xp:tr>
                                <xp:tr>
                                    <xp:td
                                        styleClass="col0">
                                        Forms
                                    </xp:td>
                                    <xp:td
                                        styleClass="col1">0</xp:td>
                                </xp:tr>
                            </xp:table>
                        </xp:paragraph>
                        <h3>NotesData Information</h3>
                        <xp:paragraph>
                            <xp:table>
                                <xp:tr>
                                    <xp:td
                                        styleClass="col0">
                                        "document" Documents
                                    </xp:td>
                                    <xp:td
                                        styleClass="col1">
                                        <xp:text>
                                            <xp:this.value><![CDATA[#{javascript:var lu = @DbLookup(@DbName(), 'documents_bytype_ascending', 'document', 2);
return @Elements(lu).toString()}]]></xp:this.value>
                                        </xp:text>
                                    </xp:td>
                                </xp:tr>
                                <xp:tr>
                                    <xp:td
                                        styleClass="col0">
                                        "comment" Documents
                                    </xp:td>
                                    <xp:td
                                        styleClass="col1">
                                        <xp:text>
                                            <xp:this.value><![CDATA[#{javascript:var lu = @DbLookup(@DbName(), 'documents_bytype_ascending', 'comment', 2);
return @Elements(lu).toString()}]]></xp:this.value>
                                        </xp:text>
                                    </xp:td>
                                </xp:tr>
                            </xp:table>
                        </xp:paragraph>
                        <h3>Using this app</h3>
                        <xp:paragraph>
                            This should be fairly obvious to anyone who
                            uses
                            Facebook. Simply click "Update Status"
                            to add a new status update.
                            From each Status
                            Update, you'll be able to add a comment via
                            the
                            inline comment form.
                        </xp:paragraph>
                        <h3>Under the hood...</h3>
                        <xp:paragraph>
                            If you want to see exactly how the NotesData
                            is
                            stored within the application, simply
                            open the views:
                        </xp:paragraph>
                        <xp:paragraph>
                            <xp:link
                                escape="true"
                                text="documents_bytype_ascending"
                                id="link5"
                                value="http://guru.gbs.com/demo/XBook.nsf/documents_bytype_ascending">
                            </xp:link>
                            <xp:br />
                            <xp:br />
                            View showing all documents, second column
                            sorted in ascending
                            order.
                        </xp:paragraph>
                        <xp:paragraph>
                            <xp:link
                                escape="true"
                                text="documents_bytype_descending"
                                id="link6"
                                value="http://guru.gbs.com/demo/XBook.nsf/documents_bytype_descending">
                            </xp:link>
                            <xp:br />
                            <xp:br />
                            View showing all documents, second column
                            sorted in descending
                            order.
                        </xp:paragraph>
                    </xp:div>
                </xp:div>
                <xp:div
                    styleClass="col1 column">
                    <xp:panel
                        styleClass="newupdate">
                        <xp:this.data>
                            <xp:dominoDocument
                                var="newupdate"
                                formName="document"
                                ignoreRequestParams="true">
                            </xp:dominoDocument>
                        </xp:this.data>
                        <h3>Update Status</h3>
                        <xp:inputText
                            value="#{newupdate.REMOTE_ADDR}"
                            styleClass="hide"
                            defaultValue="#{javascript:sessionScope.remote_addr}" />
                        <xp:inputTextarea
                            styleClass="body"
                            value="#{newupdate.body}" />
                        <xp:button
                            value="Post"
                            id="button2">
                            <xp:eventHandler
                                event="onclick"
                                submit="true"
                                refreshMode="complete"
                                immediate="false"
                                save="false">
                                <xp:this.action><![CDATA[#{javascript:newupdate.save();
context.redirectToPage("/Home.xsp")}]]></xp:this.action>
                            </xp:eventHandler>
                        </xp:button>
                    </xp:panel>
                    <xp:div
                        styleClass="updates">
                        <xp:viewPanel
                            rows="5"
                            id="viewPanel_updates"
                            var="entry_update"
                            showColumnHeader="false">
                            <xp:this.facets>
                                <xp:pager
                                    partialRefresh="true"
                                    layout="Previous Group Next"
                                    xp:key="headerPager"
                                    id="pager1">
                                </xp:pager>
                                <xp:viewTitle
                                    xp:key="viewTitle"
                                    id="viewTitle1"
                                    value="Status Updates">
                                </xp:viewTitle>
                            </xp:this.facets>
                            <xp:this.data>
                                <xp:dominoView
                                    var="updates"
                                    viewName="documents_bytype_descending"
                                    keys="document"
                                    keysExactMatch="true"
                                    ignoreRequestParams="true">
                                </xp:dominoView>
                            </xp:this.data>
                            <xp:viewColumn
                                id="viewColumn_contents"
                                displayAs="hidden">
                                <xp:this.value><![CDATA[#{javascript:return ""}]]></xp:this.value>
                                <xp:panel>
                                    <xp:this.data>
                                        <xp:dominoDocument
                                            var="thisupdate"
                                            action="openDocument"
                                            documentId="#{javascript:entry_update.getDocument().getUniversalID();}"
                                            ignoreRequestParams="true">
                                        </xp:dominoDocument>
                                    </xp:this.data>
                                    <xp:div
                                        styleClass="update">
                                        <xp:div
                                            styleClass="update_body">
                                            <xp:text
                                                value="#{thisupdate.body}" />
                                        </xp:div>
                                        <xp:div
                                            styleClass="update_timestamp">
                                            <xp:text
                                                value="#{javascript:thisupdate.getDocument().getCreated().toString()}" />
                                        </xp:div>
                                    </xp:div>
                                    <xp:div
                                        styleClass="comments">
                                        <xp:viewPanel
                                            rows="100"
                                            id="viewPanel_comments"
                                            showColumnHeader="false"
                                            viewStyleClass="viewPanel_comments"
                                            var="entry_comment">
                                            <xp:this.data>
                                                <xp:dominoView
                                                    var="comments"
                                                    viewName="documents_bytype_ascending"
                                                    keys="#{javascript:thisupdate.getDocument().getUniversalID()}"
                                                    keysExactMatch="true">
                                                </xp:dominoView>
                                            </xp:this.data>
                                            <xp:viewColumn
                                                id="viewColumn_comments"
                                                displayAs="hidden">
                                                <xp:this.value><![CDATA[#{javascript:return ""}]]></xp:this.value>
                                                <xp:panel>
                                                    <xp:this.data>
                                                        <xp:dominoDocument
                                                            var="thiscomment"
                                                            action="openDocument"
                                                            documentId="#{javascript:entry_comment.getDocument().getUniversalID();}"
                                                            ignoreRequestParams="true">
                                                        </xp:dominoDocument>
                                                    </xp:this.data>
                                                    <xp:div
                                                        styleClass="comment">
                                                        <xp:div
                                                            styleClass="comment_body">
                                                            <xp:text
                                                                value="#{thiscomment.body}" />
                                                        </xp:div>
                                                        <xp:div
                                                            styleClass="comment_timestamp">
                                                            <xp:text>
                                                                <xp:this.value><![CDATA[#{javascript:var dt = thiscomment.getDocument().getCreated();
dt.getDateOnly().toString() + ' ' + dt.getTimeOnly().toString()}]]></xp:this.value>
                                                            </xp:text>
                                                        </xp:div>
                                                    </xp:div>
                                                </xp:panel>
                                                <xp:viewColumnHeader
                                                    value=""
                                                    id="viewColumnHeader1">
                                                </xp:viewColumnHeader>
                                            </xp:viewColumn>
                                        </xp:viewPanel>
                                    </xp:div>
                                    <xp:div
                                        styleClass="newcomment">
                                        <xp:panel>
                                            <xp:this.data>
                                                <xp:dominoDocument
                                                    var="newcomment"
                                                    formName="comment"
                                                    parentId="#{javascript:thisupdate.getDocument().getUniversalID()}"
                                                    ignoreRequestParams="true">
                                                </xp:dominoDocument>
                                            </xp:this.data>
                                            <fieldset>
                                                <legend>
                                                    New Comment
                                                </legend>
                                                <xp:inputText
                                                    value="#{newcomment.REMOTE_ADDR}"
                                                    styleClass="hide"
                                                    defaultValue="#{javascript:sessionScope.remote_addr}" />
                                                <xp:inputText
                                                    styleClass="body"
                                                    value="#{newcomment.body}" />
                                                <xp:button
                                                    value="Post"
                                                    id="button3">
                                                    <xp:eventHandler
                                                        event="onclick"
                                                        submit="true"
                                                        refreshMode="complete"
                                                        immediate="false"
                                                        save="false">
                                                        <xp:this.action><![CDATA[#{javascript:newcomment.save();
context.redirectToPage("/Home.xsp")}]]></xp:this.action>
                                                    </xp:eventHandler>
                                                </xp:button>
                                            </fieldset>
                                        </xp:panel>
                                    </xp:div>
                                </xp:panel>
                                <xp:viewColumnHeader
                                    value="" />
                            </xp:viewColumn>
                        </xp:viewPanel>
                    </xp:div>
                </xp:div>
                <xp:div
                    styleClass="col2 column">
                    <xp:viewPanel
                        rows="10"
                        id="viewPanel_latestcomments"
                        var="entry_comment"
                        showColumnHeader="false"
                        viewStyleClass="viewPanel_latestcomments"
                        viewStyle="width:100px">
                        <xp:this.facets>
                            <xp:viewTitle
                                xp:key="viewTitle"
                                id="viewTitle3"
                                value="Latest Comments">
                            </xp:viewTitle>
                        </xp:this.facets>
                        <xp:this.data>
                            <xp:dominoView
                                var="updates"
                                viewName="documents_bytype_descending"
                                keys="comment"
                                keysExactMatch="true">
                            </xp:dominoView>
                        </xp:this.data>
                        <xp:viewColumn
                            id="viewColumn_latestcomments"
                            displayAs="hidden">
                            <xp:this.value><![CDATA[#{javascript:return ""}]]></xp:this.value>
                            <xp:panel>
                                <xp:this.data>
                                    <xp:dominoDocument
                                        var="thiscomment"
                                        action="openDocument"
                                        documentId="#{javascript:entry_comment.getDocument().getUniversalID();}">
                                    </xp:dominoDocument>
                                </xp:this.data>
                                <xp:div
                                    styleClass="comment">
                                    <xp:div
                                        styleClass="comment_body">
                                        <xp:text
                                            value="#{thiscomment.body}" />
                                    </xp:div>
                                    <xp:div
                                        styleClass="comment_timestamp">
                                        <xp:text>
                                            <xp:this.value><![CDATA[#{javascript:var dt = thiscomment.getDocument().getCreated();
dt.getDateOnly().toString() + ' ' + dt.getTimeOnly().toString()}]]></xp:this.value>
                                        </xp:text>
                                    </xp:div>
                                </xp:div>
                            </xp:panel>
                            <xp:viewColumnHeader
                                value="" />
                        </xp:viewColumn>
                    </xp:viewPanel>
                </xp:div>
            </xp:div>
        </xp:div>
        <xp:div
            styleClass="container_footer">
            <xp:div
                styleClass="container_content">

            </xp:div>
        </xp:div>
    </xp:div>

</xp:view>

View fullscreen: XBook Home.xsp XPage Markup

The rest is just a stylesheet:

body {
    margin: 0px;
    padding: 0px;
}

div.container_main {
    text-align: center;
    margin: 0px;
    padding: 0px;  
}

div.container_content {
    text-align: left;
    width: 975px;
    margin: 0px auto 0px auto;
    padding: 0px;
}

div.blueBar {
    background-color: #3B5998;
    padding: 4px 0px 4px 0px;
}

div.blueBar ul.navigation {
    display: inline;
    margin: 0px;
    padding: 0px;
    list-style: none;
}
div.blueBar ul.navigation li {
    margin: 0px;
    padding: 0px;
    list-style: none;
    display: inline;
}
div.blueBar ul.navigation li a {
    display: inline-block;
    vertical-align: middle;
    color: #fff;
    font-weight: normal;
    padding: 0px;
    margin: 0px;
}

div.blueBar ul.navigation li .h1 {
    font-size: 11pt;
    font-weight: bold;
    color: #fff;
    padding: 0px;
    margin: 0px 8px 0px 0px;
}
div.blueBar ul.navigation li a.icon {
    display: inline-block;
    width: 24px;
    height: 24px;
    margin-left: 2px;
    background-image: url(http://static.ak.fbcdn.net/rsrc.php/v1/yv/r/mTnxuar3oIS.png);
    background-repeat: no-repeat;
}
div.blueBar ul.navigation li a.icon1 {
    background-position: -31px -6px;
}
div.blueBar ul.navigation li a.icon2 {
    background-position: -56px -76px;
}
div.blueBar ul.navigation li a.icon3 {
    background-position: -25px -251px;
}


div.blueBar input#query {
    width: 325px;
    border: 1px solid #eee;
    margin-left: 8px;
    font-size: 8pt;
}

div.blueBar button#runsearch {
    background-image: url(http://static.ak.fbcdn.net/rsrc.php/v1/yv/r/mTnxuar3oIS.png);
    background-repeat: no-repeat;
    background-position: -81px 0;
    background-color: white;
    border: 0;
    cursor: pointer;
    display: inline-block;
    height: 18px;
    padding: 0;
    width: 22px;
    position: relative;
}
div.container_body {
    margin-top: 25px;  
}
div.container_body div.column {
    display: inline-block;
    vertical-align: top;
}
div.container_body div.col0 {
    width: 175px;
}
div.container_body div.col0 p {
    margin: 6px 0px 6px 0px;
}
div.container_body div.col0 table {
    width: 100%;
}
div.container_body div.col0 table tr td.col0 {
    font-weight: bold;
}
div.container_body div.col1 {
    width: 650px;
    padding: 0px 5px 0px 5px;
}
div.container_body div.col2 {
    width: 100px;
}
div.comment {
    margin-bottom: 8px;
}
div.comment_body span.xspTextComputedField {
    font-size: 10pt;
}
.newupdate {
    text-align: right;
    margin-bottom: 15px;
}
.newupdate h3 {
    text-align: left;
    padding: 4px 0px 4px 10px;
    background-color: #F3F3F3;
    margin: 0px 0px 4px 0px;
}
.newupdate .body {
    display: block;
    height: 50px;
    width: 640px;
}
.newcomment .body {
    width: 550px;
    display: inline;
}
.newupdate .xspButtonCommand, .newcomment .xspButtonCommand, .xspButtonSubmit {
    border: 1px solid #666;
    background-color: #5B74A8;
    color: #fff;
    font-size: 8pt;
    font-weight: bold;
    padding: 2px 8px 2px 8px !important;
    height: auto;
}
.xspDataTable, .xspDataTableViewPanel, .viewPanel_comments {
    width: 100%;
}
.xspDataTable td {
    border: none !important;
}

div.update_body {
    font-size: 12pt;
    color: #333;   
}
div.update_timestamp {
    font-size: 8pt;
    color: #999;
}
.viewPanel_latestcomments div.comment_body {
    font-size: 8pt;
    color: #333;
}
.viewPanel_latestcomments div.comment_timestamp {
    font-size: 7pt;
    color: #666;
    padding: 0px 0px 0px 0px;
    margin: 4px 0px 4px 0px;
}
.viewPanel_latestcomments .xspTextViewColumn {
    display: none;
}

.xspDataTableViewPanelHeaderStart,
.xspDataTableViewPanelHeaderMiddle,
.xspDataTableViewPanelHeaderEnd,
.xspDataTableViewPanelFooterStart,
.xspDataTableViewPanelFooterMiddle,
.xspDataTableViewPanelFooterEnd {
    background-color: transparent;
    border: none;
}

.xspDataTableViewPanel .xspDataTableViewPanelHeaderStart,
.xspDataTableViewPanel .xspDataTableViewPanelHeaderMiddle,
.xspDataTableViewPanel .xspDataTableViewPanelHeaderEnd {
    background-color: #F3F3F3;
}

.viewPanel_comments .xspDataTableViewPanelHeaderStart,
.viewPanel_comments .xspDataTableViewPanelHeaderMiddle,
.viewPanel_comments .xspDataTableViewPanelHeaderEnd,
.viewPanel_comments .xspDataTableViewPanelFooterStart,
.viewPanel_comments .xspDataTableViewPanelFooterMiddle,
.viewPanel_comments .xspDataTableViewPanelFooterEnd {
    background-color: transparent;
    border: none;
}

.button_update {
    background-color: transparent;
    border: none;
    text-align: center;
    margin: 10px 0px 0px 25px;
    font-weight: bold;
    font-size: 8pt;
}
.button_update:hover {
    text-decoration: underline;
    cursor: pointer;
}

fieldset {
    border: none;  
}
legend {
    text-align: left;  
}

.viewPanel_latestcomments {
    width: 100px;  
}

.hide {
    display: none !important;
}

View fullscreen: XBook screen.css CSS Markup

Online Demo

So, wanna take this demo for a spin? Check out the XBook online demo at http://guru.gbs.com/demo/XBook.nsf!

Conclusion

Two words really: Have. Fun. Play around with this stuff and see what you can make it do. You're smart. You're creative. You just have to forget the pre-conceived circular logic of "this is how you do this because this is how you do this..." because no one innovates by following how everyone else does it.

OK, enough of a pep talk. Go code something!

 
Patrick KwintenName:Patrick KwintenWebsite:http://quintessens.wordpress.comComment

great stuff! time to put some controls on openntf?

Chris TooheyName:Chris TooheyWebsite:http://www.dominoguru.com/Comment

Well, these are all custom controls... but there are a few controls I could submit. Perhaps when I get a free moment or two ;-)


(not published)




Evaluate this Formula: @LowerCase(@Text("FOO"))