Wednesday, August 12, 2015

Bootstrap Progress Bars - sample database

I've been digging into Bootstrap for a bit now. One of the useful components is the progress bar. David Leedy did a great NotesIn9 on them and I followed it, and it was greatly valuable. I took his work and made a sample database. This is all his work, I just transcribed it (I changed the viewScope variable names however). Hopefully having this in a sample database will be useful.

Download the file

Cheers,
Brian




Tuesday, July 14, 2015

dataTable column width

In my last post, I'd say I'd look into controlling the column width. It's a setting:

<xp:column
  id="column4"

 style="width:5.0%">

so that was easy.

Cheers,
Brian

dataTable with Categories

I've been using DataTables for a number of things lately, where I need a bit more flexibility than a viewPanel, but I don't want to build it from scratch with a Repeat.

I'm currently working on process where I'm making a nsf to replace a MS Access database. So I'm having to adjust from the relational method. This means I need to use a key to look things up in a view to display the human friendly words rather than the code. So traditional Notes views don't do that. DataTables give me the flexibility I need. For part of this, I have 'events', and these will have one to several classes at each of these events. I want to hide the classes for each event until I click something to make it look neater and to save space.

DataTables don't have a native way to show categories, so I found one. I put a repeat in a column, and populate that repeat with a NotesViewEntryCollection from a value in a row of the DataTable. I tried to use the plus/minus icons like shown here in a great post by Ulrich Krause. But when I paged the icons disappeared. Both of them. So I used the basic idea, and put a link in that was always there to show the classes, and another link to hide them if desired. It works like I desire, so fine.

So this does what I wanted. I'm putting the code below. I have a few things to adjust. First, the classes should be in a table so they display better (I'm not putting it in to make the code a little shorter). Also, the columns resize when the repeat is expanded. Something I'll look into fixing after I post this.

