Tuesday, 9 December 2014

Looking for a new job

I am currently looking for a new job, preferably in the Notes Domino XPages environment as a Developer / Notes Domino Consultant.


Extensive experience as:
- Notes Domino / XPages Developer
- Administrator Archie XRM (SQL) - CRM

Latest Courses:
- D8L55 - Introduction to IBM Lotus Domino 8.5 XPages
- N7D540 - Using Lotusscript in IBM Lotus Domino Applications
- D8520 - Building Web Applications Designer 8
- XP852 - Lotus Domino Designer 8.5.2 Basic XPage Application
- XPages and the JSF Lifecycle Courselet
- XPages How to programmatically manage the titleBarTabs Object

Specialization
Lotus Domino, LotusScript, Lotus Notes, Web Development, XPages, AJAX, HTML, XSP, JavaScript, Software Development

Currently I am moderator of the Google+ XPages Community and Curator of Collaboration Today.

For more information:
LinkedIn
Twitter

Tuesday, 2 December 2014

Select2 Auto Tokenization

In this blog post I describe the basic use of the Tokenization function which can easily be added to a Select2 field.
Select2 supports the ability to add choices automatically as the user is typing into a (search) field. This is particularly useful when the user should be able to quickly enter a number of tags by separating them with a comma or a space.
The tokenizer function can process the input typed into a (search) field after every keystroke and extract and select choices.
Tokenizer only applies to multi-selects.
The separators are defined in the tokenSeparators option, an array of strings that define token separators for the default tokenizer function. By default, this option is set to an empty array which means tokenization using the default tokenizer is disabled. It is recommended to set this option to a value similar to [',', ' '].
In the example below the built in tokenizer function is used in combination with a Multiline Edit Box (inputTextarea).

The function has to be added as an Select2 option.

<xp:scriptBlock id="scriptBlock3">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:inputTextarea1}" ).select2({
      tags:["red", "green", "blue"],
      tokenSeparators: [",", " "]        
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>

Result

Predefined Tags


Own input from the user in conjunction with entering a comma or space (tokenSeparators) to exit the input and add the tag(s) into the field.



Sample Code Custom Control

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom"
xmlns:bx="http://www.openntf.org/xsp/bootstrap">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Contact"></xp:dominoDocument>
</xp:this.data>
<xp:this.resources>
<xp:script
src="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2.min.js"
clientSide="true">
</xp:script>
<xp:styleSheet
href="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2.css">
</xp:styleSheet>
<xp:styleSheet
href="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2-bootstrap.css">
</xp:styleSheet>
<xp:script src="/JQueryXSnippet.js" clientSide="true"></xp:script>
</xp:this.resources>
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:comboBox1}" ).select2({
      placeholder: "Select a category",
      allowClear: true,
      minimumInputLength : 2
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:listBox1}" ).select2({
      placeholder: "Select a software category",
      minimumInputLength : 2,
      maximumSelectionSize : 3      
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock3">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:inputTextarea1}" ).select2({
      tags:["red", "green", "blue"],
      tokenSeparators: [",", " "]        
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:panel>
<div class="page-header">
<h1>
Select2
<xp:span style="color:rgb(255,255,255)">.</xp:span>
<small>Combo Box / List Box</small>
</h1>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - Combo Box
<xp:comboBox id="comboBox1"
value="#{document1.Categories}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");    
var res = @DbLookup("", "byKeyWord", "Category", 2);
var list = arr.concat(res);
return list; }]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</div>
<div class="panel-footer">Combo Box - Single Value</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - List Box
<xp:listBox id="listBox1"
value="#{document1.Categories}" multiple="true">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:@Text("");
@DbLookup("", "byKeyWord", "Software", 2);}]]></xp:this.value>
</xp:selectItems>
</xp:listBox>
</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - Tags Field
<xp:inputTextarea id="inputTextarea1"
value="#{document1.Tags}">
</xp:inputTextarea>
</div>
</div>
</xp:panel>
</xp:view>

IBM Verse


