From Windows 10 to Linux Mint 18

This week I decided to move over my Development host environment from Windows to Linux Mint after a post of a friend in which he stated that he had abandoned his long love with Linux Mint 17… for version 18. If you are unfamiliar with Linux Mint here is a good review on Linux Mint 18.

For the last decade I have been the regular corporate developer, so I did not mind too much about OS and when my pc became slow I just looked for a solution in newer hardware. 2 years ago I bought a new laptop (Lenova), Intel i7 processor, SSD disk, lots of GB for storage and 16GB of RAM. Oh and Windows 8. For Development I use Virtualbox with a Windows 7 guest OS where my Domino server runs on and the client programs (DDE mostly).

Things were running fast in the beginning and the update to Windows 10 was not a problem. But after a while, performance became less due to unknown reasons so I could re-install the whole thing over again (and get in trouble with my fellow users on the machine) or look for an alternative. That alternative became a dual boot option between Windows and Linux Mint.

The installation and re-installation (too small partition at first) went smoothly and within minutes I was running my Development environment hosted on Linux Mint (thanks to the Software Manager). The whole adaption of Linux Mint is a piece of cake. To me Mint desktop reminds me of Windows XP.

The long-term support of Linux Mint 18 (2021) and the possibility of Windows 10 turning from a purchase model into a subscription model is a consideration for the future. Also having features installed from scratch such as an image editor (Gimp) and Office software (Libre Office) is nice. Now I just have to consider switching over from our beloved multi-purpose client (Notes) to something more basic (Thunderbird)…

Rather would I move away my guest environment away from Windows too, but Domino Designer / Administrator is bound to Windows. #WWYT?

In the pipeline I have a Macbook, which delivery takes a bit longer than expected. I am curious how your development environments look like. Perhaps I could take a little tips from them.

Happy development =)

 

FlipSwitch style for your checkboxes

A flip switch is an alternative look for a checkbox or the two-option select menu. It can be toggled by a click or a swipe.

flipswitchoff

I am not sure if it’s originated from mobile interfaces, at least it is there where they are most common. So if you modernize an application and optimize it for mobile access you might consider adding flip switch behaviour to these form elements.

Here is an example how to do this with XPages:

htmlswith

 

Ofcourse you have to provide the CSS. The CSS depends on your theme. There are handy sites that might help you with it.

Here is my CSS:

.onoffswitch {
position: relative; width: 90px;
-webkit-user-select:none; -moz-user-select:none; -ms-user-select: none;
}
.onoffswitch-checkbox {
display: none;
}
.onoffswitch-label {
display: block; overflow: hidden; cursor: pointer;
border: 2px solid #999999; border-radius: 20px;
}
.onoffswitch-inner {
display: block; width: 200%; margin-left: -100%;
transition: margin 0.3s ease-in 0s;
}
.onoffswitch-inner:before, .onoffswitch-inner:after {
display: block; float: left; width: 50%; height: 30px; padding: 0; line-height: 30px;
font-size: 14px; color: white; font-family: Trebuchet, Arial, sans-serif; font-weight: bold;
box-sizing: border-box;
}
.onoffswitch-inner:before {
content: “ON”;
padding-left: 10px;
background-color: #34A7C1; color: #FFFFFF;
}
.onoffswitch-inner:after {
content: “OFF”;
padding-right: 10px;
background-color: #EEEEEE; color: #999999;
text-align: right;
}
.onoffswitch-switch {
display: block; width: 18px; margin: 6px;
background: #FFFFFF;
position: absolute; top: 0; bottom: 0;
right: 56px;
border: 2px solid #999999; border-radius: 20px;
transition: all 0.3s ease-in 0s;
}
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-inner {
margin-left: 0;
}
.onoffswitch-checkbox:checked + .onoffswitch-label .onoffswitch-switch {
right: 0px;
}

I hope you find this tip useful…

flipswitch

 

Add 20 years of experience to your workforce

 

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: http://www.linkedin.com/in/patrickkwinten and get in contact.

I am happy to work WITH you !

Draggable modal

