Making my Domino development environment a bit more shiny

Fix Pack 4

Recently IBM announced the Fix Pack 4 release for IBM Notes/Domino. When checking my version of Domino I noticed I was a bit behind and it was time to polish my Domino development environment a bit.

For an ex-administrator / main developer I think it is good practice to keep your (latent) administrator knowledge up to date so you can provide yourself the best possible development conditions (an Domino administrator for Developer dummies whitepaper available somewhere?).

My updates

So this is what I did:

  • Installed the Fix Packs (tip)
  • Started the Server Controller (reference)(tip)
  • Installed some plugins for my browser (Postman)
  • Set up Directory Assistance (reference)
  • Set up to run some tasks/agents scheduled via a Program document (example)
  • Customized the login form with a Bootstrap UI (example)
  • And last but not least updated some plugins from OpenNTF (serve yourself)

With this I am a bit more up to date for the next x-months.

Suggestions?

I guess your development environment is state of the art and better than mine. That is why I would like to hear how your environment looks like or the suggestions you have.

Like a mentioned before, I am not aware if there is some kind of whitepaper available for developers who like to setup a Domino development environment, or a Domino Administration guide for dummies. I once heard a good man talking about such initiative but I wonder if that ever came to light?

Administration became fancy?

Since when became Domino Administration fancy I wondered after visiting this site? Nevertheless a great initiative.

Adding a Dojo tooltip to your XPages valuepicker

Here is a simple usability tip.

In some corporate organizations not all members are acquainted with modern, modest UI. For those an icon does not always tell them that an action lies underneath it.

For example the value picker from the Extension Library offers you a nice magnifier icon out of the box (which you can set to a custom icon in case desired). If you want to help your senior colleague that there lies no danger beneath clicking that icon you could provide an alternative tooltip for it.

Here is some sample code how you could do this:

<section class=”container”>
<div class=”row”>
<div class=”col-sm-1″><label for=”exampleInputName2″>Name</label></div>
<div class=”col-sm-2″><xp:inputText id=”inputText1″></xp:inputText></div>
<div class=”col-sm-9″>
<span id=”valuePickerTooltip”>
<xe:valuePicker id=”valuePicker1″ for=”inputText1″>
<xe:this.dataProvider>
<xe:dominoViewValuePicker databaseName=”FakeNames40K.nsf”
viewName=”People”>
</xe:dominoViewValuePicker>
</xe:this.dataProvider>
</xe:valuePicker>
</span>
<xe:tooltip id=”tooltip1″ for=”valuePickerTooltip”
label=”Pick a Person from the Address Book” position=”after”>
</xe:tooltip>
</div>
</div>
<div class=”row”>
<div class=”col-sm-9 col-sm-offset-1″><button type=”submit” class=”btn btn-primary”>Send invitation</button>
</div>
</div>
</section>

As a result the user will be presented something as followed when hovering over that icon:

tooltip

Building a Live Search function with Domino Access Services & jQuery Tokeninput

Introduction

A live search is a function where get search results returned while you type. In this post I will describe how you can add such a feature using the jQuery Tokeninput plugin and perform a full text search with Domino Access Services (DAS)as your data provider.

But first let’s take a look at how the end result looks like:

searchres

As in other examples we will apply the live search to the infamous fakenames application. You can grab this directory application from Codestore.

Step 1 – Download the resources and add them to your XPage

Add the following resources to a custom control:

Step 2 – Add the filter and search field

In the result screenshot you noticed the following elements:

  • A filter (People, Groups, Holidays)
  • A search field (with typeahead).
  • A (formatted) result list.

Therefor add the following HTML on your custom control:

As you notice we will be using Bootstrap to make the appearance a bit more attractive.

search_param

The hidden input element search_param will be the container for our selected filter.  The following code will set the value:

livesearch-input

The Tokeninput plugin will inject an (initially empty) unordered result list and input field in the livesearch-input input element.

Include a function to initiate the Tokeninput plugin:

Step 3 – Activate the plugin

In order to activate the Tokeninput plugin you need to include a script block control on your custom control and ad the following script:

function getObjType() {
var val = $(“#search_param”).val();
return val;
}

var restPrefix = “./api/data/collections/name/”
var hintText = “Enter text, use asterix(*) for Fulltext wildcards”;
var searchingText = “Searching…”;
var queryParam = “search”;
var propertyToSearch = “name”;
var searchDelay = 2000;
var minChars = 2;
var resultsLimit = 5; //not working??
var noResultsText = “No matches”;
var tokenLimit = 1;
var preventDuplicates = true;
var onAdd = function(item) {
var objType = getObjType();
var docID = item[‘@unid’];
var URL = “”;
switch (objType) {
case “Groups”:
URL = “Group.xsp?unid=” + docID;
break;
case “Holidays”:
URL = “Holiday.xsp?unid=” + docID;
break;
default:
URL = “Person.xsp?unid=” + docID;
}
window.location = URL;
};
var resultsFormatter = function(item) {
var objType = getObjType();
switch (objType) {
case “Group”:
sub = “dummy group sub”;
break;
case “Holiday”:
sub = “dummy Holiday sub”;
break;
default:
sub = “” + item.job;
}
if (sub == “”) {
sub = “No title available“;
}
if (sub.length > 30) sub = sub.substring(0, 30) + “…”;
var name = item.name;
if (name.length > 30) name = name.substring(0, 30) + “…”;
var img = ‘‘;
var text = ‘

‘ + name + ‘

‘ + sub + ‘


return ‘

  • ‘ + ‘
    ‘ + img + text + ‘

‘;
};

function setPlaceHolder() {
$(“#token-input-livesearch-input”).attr(“placeholder”, “Enter text”);
}

function init() {
$(“#livesearch-input”).tokenInput(restPrefix + getObjType(), {
hintText: hintText,
searchingText: searchingText,
queryParam: queryParam,
propertyToSearch: propertyToSearch,
searchDelay: searchDelay,
minChars: minChars,
resultsLimit: resultsLimit,
noResultsText: noResultsText,
tokenLimit: tokenLimit,
onAdd: onAdd,
preventDuplicates: preventDuplicates,
resultsFormatter: resultsFormatter
});
setPlaceHolder();
}

function re_init(objType) {
$(“#token-input-livesearch-input”).remove();
$(“.token-input-list”).remove();
$(“#livesearch-input”).tokenInput(restPrefix + getObjType(), {
hintText: hintText,
searchingText: searchingText,
queryParam: queryParam,
propertyToSearch: propertyToSearch,
searchDelay: searchDelay,
minChars: minChars,
resultsLimit: resultsLimit,
noResultsText: noResultsText,
tokenLimit: tokenLimit,
onAdd: onAdd,
preventDuplicates: preventDuplicates,
resultsFormatter: resultsFormatter
});
setPlaceHolder();
}

function submitSearch() {
//not required, overwritten by onAdd function.
}

As you see the Tokeinput plugin can be steered via diverse parameters. A clear description of the available options you can read here.

In our case we determine:

Data Provider

var restPrefix = “./api/data/collections/name/”

This defines we will be using Domino Access Services as data provider. We will use the names of the views People, Groups, Holidays which correspond with the options in our filter list.

Remember you need to enable DAS for the database AND the views.

onAdd = function(item)

The variable onAdd is a function that will be called when we select an item from the result list. We have set to allow only one item to be selected and the onAdd function will open a new window location with the corresponding object/document.

URL = “Person.xsp?unid=” + docID;
}
window.location = URL;

resultsFormatter = function(item)

This variable defines how the items in the collection provided by Domino Access Services will be presented in the UI. You can be as creative with it as you like. I choose for the option for an image, distinguished name and a sub-title e.g. the function for a person.

Ready

Are we done already? Yes we are! All the heavy lifting is done by the Tokeninput plugin and Domino Access Services.

Notice that Full Text search in Domino Access Services supports the usage of an asterix. Otherwise you get only results returned with an exact match.

firebugUse a plugin for your browser to check the URL call and response to DAS.

Some final thoughts

Do I found the live search feature useful?

– Yeah. Especially in mobile web applications you want to avoid that a user has to go back to home navigation each and every time. And with large data-sets infinite scrolling is a good option.

Do I find the Tokeninput plugin valuable?

– I find the plugin easy to understand but I noticed not all properties are implemented :-/  An example of something what I expected to be implemented is the number of returned results (fixed to max 10 items).

Can I recommend the plugin?

– In case you use Bootstrap applying a bootstrap theme meant mostly stripping the default style sheet. In case you use the Application Layout control from the Extension Library you will discover some problems:

  • When applying the live search in the search bar you get overlay with the Utility links.
  • When applying a filter option you get scrolling issues when opening the dropdown menu in the navbar section.
  • The result list can not be displayed direct under the search field due to the overlay of the navbar and it’s margins.