IBM Verse integrates email, meetings, calendars, file sharing, instant messaging and social updates through a single environment. IBM Verse improves your productivity with an experience that personalizes and unites inbox, calendar, to-do's, social networks, chats, meetings and documents.
IBM Verse delivers a cloud-based approach to managing your workday.
Designed for web and mobile, with its simple, see-only-what-you-need interface, IBM Verse helps you focus on the things that matter most. Lightening-fast search and an array of intelligent, security-rich and engaging social apps help you prioritize and open up new ways to work.


Meet IBM Verse
Meet IBM Verse, a revolutionary product that will change the way you reimagine work.


A Day With IBM Verse
What does a day in the life of IBM Verse look like? Check out this three minute video on how IBM Verse can help you reimagine work


More info : IBM Verse

Tuesday, 25 November 2014

Select2 maximumSelectionSize

In this blog post I describe the basic use of the property maximumSelectionSize which can easily be added to a Select2 field.
Select2 allows the developer to limit the number of items that can be selected in a multi-select control, for example a List Box. In the example below only 3 or less items can be selected.
If this number is less than 1 selection is not limited.
Once the number of selected items reaches the maximum specified the contents of the dropdown will be populated by the formatSelectionTooBig function.
The formatSelectionTooBig function returns a String containing "You can only select (maximumSelectionSize value) items" message or Function used to render the message.


The property maximumSelectionSize can not be added as an attribute to a List Box.

<xp:this.attrs>
<xp:attr name="maximumSelectionSize"value="3">
</xp:attr>

Just like the property minimumInputLength, the property maximumSelectionSize is also NOT available in the Select2 Picker for Combo / List Box from the OpenNTF Bootstrap4XPages plugin.


The property maximumSelectionSize has to be added as an Select2 option.

<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:listBox1}" ).select2({
      placeholder: "Select a software category",
      minimumInputLength : 2,
      maximumSelectionSize : 3
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>

Result



Sample Code Custom Control

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom"
xmlns:bx="http://www.openntf.org/xsp/bootstrap">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Contact"></xp:dominoDocument>
</xp:this.data>
<xp:this.resources>
<xp:script
src="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2.min.js"
clientSide="true">
</xp:script>
<xp:styleSheet
href="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2.css">
</xp:styleSheet>
<xp:styleSheet
href="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2-bootstrap.css">
</xp:styleSheet>
<xp:script src="/JQueryXSnippet.js" clientSide="true"></xp:script>
</xp:this.resources>
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
  $(document).ready(
    function() { 
      x$( "#{id:comboBox1}" ).select2({
      placeholder: "Select a category",
      allowClear: true,
      minimumInputLength : 2          
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
  $(document).ready(
    function() { 
      x$( "#{id:listBox1}" ).select2({
      placeholder: "Select a software category", 
      minimumInputLength : 2,
      maximumSelectionSize : 3
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:panel>
<div class="page-header">
<h1>
Select2
<xp:span style="color:rgb(255,255,255)">.</xp:span>
<small>Combo Box / List Box</small>
</h1>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - Combo Box
<xp:comboBox id="comboBox1"
value="#{document1.Categories}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");      
var res = @DbLookup("", "byKeyWord", "Category", 2);  
var list = arr.concat(res);
return list; }]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</div>
<div class="panel-footer">Combo Box - Single Value</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - List Box
<xp:listBox id="listBox1"
value="#{document1.Categories}" multiple="true">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:@Text("");
@DbLookup("", "byKeyWord", "Software", 2);}]]></xp:this.value>
</xp:selectItems>
</xp:listBox>
</div>
</div>
</xp:panel>
</xp:view>

Select2 minimumInputLength

In this blog post I describe the basic use of the property minimumInputLength which can easily be added to a Select2 field.
Select2 supports a minimum input setting which is useful for large remote datasets where short search terms are not very useful.
With this property the number of characters necessary to start a search can be indicated.
The property minimumInputLength can not be added as an attribute to a Combo Box / List Box.

<xp:this.attrs>
<xp:attr name="minimumInputLength" value="2"></xp:attr>
</xp:this.attrs>

The property minimumInputLength is also NOT available in the Select2 Picker for Combo / List Box from the OpenNTF Bootstrap4XPages plugin.


So the property minimumInputLength has to be added as an Select2 option.

<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:comboBox1}" ).select2({
      placeholder: "Select a category",
      allowClear: true,
      minimumInputLength : 2      
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>

Result



Sample Code Custom Control

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom"
xmlns:bx="http://www.openntf.org/xsp/bootstrap">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Contact"></xp:dominoDocument>
</xp:this.data>
<xp:this.resources>
<xp:script
src="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2.min.js"
clientSide="true">
</xp:script>
<xp:styleSheet
href="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2.css">
</xp:styleSheet>
<xp:styleSheet
href="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2-bootstrap.css">
</xp:styleSheet>
<xp:script src="/JQueryXSnippet.js" clientSide="true"></xp:script>
</xp:this.resources>
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:comboBox1}" ).select2({
      placeholder: "Select a category",
      allowClear: true,
      minimumInputLength : 2      
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:listBox1}" ).select2({
      placeholder: "Select a software category",
      minimumInputLength : 2
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:panel>
<div class="page-header">
<h1>
Select2
<xp:span style="color:rgb(255,255,255)">.</xp:span>
<small>Combo Box / List Box</small>
</h1>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - Combo Box
<xp:comboBox id="comboBox1"
value="#{document1.Categories}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");    
var res = @DbLookup("", "byKeyWord", "Category", 2);
var list = arr.concat(res);
return list; }]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</div>
<div class="panel-footer">Combo Box - Single Value</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - List Box
<xp:listBox id="listBox1"
value="#{document1.Categories}" multiple="true">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:@Text("");
@DbLookup("", "byKeyWord", "Software", 2);}]]></xp:this.value>
</xp:selectItems>
</xp:listBox>
</div>
</div>
</xp:panel>
</xp:view>

