Wednesday, 19 July 2017

Using Vex - Beautiful Functional Dialogs in Vanilla JavaScript in XPages


In my continuous search for modern plugins for my XPages applications I came across Vex.
Vex is a modern dialog library which is highly configurable, easily stylable, and gets out of the way. Vex is tiny (5.5kb minified and gzipped), has a clear and simple API, works on mobile devices, and can be customized to match your style in seconds.

Features
Drop-in replacement for alert, confirm, and prompt
Easily configurable animations which are smooth as butter
Lightweight with no external dependencies
Looks and behaves great on mobile devices
Open multiple dialogs at once and close them individually or all at once
UMD support

One of the simplest ways to use vex is to call vex.dialog.alert, vex.dialog.confirm, or vex.dialog.prompt.
Vex has support for plugins that can extend and modify the behavior of vex. Plugins are a great way to extend the functionality of Vex while keeping the dependencies lightweight. In the examples below I use vex-dialog, a plugin for vex that contains dropin replacements for alert, confirm, and prompt.
In order to use Vex, the JavaScript and CSS file(s) need to be included on the XPage / Custom Control. The latest version can be downloaded from GitHub: vex and vex-dialog.

Adding the JS and CSS files
The JavaScript and CSS files must be added to the WebContent Folder in the Package Explorer.
In this example the Folders vex and vexdialog have been added in the WebContent Folder.
Next the JavaScript and CSS files, vex.combined.js, vex.dialog.js, vex.css and vex-theme-os.css must be included on the XPage or Custom Control. In this example I add the files to an XPage. I also added a theme, vex-theme-os using classname to overwrite the default theme.

<script type="text/javascript" src="vex/js/vex.combined.js"></script>
<script type="text/javascript" src="vexdialog/vex.dialog.js"></script>
<script>vex.defaultOptions.className = 'vex-theme-os'</script>
<script type="text/javascript" src="enable_amd.js" clientSide="true"></script>
<link rel="stylesheet" href="vex/css/vex.css" />
<link rel="stylesheet" href="vex/css/vex-theme-os.css" />

AMD Loader Fix
For Vex in XPages there is a need for an AMD Loader Fix. Reason: newer jQuery plugins try to use its AMD loader, but that doesn't play well with the Dojo implementation in XPages. In the example below I use two javascript libraries, disable_amd.js and enable_amd.js, a solution provided by Mark Leussink. You can add these scripts to in the Script Libraries of the XPages application.

disable_amd.js
if (typeof define === 'function' && define.amd) {if(define.amd.vendor =='dojotoolkit.org'){define._amd = define.amd;delete define.amd;}}

enable_amd.js
if (typeof define === 'function' && define._amd) {define.amd = define._amd; delete define._amd;}

The first one is loaded before the js files, the second one after the js files.

<script type="text/javascript" src="disable_amd.js" clientSide="true"></script>
<script type="text/javascript" src="vex/js/vex.combined.js"></script>
<script type="text/javascript" src="vexdialog/vex.dialog.js"></script>
<script type="text/javascript" src="enable_amd.js" clientSide="true"></script>
<script>vex.defaultOptions.className = 'vex-theme-os'</script>
<link rel="stylesheet" href="vex/css/vex.css" />
<link rel="stylesheet" href="vex/css/vex-theme-os.css" />

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).

Vex Plugin initialization
Vex can be initialized using a simple script. In the example below I used use a button for a vex-dialog-confirm (CSJS).

<xp:button value="Label" id="button1">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[vex.dialog.confirm({
message: 'Are you absolutely sure you want to delete this document?',
callback: function (value) {
if (value) {
console.log('The document has been deleted.')
} else {
console.log('Abort delete document.')
}
}
})]]></xp:this.script>
</xp:eventHandler>
</xp:button>

It is also possible to 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. See also the blog post by Csaba Kiss, x$ selector problem with JQuery 3.
The script itself can be made up as follows. The name of the id in the script must correspond with the id of the Button.

<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:button2}" ).bind("click",function(){vex.dialog.confirm({
message: 'Are you absolutely sure you want to delete this document?',
callback: function (value) {
if (value) {
console.log('The document has been deleted.')
} else {
console.log('Abort delete document.')
};
}
});
});
});
]]></xp:this.value>
</xp:scriptBlock>

Final Result
The final result is a modern responsive Modal.


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"><script type="text/javascript" src="disable_amd.js" clientSide="true"></script>
<script type="text/javascript" src="vex/js/vex.combined.js"></script>
<script type="text/javascript" src="vexdialog/vex.dialog.js"></script>
<script>vex.defaultOptions.className = 'vex-theme-os'</script>
<script type="text/javascript" src="enable_amd.js" clientSide="true"></script>
<link rel="stylesheet" href="vex/css/vex.css" />
<link rel="stylesheet" href="vex/css/vex-theme-os.css" />
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
$(document).ready(
function() {
x$( "#{id:button2}" ).bind("click",function(){vex.dialog.confirm({
message: 'Are you absolutely sure you want to delete this document?',
callback: function (value) {
if (value) {
console.log('The document has been deleted.')
} else {
console.log('Abort delete document.')
};
}
});
});
});
]]></xp:this.value>
</xp:scriptBlock>
<xc:ccLayout><xp:this.facets>
<xp:panel xp:key="facetMiddle">
<xp:br></xp:br>
<xp:button value="Delete document CSJS" id="button1">
<xp:eventHandler event="onclick" submit="false">
<xp:this.script><![CDATA[vex.dialog.confirm({
 message: 'Are you absolutely sure you want to delete this document?',
 callback: function (value) {
 if (value) {
 console.log('The document has been deleted.')
 } else {
 console.log('Abort delete document.')
 }
 }
})]]></xp:this.script>
</xp:eventHandler>
</xp:button>
<xp:button value="Delete Document x$ jQuery selector" id="button2"></xp:button>
</xp:panel>
</xp:this.facets>
</xc:ccLayout>
</xp:view>

More information: Vex Documentation

No comments:

Post a Comment