Fixing the Tooltip function in XPages #2

In a previous post I wrote about the disfunction of the tooltip after validation with the Domino server. It turns out my gigia-form has a lot of fields with visibility properties set that are calculated after partial refresh. To have tooltip fixed for the fields that become visible during interaction with the user I needed to apply another patch.

From the xsnippet for the standby control I took the first part to set up the ability to subscribe to the different partial refresh events. Then I added some lines to subscribe to the partialrefresh-complete state:

The initToolTip function did not changed:

With this subscription the tooltip becomes applied to fields that become visible after validation (when the user continues to fill in the form).

The possibility to subscribe to partialrefresh states is also a use-case for other plugins I use, for example to automatically adapt textareas to user-input.

Fixing the Tooltip function in XPages

A colleague noticed that the tooltip function on a Xpage stopped working after submitting the page to the server and when the validation did not pass. The same behaviour occurred when I added a computed text control that would spit out an anchor reference using a tooltip. Odd.

I found an old post of mine where I described the use of the xe:tooltip control. This control seems to keep working even when the XPage fails to validate. So that is a win.

However, in my case I would have to apply the control on many places which does not make me happy.

I also wanted to alter the layout of the tooltip a bit via a template so I found this piece of code. To my delight I noticed that the tooltip also kept working after a failed validation!

So a simple bit of code can fix tooltip again:

So after applying a template for the tooltip and applying some CSS my tooltip looks a bit more readable and less boring:

Note that I have to set the xp:this.title property for the inputTextArea control. Adding an additional attribute for the placeholder won’t do for the template.

For Nathan T(eacher) Freeman

Today I read the sad news that Nathan T Freeman is no longer among us. I was actually googling last week, curious what he was working on.

I met Nathan a couple of times. The first time was at a Lotussphere sponsor party (by Nokia, 2008?) with a Rock Hero theme. I was honoured you and Tim Tripcony joined our table. Probably because team Sweden was already into heavy (free beer, duh) drinking and getting louder and louder.

I thought you and Tim were the rock heroes in the Domino world. But actually you were more a teacher for me. I actually made a long-long ago a song for all my teachers then, and see: you were one of them.

Thanks for your guidance with helping me find the solutions for my technical challenges!

Uncategorized

TestiNG XPages

Introduction with Selenium IDE

A while ago I started my journey into testing applications. Like most people I started with Selenium IDE since it’s free, easy to install and setup. The idea was to record the workflow in an application and play it back after the development of every new feauture.

A nice idea but it does not work so well with the dynamic ID’s XPages generates for it’s controls. Instead of the id attribute you can then go via XPath and apply parameters. Here is an example for my Edit Box control that has id ‘inputCustusomerName’ -> starts with @id,’view:’ and contains @id,’inputCustusomerName’.

It becomes a lot of fiddling with the IDE and basically it becomes a long, long script (if you have a larger workflow) which you are capable of structuring in smaller pieces via the suite option.

Selenium WebDriver

When talking with more experienced test people they all drop the IDE and go for Selenium Webdriver. I will not go into details on WebDriver but the specs of WebDriver overclasses the IDE by far and it’s available in different languages. Since my XPages applications are already written mostly in Java so one is acquainted in a sense with an Eclipse environment (DDE) the step to start writing code in Eclipse IDE is not that big.

So with WebDriver used across the organization I feel more assured to join that community instead working on tests on an island (with Domino is also in a way). We have actually an infrastructure for WebDriver with Selenium Grid and support via a framework based upon Selenium WebDriver.

TestNG

When you start writing your tests in the beginning you end up like with the Selenium IDE in a long script that can do one thing. If you want to take the next leap then check TestNG. It extends the test capabilities by far and allows to structure and configure your tests to way you want.

ith TestNG your can setup ‘testsuites’ and in those suites you can define which tests to run. I use the suites to run tests in different roles.

At first I looked at the option to run my tests from DDE ( I found some posts/presentations where it looked it should be possible) to avoid moving to another development IDE. But after installing the TestNG plugin in DDE and writing some scripts using WebDriver when running the TestNG suite it searched for files that where outside my NSF (workspace directory location). So the option to remain coding in DDE I gave up.

Test framework

If you work in a larger organization you are probably not the first person who writes tests. I found in my organization a supported test framework that is based upon Selenium WebDriver and TestNG and includes more features like for example ReportNG which allows you to create HTML reports of your tests. Selenium WebDriver has a feature to take a screenshot so that is nice to include in your test report.

The framework has many more features which I have not touched (yet).

Lessons learned

With Selenium WebDriver you will face the same problems with dynamic id’s as in Selenium IDE. Use XPath as selector the web element e.g.:

When accessing lists, like link controls in a repeat control these XPath reference does not work. they all end with the same ID part. So when you register a new customer and that customer will appear in a table you do not know in which row that customer will appear depending on the content in that table. You can even have so many customers in the table so that you need to use a pager.

In Domino it is common you define userroles in your Access Control List and then distribute these roles to users/groups. Especially if you want to test a workflow you access the application in different roles. Via TestNG tend to provide a role as parameter, and for that role I use different user credentials. When working in a team and Git you do not want to expose these credentials so I started to use Jasypt for decrypting these values.

If you have an application that supports multiple languages you also want to check your application in those languages. In WebDriver you can find links by their text and these textes probably differ in languages.

Conclusion

Tests are a common part of development and in modern development test drive development. As a Domino developer you have to adapt to this paradigm. If your team is too small for test developers you probably have to write those test yourself. Writing tests expands your development skills and you talk with colleagues in different areas of your organization you otherwise never would have contact with.