Monday, 17 November 2014

Select2 Placeholder Combo Box

Following the XPages And More Demo Database I got some questions regarding a placeholder in Select2 for a single value field.
In this blog post I describe how to add a placeholder to a Combo Box.
The placeholder can be declared via a data-placeholder attribute attached to the select, or via the placeholder configuration element.
When a placeholder is used for a non-multi-value select box such as a Combo Box, an empty tag is required as a first option.
Optionally, a clear button (visible once a selection is made) is available to reset the select box back to the placeholder value.

A. Declaration via a data-placeholder attribute

<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:comboBox1}" ).select2();
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>

<div class="panel panel-default">
<div class="panel-body">
Select2 - Combo Box
<xp:comboBox id="comboBox1"
value="#{document1.Categories}">
<xp:this.attrs>
<xp:attr name="placeholder"
value="Select a Category">
</xp:attr>
</xp:this.attrs>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");    
var res = @DbLookup("", "byKeyWord", "Category", 2);
var list = arr.concat(res);
return list; }]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</div>
<div class="panel-footer">Combo Box - Single Value</div>
</div>

Result


B. Declaration via placeholder configuration element

<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
  $(document).ready(
    function() {
      x$( "#{id:comboBox1}" ).select2({
      placeholder: "Select a category",
      allowClear: true
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>

<div class="panel panel-default">
<div class="panel-body">
Select2 - Combo Box
<xp:comboBox id="comboBox1"
value="#{document1.Categories}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");    
var res = @DbLookup("", "byKeyWord", "Category", 2);
var list = arr.concat(res);
return list; }]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</div>
<div class="panel-footer">Combo Box - Single Value</div>
</div>

The required empty tag can be added through an empty array 'value' as a first selection.
var arr = new Array("")
A possible problem can be that there is no empty value present in the selection list itself.
If a value has been selected it can not be put back to an empty value.
To deselect the selected value an 'allow clear' element can be added to the comboBox.
Note that this option only works with non-multi-value based selects because multi-value selects always provide such a button for every selected option. 

Result



Sample Code Custom Control

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Contact"></xp:dominoDocument>
</xp:this.data>
<xp:this.resources>
<xp:script
src="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2.min.js"
clientSide="true">
</xp:script>
<xp:styleSheet
href="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2.css">
</xp:styleSheet>
<xp:styleSheet
href="/.ibmxspres/domino/xsp/.ibmxspres/.extlib/bootstrap/select2/select2-bootstrap.css">
</xp:styleSheet>
<xp:script src="/JQueryXSnippet.js" clientSide="true"></xp:script>
</xp:this.resources>
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
  $(document).ready(
    function() { 
      x$( "#{id:comboBox1}" ).select2({
      placeholder: "Select a category",
      allowClear: true
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
  $(document).ready(
    function() { 
      x$( "#{id:listBox1}" ).select2({
      placeholder: "Select a software category"      
      });
               }
           );
  ]]></xp:this.value>
</xp:scriptBlock>
<xp:panel>
<div class="page-header">
<h1>
Select2
<xp:span style="color:rgb(255,255,255)">.</xp:span>
<small>Combo Box / List Box</small>
</h1>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - Combo Box
<xp:comboBox id="comboBox1"
value="#{document1.Categories}">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");      
var res = @DbLookup("", "byKeyWord", "Category", 2);  
var list = arr.concat(res);
return list; }]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
</div>
<div class="panel-footer">Combo Box - Single Value</div>
</div>
<div class="panel panel-default">
<div class="panel-body">
Select2 - List Box
<xp:listBox id="listBox1"
value="#{document1.Categories}" multiple="true">
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:@Text("");
@DbLookup("", "byKeyWord", "Software", 2);}]]></xp:this.value>
</xp:selectItems>
</xp:listBox>
</div>
<div class="panel-footer">List Box - Multiple Values</div>
</div>
</xp:panel>
</xp:view>

