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.

Tuesday, 4 November 2014

Fixes POODLE and SHA-2

Fixes for IBM Notes and Domino regarding POODLE and SHA-2 available

IBM has released interim fixes for IBM Notes and Domino tonight that address the POODLE and SHA-2 issues.

IBM Notes and Domino Wiki Article
IBM Domino Interim Fixes to support TLS 1.0 which can be used to prevent the POODLE attack

Installing this interim fix on your Domino server will enable TLS 1.0 across the following protocols: HTTP, SMTP, LDAP, POP3, IMAP & DIIOP. No additional configuration is required to set up TLS. With this interim fix, Domino servers previously configured for SSL will connect with browsers (and other SSL/TLS clients) that request a TLS connection using TLS 1.0. This interim fix also supports TLS_FALLBACK_SCSV to prevent the POODLE downgrade attack: Domino will not permit web browsers that also support TLS_FALLBACK_SCSV TLS to fall back to SSL V3.
This Domino interim fix is available on all platforms for the following releases: 9.0.1 FP2, 9.0, 8.5.3 FP6, 8.5.2 FP4, 8.5.1 FP5.

Interim Fixes for 9.0.1.x IBM Notes, IBM Domino & IBM iNotes


More information :

Planned SHA-2 deliveries for IBM Domino 9.x
Generating a SHA-2 Keyring file
IBM Notes Domino Wiki SHA-2
IBM Notes Domino Wiki TLS