Wednesday, 6 September 2017

Tokenize Combo Boxes and List Boxes in XPages Applications


Tokenize2 is a plugin which allows your users to select multiple items from a predefined list or ajax using autocompletion as they type to find each item. You may have seen a similar type of text entry when filling in the recipients field sending messages on Facebook or Tags on Tumblr. Tokenize2 has a lot of amazing options and events. Tokenize2 (currently v1.0) has a few easy ways to quickly get started, each one appealing to a different skill level and use case.
In order to use Tokenize2, the JavaScript and CSS file(s) need to be included on the XPage / Custom Control. The latest version can be downloaded from GitHub: Tokenize2.
Below a basic example how Tokenize2 can be used in an XPages application.

Adding the JS and CSS files
The JavaScript and CSS files must be added to a WebContent Folder in the Package Explorer.
In this example the Folder tokenize2 has been added to the WebContent Folder.
Next the JavaScript and CSS files, tokenize2.min.js and tokenize2.min.css, must be included on the XPage or Custom Control. In this example I add the files to an XPage.

<script type="text/javascript" src="tokenize2/tokenize2.min.js"></script>
<link rel="stylesheet" href="tokenize2/tokenize2.min.css" />

Adding the x$ jQuery selector for XPages
Furthermore I recommend to use the the great XSnippet by Mark Roden, x$ jQuery selector for XPages, to initialize the plugin. The XSnippet can be added to the Script Libraries. See also the blog post by Csaba Kiss, x$ selector problem with JQuery 3.
The script itself can be made up as follows. In this example I use a few standard options.

<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:listBox1}" ).tokenize2({
placeholder: "Select a value",
tokensMaxItems: 2,
searchMinLength: 1    
});    
})
]]></xp:this.value>
</xp:scriptBlock>

AMD Loader Fix
Finally, the JavaScript file tokenize2.min.js needs to be adjusted. Reason: newer jQuery plugins try to use its AMD loader, but that doesn't play well with the Dojo implementation in XPages. The source code of the library can be adjusted in a very simple way with just a slight modification.

1. Go to the WebContent Folder and select the specific JavaScript file
2. Select Open With - Client/Server JS Editor


3. Find and Remove define.amd and replace it with false
4. Save the JavaScript file tokenize2.min.js

Note: There are other solutions for the AMD Fix. For more information about thes solution see my blog post Bootstrap Plugins in XPages Part VI - jQuery and JavaScript AMD (Asynchronous Module Definition) Fixes (2).

Final Result
The final result is a responsive Combo- or List Box with selected items displayed as tokens/tags including some additional options in the initial setup. 


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.resources>
<xp:script src="/jQuerySelector.js" clientSide="true"></xp:script>
</xp:this.resources>
<script type="text/javascript" src="tokenize2/tokenize2.min.js"></script>
<link rel="stylesheet" href="tokenize2/tokenize2.min.css" />
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:listBox1}" ).tokenize2({
placeholder: "Select a value",
tokensMaxItems: 2,
searchMinLength: 1    
});    
})
]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:comboBox1}" ).tokenize2();    
})
]]></xp:this.value>
</xp:scriptBlock>
<xc:ccLayout>
<xp:this.facets>
<xp:panel xp:key="facetMiddle">
<xp:br></xp:br>
<xp:listBox id="listBox1" multiple="true">
<xp:this.attrs>
<xp:attr name="multiple" value=""></xp:attr>
</xp:this.attrs>
<xp:selectItem itemLabel="Africa" itemValue="Africa"></xp:selectItem>
<xp:selectItem itemLabel="America" itemValue="Ameria"></xp:selectItem>
<xp:selectItem itemLabel="Asia" itemValue="Asia"></xp:selectItem>
<xp:selectItem itemLabel="Europe" itemValue="Europe"></xp:selectItem>
</xp:listBox>
<xp:br></xp:br>
<xp:comboBox id="comboBox1">
<xp:this.attrs>
<xp:attr name="multiple" value=""></xp:attr>
</xp:this.attrs>
<xp:selectItems>
<xp:this.value><![CDATA[#{javascript:var arr = new Array("");  
var res = @DbColumn("C0007C43:002CD36F", "($Names)", 0) 
var list = arr.concat(res);
return list;
}]]></xp:this.value>
</xp:selectItems>
</xp:comboBox>
<xp:br></xp:br>
</xp:panel>
</xp:this.facets>
</xc:ccLayout>
</xp:view>

1 comment:

  1. hello, select2's similar functions works very slow with large value sets... looking for an alternative, i will try this.

    ReplyDelete