In one of the next blog post I will also be discussing some other features of Select2.

Friday, 14 November 2014

Demo Database XPages And More

The first version of the demo database is available for download and contains the examples below.
The focus in this first version is on the code examples and not (yet) on the UI.
The demo database uses the OpenNTF Bootstrap4XPages plugin which will be 'replaced' in the next version of the demo database. The OpenNTF Bootstrap4XPages plugin will be included in the new release of the OpenNTF Extension Library (see XPages Goes Responsive).

Remarks:
- The demo database uses the OpenNTF Bootstrap4XPages plugin.
- The database is set up for demonstration purposes only.
- For more information see the associated blog posts.
- Check the Custom Controls for the code examples.
- The WebContent Folder contains the following resources/plugins.


1. Bootstrap DateTimePicker
Associated XPage : BootstrapDateTimePicker
More info : Using Bootstrap DateTimePicker


2. Reusable Bootstrap Text / Rich Text Fields
Associated XPage : BootstrapReusableFields
Associated Custom Controls : ccRBSTextField / ccRBSRichTextField
More info : Reusable Bootstrap Text Field and Reusable Rich Text Field


3. Bootstrap Text Fields With Validation
Associated XPage : BootstrapTextFieldsWithValidation
Associated Custom Control : ccvalidationBSTextField
More info :  Validation Reusable Text Field

4. Bootstrap RichText Field With Validation
Associated XPage : BootstrapRichTextFieldWithValidation
Associated Custom Control : ccvalidationBSRichTextField
More info : Validation Rich Text Field

5. Bootstrap Reusable Fields including validation (and Font Awesome)
Associated XPage : BootstrapReusableFieldsWithValidation
Associated Custom Controls : ccvalidationBSRichTextField / ccvalidationBSTextField
(aggregation of point 3 and 4)
More info : Font Awesome Icons


6. BootstrapCK4 Skin for CKEditor4
Associated XPage : CKEditorSkin
Associated Custom Controls : ccCKEditorSkin and ccBSCKE
More info : BootstrapCK4 Skin for CKEditor


7. Bootstrap FileInput Plugin
Associated XPage : FileInput
More info : Using FileInput in XPages


8. Select2 (Bootstrap4XPages Plugin)
Associated XPages : Select2InXPages / Select2InXPagesPlugin
Associated Custom Controls : ccselect2 / ccselect2plugin
More info : Using Select2 in XPages (Part I) and Using Select2 in XPages (Part II)


9. Using Font Awesome Icons
Associated XPages : FontAwesomeIcons / FontAwesomeIconComputedText
Associated Custom Controls : ccRBSTextFieldFA / ccRBSTextFieldFAComputedText
More info : Font Awesome Icons

The demo database will be expanded in the future with more examples associated with future blog post.

Download Demo Database XPages And More

Monday, 10 November 2014

XPages Goes Responsive