The consequence of these problems above made me decide to place the search bar in the main column section instead of the search bar and align it to the right via the pull-right class in Bootstrap. The result looks similar but I loose some white space. (perhaps the solution lies in understanding Bootstrap a bit more).

In case you can live with these conditions or restrictions I think you have an awesome desired feature!

Your turn!

What are your thoughts? In case you have provide a live search feature via some other plugin or custom code I am happy to hear from you.

I have uploaded a sample on Dropbox. I am happy to hear the improvements you have made.

Happy coding =)

Using the language bean from XPages Toolkit for Internationalization

Introduction

You have people who tend to tick around where they live and work and you have people who tend to switch location now and then. Especially in Europe which is divided into many countries with many different languages, somehow operating under one flague,  you are sometimes amazed that organizations have not fully adapted to the trend of “travelling” co-workers.

different langiages

If you are lucky an application is presented bilingual but in a lot of occasions an application is presented either in English (when that is the official language of communication) or in a native language where the application is initiated and being used.

But what if that cross-border European co-worker enters the work floor?

Internationalization

Internationalization refers to the process whereby you prepare your application for users from varied geographies. There are two parts to this:

The need for localization is obvious; a German user wants to see an application in German and a French user in French, and so on. Localization involves making different language versions of all the application’s user interface available and ensuring the correct strings are used based on user preferences.

Support in XPages

In the IBM Notes and Domino Application Development wiki you can learn about the support for internationalization in XPages.

In this post I will describe how you can use the language bean that is part of the XPages Toolkit available in OpenNTF.

Sample application

In this post we will build a simple XPages UI which looks as followed:

sample

In a combo-box you get presented a list with available language options. And based upon your selection values will be collected from a set of property files.

I will include a dropbox link to the sample application.

Walkthrough

First: download & install the library. Beside the library there is also a sample application which comes in handy to borrow code from.

Java classes

The following files you will need:

class

Property files

The property files contain the actual string values. The amount of files depends on the number of languages you want to support. In our case 4: English (default), Swedish, German and Dutch. There will be three types of files: general, contacts and keywords.  That makes 12 (4*3) in total.

propfiles

Here is what the files could look like. First the general poperties file:

AppTitle=Language Bean
Formula=Formula
Bean=Bean
NotAvailable=Not Available
SwitchLanguage=Choose Your Language
Select=Select
Header=Demo Language Bean
SubHeader=Register A Person
Submit=Submit

Which becomes in Swedish:

AppTitle=Språk Böna
Formula=Formel
Bean=Böna
NotAvailable=Inte Tillgänglig
SwitchLanguage=Välj Ditt Språk
Select=Välj
Header=Demo Språk Böna
SubHeader=Registrera En person
Submit=Skicka

The contacts properties files:

LastName=Last Name
FirstName=First Name
Gender=Gender
Hair=Hair

In German:

LastName=Nachname
FirstName=Vorname
Gender=Geschlecht
Hair=Har

And at last the keywords properties file:

Male=male
Female=female
White=white
Brown=brown
Black=black
Red=red

Which becomes in Dutch:

Male=mannelijk
Female=vrouwelijk
White=wit
Brown=bruin
Black=zwart
Red=rood

The properties files are “registrered” in the language bean via the following method:

public List<String> getPropertyFileNames() {
List<String> propertyFileNames = new ArrayList<String>();
propertyFileNames.add(“contact”);
propertyFileNames.add(“keywords”);
propertyFileNames.add(“general”);
return propertyFileNames;
}

Layout custom control

My demo app contains 2 pages which demonstrates the 2 options you have with the toolkit: use the language bean or the toolkit @formula.