In my situation WebDriver is a common tool and I could not find any JavaScript supported framework available in our organization. Writing test scripts with WebDriver is not a big step for XPages developers and I recommend to take a look at TestNG to be able to structure your tests from the start.

Test is a wide area and I have only explored a part of it. Test is also an important part of CICD (continious integration continious delivery) if you happen to have as goal to deliver an automated process for the build of your Domino applications.

Good luck and enjoy the journey!

It’s a bug, it’s a pain, it’s an xp:checkBoxGroup!

Many where wondered why the xp:checkBoxGroup with the Bootstrap theme was transformed into a HTML table.

I have not heard so many complained that when you add a styleClass to it another class attribute is added and the browser simply ignores the second class attribute. Hell yeah, when you create a div element and add two class attributes DDE complains that a class attribute was already added for that element.

So:

xp:checkBoxGroup id=”checkBoxGroup1″ styleClass=”testBox”

becomes in your browser source

div class=”checkbox” id=”view:_id1:checkBoxGroup1″ class=”testBox”

and your browser renders:

div class=”checkbox” id=”view:_id1:checkBoxGroup1″

Save your day, Save the state of your repeat control

I am writing a demo application with a faceted search functionality. For displaying the “results” I am using a repeat control.

Now users want to switch back and forth between the “view” and the “document”. If you display the “results ” in a “view” with an “view panel” control you can apply a pager to that view and for that pager you can apply a “pager save state” control. So when you go from “results” xpage to the “document” xpage and back you land in the same state (same page in that view) and the user does not have to navigate again to the last page in the view panel control.

Now with the repeat control that is a different thing. The “pager save state” was not designed for it. Luckily there is an approach which will deliver you the same result. Add for your repeat control the property: first=”#{javascript:return (sessionScope.first != null)?sessionScope.first:0;}”. Than from the link (could be a button or whatever) in the repeat control add the following in the onClick event handler: sessionScope.put(‘first’,getComponent(“rpCollection”).first);. Then do your normal stuff (like redirect to a page). If you from that redirected page go back to the “results” page the repeat control will show the last set of items from where you left.

I hope it will save your day and your project. Happy coding! 🙂

Adding the optgroup tag quickly to your xp:combobox

Today I was working on modernizing an xpages application when I came up with a simple enhancement: adding the optgroup tag to a xp:combobox.

By default this option is no available in XPages and if you look around there are some suggestions from hard-coded to DOM modification but I rather looked for a proper JSF implementation.

The data for my combobox resides in a categorized Notes view in a solid NSF so I had two options: navigating through the NotesView via a ViewNavigator (probably next post) or a quick and dirty combo of a dbcolumn and dblookup.

In context with the combobox control the dbcolumn/lookup combo seems suitable 🙂

Here is the simplified setup for my xp:combobox:

As data source I am calling a method on a managed bean. The method is as followed:

The result is nice and straight-forward:

If you questions or difficulties with the implementation, just give me call. Happy development 🙂

Adding a GDPR message to my XPages app

GDPR or Cookies plugins are nothing new. A simple search will give you a quick overview which jQuery based plugins are available.

So I decided the one that looked nicest to me and implemented it my XPages app. It worked but not when I met a user who was using IE. No JS error or whatever so where to start debugging? 😦

When looking in the original code I noticed that a different version of jQuery was used than is available on or Domino V10 server. So I posted an idea for an upgrade on the HCL Products Ideas Portal.

In the end I tried the Customizable EU Cookie Notice Popup Plugin which uses the 2.1.1 version of jQuery which is the same version as on the Domino server. (Loading multiple versions jQuery makes Dojo complain).

But then the requirements of the project changes and the functionality should become more to highlight news or updates within the application so I had to add some additional functionality:

  • enable / disable news display/popup
  • option to steer location / appearance on screen
  • from / until dates, so a period when the message should be displayed.

I decided when the option to enable the display but leave the from and until dates empty the popup will be displayed as long as the session of the browser lasts.

So these settings are stored in a Notes – Configuration document and made available as session scope variables.

Also the content of the popup has to be easily editable so for this I use Notes – Keywords documents so I can have messages in multiple languages.

When the code was working I lifted it up into a custom control which I can now re-use across other applications. Not that the custom control contains custom properties (yet)

undefined

The function to set the cookie expiry date is as followed:

To set a java date in a scope variable can be a little tricky. I did it as follow:

But this is all the code I needed. The result is as followed:

Note: I have altered the JS file of the plugin to bootstrap it more and to make it responsive.

When I press the OK button a cookie is set that last a browser session (I left the from and until dates empty in my settings):


If you like this post then please support my idea for upgrading the jQuery version on Domino: https://domino-ideas.hcltechsw.com/ideas/DDXP-I-637

Happy development 🙂

RAD Table walker

For a project I received some very unclear description for a change. After a conversation I came up with the suggestion to rebuild the UI and present a Bootstrap table with add and delete buttons. Something what developers would call a table walker.

So how did I do this?

First I had to extend the Model object of my MVC model. The table repeats rows with persons details so I added:

The Person class is simplified as followed:

On my model object I also added getters and setters and and an add method:

Then I had to build the table with the following important elements:

  • a repeat control to represent my arraylist of Person objects
  • input fields bounded to the Person name and email
  • a button for each row to remove the Person from the arraylist
  • a button to display a new blank row to register a new Person

The code is not that long or complicated. I highlighted the important parts with bleeding yellow:

In the next phase I decided to replace the input field the name field with namespickers (by first name or by last name) wrapped as Bootstrap field add-ons. Here is the rough code:

This all resulted in a nice BS table with add / remove buttons:

Now I am just waiting for customer approval. That is mostly the longest part in Rapid Application Design.