Bootstrap is now part of the latest XPages Extension Library!
Responsive Web Design Support in XPages, Enhanced Application Layout Wizard and Enhancements to the theme combo boxes in the Xsp Properties editor have been added to the new release of the XPages Extension Library.

From the release notes:
Support for Bootstrap, a Responsive Web Design (RWD) framework, is a new feature that has been added to the new release of the XPages Extension Library. It comes in the form of an XPages Responsive Bootstrap plugin that you can leverage in XPages applications.
The plugin provides two themes that you can use in your applications as well as Bootstrap v3.2.0 & jQuery v2.1.1. With Bootstrap you can create dynamic responsive web applications that provide an optimised user experience for a range of devices, from mobile phones to large desktop monitors.

Responsive Application Layout Configuration


The XRB plugin adds a new renderer for the Application Layout control and a new Application Configuration complex type for the control. The new renderer type (com.ibm.xsp.theme.bootstrap.layout.ResponsiveAppLayout) is automatically applied to Application Layout controls in your application when you enable either of the Bootstrap themes in the application's xsp.properties. The renderer gives the Application Layout a Bootstrap look and feel, as well as making the control responsive.
The new Bootstrap Responsive Application Configuration further enhances the responsive capabilities of the App Layout control. You can add it to a new App Layout control using the enhanced Application Layout wizard or via the Properties panel for the control.


You can also update existing Application Layout controls to use the responsive configuration, by changing your application layout configuration from "xe:applicationConfiguration" or "xe:oneuiApplication" to use "xe:bootstrapResponsiveConfiguration" instead.

jQuery 2.1.1 is packaged as part of the XPages Repsonsive Bootstrap plugin. "jquery-2.1.1.js" is provided as a resource in the "Bootstrap3.2.0" & "Bootstrap3.2.0_flat" themes.

You can download the new release from the OpenNTF website : XPages Extension Library.

See also the blog post from Mark Leussink Bootstrap in XPages: now part of the Extension Library.

Using Bootstrap in XPages means from today using the OpenNTF XPages Extension Library!

Collaboration Today

Since last Friday, I am a member of the curators team of Collaboration Today.
Curators add content to the site, categorize it and can mark to show up on the home page.
I hope in this manner to contribute further to the Notes Domino XPages community.
For those who do not yet know Collaboration Today.
Collaboration Today is a news aggregator for IBM Collaboration Solutions professionals covering news about various IBM products like IBM Connections, IBM Domino, IBM WebSphere Portal etc. and cross product topics like mobile, cloud and analytics.

Collaboration Today was created by Bruce Elgort, Per Henrik Lausten, Serdar Basegmez, Frank van der Linden and Niklas Heidloff in the summer of 2012.

Follow Collaboration Today on Twitter.
Website Collaboration Today.



Friday, 7 November 2014

Validation Rich Text Field

For the validation of a reusable Bootstrap Rich Text Field it is possible to use the same validation method as for a reusable Bootstrap Text Field.
See for more information Validation Reusable Text Fields and Reusable Bootstrap Rich Text Fields.
For the validation of a reusable Bootstrap Rich Text Field there are two additions advisable compared to a reusable Bootstrap Text Field.

1. Style property / attribute
A style property can be added to the reusable Bootstrap Richt Text Field to create a red box around the field using .isValid()
<xp:this.style><![CDATA[#{javascript:if(!getComponent('inputRichText1').isValid()){
    return "border-color:rgb(255,0,0);border-style:solid;border-width:thin";
} else{
    return ""};}]]></xp:this.style>

2. Validation 'if user only clicks in the Rich Text Field'
This extra validation is advisable because when a user only clicks in the reusable Bootstrap Rich Text Field the content '<p dir="ltr">&nbsp;</p>' is added in the Rich Text Field and the Rich Text Field is no longer 'empty'. A 'required validation' will fail.


One of the possible solutions is the following (quick and dirty) validation expression.
var string = getComponent("inputRichText1").getValueAsString();
var click = '<p dir="ltr">&nbsp;</p>';
if (@Contains(string,click)){
return false;
}
else {
return true
}

