dominoGuru.com

Your Development & Design Resource

Customizing XPage RadioGroup Controls for Vertical Navigation Menus

dominoGuru.com XPages Quicktips While creating an XPages-based user interface for my Remote Console HD application, I ran into a particular issue with the xp:radioGroup Control that I think warrants sharing under the provision of "stuff that took me far longer than it should of, therefore I'll save someone else the trouble once Google indexes this post...".

The desired user interface for Remote Console HD meant that I would have to create a simple left-handed navigation menu ContentPane with the selected content displaying on the main/NotesView ContentPane.

Remote Console HD Demo Screencap - Click to Zoom Remote Console HD Demo Screencap - Click to Zoom

To get started, I used a dijit.layout.SplitContainer and two dijit.layout.ContentPane pass-thru HTML DIV Elements:

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" dojoParseOnLoad="true"
    dojoTheme="true" style="margin: 0px !important; padding: 0px important">

    <xp:this.resources>
        <xp:dojoModule name="dijit.layout.ContentPane" />
        <xp:dojoModule name="dijit.layout.SplitContainer" />
    </xp:this.resources>

    <div dojoType="dijit.layout.SplitContainer" orientation="horizontal"
        sizerWidth="7" activeSizing="true" style="height: 100%; margin: 0px !important; padding: 0px !important;">

        <div dojoType="dijit.layout.ContentPane" sizeMin="200" sizeShare="2"
            style="margin: 0px !important; padding: 0px !important; background-color: #eee;">
           
        </div>

        <div dojoType="dijit.layout.ContentPane" sizeMin="400" sizeShare="10">
           
        </div>

    </div>

</xp:view>

This gave me my left-navigation, right-content layout. Now, all I needed to do was actually create my "navigation" controls.

I started with a radioGroup Control mostly so I can refer back to the Control value if needed:

<xp:radioGroup id="selectedServers" layout="pageDirection" style="border: none;">
    <xp:selectItems>
        <xp:this.value>
            <![CDATA[#{javascript:var slist = @DbColumn("names.nsf","($Servers)",1);
                @Text(@Name("[Abbreviate]", slist) + "|" + slist)}]]>
        </xp:this.value>
    </xp:selectItems>
</xp:radioGroup>

Basing a simple Repeat Control on this radioGroup Control value, I was able to create the Server "cards" which are displayed on the right-hand side of the navigation (each with their own data source).It was simply a matter of writing my "card" and creating Panel Controls that themselves support their own data source for things like the Applications, Logs, or Remote Console-specific activity logs.

Wanting to make this resemble vertical tab navigation instead of a simple vertical-aligned series of radio-type INPUT Elements, I decided to hide the actual radio part of the Control with CSS and rely on the user click on the LABEL for each "server" they select.

First, you need to know what HTML a radioGroup Control generates:

<div id="view:_id1:frame_navigation" class="navigation">
    <fieldset id="view:_id1:selectedServers" style="border: none;" class="xspRadioButton">
        <table class="xspRadioButton" style="border: none;">
            <tbody>
                <tr>
                    <td>
                        <label>
                            <input type="radio" name="view:_id1:selectedServers" value="CN=acme/O=GBSBLOGS"> acme/GBSBLOGS
                        </label>
                    </td>
                </tr>
                ...
            </tbody>
        </table>
    </fieldset>
</div>

... and now that I know what my generated HTML will look like for my radioGroup Control, I simply style as desired:

div.navigation fieldset, div.navigation fieldset table, div.navigation fieldset table tbody, div.navigation fieldset table tbody tr, div.navigation fieldset table tbody tr td, div.navigation fieldset table tbody,
div.navigation fieldset table tbody tr td {
    display: block;
    margin: 0px !important;
    padding: 0px !important;
}

div.navigation fieldset table tbody tr td label {
    display: block;
    width: 100%;
    border-bottom: 1px dashed #666;
    background-color: #fff;
    font-weight: normal;
    margin: 0px;
    padding: 20px 0px 20px 0px;
    text-align: left;
    cursor: pointer;
    background-image: url(listArrow.png);
    background-position: center right;
    background-repeat: no-repeat;
    color: #666;
}

div.navigation fieldset table tbody tr td label input {
    visibility: hidden;
}

radioGroup Control vs. CSS Styled radioGroup 
Control Vertical Navigation Menus radioGroup Control vs. CSS Styled radioGroup Control Vertical Navigation Menus

The navigation was working great at a technical level... but not so much from a user experience standpoint: I couldn't tell which of my "cards" were active (outside of reading the title) as the radioGroup Control does not change the Label when selected.

Of course, it's not intended to change the label (the active state is shown by filling in the "radio"...) but I really needed some way of changing the label -- preferably the className (class attribute of the LABEL Element) -- to "active" or something.

... after entirely way too much time spent trying to figure out how to do this, I came up with the following CSJS (Client-Side JavaScript) function:

function navigation_active(obj) {
   
    for (i=0; i<obj.length; i++) {
        if (obj[i].checked == true) {
            obj[i].parentNode.className = 'active';
        } else {
            obj[i].parentNode.className = '';
        }
    }

}

-- and updating my radioGroup Control markup in my XPage:

<xp:radioGroup id="selectedServers" layout="pageDirection" style="border: none;">
    <xp:selectItems>
        <xp:this.value>
            <![CDATA[#{javascript:var slist = @DbColumn("names.nsf","($Servers)",1);
            @Text(@Name("[Abbreviate]", slist) + "|" + slist)}]]>
        </xp:this.value>
    </xp:selectItems>
    <xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="frame_notesview">
        <xp:this.script>
            <![CDATA[navigation_active(document.getElementsByName('#{id:selec tedServers}'))]]>
        </xp:this.script>
    </xp:eventHandler>
</xp:radioGroup>

And that's pretty much it really. Now, the LABEL Element's className is switched to "active" via the CSJS when I change a value on the radioButton Control.

NOTE: This technique will not work with Internet Explorer. You'll have to employ a UserAgent switch and compute the event (change it from "onchange" to "onclick".

... and earlier in this article I said "I started with a radioGroup Control..." mostly because by the time I though to write this article... I changed my mind.

Since I'm using a Repeat Control to dynamically build my Server "card", there's no reason I can't display multiple "cards"!

<xp:checkBoxGroup id="selectedServers" layout="pageDirection" style="border: none;">
    <xp:selectItems>
        <xp:this.value>
            <![CDATA[#{javascript:var slist = @DbColumn("names.nsf","($Servers)",1);
            @Text(@Name("[Abbreviate]", slist) + "|" + slist)}]]>
        </xp:this.value>
    </xp:selectItems>
    <xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="frame_notesview">
        <xp:this.script>
            <![CDATA[navigation_active(document.getElementsByName('#{id:selec tedServers}'))]]>
        </xp:this.script>
    </xp:eventHandler>
</xp:checkBoxGroup>

Using a checkBoxGroup gets the job done as well, but this time it's multi-value!

Remote Console HD Demo 
Screencap using checkBoxGroup - Click to Zoom Remote Console HD Demo Screencap using checkBoxGroup - Click to Zoom


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.