<?xml version=”1.0″ encoding=”UTF-8″?>
<xp:view xmlns:xp=”http://www.ibm.com/xsp/core&#8221; xmlns:xe=”http://www.ibm.com/xsp/coreex”&gt;
<xe:applicationLayout id=”applicationLayout1″><xp:this.facets>
<xp:panel xp:key=”LeftColumn”>
<xe:navigator id=”navigator1″>
<xe:this.treeNodes>
<xe:pageTreeNode page=”/bean.xsp”>
<xe:this.label><![CDATA[#{javascript:xptI18NBean.getValue(“general.Bean”)}]]></xe:this.label>
</xe:pageTreeNode>
<xe:pageTreeNode page=”/formula.xsp”>
<xe:this.label><![CDATA[#{javascript:xptI18NBean.getValue(“general.Formula”)}]]></xe:this.label>
</xe:pageTreeNode>
</xe:this.treeNodes>
</xe:navigator></xp:panel></xp:this.facets>
<xp:callback facetName=”facet_1″ id=”callback1″></xp:callback>
<xe:this.configuration>
<xe:simpleResponsiveConfiguration navbarText=”Language Bean”
collapsedLeftMenuLabel=”Pages”>
<xe:this.navbarUtilityLinks>
<xe:basicLeafNode
href=”https://quintessens.wordpress.com/&#8221;
label=”Kwintessential Notes” title=”Visit My Site”>
</xe:basicLeafNode>
<xe:basicLeafNode
href=”http://www.openntf.org/main.nsf/project.xsp?r=project/XPages%20Toolkit&#8221;
label=”XPages Toolkit” title=”Visit Project on OpenNTF”>
</xe:basicLeafNode>
</xe:this.navbarUtilityLinks>
</xe:simpleResponsiveConfiguration>
</xe:this.configuration>
</xe:applicationLayout>
</xp:view>

Bean XPage

I will spare you the  complete code for the Bean page. Check the download if you want the complete code.  The principle is simple. You collect the value via the following pattern

xptI18NBean.getValue(“[properties file].[key]”)

That could become something like:

xptI18NBean.getValue(“general.SwitchLanguage”)

Switching language

In order to switch language a combobox control is presented with the following code:

<xp:comboBox id=”cbSwitchLanguage” defaultValue=”#{javascript:xptI18NBean.getCurrentLanguage()}”>
<xp:selectItems>
<xp:this.value>
<![CDATA[#{javascript:xptI18NBean.getAllLanguages()}]]>
</xp:this.value>
</xp:selectItems>
<xp:eventHandler event=”onchange” submit=”true” refreshMode=”complete”>
<xp:this.action>
<![CDATA[#{javascript:var sv = getComponent(“cbSwitchLanguage”).getValue()
if(sv != null && sv != “”) {
var locSet:Locale = new Locale(sv);
context.setLocale(locSet);
context.reloadPage();
}}]]>
</xp:this.action>
</xp:eventHandler>
</xp:comboBox>

Language options

The getAllLanguages method in the language bean “registers” the available language options:

public List<String> getAllLanguages() {
List<String> languages = new ArrayList<String>();
languages.add(“en”);
languages.add(“de”);
languages.add(“sv”);
languages.add(“nl”);
return languages;
}

That is basically it!

Formula XPage

This page differs from the Bean page in the way it accesses the property files. It uses a formula which is defined in the XPages Toolkit library.

The formula follows the following pattern:

@XPTLanguageValue(“[properties file].[keyword]”)

Which could become something like:

@XPTLanguageValue(“general.SwitchLanguage”)

Download

A sample application for download is available under the following URL.

Wrapup

I am curious what method you use to make your applications available in multiple languages. Please drop a line how you have solved it.

I found the language bean in the XPages Toolkit very intuitive and easy to use. At least in some cases it solves the problem nice and quickly so my thanks go out to it’s project members.

svenska

Adding a sliding menu to your Bootstrap Application Layout control

Introduction

Since responsive webdesign (RWD) is on top of the list in most application development projects these days I assume most of us have been looking at the options within IBM Notes.

Bootstrap

In case you use the Bootstrap plugin in the Extension Library you have noticed that the menu in the left column get presented above the main column in smaller devices.

bs_desktop

Image: Display on desktop

bs_phone

Image: Display on phone

As you can see in a more advanced application the menu options already suppress the content too much at the bottom. So what are your options?

Off Canvas Slide Menu For Bootstrap

In this post I will describe how I implemented in XPages a slide menu which is described here. We still use the Application Layout control with the Bootstrap RWD functionality since it contains more functionality than just to provide a navbar.

Step 1 – Provide a Menu icon

We need something (text, button, icon) from where we can initiate the appearance of the menu. In our case I choose to include a ‘hamburger’ menu icon in the navBarLogo property:

<xe:this.configuration>
<xe:simpleResponsiveConfiguration navbar=”true”
loaded=”true” navbarLogo=”/1432224591_menu-alt.png”
navbarLogoStyleClass=”extraMenu” navbarText=”MyApp”>
</xe:simpleResponsiveConfiguration>
</xe:this.configuration>

For example iconfinder provide great icons.

Step 2 – Register Click event for Menu icon

I included “extraMenu” as an additional styleclass. This styleclass we will use when the document is ready. We do this in a Script Block control:

<xp:scriptBlock id=”onLoadScript” type=”text/javascript”>

<xp:this.value><![CDATA[
$(document).ready(function(){
$(“.extraMenu“).attr(“id”,”nav-expander“);
//Navigation Menu Slider
$(‘#nav-expander‘).on(‘click‘,function(e){
e.preventDefault();
$(‘body’).toggleClass(‘nav-expanded’);
});
$(‘#nav-close’).on(‘click’,function(e){
e.preventDefault();
$(‘body’).removeClass(‘nav-expanded’);
});

// Initialize navgoco with default options
$(“.main-menu”).navgoco({
caret: ‘<span class=”caret”></span>’,
accordion: false,
openClass: ‘open’,
save: true,
cookie: {
name: ‘navgoco’,
expires: false,
path: ‘/’
},
slide: {
duration: 300,
easing: ‘swing’
}
});
});]]></xp:this.value>
</xp:scriptBlock>

When the document is ready we assign the ID attribute to the navbarLogo since this ID is used to bind an click event on. We could have bind the event directly on the class but I am not sure if the ID is used in any other way (don’t break what isn’t broken).

Step 3 – Provide a menu that slides in.

In this example I simply provide the menu that is used in the demo:

<nav>
<ul class=”list-unstyled main-menu”>
<!–Include your navigation here–>
<li class=”text-right”>
<a href=”#” id=”nav-close”>X</a>
</li>
<li><a href=”#”>Menu One<span class=”icon”></span></a></li>
<li><a href=”#”>Menu Two<span class=”icon”></span></a></li>
<li><a href=”#”>Menu Three<span class=”icon”></span></a></li>
<li>
<a href=”#”>Dropdown</a>
<ul class=”list-unstyled”>
<li class=”sub-nav”><a href=”#”>Sub Menu One<span class=”icon”></span></a></li>
<li class=”sub-nav”><a href=”#”>Sub Menu Two<span class=”icon”></span></a></li>
<li class=”sub-nav”><a href=”#”>Sub Menu Three<span class=”icon”></span></a></li>
<li class=”sub-nav”><a href=”#”>Sub Menu Four<span class=”icon”></span></a></li>
<li class=”sub-nav”><a href=”#”>Sub Menu Five<span class=”icon”></span></a></li>
</ul>
</li>
<li><a href=”#”>Menu Four<span class=”icon”></span></a></li>
<li><a href=”#”>Menu Five<span class=”icon”></span></a></li>
</ul>
</nav>

Step 4 – Include the supporting files

The demo uses the following files which you should add to your application as resources:

js

<script
src=”/jquery.navgoco.js”>
</script>

css

<xp:this.resources>
<xp:styleSheet href=”/main.css”></xp:styleSheet>
</xp:this.resources>

The result

The image below gives you an indication what the result looks like. When you click the hamburger icon the menu appears from the right. With the X marker you can close the menu again.

result

Notice that my content is not suppressed below the menu as the Bootstrap plugin would do.

Download

An demo XPages application is available on my dropbox account

Domino Access Service – Posting a document

Introduction

In our app described in previous posts I have included an interface to post a new document using Domino Access Services. Here is how I did it.

HTML structure

The main part of the ‘form’ is the HTML structure.

form

Since we use Bootstrap I included form-groups to layout the fields. In my example I still use XPages, but the inputfields you can replace with HTML input elements.

<form role=”form”>

<h2>Registration</h2>
<div id=”entryForm”>
<div class=”form-group”>
<xp:label value=”Firstname:” id=”label2″></xp:label>
<xp:inputText id=”inpFirstname” styleClass=”firstName”>
<xp:this.attrs>
<xp:attr name=”placeholder” value=”Enter firstname”></xp:attr>
</xp:this.attrs>
</xp:inputText>
</div>
<div class=”form-group”>
<xp:label value=”Lastname:” id=”label3″></xp:label>

<xp:inputText id=”inpLastname” styleClass=”lastName”>
<xp:this.attrs>
<xp:attr name=”placeholder” value=”Enter lastname”></xp:attr>
</xp:this.attrs>
</xp:inputText>
</div>
<div class=”form-group”>
<xp:label value=”Email:” id=”label1″></xp:label>
<xp:inputText id=”inpEmail” styleClass=”email” type=”email”>
<xp:this.attrs>
<xp:attr name=”placeholder” value=”Enter email”></xp:attr>
</xp:this.attrs>
</xp:inputText>
</div>
<div class=”form-group”>
<xp:label value=”Password:” id=”label4″></xp:label>
<xp:inputText id=”inpPassword” type=”” styleClass=”wannebepassword”>
<xp:this.attrs>
<xp:attr name=”placeholder” value=”Enter password”></xp:attr>
</xp:this.attrs>
</xp:inputText>
</div>
<xp:button value=”Submit” id=”button1″ styleClass=”btnRegister btn btn-default”>
</xp:button>
</div>
</form>
<div id=”formResponse”></div>

JavaScript

On the onClientLoad event of the XPage I have included the following script.

Parameters

Keep in mind to include the form name in the URL parameter (?form=Person) since you cannot include that pair in the JSON object that is send to Domino Access Service.

The &computewithform=true parameter ensures the HTTPPassword field will be translated with the @Password function.

<xp:eventHandler event=”onClientLoad” submit=”false”>
<xp:this.script>
<![CDATA[$(document).ready(function() {
$(“.wannebepassword”).attr(“type”, “password”);
$(“.btnRegister”).click(function(e) {
var firstName = $(“.firstName”).val();
var lastName = $(“.lastName”).val();
var email = $(“.email”).val();
var password = $(“.wannebepassword”).val();
var newName = $(“.firstName”).val() + ” ” + $(“.lastName”).val();
if (newName !== ” “) {
var newPersonObj = {
FirstName: firstName,
LastName: lastName,
FullName: newName,
InternetAddress: email,
HTTPPassword: password,
Form: “Person”
};
$.ajax({
url: ‘http://server/fakenames40k.nsf/api/data/documents?form=Person&computewithform=true&#8217;,
type: ‘POST’,
data: JSON.stringify(newPersonObj),
dataType: ‘xml’,
accepts: {
xml: ‘text/xml’,
text: ‘text/plain’
},
contentType: “application/json”
}).done(function(data, textStatus, jqXHR) {
var newPersonLocation = jqXHR.getResponseHeader(“Location”);
$(“#entryForm”).hide();
$(“#formResponse”).html(‘Registration successfull.<br/><a class=”btn btn-default” href=”‘ + newPersonLocation + ‘”>Check it out!</a>’);
}).fail(function(jqXHR, textStatus, errorThrown) {
alert(“Registration has failed:” + errorThrown);
console.log(‘Registration has failed.’);
});
} else {
alert(“Please enter a name”);
}
return false;
});
});]]>
</xp:this.script>
</xp:eventHandler>

Password attribute

XPages does not allow you to define the password type as attribute. I found the answer from Tim Tripcony on Stackoverflow helpful to define a work-around.

Wrap up

That is about it!

This is just a simple example. Probably you would normally include some more validation (avoid double entries) but you get the idea.

Adding search to our app

Introduction

In this post I will demonstrate how to apply a search to our application described in previous posts, in which we read the JSON from Domino Access Service and parse it with the Jackson library to display it thereafter with a Repeat control.

Since I am using in our application the Application Layout control with a responsive Bootstrap UI (shameless pitch to glory the persons who delivered this great functionality to XPages) which includes a searchBar section and scrolling through 40K of person records is not something you want to anguish your thumb with, a search functionality gives the advantage to skip scrolling through unnecessary documents.

searchBar section

Here is how I set up the searchBar section in the Application Layout control:

searchbar

As you can see I have defined a result page for the search, called search.xsp.

Here is how the search bar will look like for the user:

searchbox

XPage search

beforePageLoad event

The beforePageLoad event has slightly changed compared with event in our initial XPage. This time we search for the search parameter defined in the searchBar section:

var query = context.getUrlParameter(“search”);
var persons = new Array();
persons = personsBean.getPersons(“http://dev1/fakenames40k.nsf/api/data/collections/name/people?count=25&search=” + query);
viewScope.put(“names”,persons);

Next is the result list. I have added an additional list item and added the active class:

This item will display the search query we have provided:

acgtive

The Repeat control has also changed slighty. The rows property has been adjusted. We calculate the number of documents returned by the full text search.

<![CDATA[#{javascript:database.updateFTIndex(true);
var query:string = context.getUrlParameter(“search”);
var vw:NotesView = database.getView(“people”);
var totNums:Integer = vw.FTSearch(query).toFixed();
return totNums}]]>

Also the text that indicates where we are in the result set has been modified:

Tip: since we are actually performing FT searches here perhaps it is better to put the counted results already from our initial call in a scope variable and re-use it =(

The button in our infinite scroll function/custom control has also been adapted. Here is the code:

Here is what the end result looks like after a search:

endresult