Sample Code Custom Control

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xpt="http://www.openntf.org/xsp/xpt"
xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xc:ccBSCKE></xc:ccBSCKE>
<xp:div>
<xp:this.styleClass><![CDATA[#{javascript:"form-group" + ( getComponent("inputRichText1").isValid() ? "" : " has-error" )}]]></xp:this.styleClass>
<xp:label styleClass="col-sm-2 control-label"
for="inputRichText1" value="${compositeData.fieldLabel}" />
<div class="col-sm-10">
<xp:inputRichText id="inputRichText1"
required="${compositeData.required}" value="#{document1.Body}">
<xp:this.validators>
<xp:validateRequired
message="#{javascript:compositeData.fieldLabel + ' is required'}">
</xp:validateRequired>
<xp:validateExpression
message="#{javascript:compositeData.fieldLabel + ' is required'}">
<xp:this.expression><![CDATA[#{javascript:var string = getComponent("inputRichText1").getSubmittedValue();
var click = '<p dir="ltr">&nbsp;</p>';
if (@Contains(string,click)){
return false;
}
else {
return true
}}]]></xp:this.expression>
</xp:validateExpression>
</xp:this.validators>
<xp:this.dojoAttributes>
<xp:dojoAttribute name="skin">
<xp:this.value><![CDATA[#{javascript:return @ClientType().equals("Web") ? "bootstrapck,/"+database.getFilePath()+"/bootstrapck/" : ""}]]></xp:this.value>
</xp:dojoAttribute>
<xp:dojoAttribute value="Full" name="toolbar">
</xp:dojoAttribute>
</xp:this.dojoAttributes>
<xp:this.dojoType><![CDATA[#{javascript:return @ClientType().equals("Web") ? "org.wavin.joldenburger.CKEDITOR" : ""}]]></xp:this.dojoType>
<xp:this.style><![CDATA[#{javascript:if(!getComponent('inputRichText1').isValid()){
    return "border-color:rgb(255,0,0);border-style:solid;border-width:thin";
} else{
    return ""};}]]></xp:this.style>
</xp:inputRichText>
<xp:text escape="true" id="computedField1"
styleClass="help-block" value="${compositeData.helpText}">
<xp:this.rendered><![CDATA[#{javascript:getComponent("inputRichText1").isValid() && compositeData.helpText != null}]]></xp:this.rendered>
</xp:text>
<xp:message id="message1" for="inputRichText1"
styleClass="help-block">
</xp:message>
</div>
</xp:div>
</xp:view>

Last Friday, in response to this blog post, another solution was provided by Knut Herrmann. This solution has also been tested and works great.

Sample Code Custom Control

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xpt="http://www.openntf.org/xsp/xpt"
xmlns:xe="http://www.ibm.com/xsp/coreex"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xc:ccBSCKE></xc:ccBSCKE>
<xp:div>
<xp:this.styleClass><![CDATA[#{javascript:"form-group" + ( getComponent("inputRichText1").isValid() ? "" : " has-error" )}]]></xp:this.styleClass>
<xp:label styleClass="col-sm-2 control-label"
for="inputRichText1" value="${compositeData.fieldLabel}" />
<div class="col-sm-10">
<xp:inputRichText id="inputRichText1"
required="${compositeData.required}" value="#{document1.Body}">
<xp:this.validators>
<xp:validateRequired
message="#{javascript:compositeData.fieldLabel + ' is required'}">
</xp:validateRequired>
<xp:validateExpression
message="#{javascript:compositeData.fieldLabel + ' is required'}">
<xp:this.expression><![CDATA[#{javascript:var rt = (value + " ").replace(/(<((?!img|a\s)[^>]+)>)|&nbsp;/ig, "").trim();
return rt !== "";
}]]></xp:this.expression>
</xp:validateExpression>
</xp:this.validators>
<xp:this.dojoAttributes>
<xp:dojoAttribute name="skin">
<xp:this.value><![CDATA[#{javascript:return @ClientType().equals("Web") ? "bootstrapck,/"+database.getFilePath()+"/bootstrapck/" : ""}]]></xp:this.value>
</xp:dojoAttribute>
<xp:dojoAttribute value="Full" name="toolbar">
</xp:dojoAttribute>
</xp:this.dojoAttributes>
<xp:this.dojoType><![CDATA[#{javascript:return @ClientType().equals("Web") ? "org.wavin.joldenburger.CKEDITOR" : ""}]]></xp:this.dojoType>
<xp:this.style><![CDATA[#{javascript:if(!getComponent('inputRichText1').isValid()){
    return "border-color:rgb(255,0,0);border-style:solid;border-width:thin";
} else{
    return ""};}]]></xp:this.style>
</xp:inputRichText>
<xp:text escape="true" id="computedField1"
styleClass="help-block" value="${compositeData.helpText}">
<xp:this.rendered><![CDATA[#{javascript:getComponent("inputRichText1").isValid() && compositeData.helpText != null}]]></xp:this.rendered>
</xp:text>
<xp:message id="message1" for="inputRichText1"
styleClass="help-block">
</xp:message>
</div>
</xp:div>
</xp:view>

Sample Code XPage

<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Contact"></xp:dominoDocument>
</xp:this.data>
<xc:ccLayoutBootstrap>
<xp:this.facets>
<xp:panel xp:key="facetMiddle">
<div class="page-header">
<h1>
Bootstrap Rich Text Field
<xp:span style="color:rgb(255,255,255)">
</xp:span>
<small>Including Validation</small>
</h1>
</div>
<xp:br></xp:br>
<xc:validationBSRichTextField required="true"
fieldLabel="Remarks" fieldName="Body"
helpText="Remarks is a mandatory field">
</xc:validationBSRichTextField>
<xp:br></xp:br>
<xp:br></xp:br>
<xp:button value="Save" id="button1"
styleClass="btn btn-primary">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:saveDocument></xp:saveDocument>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:this.facets>
</xc:ccLayoutBootstrap>
</xp:view>

Final result




Based on the above an excellent validation for a required reuseable Bootstrap Rich Text Field has been created.
Thanks to Knut Herrmann for his reaction and provided solution.
If you have a different or better solution please let me know by leaving a comment.

Wednesday, 5 November 2014

The View Anthologies

There are some new books available from The View Anthologies.

NEW! A Guide to IBM Collaboration Solutions: IBM Mail Next, IBM Notes 9, IBM Connections 5, IBM Sametime 9 & IBM Domino 9



A 2015 Guide to IBM Collaboration Solutions provides the information you need to ride the social business wave like a pro and includes best practices from authors Susan Bulloch, Andy Higgins, Frank van der Linden, and Charlie Price.

NEW! The Definitive Guide for Mastering XPages



A sequel to the popular Advancing Your XPages Skills compilation, this brand new anthology offers techniques and tips to streamline your development and lower maintenance costs. Dive into topics like Twitter Bootstrap, localization, JSON, responsive design, and mobile development.
The Definitive Guide for Mastering XPages features step-by-step instruction, sample code, and best practice advice from XPages experts Brad Balassaitis, Kathy Brown, Troy Reimer, Martin Donnelly, Tony McGuckin, and Mark Wallace.

Validation Reusable Text Field

On the Bootstrap4XPages website I came across this validation method for reusable Bootstrap Text Fields by Mark Leussink.
In my opinion this is probably the best validation method that can be used for this type of fields.
In order to document this for myself I describe in this blog post the additions that have to be made to the design of a reusable Bootstrap Text Field as described in this blog post.

Bootstrap includes validation styles for error, warning, and success states on form controls.
To use, add .has-warning, .has-error, or .has-success to the parent element.
Any .control-label, .form-control, and .help-block within that element will receive the validation styles.
On an XPage every input control has an isValid() method.
Therefore is relatively easy to combine these two.

Steps for adding Validation to a reusable Bootstrap Text Field

1. Required Custom Control Property
First a required property has to be added to the reusable Bootstrap Text Field. This property is needed to indicate that the field is required.
required="${compositeData.required}


2. StyleClass Attribute
Secondly the bootstrap validation style 'has-error' has to be added to the styleClass attribute of the form-group and this attribute has to be made div computed.
<xp:div>
<xp:this.styleClass><![CDATA[#{javascript:"form-group" + ( getComponent("inputText1").isValid() ? "" : " has-error" )}]]></xp:this.styleClass>


3. Validation message
Further an error message has to be added which is to be displayed if the validation is performed and the field is 'not valid'.
<xp:this.validators>
       <xp:validateRequired message="#{javascript:compositeData.fieldLabel + ' is required'}"></xp:validateRequired>
</xp:this.validators>


4. Displaying the HelpText
If the reusable Bootstrap Text Field is using a Help Text it must be ensured that the Help Text is only rendered / displayed if the field is not marked as an error. 
<xp:text escape="true" id="computedField1" styleClass="help-block" value="${compositeData.helpText}">
        <xp:this.rendered><![CDATA[#{javascript:getComponent("inputText1").isValid() && compositeData.helpText != null}]]></xp:this.rendered>
</xp:text>


5. Error Message
The final step is to create a control for showing the error message below the field.
<xp:message id="message1" for="inputText1" styleClass="help-block"></xp:message>

Sample Code Custom Control
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core" xmlns:xe="http://www.ibm.com/xsp/coreex">
<xp:div>
<xp:this.styleClass><![CDATA[#{javascript:"form-group" + ( getComponent("inputText1").isValid() ? "" : " has-error" )}]]></xp:this.styleClass>
<xp:div styleClass="form-group">
<xp:label styleClass="col-sm-2 control-label" for="inputText1"
value="${compositeData.fieldLabel}" />
<div class="col-sm-10">
<div class="input-group">
<span class="input-group-addon">
<xp:text escape="true" id="computedField2"
styleClass="${compositeData.faicon}" tagName="i">
</xp:text>
</span>
<xp:inputText type="text" id="inputText1"
loaded="${!empty compositeData.placeholder}"
value="#{compositeData.dataSource[compositeData.fieldName]}"
required="${compositeData.required}">
<xp:this.attrs>
<xp:attr name="placeholder"
value="${compositeData.placeholder}">
</xp:attr>
</xp:this.attrs>
<xp:this.validators>
            <xp:validateRequired message="#{javascript:compositeData.fieldLabel + ' is required'}"></xp:validateRequired>
          </xp:this.validators>
</xp:inputText>
</div>
<xp:text escape="true" id="computedField3" styleClass="help-block" value="${compositeData.helpText}">
        <xp:this.rendered><![CDATA[#{javascript:getComponent("inputText1").isValid() && compositeData.helpText != null}]]></xp:this.rendered>
      </xp:text>
<xp:message id="message1" for="inputText1" styleClass="help-block"></xp:message>
</div>
</xp:div>
</xp:div>
</xp:view>

Sample Code XPage
<?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core"
xmlns:xc="http://www.ibm.com/xsp/custom">
<xp:this.data>
<xp:dominoDocument var="document1" formName="Contact"></xp:dominoDocument>
</xp:this.data>
<xc:ccLayoutBootstrap>
<xp:this.facets>
<xp:panel xp:key="facetMiddle">
<div class="page-header">
<h1>
Bootstrap Reusable Fields
<xp:span style="color:rgb(255,255,255)">
</xp:span>
<small>Including Validation</small>
</h1>
</div>
<xc:RBSTextFieldFAComputedText dataSource="#{document1}"
required="true" faicon="fa fa-user" fieldLabel="FirstName"
fieldName="FirstName" helpText="FirstName is a mandatory field"
placeholder="FirstName">
</xc:RBSTextFieldFAComputedText>
<xc:RBSTextFieldFAComputedText dataSource="#{document1}"
required="true" faicon="fa fa-user" fieldLabel="LastName"
fieldName="LastName" helpText="LastName is a mandatory field"
placeholder="LastName">
</xc:RBSTextFieldFAComputedText>
<xp:br></xp:br>
<xp:button value="Save" id="button1"
styleClass="btn btn-primary">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action>
<xp:saveDocument></xp:saveDocument>
</xp:this.action>
</xp:eventHandler>
</xp:button>
</xp:panel>
</xp:this.facets>
</xc:ccLayoutBootstrap>
</xp:view>

Final Result



There are several other possibilities / methods to add validation to an XPages application including Bootstrap. During the last periode I took a closer look at some of these possibilities / methods like Nod and BootstrapValidator v0.5.2 but finally I ended up with the above validation method. 
At the moment I'm working on a first setup with AngularJS Form Validation. More on this in a later blog post.