For a project a request was to make a Bootstrap modal (a Dialog control in the Extension Library) as draggable. By default, the modal does not have that feature. So can you make it draggable again?

In xsp-mixin stylesheet the class xsp-responsive-modal is using !important for the left and top properties which prevents that the modal is draggable. A work-around can be achieved by replacing these class properties with your own that does not use !important.

To replace the default class add for the onShow event of the dialog:

<xe:this.onShow>
<![CDATA[
x$(“#{id:dialog1}”).removeClass(“xsp-responsive-modal”).addClass(“draggable-responsive-modal”);
]]>
</xe:this.onShow>

Your custom class could look as followed:

.draggable-responsive-modal {
display: block;
width: auto;
left: 0;
top: 0;
z-index: 1050 !important;
}

The x$() function is the infamous utility function from Mark Roden to work with JQuery.

I added the code to GitHub Gist: https://gist.github.com/PatrickKwinten/1d442e28ff0d59f8e01728bffab13e4f

Add 20 years of experience to your workforce

 

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: http://www.linkedin.com/in/patrickkwinten and get in contact.

I am happy to work WITH you !

Question: Is it possible to set via a resource via a theme so it is applied to any XPage in an application?

I received a question if it is possible to set (or add) a resource via a Theme resource so it will become available to any XPage or Custom control?

Yes ofcourse you can e.g. via:

<resource>
<content-type>text/css</content-type>
<href>custom.css</href>
</resource>

but you should keep in mind is that a Theme is ONLY applied in the Render Response phase. So if for example you include an SSJS library to the Theme, you will not be able to use it in the beforePageLoad or afterPageLoad event. A mistake that is common made.

My recommendation would therefor be to use a Theme more for applying default settings or to overwrite properties to a specific type of component, e.g. a default pageName property on the ViewRoot component.

In terms of adding resources I would advice to use a Custom control design element. SSJS that will be computed dynamically only run once per page load / refresh in a theme (just in Render Response), compared to every phase of the lifecycle in a Custom control.

Happy development =)

End of contract – a retrospect

Introduction – I am out of work !

Hi there. Recently I was informed that the company that invited me urgently to move abroad for a professional and challenging work environment was not intending to continue my contract after my trial period.

Reactions I received were ‘how sad’ and ‘probably we are less easy to work with than we intend to be’.

I guess a healthy and professional work-environment depends on the people and handling expectations, all supported by management. I do may say this has been MY WORST WORKING EXPERIENCE EVER, and this should summarize it.

However, the unsuspected decision (there has never been a discussion, so no outcome) has brought me and my family with infants in a small social nightmare. We have made a considerable investment with a transmigration, short-term high-price accommodation etcetera) based on the promises we received.

In an attempt to make this post not the saddest of all ‘I am a IBM ICS developer and looking for a job ‘ (you may reply however in case you know a job opportunity) I was thinking writing about my activities the last x months and my plans for the near future.

Log of activities

Spring Tool Suite

The last months I have been developing my first Java program in Spring Tool Suite (STS). The program runs as a service and basically it collects data from a financial service and create reports (spreadsheets) from the received data. The bit where IBM Notes plays a role is that for logging activities OpenLog is being used. For displaying the log entries I build an interface with the help of XPages.

Why STS? – Because I was told so.

What is your experience? – After programming in XPages with more and more Java (Managed beans, Java classes, External libraries, Expression Language) the learning curve was quiet steep. Luckily I got help with a patient colleague who showed and explained me a lot of ins and outs in developing in STS (Thanks!).  A lot of things that are simply to manage in JSF (e.g beans) I had to setup myself and I have been taking the existance of scope variables for granted. On the other hand the REST templates in STS work like a charm and make it easy to work with REST services.

So this project has been a good learning experience for me, although the working conditions (read: project specifications) were poor.

XPages 2.0 err 1.0

Further I have been working on XPages development by updating an existing XPages application.

When I first looked at the application I saw a load of design elements. Basically each type of document had it own large set of design elements to display information in different views, so with the help of the Dynamic Content control, some Java collections and work more with one JSON configuration file instead of losely coupled keyword documents I managed to reduce the amount of design elements dramatically.

