Tuesday, 11 October 2016

Using Tokenfield for Bootstrap in XPages for Elegant Taggable Fields with Copy-Paste and Keyboard Support

Tokenfield is an advanced tagging / tokenizing plugin for jQuery and Twitter Bootstrap with a focus on keyboard and copy-paste support. Main features are copy and paste support, keyboard navigation, edit existing tokens, multiple lines of tokens and responsiveness. Tokenfield for Bootstrap is easy to implement within each XPages application.
In order to use Tokenfield for Bootstrap the JavaScript and CSS file(s) need to be included on the XPage / Custom Control. The latest version can be downloaded from GitHub: Tokenfield for Bootstrap.

Adding the JS and CSS files
The JavaScript and CSS files must be added to the WebContent Folder in the Package Explorer.
In the example below a Folder bootstraptokenfield has been added in the WebContent Folder.


Next the JavaScript and CSS files, bootstrap-tokenfield.js, jquery-ui.js, bootstrap-tokenfield.css, tokenfield-typeahead.js and jquery-ui.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="bootstraptokenfield/bootstrap-tokenfield.js"></script>
<script type="text/javascript" src="bootstraptokenfield/jquery-ui.js"></script>
<link rel="stylesheet" href="bootstraptokenfield/css/bootstrap-tokenfield.css" />
<link rel="stylesheet" href="bootstraptokenfield/css/tokenfield-typeahead.css" />
<link rel="stylesheet" href="bootstraptokenfield/css/jquery-ui.css" />

Note: The jQuery-UI files are only required if jQuery-UI autocomplete is used. If JQuery-UI autocomplete is beging used there is also a need for bootstrap styling. Create a custom.css file with the following code and add the stylesheet to the XPage: CSS Github Gist. In the Code XPage is an extended example included for using autocomplete (inputText3 /scriptBlock3).

Adding the x$ jQuery selector for XPages
Furthermore I use the the great XSnippet by Mark Roden, x$ jQuery selector for XPages, to initialize the plugin and include it on the XPage. The XSnippet can be added to the Script Libraries. In this example the name of the Script Library is JQueryXSnippet.js.

<xp:this.resources>
<xp:script src="/JQueryXSnippet.js" clientSide="true"></xp:script>
</xp:this.resources>

The script itself can be made up as follows. The name of the id in the script must correspond with the id of the Edit Box. In the example below I used some extra options.

<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:inputText1}" ).tokenfield({
tokens: ['red', 'blue', 'green']
});
}
);
]]></xp:this.value>
</xp:scriptBlock>

The final result is a responsive Tokenfield for Bootstrap including jQuery-UI autocomplete and Bootstrap Styling.


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="/JQueryXSnippet.js" clientSide="true"></xp:script>
<xp:styleSheet href="/custom.css"></xp:styleSheet>
</xp:this.resources>
<script type="text/javascript" src="bootstraptokenfield/bootstrap-tokenfield.js"></script>
<script type="text/javascript" src="bootstraptokenfield/jquery-ui.js"></script>
<link rel="stylesheet" href="bootstraptokenfield/css/bootstrap-tokenfield.css" />
<link rel="stylesheet" href="bootstraptokenfield/css/tokenfield-typeahead.css" />
<link rel="stylesheet" href="bootstraptokenfield/css/jquery-ui.css" />
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:inputText1}" ).tokenfield({
tokens: ['red', 'blue', 'green']
});
}
);
]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock2">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:inputText2}" ).tokenfield();
}
);
]]></xp:this.value>
</xp:scriptBlock>
<xp:scriptBlock id="scriptBlock3">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:inputText3}" ).tokenfield({
autocomplete: {
source: ['red','blue','green','yellow','violet','brown','purple','black','white'],
delay: 100  
},
showAutocompleteOnFocus: false
});
x$( "#{id:inputText3}").on('tokenfield:createtoken', function (event) {
var existingTokens = $(this).tokenfield('getTokens');
$.each(existingTokens, function(index, token) {
if (token.value === event.attrs.value)
event.preventDefault();
});
// Close autocomplete
x$("#{id:inputText3}").keypress(function(e){
if (!e) e = window.event;
if (e.keyCode == '13'){
x$("#{id:inputText3}").autocomplete('close');
return false;
}
});
// Prevent Duplicates
x$("#{id:inputText3}").on('tokenfield:createdtoken tokenfield:removedtoken', function (event) {
var field = $(this);
var currentTokens = field.tokenfield('getTokens');
var originalSource = field.data('bs.tokenfield').options.autocomplete.source;
var newSource = originalSource.slice(); //clone original autocomplete source
for (var i = newSource.length - 1; i >= 0; i--) {
for (var j = currentTokens.length - 1; j >= 0; j--) {
if (JSON.stringify(currentTokens[j].label) == JSON.stringify(newSource[i])
|| JSON.stringify(currentTokens[j]) == JSON.stringify(newSource[i]) ) {
//remove the token from the newSource
var index = newSource.indexOf(newSource[i]);
if (index > -1)
newSource.splice(index, 1);
};
};
};
//update source
field.data('bs.tokenfield').$input.autocomplete({source: newSource})
})
});
}
);
]]></xp:this.value>
</xp:scriptBlock>
<xc:ccLayout>
<xp:this.facets>
<xp:panel xp:key="facetMiddle">
<h3>Tokenfield for Bootstrap</h3>
<h4>Advanced Tagging - Tokenizing Plugin for jQuery and Twitter Bootstrap with a focus on keyboard and copy-paste support.</h4>
<br />
<div class="col-md-7">
<xp:inputText id="inputText1">
</xp:inputText>
<br />
<xp:inputText id="inputText2">
</xp:inputText>
<br />
<xp:inputText id="inputText3">
</xp:inputText>
</div>
</xp:panel>
</xp:this.facets>
</xc:ccLayout>
</xp:view>

No comments:

Post a Comment