Cheers,
Brian

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
    <xp:this.data>
        <xp:dominoView
            var="view1"
            viewName="Event\Name">
            <xp:this.databaseName><![CDATA[#{javascript:var curServer = @Subset(@DbName(),1);
if(@Left(curServer.toLowerCase(), "/") == "cn=svrname") {
    session.getDatabase('
svrname/OU', 'foldername\\Data.nsf');
} else {
    session.getDatabase('', '
foldername\\Data.nsf');
}}]]></xp:this.databaseName>
        </xp:dominoView>
    </xp:this.data>
    <xp:dataTable
        id="dataTable1"
        rows="30"
        var="rowData"
        value="#{view1}">
        <xp:this.facets>
            <xp:pager
                partialRefresh="true"
                layout="Previous Group Next"
                xp:key="header"
                id="pager1">
            </xp:pager>
            <xp:pager
                partialRefresh="true"
                layout="Previous Group Next"
                xp:key="footer"
                id="pager2">
            </xp:pager>
        </xp:this.facets>
        <xp:column id="column1">
            <xp:this.facets>
                <xp:label
                    value="Event Name"
                    id="label1"
                    xp:key="header">
                </xp:label>
            </xp:this.facets>
            <xp:link
                escape="true"
                id="link1">               
            </xp:link>
            <xp:text
                escape="true"
                id="computedField4">
            <xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[0];}]]></xp:this.value></xp:text></xp:column>
        <xp:column id="column2">
            <xp:text
                escape="true"
                id="computedField5">
            <xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[4];}]]></xp:this.value></xp:text>
           
            <xp:this.facets>
                <xp:label
                    value="Date"
                    id="label2"
                    xp:key="header">
                </xp:label>
            </xp:this.facets>
        </xp:column>
        <xp:column id="column3">
        
            <xp:this.facets>
                <xp:label
                    value="Group"
                    id="label3"
                    xp:key="header">
                </xp:label>
            </xp:this.facets>
            <xp:text
                escape="true"
                id="computedField6">
            <xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[3];}]]></xp:this.value></xp:text></xp:column>
        <xp:column id="column4">           
            <xp:this.facets>
                <xp:label
                    value="Number"
                    id="label4"
                    xp:key="header">
                </xp:label>
            </xp:this.facets>
            <xp:text
                escape="true"
                id="computedField7">
                <xp:this.value><![CDATA[#{javascript:rowData.getColumnValues()[2];}]]></xp:this.value>
                <xp:this.converter>
                    <xp:convertNumber
                        type="number"
                        integerOnly="true">
                    </xp:convertNumber>
                </xp:this.converter>
            </xp:text></xp:column>
        <xp:column id="column6">
        <xp:panel id="mainpanel">   
            <xp:link
                escape="true"
                text="Classes"
                id="link6">
            <xp:eventHandler
                event="onclick"
                submit="false">
                <xp:this.script><![CDATA[var visibility = 'show';
XSP.partialRefreshGet("#{id:mainpanel}", {
params: {'$$xspsubmitvalue': visibility},
onComplete: function () {
    XSP.partialRefreshGet("#{id:secondpanel}", {
        params: {'$$xspsubmitvalue': visibility}});}
});]]></xp:this.script>
            </xp:eventHandler></xp:link>
        </xp:panel></xp:column>
        <xp:column id="column5">
            <xp:this.facets>
                <xp:label
                    value="Courses"
                    id="label5"
                    xp:key="header">
                </xp:label>
            </xp:this.facets>
            <xp:panel id="secondpanel">
            <xp:repeat
                id="repeat1"
                rows="30"
                rendered="#{javascript:context.getSubmittedValue()== 'show'}"
                var="rptRowData">
                <xp:this.value><![CDATA[#{javascript:var curServer = @Subset(@DbName(),1);
if(@Left(curServer.toLowerCase(), "/") == "cn=svrname") {
    var dataDb:NotesDatabase=session.getDatabase('
svrname/ou', 'foldername\\Data.nsf');
} else {
    var dataDb:NotesDatabase=session.getDatabase('', '
foldername\\Data.nsf');
}

var v:NotesView=dataDb.getView('Class Instance\\Event-Course');
var nvec:NotesViewEntryCollection=v.getAllEntriesByKey(rowData.getColumnValues()[2] + '', true);
return nvec;}]]></xp:this.value>
                <xp:text
                    escape="true"
                    id="computedField1">
                    <xp:this.value><![CDATA[#{javascript:rptRowData.getColumnValues()[1];}]]></xp:this.value>
                </xp:text>
                &#160;&#160;&#160;
                <xp:text
                    escape="true"
                    id="computedField2">
                    <xp:this.value><![CDATA[#{javascript:rptRowData.getColumnValues()[2];}]]></xp:this.value>
                    <xp:this.converter>
                        <xp:convertNumber
                            type="number"
                            integerOnly="true">
                        </xp:convertNumber>
                    </xp:this.converter>
                </xp:text>
                &#160;&#160;&#160;&#160; &#160;
                <xp:text
                    escape="true"
                    id="computedField3">
                    <xp:this.value><![CDATA[#{javascript:var cNumV:NotesView=database.getView('Course Number');
var cNVE:NotesViewEntry=cNumV.getEntryByKey(rptRowData.getColumnValues()[1], true);
if(cNVE != null){
return cNVE.getColumnValues()[1];
}
return "Course Name not found";}]]></xp:this.value>
                </xp:text>
                &#160;&#160;&#160;&#160;&#160;&#160;
            </xp:repeat>
            <xp:link
                escape="true"
                text="Close"
                rendered="#{javascript:context.getSubmittedValue()== 'show'}"
                id="link5">
                <xp:eventHandler
                    event="onclick"
                    submit="false">
                    <xp:this.script><![CDATA[var visibility = 'hide';
XSP.partialRefreshGet("#{id:mainpanel}", {
    params: {'$$xspsubmitvalue': visibility},
    onComplete: function () {
    XSP.partialRefreshGet("#{id:secondpanel}", {
    params: {'$$xspsubmitvalue': visibility}});}
});]]></xp:this.script>
                </xp:eventHandler>
            </xp:link>
            </xp:panel>
        </xp:column>
    </xp:dataTable>
    <xp:br></xp:br>
    </xp:view>




Saturday, July 4, 2015

StartKeys for categorized viewPanel and number column

In case this helps someone:

I have a database shared by a couple of departments, I use a field to segregate them. Each document has a MemberKey with a number value.

The first column is the department, sorted but not categorized, then a view were the column is sorted on numbers. As numbers they don't sort in the "proper" order. So I created a new column that padded it with zeroes to for the sort to be correct:

@Right("00000" + @Text(MemberKey);5)

So the third column is just the number, so it appears properly.

So I want this in an XPage viewPanel and to use the startKeys to get the the number desired.

I set the viewPanel to filter by the department name, and don't display the padded view. But it doesn't work. It doesn't work if I use the padded column either. It's because I'm getting just one category, so it's not really "starting" there.

I noticed the startKeys element can take a Vector, so I tried that. And it works.

I have a view panel that does not

I have a field  where I populate a viewScope called vFilter. If that is null, it return just one element in the vector, the department. Otherwise it returns a two element vector, with the department and the number I want to go to.

Here is my code in the startKeys element. (I'm using part of Thomas Adrian's Intrapages).

var query = new java.util.Vector();
var v = database.getView("(LookupUsers)");
var userdoc:NotesDocument = v.getDocumentByKey("User_UNID_" + userid,true);
if(userdoc!=null){
    query.add(userdoc.getItemValueString('regDepartment'));
    } else {
    query.add("Department not found");
    }
if(viewScope.vFilter != null){
query.add(@Right('00000' +  viewScope.vFilter,5));
return query;
}
return query;


Cheers,
Brian

Wednesday, July 1, 2015

ComboBox - Validate so default value is not selected

One of the things that I've been trying to get to work in XPages is getting validation to reject the default value of a combobox. Well, this morning I sat down and decided to get it done. I've used other methods to get around this until now, but this seems to do it.

I have a combobox with "--Select--" as the default value. If that value is still there on submission, I want a display error control to execute. To do this, I think you need to have "--Select--" as the itemValue as well as the itemLabel, but I'm not sure, as I habitually use both anyway.

Add a validateContraint, and use the RegEx "^((?!--Select--).)*$" , I got this from this StackOverflow Post. So on submission, if a value hasn't been selected (errm, sorry) no dice.

I tested on a combobox that needed the user to select the month, the entire element is below.

There may be a better way, but having this will be a relief for me.

Cheers,
Brian
                    <xp:comboBox
                        id="comboBox1"
                        value="#{document1.rptCover}"
                        style="width:125.0px"
                        defaultValue="--Select--">

                        <xp:this.validators>                           
                            <xp:validateConstraint
                                regex="^((?!--Select--).)*$"
                                message="Select a month">
                            </xp:validateConstraint>
                        </xp:this.validators>
                        <xp:selectItem
                            itemLabel="--Select--"
                            id="selectItem15" itemValue="--Select--"/>

                        <xp:selectItem
                            itemLabel="January"
                            itemValue="January"
                            id="selectItem1" />

                        <xp:selectItem
                            itemLabel="February"
                            itemValue="February"
                            id="selectItem2" />

                        <xp:selectItem
                            itemLabel="March"
                            itemValue="March"
                            id="selectItem3" />

                        <xp:selectItem
                            itemLabel="April"
                            itemValue="April"
                            id="selectItem4" />

                        <xp:selectItem
                            itemLabel="May"
                            itemValue="May"
                            id="selectItem5" />

                        <xp:selectItem
                            itemLabel="June"
                            itemValue="June"
                            id="selectItem6" />

                        <xp:selectItem
                            itemLabel="July"
                            itemValue="July"
                            id="selectItem7" />

                        <xp:selectItem
                            itemLabel="August"
                            itemValue="August"
                            id="selectItem8" />

                        <xp:selectItem
                            itemLabel="September"
                            itemValue="September"
                            id="selectItem9" />

                        <xp:selectItem
                            itemLabel="October"
                            itemValue="October"
                            id="selectItem10" />

                        <xp:selectItem
                            itemLabel="November"
                            itemValue="November"
                            id="selectItem11" />

                        <xp:selectItem
                            itemLabel="December"
                            itemValue="December"
                            id="selectItem12" />
                    </xp:comboBox>

Friday, June 26, 2015

Populate an InputText Date field (that has a calendar picker)

I didn't see much on this, so I'm posting in case it helps someone.

I'm working on an application that has an XPage that a user fills out, then clicks to get a new version of that page. Most of the data should carry over, including an inputText field for a Domino document bound to a date field and I have the default datepicker on it.

I put the values from the first page into sessionScopes and used that to populate them for the next page. Easier on the user. All of them worked except the date.

Here is what worked.

Getting the value:

var nDT:NotesDateTime = document1.getItemValueDateTime('EventDate');
sessionScope.put("EventDate", nDT.getDateOnly());


Setting the value in afterPageLoad:

document1.replaceItemValue('EventDate', session.createDateTime(sessionScope.EventDate));

I've not found a way to set the component value yet, it's just not worked in any permutation I've tried so far. This does what I need so far, so I stopped trying on the component.

Cheers,
Brian

Wednesday, June 10, 2015

Looking for Domino/XPages Developer positions

My employer had decided to migration off the Domino platform. The direction chosen is not one I'm comfortable with, and so we have decided to part ways. They are doing no new development, and there will be limited allowance for changes to the existing .nsfs. I'm sad to have to go from what otherwise has been a great position, but where they are going is the one I don't want to go.

So, this puts me open. I'm up for contract or perm situations. I've been hitting the boards, but if you have a suggestion, please contact me at my yahoo.com address: brian.moore100 I've got quite a bit of experience, and I can bring that to work for you.

Cheers,
Brian