Besides that a search interface had to be added. When I proposed to use the jQuery DataTables plugin for a more dynamic and potential search function instead of a custom form with hard-coding the dropdown boxes I was like talking abracadabra, my blog posts on the datatables plugin prove however this can be implemented fairly quick and easy.

So no chance here to introduce Managed beans, Java classes, JSON as data format for document collections, REST services, use XPages only as render engine, avoid SSJS as much as possible, avoid setting up unnecessary Notes view for delivering (slightly) different sets of data, use expression language above SSJS (when possible). So no chance to prove my skills here. Should I feel sorry for the customer?

Working on a Mac

For some it’s like nature but do you remember the time you came from a Windows environment and started working with a Mac? The last couple of months I have been working with Mac and this was also a great learning experience!

The future

So what will bring the future? From what I understand the Notes market in Sweden has been very low the last couple of years so I might have a problem here. My skills are mainly focussed on XPages development, and the expectations for this platform are very unclear (did I hear a roadmap for IBM Notes / Domino somewhere ?)(please do not post depressing comments about the prospects of this product).

The lack of updates from IBM and the limit amount of companies embracing this technology let consider me to look for alternatives.

React

I have decided to study some upcoming or rising technologies for web development and one of them I consider React. For a couple of years I have been experimenting with Angular and data residing in IBM Notes. It feels to me that Angular has more rules to follow than React (React is about the view in the MVC concept) so the latter looks more easy to start with.

Knut Herrman gave me a nice introduction on React as front-end for Domino a while ago.

So hopefully I can demonstrate soon my first “React application” to you.

Graph data modelling

The data that we live with becomes more connected so another ‘leg’ I would like to stand on in the near future is on graph data modelling. I have followed several courses for Neo4j now and been exploring the Graph db in the OpenNTF Domino API whichs allows me to build applications in an environment I feel comfortable in.

I have blogged about Graph data-modelling with Notes data in other posts so expect some more posts about this.

One thing I notice the job opportunities in this area seem to be scarce but perhaps I am looking under the wrong categories on the wrong sites.

So hire me!

I am open for all opportunities; a permanent job, a fixed contract, sub contract. Everything working with interesting technology is better than sitting at home. So if you happen to know something of interest do not hesitate to contact me.

For more information on my work experience I direct you initially to my LinkedIn profile.

 

 

 

 

 

 

Building a search function with DataTables plugin (VIII)

Introduction

Dates, everybody loves to filter on dates. In Notes views to filter (select) on dates is a criminal offence but luckily filtering on dates in the datatable component is not that hard.

For our search function we are going to apply something as followed:

datatables08

It are two input fields, set as type ‘date’. In some browsers you get a datepicker presented. If you want to have a more fancy one you can always bring in an add-on.

Implementation

So for our HTML structure we included in our XPage:

datatables08b

So what are we going to filter on? In my example I have choosen to filter on the birthday. This is not a field available in the names.nsf so we have to add this ourselfs (now you know why HR always forget your birthdays). To do so I have updated my agent to generate person documents. This was my quickest approach:

bday = Round(Rnd()* 28 ,0)
If bday = 0 Then
bday = 1
End If

bmonth = Round(Rnd()* 12 ,0)
If bmonth = 0 Then
bmonth = 1
End If

byear = arr_birthyear( Round(Rnd()* UBound(arr_birthyear) ,0) )
birth = CStr(bmonth) + “-” + CStr(bday) + “-” + byear

Dim dateTime As NotesDateTime
Set dateTime = session.CreateDateTime( birth )
Call doc.ReplaceItemValue(“Birthday”, dateTime)

If you have a better one (I am sure of that) please drop a line how I can obtain it.

So with this birthday field on the person document, we need to updated our Notes view (adding a column). I had to hard-code the format otherwise I did not get a full year displayed:

@Text(@Year(birthday)) +”-“+
@If(
@Length(@Text(@Month(birthday))) <2;
“0” + @Text(@Month(birthday));
@Text(@Month(birthday))
) +”-“+
@If(
@Length(@Text(@Day(birthday))) <2;
“0” + @Text(@Day(birthday));
@Text(@Day(birthday))
)

 

Also we need to “broadcast” this additional value via our custom service bean:

String birthday = String.valueOf(columnValues.get(12));
if (null!=birthday){
jo.put(“bday”,birthday);
}

Nothing that fancy. We also need to include the extra column to our table header:

<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Company</th>
<th>Job</th>
<th>Birthday</th>
</tr>
</thead>

THEN comes the main modification, in our JavaScript.

We need a function to normalize the date (from string to Date object):

var normalizeDate = function(dateString) {
var date = new Date(dateString);
var normalized = date.getFullYear() + ” + ((“0″ + (date.getMonth() + 1)).slice(-2)) + ” + (“0” + date.getDate()).slice(-2);
return normalized;
}

To apply a date filter to the datatable I have setup the next function:

var filterByDate = function(column, startDate, endDate) {
$.fn.dataTableExt.afnFiltering.push(
function(oSettings, aData, iDataIndex) {
var rowDate = normalizeDate(aData[column]),
start = normalizeDate(startDate),
end = normalizeDate(endDate);
if (start <= rowDate && rowDate <= end) {
return true;
} else if (rowDate >= start && end === ” && start !== ”) {
return true;
} else if (rowDate <= end && start === ” && end !== ”) {
return true;
} else {
return false;
}
}
);
};

In our datatables initialitation script we set the dates for the input fields (let’s hope people may retire in your country at age 65):

var d = new Date();
d.setYear(d.getYear() – 65);
document.getElementById(‘start’).valueAsDate = d;
document.getElementById(‘end’).valueAsDate = new Date();

We need to register any change in the input date fields and call the filterByDate function:

$(“.datePicker”).on(“keyup change”, function() {
var startDate = $(‘#start’).val(),
endDate = $(‘#end’).val();
filterByDate(4, startDate, endDate); // call our filter function
$(“#persons”).dataTable().fnDraw(); // manually redraw the table after filtering
});

To remove the filter we register a function on the onclick event of the Clear Data Filter button:

$(‘#clearFilter’).on(‘click’, function(e){
e.preventDefault();
$.fn.dataTableExt.afnFiltering.length = 0;
$(“#persons”).dataTable().fnDraw();
});

With all this in place we are good to go!

Wrap-up

Yet another great feature for our search form! Perhaps you prefer a slider more suitable for selecting date-ranges or a more fancy date-pciker that works across browsers. The choices are up to you!

Building a search function with DataTables plugin (VII)

Introduction

From my experience some Notes may contain a lot of columns (not sure what the limit is?) and represented on the web, often users need so see the same amount of columns. So what do you do then?

Column visibility to the rescue!

Part of the buttons module is the column visibility. This requires to load an additional resource:

<resource>
<content-type>application/x-javascript</content-type>
<href>DataTables/buttons-1.2.1/js/buttons.colVis.js</href>
</resource>

Also remember here to disable AMD loading.

From here it is quiet easy to have the visibility option available as a button in the ‘button bar’. Just add the colvis option in the configuration.

In case you want to result of (in)visibility of columns represented in any export option you need to specify the exportOptions property for the buttons e.g. as followed:

buttons: [
‘copy’,
‘csv’,
‘excel’,
{
extend: ‘pdfHtml5’,
orientation: ‘landscape’,
pageSize: ‘LEGAL’,
title: ‘Person Details’
},
{
extend: ‘print’,
exportOptions: {
columns: ‘:visible’
}
},
‘colvis’
],

Result

As a result a new button is presented and when clicked you can choose which column to make (in)visible:

datatables07

column API

In case you do not want to present a button, but for example anchor links the column API comes at help.

Here is a sample how to register change in a column visibility when clicking an anchor:

$(‘a.toggle-vis’).on( ‘click’, function (e) {
var db = $(“#persons”).DataTable();
e.preventDefault();

// Get the column API object
var column = db.column( $(this).attr(‘data-column’) );

// Toggle the visibility
column.visible( ! column.visible() );
} );

And here is the HTML for presenting the anchors:

Column visibility:FirstnameLastnameCompanyJob title

Finally the end result. Ofcourse you can be creative with CSS for the anchor links, adding different layout for each column state. Be creative!

datatables07b

In another post I will describe how you can accomplish something similar in Xpages with a viewpanel (with a bit of more code)…

Building a search function with DataTables plugin (VI)

Introduction

Often business analists who work with the data in tables eat & sleep in their spreadsheet world so a common asked question is: can we export the data? “Ofcourse you can!” with the datatable component.

Modifications

Below is a short summary of the changed/added items.

Configuration

In order to add the buttons you specify in the datatable configuration which buttons you would like to have e.g.:

dom: ‘Bfrtip’,
buttons: [
‘copy’,
‘csv’,
‘excel’,
{
extend: ‘pdfHtml5’,
orientation: ‘landscape’,
pageSize: ‘LEGAL’,
title: ‘Person Details’
},
‘print’
]

 

Required files

Which files are required for the buttons feature depend on which buttons you would like to display. In the download builder you can specify for which options you would like to go.

AMD fix

An important thing to notice is that most JS files use AMD loading. There have been posted multiple questions and answers how to fix AMD loading with XPages. In my repository I have just removed the amd checking.

Files overview

Probably the files you would like to use will be listed in the Theme design element:

<!– adding buttons –>
<resource>
<content-type>application/x-javascript</content-type>
<href>DataTables/buttons-1.2.1/js/dataTables.buttons.js</href>
</resource>
<resource>
<content-type>application/x-javascript</content-type>
<href>DataTables/buttons-1.2.1/js/buttons.flash.js</href>
</resource>
<resource>
<content-type>application/x-javascript</content-type>
<href>DataTables/jszip-2.5.0/jszip.js</href>
</resource>
<resource>
<content-type>application/x-javascript</content-type>
<href>DataTables/pdfmake-0.1.18/build/pdfmake.js</href>
</resource>
<resource>
<content-type>application/x-javascript</content-type>
<href>DataTables/pdfmake-0.1.18/build/vfs_fonts.js</href>
</resource>
<resource>
<content-type>application/x-javascript</content-type>
<href>DataTables/buttons-1.2.1/js/buttons.html5.js</href>
</resource>
<resource>
<content-type>application/x-javascript</content-type>
<href>DataTables/buttons-1.2.1/js/buttons.print.js</href>
</resource>
<resource>
<content-type>text/css</content-type>
<href>DataTables/buttons-1.2.1/css/buttons.dataTables.min.css</href>
</resource>

 

Result

As a result you will see the buttons displayed above the table. If you apply filtering to the table the buttons will pick up the provided terms.

datatables06

A little less coding than an X-agent to create a PDF or spreadsheet:-)

A downsize might be that users are not aware of the amount of data that might reside in your datatable (the only x-number of entries are displayed). Pressing the PDF button with 40K of documents in your notes view takes a bit of time…

Building a search function with DataTables plugin (V)

Introduction

In the last post we moved the input fields out of the table and into a separate form. In this post I will include a nice usability feature for search term highlighting. This feature is particular helpful if you allow search in columns where values do not differ so much from each other like order numbers or article numbers.

Say hello to Mark()

Mark.js is a JavaScript keyword highlighter function. You can use it as pure JavaScript or jQuery plugin.

First let me show the end-result and then we will walk through the changes:

datatables05

Modifications

In order to enable Mark I made chances to the following items:

  • webcontent folder
  • theme
  • custom stylesheet
  • xpage
  • javascript library

In the webcontent folder I included the distributed files. I included only the jQuery plugin as a resource in the Theme document:

<resource>
<content-type>application/x-javascript</content-type>
<href>mark/jquery.mark.js</href>
</resource>

In the custom stylesheet I added a class definition to distinguish the searched term with some highlight:

span.markSearched {
background: yellow;
color: black;
}

In our xpage I added the name attribute for each input element e.g. name=firstname. This attribute will be used as reference to apply the Mark feature.

The main changes take place in the JavaScript. I have written a separate function for it so we do not need to call it on loading:

$(function() {
var db = $(“#persons”).DataTable();
db.destroy();
localStorage.clear();
// Map inputs with columns (nth-child(X))
var inputMapper = {
“firstname”: 1,
“lastname”: 2,
“company”: 3,
“job”: 4
};

// Initialize DataTables
var db = $(“#persons”).DataTable({

stateSave : saveState,
fixedHeader: true,
“language” : {
“lengthMenu” : “Entries per page _MENU_”,
// “info” : “Page _PAGE_ of _PAGES_”,
“infoEmpty” : “No entries found”,
“infoFiltered” : “”
},
scrollY : yScroll,
“ajax” : “api.xsp/Persons” ,
“columns” : [
{
data : “firstname”,
“defaultContent”: “<i>Not set</i>”
},{
data : “lastname”,
“defaultContent”: “<i>Not set</i>”
},{
data : “company”
}
,{
data : “job”
}
],

// Set elements per page
pageLength: 10,
// Disable entry selection
bLengthChange: false,
// Act on table rendering
drawCallback: function() {
// Iterate over all inputs (by mapper names)
$.each(inputMapper, function(colName, index) {
// Determine the entered keyword

var val = $(“input[name='” + colName + “‘]”).val();
// Determine the column related to the input
var $col = $(“.datatables-table tbody tr > td:nth-child(” + index + “)”);
// Remove marks in related column
$col.unmark({
“element”: “span”,
“className”: “markSearched”
});
// Mark in related column
$col.mark(val, {
// Define mark.js options (see https://markjs.io/)
“element”: “span”,
“className”: “markSearched”
});
})
}
});

// Trigger table redraw on search keyword change
$(“input”).on(“keyup change”, function() {
var db = $(“#persons”).DataTable();
var $this = $(this);
var val = $this.val();
var key = $this.attr(“name”);

// Search inside DataTable column
// subtract -1 because :nth-child starts with 1,
// DataTables with 0
db.columns(inputMapper[key] – 1).search(val).draw();
});

});

In the inputMapper variable we define the input fields and their order appearance in the table.

Instead the initComplete callback we will use the drawCallback function instead. The initComplete runs once, the drawCallback runs everytime the table is redrawn, e.g. when we enter search terms. For each input element we take the entered value and match it with values in the corresponding column. When a match is found a span element with the classname markSearched is applied.

Finally we register events for the input elements so if characters are entered or removed the table gets redrawn.

Wrap up

That’s it! I hope you like this feature. I wonder how easily you could do this with a viewPanel control…

 

 

 

Building a search function with DataTables plugin (IV)

Introduction

In the previous posts I demonstrated how to setup your application to generate a datatable component from your Notes view(s) and how to apply filtering & search capabilities to the columns.

In this post I will demonstrate how to build an external form to filter the datatable. I guess in most cases you want to provide some sort of search form and displayed separate from your table (left, right, top). For now we restrict the search form with input boxes.

Modifications

I have applied some modifications to the application. The complete and final code you can view in my Github repository.

Modifications:

  • java class that works as a custom service bean
  • javascript library for initializing datatable
  • xpage to display the datatable

Let’s add a form

The first thing we will do is by adding a Bootstrapped styled form to the xpage:

datatables04pre

Notice the following things:

  • The filter class for the input element
  • The data-column-index attribute for the input element

The filter class will be used to register events on:

$(‘.filter’).on(‘keyup change’, function () {
//clear global search values
db.search(”);
db.column($(this).data(‘columnIndex’)).search(this.value).draw();
});

The data-column-index attribute directs to the index of the corresponding column in the datatable.

With the form in place and the script updated we need to extend our java class so the values for the job title are included:

String job = String.valueOf(columnValues.get(10));
if (null!=job){
jo.put(“job”,job);
}

Let’s see the result

For example if I am looking for a person with firstname starting with Car.., from company Firm (something) acting as a host I get presented:

datatables04

Now with the initial search form in place we will extend it with features to improve it’s usability…