SlideShare a Scribd company logo
Break out of The Box – Part 2
Integrate existing Domino Data with modern websites
Karl-Henry Martinsson
Demand Better Solutions, LLC
I AM...
 Swede living in Dallas, TX
 Developer at Demand Better Solutions, LLC
 Programming since 1982
 Web developer since 1994
 Notes/Domino developer since 1996
 IBM Champion since 2014
http://www.demandbettersolutions.com
http://www.texasswede.com
http://blog.texasswede.com
My Story
 Old infrastructure
• Domino 8.5.2 server and Notes 8.5.2 Basic client
 Company unwilling to upgrade
• Memory requirements for Standard client
• Citrix environment – limited memory available
• Upper management thinks Notes/Domino is legacy
 Management requests
• New web applications with modern look-and-feel
• Future mobile support (phone/tablet)
Bootstrap and jQuery to the Rescue!
Why Not Xpages?
 Infrastructure not supporting XPages (Domino 8.5)
 No XPages development skills
 Tight deadline – no time to learn
 Better control of versions – not having to wait for IBM
 Access to frameworks not yet in Domino (e.g. jQuery)
 Use time-saving jQuery/Bootstrap plugins
Why Integrate?
 Limited or no migration options
 Desire to modernize front-end
 Code re-use
 Take advantage of the power of Domino
 Use existing skillset (Domino, Lotusscript)
 Learn valuable new skills (Javascript/jQuery/Ajax)
 No one will know you are using a Domino backend!
How does it work?
.NSF
 HTML and CSS
 jQuery (Javascript)
 Choice of framework
• Bootstrap
• jQuery UI / jQuery Mobile
• and many other...
 Process Ajax from browser
 Generate and return JSON
• Lotusscript agents
• XPages agents
• ?ReadViewEntries
• ExtLib REST Service control
Ajax call
JSON data
Server – IBM Domino
 Lotusscript agents
 NSF databases
 Existing business logic
 Can use existing classes and script libraries
Works on Domino version 5.0 and higher
Update to recent version highly recommended
Where does everything live?
 HTML pages, CSS files and Javascript
• Notes page element
• Notes resources
• CDN (.js and .css)
• Server file system – in Data/Domino/HTML
• Another web server
 Lotusscript agents
• .NSF database on Domino server
Development Tools
 Domino Designer
 Browser with Dev Tools
• Firefox with Firebug plugin
• Internet Explorer Developer Tools (built-in)
• Chrome Developer Tools (built-in)
 Online resources
• JSONLint
• Stack Overflow
• Google Search
What is jQuery?
 Fast, small and feature rich Javascript library
 Simplify using Javascript on a web page
 Available as CDN and as downloaded local files
 Three code streams:
• jQuery 1.x
 Supporting all browsers
• jQuery 2.x
 Removed support for IE 8 and earlier
 Smaller and faster
• jQuery 3.x
 Continuation of jQuery 2.x
 Some breaking functionality – e.g. in Ajax calls
 Only version to get new functionality
 Free to use (MIT license)
What is Bootstrap?
 Developed by Twitter
 Open source front-end framework
 Mainly CSS, with some jQuery
 Cross-browser
 Responsive (out-of-the-box in version 3.0+)
 Supports themes, color schemes and plugins
 Available through CDN or as local files
 Many 3rd party resources and plugins
 Current version 3.3.7, version 4 is in early testing
What does Bootstrap look like?
 Attractive look out of the box
 Themes used to modify colors and controls
 Override with your own CSS for customization
 Many free and premium add-ons available
Bootstrap 2 using the theme “United”,
with additional CSS for page curls.
Bootstrap 3 using the default theme.
How do you use jQuery and Bootstrap?
 Link to .js and .css files in HTML header
• Download files locally
• Use CDN for easy linking – my preferred approach
 Start writing your code!
Tips:
 Use // without protocol to use HTTP or HTTPS as needed.
 ViewPort meta tag helps with scaling of page.
 Never edit the Bootstrap CSS file (even if local), always override the CSS.
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Demo 1 - MWLUG 2016</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<link href="demo1.css" rel="stylesheet">
Ajax – Asynchronous Javascript and XML
 Asynchronous – call is processed in background
 Result is passed back when done, then processed
 Data can be returned in different formats:
• XML – original format, rarely used anymore
• JSON –now more common, easy to parse in Javascript
• JSONP – JSON with Padding, when calling other servers
• Can also return plain text or HTML
 Using only a few lines of jQuery code
 Supported as data source directly in many plugins
Ajax call using jQuery
 Arguments passed as JSON
 cache: false – “cache buster”
$.ajax({
url: '/websites/example.nsf/ajax_GetUserDetails?OpenAgent',
data: {name: userName},
cache: false
}).done(function(data) {
// Process returned data here
}).fail(function(e) {
// Process failed call here
}).always(function() {
// This code will always execute
});
or
$.ajax({
url: '/websites/example.nsf/ajax_GetUserDetails?OpenAgent',
data: {name: userName},
cache: false
}).success(function(data) {
// Process returned data here
});
JSON – JavaScript Object Notation
 Describe data as Javascript objects
 Preferred to XML in web applications
• Less “chatty” (less bandwidth)
• Very easy to access values directly in Javascript
 Supports all Javascript data types
 Can contain arrays of objects
 Can be very complex if needed
 Use JSONLint to validate!
JSON Examples
Generate JSON on Domino
 ?ReadViewEntries&OutputFormat=JSON
• Available in Domino 7.0.2+
• Can be hard to parse
 Formula in Notes view
• http://www.eknori.de/2011-07-23/formula-magic/
 Lotusscript agent
• Generate your own JSON
• Test at JSONLint.com
• Use JSON classes
 Class.JSON (available in demo database)
 JSON Lotusscript Classes by Troy Reimer (on OpenNTF.org)
Generate JSON on Domino – Xpages Style
 XPages agent (SSJS XAgent)
• Domino 8.5.2 and XPages knowledge
• Better performance than Lotusscript
• http://www.wissel.net/blog/d6plinks/shwl-7mgfbn
 REST Services control from Extension Library
• Domino 8.5.2 and ExtLib on server
Demo 1
Table using bootstrap-table plugin
Bootstrap-table plugin
 Plugin by @wenzhixin
 Get it at http://bootstrap-table.wenzhixin.net.cn
 CDN hosted version at CloudFlare.com
 Minimal HTML markup
 Javascript mainly to define columns and settings
Bootstrap-table – Add to the webpage
HTML
<div id="tableToolbar">
<div class="toolbarText">My Contacts</div>
</div>
<table id="ContactTable"></table>
jQuery (partial)
$("#ContactTable").bootstrapTable({
url: 'ajax_Demo7_GetAllContacts?OpenAgent',
search: true,
showRefresh: true,
pagination: true,
pageSize: 25,
classes: "table-condensed table-hover table-striped tableContent",
toolbar: "#tableToolbar",
columns: [{
field: 'FirstName',
title: 'First Name',
width: 80,
sortable: true
}, {
field: 'LastName',
title: 'Last Name',
width: 90,
sortable: true
}, {
…
…
…
Bootstrap-table – Generate JSON data
Lotusscript code (partial)
'*** Get all documents in view to process
Set db = session.CurrentDatabase
Set view = db.GetView("(LookupContactsByLastName)")
Set col = view.AllEntries
'*** Start of JSON string
jsonString = “”
'*** Loop through all entries and build JSON to return
Set entry = col.GetFirstEntry
Do Until entry Is Nothing
'*** Build JSON for each entry and add to string
Set json = New JSONData()
Call json.SetValue("LastName", CStr(entry.ColumnValues(0)))
Call json.SetValue("FirstName", CStr(entry.ColumnValues(1)))
Call json.SetValue("Company", CStr(entry.ColumnValues(2)))
Call json.SetValue("Address", CStr(entry.ColumnValues(3)))
Call json.SetValue("City", CStr(entry.ColumnValues(4)))
Call json.SetValue("State", CStr(entry.ColumnValues(5)))
Call json.SetValue("ZIP", CStr(entry.ColumnValues(6)))
Call json.SetValue("DocUNID", CStr(entry.ColumnValues(9)))
'*** Add new JSON to existing JSON string
jsonString = jsonString + json.GetJSON() + "," + Chr$(13)
Set entry = col.GetNextEntry(entry)
Loop
'*** Remove the trailing comma and line break if we have data
If Len(jsonString) > 0 then
jsonString = Left$(jsonString,Len(jsonString)-2)
End If
'*** Add brackets for array
jsonString = "[ " + Chr$(13) + jsonString + Chr$(13) + “ ]“
'*** MIME Header to tell browser what kind of data we will send
Print "content-type: application/json"
'*** Send JSON back to browser
Print jsonString
Bootstrap-table – Examine returned JSON
Bootstrap-table – The Result
Demo 2
Contact database using Bootstrap
Contact database - Overview
 Display contacts – use Demo 1 as base
 Click on user in table to display details
 Buttons
• Edit
• Save
• New
• Delete
 Add refresh/reload of contacts when updated
Contact database – Add elements
 Lotusscript agents
• ajax_GetAllContacts
• ajax_GetContactDetails
• ajax_SaveContact
 If DocUNID is blank, create new contact
 Otherwise update existing contact
• ajax_DeleteContact
 HTML page changes
• Add section for contact details
• Detect click on row to display details
• Add buttons and jQuery code to call Lotusscript agents
HTML – buttons
<button class="btn btn-sm btn-primary" id="btnNewContact">New</button>
<button class="btn btn-sm btn-primary" id="btnEditContact">Edit</button>
<button class="btn btn-sm btn-success" id="btnSaveContact">Save</button>
<button class="btn btn-sm btn-danger pull-right" id="btnDeleteContact">Delete</button>
jQuery – Edit and New buttons
//*** Button actions
$("#btnEditContact").on("click", function(e) {
setEditMode();
});
$("#btnNewContact").on("click", function() {
setEditMode();
// Empty all input fields
$('input[data-notesfield]').each( function() {
$(this).val("");
});
// Empty hidden DocUNID field
$("#docUNID").attr("data-UNID","");
// Hide ‘Delete’ button
$("#btnDeleteContact").hide();
});
Contact database – New buttons
Contact database – New buttons
jQuery – Save button
$("#btnSaveContact").on("click", function() {
$("#btnSaveContact").hide();
var json = new Object();
// Store field values in JSON object
var docunid = $("#docUNID").attr("data-UNID");
json["DocUNID"] = docunid;
$('input[data-notesfield]').each( function() {
var id = $(this).attr("id");
var notesfield = $(this).attr("data-notesfield");
json[notesfield] = $(this).val();
});
// Perform a call to the server to save values
$.ajax({
url: "ajax_Demo8_SaveContact?OpenAgent",
type: "POST",
data: json
}).done(function(data) {
if (data.status=="error") {
alert("Failure: " + data.msg);
} else if (data.status=="success") {
setReadMode(); // Convert INPUT back to DIV
$("#contactTable").bootstrapTable("refresh", {silent: true});
}).fail( function(e) {
alert("Failure!","Failed to save contact. Error: " + e.errorThrown);
});
$("#btnEditContact").show();
});
Contact database – New buttons
jQuery – Delete button
$("#btnDeleteContact").on("click", function(e) {
var docunid = $("#docUNID").attr("data-UNID");
$.ajax({
url: "ajax_Demo8_DeleteContact?OpenAgent",
type: "POST",
data: {DocUNID: docunid }
}).done(function(data) {
if (data.status=="error") {
alert("Failure: " + data.msg);
} else if (data.status=="success") {
$("#contactTable").bootstrapTable("refresh", {silent: true});
// Empty all input fields
$('input[data-notesfield]').each( function() {
$(this).val("");
});
// Empty all div with Notes data
$('div[data-notesfield]').each( function() {
$(this).html("");
});
// Empty hidden DocUNID storage
$("#docUNID").attr("data-UNID","")
$("#btnDeleteContact").hide();
$("#btnEditContact").hide();
}
}).fail( function(e) {
alert("Failure!","Failed to delete contact. Error: " + e.errorThrown);
});
});
Contact database – Detect click on row
jQuery – Detect click on table row
// Detect click on row in table
$("#contactTable").on('click-row.bs.table', function (e, row, $element) {
// Convert INPUT fields back to DIV just in case
setReadMode();
// Hide save button if visible
$("#btnSaveContact").hide();
// Get DocUNID value in table and load corresponding values from server
var unid = row.DocUNID;
displayDetails(unid);
});
Contact database – Load details
jQuery – Load contact details from server and display on page
// Get contact details from Domino server and populate fields
// using the DocUIND value as lookup key
function displayDetails(docunid) {
$.ajax({
url: 'ajax_Demo8_GetContactDetails?OpenAgent',
data: {DocUNID: docunid},
cache: false
}).success(function(data) {
if(data.status=="success") {
// For each element with data-notesfield attribute
$('div[data-notesfield]').each( function() {
notesfield = $(this).attr("data-notesfield");
if (data[notesfield]!=null) {
fieldvalue = data[notesfield];
$(this).html(fieldvalue);
}
});
// Store DocUNID in enmpty div for later use
$("#docUNID").attr("data-UNID",data.DocUNID);
// Display previously hidden editand delete buttons
$("#btnEditContact").show();
$("#btnDeleteContact").show();
}
});
}
Contact database – Fancy stuff
jQuery – Switch between DIV (plan text) and INPUT (editable)
// Put contact details into edit mode by changing DIV to INPUT
function setEditMode() {
$("#btnEditContact").hide();
// Change all div with Notes data to input
$('div[data-notesfield]').each( function() {
var id = $(this).attr("id");
var notesfield = $(this).attr("data-notesfield");
var input = "<input class='jsonData inputNotesField form-control input-sm' id='" + id
input = input + "' data-notesfield='" + notesfield + "' value='" + $(this).html() + "'></input>";
$(this).replaceWith(input)
});
$("#btnSaveContact").show();
$("#btnEditContact").hide();
}
// Put contact details into read mode by changing INPUT to DIV
function setReadMode() {
$('input[data-notesfield]').each( function() {
var id = $(this).attr("id");
var notesfield = $(this).attr("data-notesfield");
var div = "<div class='jsonData displayNotesField' id='" + id
div = div + "' data-notesfield='" + notesfield + "'>" + $(this).val() + "</div>";
$(this).replaceWith(div)
});
}
Contact database
Demo 3
Contact database using jQuery Mobile
jQuery UI and jQuery Mobile
 UI Frameworks
 jQuery UI – alternative to Bootstrap
• Set of components
 Widgets
 Effects
 Interactions
• Built on top of jQuery
 jQuery Mobile – emulates native mobile app look
• Header/footer
• Grid layout
• Buttons
• Listview widget
• Forms
• …and much more!
Contact database – jQuery Mobile
 Reuse agents from previous demo
 New HTML code
• Multi page application with two pages
 Contact list using Listview widget
 Contact details using form elements
 New Javascript/jQuery
• Some code can be reused!
 Notification overlay when saved
• Using notifIt! plugin
• Can use other plugins, many available!
Contact database – Android, iOS, WinMobile
 Create native apps using PhoneGap
 One source, multiple targets
 Create folder structure on disk
• .html, .css and .js
• config.xml in root folder
 Create ZIP file
 Upload to PhoneGap Build
 Download finished apps
• Android
• iOS
• Windows Mobile
Demo 4
Calendar using FullCalendar plugin
FullCalendar plugin
 Get it at http://fullcalendar.io
 Lotusscript agents
• ajax_Calendar_GetAllEvents
 Returning events between specific days
 Calendar automatically sends start and end date
• ajax_Calendar_GetEventDetails
• ajax_Calendar_UpdateEvent
 Triggered when moving event or changing duration
 Arguments: DocUNID, start date and end date
FullCalendar plugin
 Calendar points to JSON of event data
 Automatically sends start and end dates
 Agent returns only events within date range
jQuery – Display calendar and load JSON of event data from server
var eventSource = 'ajax_Calendar_GetAllEvents?OpenAgent';
$("#notesCalendar").fullCalendar({
events: eventSource
});
FullCalendar plugin
Lotusscript agent ajax_Calendar_GetAllEvents
'*** Local variables to hold arguments passed from URL
Dim startdate As String
Dim enddate As String
'*** Other local variables
Dim jsontext As String
'*** Create new URLData object
Set url = New URLData()
'*** Create new JSONData object
Set json = New JSONData()
'*** Check start date and convert from ISO to US date format
If url.IsValue("start") Then
startdate = ISOtoUS(url.GetValue("start"))
Else
startdate = "01/01/1980"
End If
'*** Check end date and convert to US date format
If url.IsValue("end") Then
enddate = ISOtoUS(url.GetValue("end"))
Else
enddate = "12/31/2199"
End If
FullCalendar plugin
Lotusscript agent ajax_Calendar_GetAllEvents (continued)
'*** Send MIME header to browser
Print "content-type: application/json"
jsontext = ""
Set db = session.CurrentDatabase
Set view = db.GetView("Events")
Set col = view.AllEntries
Set entry = col.GetFirstEntry()
Do Until entry Is Nothing
If CDat(entry.ColumnValues(0))>=CDat(startdate) Then
If CDat(entry.ColumnValues(0))<=CDat(enddate) Then
Call json.SetValue("id", CStr(entry.ColumnValues(5)))
Call json.SetValue("title",CStr(entry.ColumnValues(3)))
Call json.SetValue("start", Format$(CDat(entry.ColumnValues(0)),"mm/dd/yyyy hh:nn ampm"))
Call json.SetValue("end", Format$(entry.ColumnValues(1),"mm/dd/yyyy hh:nn ampm"))
'*** Make the entry editable in calendar (allow changing date/time)
Call json.SetBoolean("editable", True)
End If
End If
jsontext = jsontext + json.GetJSON() + "," + Chr$(13)
Set entry = col.GetNextEntry(entry)
Loop
If Len(jsontext)>4 Then
jsontext = Left$(jsontext,Len(jsontext)-2)
End If
Print "[ " + jsontext + " ]"
FullCalendar plugin
FullCalendar plugin – Events triggered on click, resize and drop/move
…
eventClick: function(calEvent, jsEvent, view) {
var unid = calEvent.id;
displayEventDetails(unid);
},
eventResize: function(event, delta, revertFunc) {
if (!confirm(event.title + " will now end at " + event.end.format("h:mm a") + "nAre you sure?")) {
revertFunc();
} else {
var unid = event.id;
updateEvent(unid,event.start.format("MM/DD/YYYY hh:mm a"),event.end.format("MM/DD/YYYY hh:mm a"));
displayEventDetails(unid)
}
},
eventDrop: function(event, delta, revertFunc) {
var prompt = event.title + "<br>was moved to " + event.start.format("MM/DD/YYYY")
prompt = prompt + " at " + event.start.format("h:mm a");
bootbox.confirm(prompt + "<br>Are you sure you want to do that?", function(result) {
if(result==true) {
var unid = event.id;
updateEvent(unid,event.start.format("MM/DD/YYYY hh:mm a"),event.end.format("MM/DD/YYYY hh:mm a"));
displayEventDetails(unid)
} else {
revertFunc();
}
});
}
…
FullCalendar plugin
Javascript code – Send event update to server
function updateEvent(docunid,startDT,endDT) {
var json = new Object();
json["DocUNID"] = docunid;
json["EventStart"] = startDT;
json["EventEnd"] = endDT;
// Perform a call to the server to save new event date/time
$.ajax({
url: "ajax_Calendar_UpdateEvent?OpenAgent",
type: "POST",
data: json
}).done(function(data) {
if (data.status=="error") {
bootstrapAlert(data.msg,"danger");
} else if (data.status=="success") {
bootstrapAlert(data.msg,"success");
}
}).fail( function(e) {
bootstrapAlert("Failed to create progress note. Error: " + e.errorThrown,"danger");
});
}
FullCalendar plugin
Lotusscript agent – ajax_Calendar_UpdateEvent
'--- Local variables
Dim startDate As String
Dim endDate As String
'*** Get document
Set db = session.CurrentDatabase
If url.GetValue("DocUNID")<>"" Then
Set doc = db.GetDocumentByUNID(url.GetValue("DocUNID"))
End If
'*** Check that we found a document, otherwise exit
If doc Is Nothing Then
Set json = New JSONData()
json.success = False
json.SetErrorMsg("Failed to locate document '" & url.GetValue("DocUNID"))
Call json.SendToBrowser()
Exit Sub
End If
Call doc.ReplaceItemValue("EventStart",CDat(url.GetValue("EventStart")))
Call doc.ReplaceItemValue("EventEnd",CDat(url.GetValue("EventEnd")))
Call doc.Save(True,False)
Set json = New JSONData()
json.success = True
json.SetMsg("Updated '" & doc.GetItemValue("EventTitle")(0) & "' with new date/time")
Call json.SendToBrowser()
FullCalendar – End Result
Summary
What have we seen?
 Ajax/JSON – efficient way to access Domino data
 CRUD using server based agents (Lotusscript)
 jQuery and Bootstrap to speed up development
Why learn this?
 Quickly create attractive and modern web applications
 Still access existing Domino data with ease
 Acquire some new and easy-to-learn skills
 Those skills are beneficial on other platforms as well
 Many plugins available for free – less work for you!
 Your customers and/or boss will love you!
Questions?
Thank you!
Karl-Henry Martinsson
Email: texasswede@gmail.com
Twitter, Skype: @texasswede
http://www.linkedin.com/in/texasswede
http://blog.texasswede.com
Ad

More Related Content

What's hot (19)

REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
John Dalsgaard
 
Exciting JavaScript - Part II
Exciting JavaScript - Part IIExciting JavaScript - Part II
Exciting JavaScript - Part II
Eugene Lazutkin
 
Performance Of Web Applications On Client Machines
Performance Of Web Applications On Client MachinesPerformance Of Web Applications On Client Machines
Performance Of Web Applications On Client Machines
Curelet Marius
 
High Performance Ajax Applications
High Performance Ajax ApplicationsHigh Performance Ajax Applications
High Performance Ajax Applications
Julien Lecomte
 
How to Build Real-time Chat App with Express, ReactJS, and Socket.IO?
How to Build Real-time Chat App with Express, ReactJS, and Socket.IO?How to Build Real-time Chat App with Express, ReactJS, and Socket.IO?
How to Build Real-time Chat App with Express, ReactJS, and Socket.IO?
Katy Slemon
 
Server side
Server sideServer side
Server side
philipsinter
 
New Flash Builder 4 WSDL and HTTP Connectors
New Flash Builder 4 WSDL and HTTP ConnectorsNew Flash Builder 4 WSDL and HTTP Connectors
New Flash Builder 4 WSDL and HTTP Connectors
rtretola
 
Krug Fat Client
Krug Fat ClientKrug Fat Client
Krug Fat Client
Paul Klipp
 
Building Faster Websites
Building Faster WebsitesBuilding Faster Websites
Building Faster Websites
Craig Walker
 
Building Your First App with MongoDB
Building Your First App with MongoDBBuilding Your First App with MongoDB
Building Your First App with MongoDB
MongoDB
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. REST
Sam Brannen
 
Improve WordPress performance with caching and deferred execution of code
Improve WordPress performance with caching and deferred execution of codeImprove WordPress performance with caching and deferred execution of code
Improve WordPress performance with caching and deferred execution of code
Danilo Ercoli
 
Asynchronous Web Programming with HTML5 WebSockets and Java
Asynchronous Web Programming with HTML5 WebSockets and JavaAsynchronous Web Programming with HTML5 WebSockets and Java
Asynchronous Web Programming with HTML5 WebSockets and Java
James Falkner
 
WordPress Development Tools and Best Practices
WordPress Development Tools and Best PracticesWordPress Development Tools and Best Practices
WordPress Development Tools and Best Practices
Danilo Ercoli
 
Angular - Chapter 7 - HTTP Services
Angular - Chapter 7 - HTTP ServicesAngular - Chapter 7 - HTTP Services
Angular - Chapter 7 - HTTP Services
WebStackAcademy
 
Mobile Hybrid Development with WordPress
Mobile Hybrid Development with WordPressMobile Hybrid Development with WordPress
Mobile Hybrid Development with WordPress
Danilo Ercoli
 
40+ tips to use Postman more efficiently
40+ tips to use Postman more efficiently40+ tips to use Postman more efficiently
40+ tips to use Postman more efficiently
postmanclient
 
Sherlock Homepage - A detective story about running large web services - NDC ...
Sherlock Homepage - A detective story about running large web services - NDC ...Sherlock Homepage - A detective story about running large web services - NDC ...
Sherlock Homepage - A detective story about running large web services - NDC ...
Maarten Balliauw
 
Interoperable Web Services with JAX-WS and WSIT
Interoperable Web Services with JAX-WS and WSITInteroperable Web Services with JAX-WS and WSIT
Interoperable Web Services with JAX-WS and WSIT
Carol McDonald
 
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
REST services and IBM Domino/XWork - DanNotes 19-20. november 2014
John Dalsgaard
 
Exciting JavaScript - Part II
Exciting JavaScript - Part IIExciting JavaScript - Part II
Exciting JavaScript - Part II
Eugene Lazutkin
 
Performance Of Web Applications On Client Machines
Performance Of Web Applications On Client MachinesPerformance Of Web Applications On Client Machines
Performance Of Web Applications On Client Machines
Curelet Marius
 
High Performance Ajax Applications
High Performance Ajax ApplicationsHigh Performance Ajax Applications
High Performance Ajax Applications
Julien Lecomte
 
How to Build Real-time Chat App with Express, ReactJS, and Socket.IO?
How to Build Real-time Chat App with Express, ReactJS, and Socket.IO?How to Build Real-time Chat App with Express, ReactJS, and Socket.IO?
How to Build Real-time Chat App with Express, ReactJS, and Socket.IO?
Katy Slemon
 
New Flash Builder 4 WSDL and HTTP Connectors
New Flash Builder 4 WSDL and HTTP ConnectorsNew Flash Builder 4 WSDL and HTTP Connectors
New Flash Builder 4 WSDL and HTTP Connectors
rtretola
 
Krug Fat Client
Krug Fat ClientKrug Fat Client
Krug Fat Client
Paul Klipp
 
Building Faster Websites
Building Faster WebsitesBuilding Faster Websites
Building Faster Websites
Craig Walker
 
Building Your First App with MongoDB
Building Your First App with MongoDBBuilding Your First App with MongoDB
Building Your First App with MongoDB
MongoDB
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. REST
Sam Brannen
 
Improve WordPress performance with caching and deferred execution of code
Improve WordPress performance with caching and deferred execution of codeImprove WordPress performance with caching and deferred execution of code
Improve WordPress performance with caching and deferred execution of code
Danilo Ercoli
 
Asynchronous Web Programming with HTML5 WebSockets and Java
Asynchronous Web Programming with HTML5 WebSockets and JavaAsynchronous Web Programming with HTML5 WebSockets and Java
Asynchronous Web Programming with HTML5 WebSockets and Java
James Falkner
 
WordPress Development Tools and Best Practices
WordPress Development Tools and Best PracticesWordPress Development Tools and Best Practices
WordPress Development Tools and Best Practices
Danilo Ercoli
 
Angular - Chapter 7 - HTTP Services
Angular - Chapter 7 - HTTP ServicesAngular - Chapter 7 - HTTP Services
Angular - Chapter 7 - HTTP Services
WebStackAcademy
 
Mobile Hybrid Development with WordPress
Mobile Hybrid Development with WordPressMobile Hybrid Development with WordPress
Mobile Hybrid Development with WordPress
Danilo Ercoli
 
40+ tips to use Postman more efficiently
40+ tips to use Postman more efficiently40+ tips to use Postman more efficiently
40+ tips to use Postman more efficiently
postmanclient
 
Sherlock Homepage - A detective story about running large web services - NDC ...
Sherlock Homepage - A detective story about running large web services - NDC ...Sherlock Homepage - A detective story about running large web services - NDC ...
Sherlock Homepage - A detective story about running large web services - NDC ...
Maarten Balliauw
 
Interoperable Web Services with JAX-WS and WSIT
Interoperable Web Services with JAX-WS and WSITInteroperable Web Services with JAX-WS and WSIT
Interoperable Web Services with JAX-WS and WSIT
Carol McDonald
 

Similar to Break out of The Box - Part 2 (20)

IBM Connect 2016 - Break out of the Box
IBM Connect 2016 - Break out of the BoxIBM Connect 2016 - Break out of the Box
IBM Connect 2016 - Break out of the Box
Karl-Henry Martinsson
 
AD102 - Break out of the Box
AD102 - Break out of the BoxAD102 - Break out of the Box
AD102 - Break out of the Box
Karl-Henry Martinsson
 
Lotus Domino 8.5
Lotus Domino 8.5Lotus Domino 8.5
Lotus Domino 8.5
Lalit Sharma
 
Intro to .NET for Government Developers
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government Developers
Frank La Vigne
 
Internet Explorer 8
Internet Explorer 8Internet Explorer 8
Internet Explorer 8
David Chou
 
.NET7.pptx
.NET7.pptx.NET7.pptx
.NET7.pptx
Udaiappa Ramachandran
 
Building high performing web pages
Building high performing web pagesBuilding high performing web pages
Building high performing web pages
Nilesh Bafna
 
Client Side Performance @ Xero
Client Side Performance @ XeroClient Side Performance @ Xero
Client Side Performance @ Xero
Craig Walker
 
Modern Web Development
Modern Web DevelopmentModern Web Development
Modern Web Development
Robert Nyman
 
How to generate customized java 8 code from your database
How to generate customized java 8 code from your databaseHow to generate customized java 8 code from your database
How to generate customized java 8 code from your database
Speedment, Inc.
 
Silicon Valley JUG - How to generate customized java 8 code from your database
Silicon Valley JUG - How to generate customized java 8 code from your databaseSilicon Valley JUG - How to generate customized java 8 code from your database
Silicon Valley JUG - How to generate customized java 8 code from your database
Speedment, Inc.
 
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
Speedment, Inc.
 
How to JavaOne 2016 - Generate Customized Java 8 Code from Your Database [TUT...
How to JavaOne 2016 - Generate Customized Java 8 Code from Your Database [TUT...How to JavaOne 2016 - Generate Customized Java 8 Code from Your Database [TUT...
How to JavaOne 2016 - Generate Customized Java 8 Code from Your Database [TUT...
Malin Weiss
 
PPT
PPTPPT
PPT
webhostingguy
 
Ajax Performance Tuning and Best Practices
Ajax Performance Tuning and Best PracticesAjax Performance Tuning and Best Practices
Ajax Performance Tuning and Best Practices
Doris Chen
 
JavaScript front end performance optimizations
JavaScript front end performance optimizationsJavaScript front end performance optimizations
JavaScript front end performance optimizations
Chris Love
 
Node.js: The What, The How and The When
Node.js: The What, The How and The WhenNode.js: The What, The How and The When
Node.js: The What, The How and The When
FITC
 
Intro JavaScript
Intro JavaScriptIntro JavaScript
Intro JavaScript
koppenolski
 
Tuning web performance
Tuning web performanceTuning web performance
Tuning web performance
George Ang
 
Scaling asp.net websites to millions of users
Scaling asp.net websites to millions of usersScaling asp.net websites to millions of users
Scaling asp.net websites to millions of users
oazabir
 
IBM Connect 2016 - Break out of the Box
IBM Connect 2016 - Break out of the BoxIBM Connect 2016 - Break out of the Box
IBM Connect 2016 - Break out of the Box
Karl-Henry Martinsson
 
Intro to .NET for Government Developers
Intro to .NET for Government DevelopersIntro to .NET for Government Developers
Intro to .NET for Government Developers
Frank La Vigne
 
Internet Explorer 8
Internet Explorer 8Internet Explorer 8
Internet Explorer 8
David Chou
 
Building high performing web pages
Building high performing web pagesBuilding high performing web pages
Building high performing web pages
Nilesh Bafna
 
Client Side Performance @ Xero
Client Side Performance @ XeroClient Side Performance @ Xero
Client Side Performance @ Xero
Craig Walker
 
Modern Web Development
Modern Web DevelopmentModern Web Development
Modern Web Development
Robert Nyman
 
How to generate customized java 8 code from your database
How to generate customized java 8 code from your databaseHow to generate customized java 8 code from your database
How to generate customized java 8 code from your database
Speedment, Inc.
 
Silicon Valley JUG - How to generate customized java 8 code from your database
Silicon Valley JUG - How to generate customized java 8 code from your databaseSilicon Valley JUG - How to generate customized java 8 code from your database
Silicon Valley JUG - How to generate customized java 8 code from your database
Speedment, Inc.
 
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
JavaOne2016 - How to Generate Customized Java 8 Code from Your Database [TUT4...
Speedment, Inc.
 
How to JavaOne 2016 - Generate Customized Java 8 Code from Your Database [TUT...
How to JavaOne 2016 - Generate Customized Java 8 Code from Your Database [TUT...How to JavaOne 2016 - Generate Customized Java 8 Code from Your Database [TUT...
How to JavaOne 2016 - Generate Customized Java 8 Code from Your Database [TUT...
Malin Weiss
 
Ajax Performance Tuning and Best Practices
Ajax Performance Tuning and Best PracticesAjax Performance Tuning and Best Practices
Ajax Performance Tuning and Best Practices
Doris Chen
 
JavaScript front end performance optimizations
JavaScript front end performance optimizationsJavaScript front end performance optimizations
JavaScript front end performance optimizations
Chris Love
 
Node.js: The What, The How and The When
Node.js: The What, The How and The WhenNode.js: The What, The How and The When
Node.js: The What, The How and The When
FITC
 
Intro JavaScript
Intro JavaScriptIntro JavaScript
Intro JavaScript
koppenolski
 
Tuning web performance
Tuning web performanceTuning web performance
Tuning web performance
George Ang
 
Scaling asp.net websites to millions of users
Scaling asp.net websites to millions of usersScaling asp.net websites to millions of users
Scaling asp.net websites to millions of users
oazabir
 
Ad

Recently uploaded (19)

OSI TCP IP Protocol Layers description f
OSI TCP IP Protocol Layers description fOSI TCP IP Protocol Layers description f
OSI TCP IP Protocol Layers description f
cbr49917
 
APNIC -Policy Development Process, presented at Local APIGA Taiwan 2025
APNIC -Policy Development Process, presented at Local APIGA Taiwan 2025APNIC -Policy Development Process, presented at Local APIGA Taiwan 2025
APNIC -Policy Development Process, presented at Local APIGA Taiwan 2025
APNIC
 
(Hosting PHising Sites) for Cryptography and network security
(Hosting PHising Sites) for Cryptography and network security(Hosting PHising Sites) for Cryptography and network security
(Hosting PHising Sites) for Cryptography and network security
aluacharya169
 
Smart Mobile App Pitch Deck丨AI Travel App Presentation Template
Smart Mobile App Pitch Deck丨AI Travel App Presentation TemplateSmart Mobile App Pitch Deck丨AI Travel App Presentation Template
Smart Mobile App Pitch Deck丨AI Travel App Presentation Template
yojeari421237
 
5-Proses-proses Akuisisi Citra Digital.pptx
5-Proses-proses Akuisisi Citra Digital.pptx5-Proses-proses Akuisisi Citra Digital.pptx
5-Proses-proses Akuisisi Citra Digital.pptx
andani26
 
Top Vancouver Green Business Ideas for 2025 Powered by 4GoodHosting
Top Vancouver Green Business Ideas for 2025 Powered by 4GoodHostingTop Vancouver Green Business Ideas for 2025 Powered by 4GoodHosting
Top Vancouver Green Business Ideas for 2025 Powered by 4GoodHosting
steve198109
 
Best web hosting Vancouver 2025 for you business
Best web hosting Vancouver 2025 for you businessBest web hosting Vancouver 2025 for you business
Best web hosting Vancouver 2025 for you business
steve198109
 
Mobile database for your company telemarketing or sms marketing campaigns. Fr...
Mobile database for your company telemarketing or sms marketing campaigns. Fr...Mobile database for your company telemarketing or sms marketing campaigns. Fr...
Mobile database for your company telemarketing or sms marketing campaigns. Fr...
DataProvider1
 
Computers Networks Computers Networks Computers Networks
Computers Networks Computers Networks Computers NetworksComputers Networks Computers Networks Computers Networks
Computers Networks Computers Networks Computers Networks
Tito208863
 
Understanding the Tor Network and Exploring the Deep Web
Understanding the Tor Network and Exploring the Deep WebUnderstanding the Tor Network and Exploring the Deep Web
Understanding the Tor Network and Exploring the Deep Web
nabilajabin35
 
White and Red Clean Car Business Pitch Presentation.pptx
White and Red Clean Car Business Pitch Presentation.pptxWhite and Red Clean Car Business Pitch Presentation.pptx
White and Red Clean Car Business Pitch Presentation.pptx
canumatown
 
highend-srxseries-services-gateways-customer-presentation.pptx
highend-srxseries-services-gateways-customer-presentation.pptxhighend-srxseries-services-gateways-customer-presentation.pptx
highend-srxseries-services-gateways-customer-presentation.pptx
elhadjcheikhdiop
 
Reliable Vancouver Web Hosting with Local Servers & 24/7 Support
Reliable Vancouver Web Hosting with Local Servers & 24/7 SupportReliable Vancouver Web Hosting with Local Servers & 24/7 Support
Reliable Vancouver Web Hosting with Local Servers & 24/7 Support
steve198109
 
DNS Resolvers and Nameservers (in New Zealand)
DNS Resolvers and Nameservers (in New Zealand)DNS Resolvers and Nameservers (in New Zealand)
DNS Resolvers and Nameservers (in New Zealand)
APNIC
 
Determining Glass is mechanical textile
Determining  Glass is mechanical textileDetermining  Glass is mechanical textile
Determining Glass is mechanical textile
Azizul Hakim
 
project_based_laaaaaaaaaaearning,kelompok 10.pptx
project_based_laaaaaaaaaaearning,kelompok 10.pptxproject_based_laaaaaaaaaaearning,kelompok 10.pptx
project_based_laaaaaaaaaaearning,kelompok 10.pptx
redzuriel13
 
APNIC Update, presented at NZNOG 2025 by Terry Sweetser
APNIC Update, presented at NZNOG 2025 by Terry SweetserAPNIC Update, presented at NZNOG 2025 by Terry Sweetser
APNIC Update, presented at NZNOG 2025 by Terry Sweetser
APNIC
 
IT Services Workflow From Request to Resolution
IT Services Workflow From Request to ResolutionIT Services Workflow From Request to Resolution
IT Services Workflow From Request to Resolution
mzmziiskd
 
Perguntas dos animais - Slides ilustrados de múltipla escolha
Perguntas dos animais - Slides ilustrados de múltipla escolhaPerguntas dos animais - Slides ilustrados de múltipla escolha
Perguntas dos animais - Slides ilustrados de múltipla escolha
socaslev
 
OSI TCP IP Protocol Layers description f
OSI TCP IP Protocol Layers description fOSI TCP IP Protocol Layers description f
OSI TCP IP Protocol Layers description f
cbr49917
 
APNIC -Policy Development Process, presented at Local APIGA Taiwan 2025
APNIC -Policy Development Process, presented at Local APIGA Taiwan 2025APNIC -Policy Development Process, presented at Local APIGA Taiwan 2025
APNIC -Policy Development Process, presented at Local APIGA Taiwan 2025
APNIC
 
(Hosting PHising Sites) for Cryptography and network security
(Hosting PHising Sites) for Cryptography and network security(Hosting PHising Sites) for Cryptography and network security
(Hosting PHising Sites) for Cryptography and network security
aluacharya169
 
Smart Mobile App Pitch Deck丨AI Travel App Presentation Template
Smart Mobile App Pitch Deck丨AI Travel App Presentation TemplateSmart Mobile App Pitch Deck丨AI Travel App Presentation Template
Smart Mobile App Pitch Deck丨AI Travel App Presentation Template
yojeari421237
 
5-Proses-proses Akuisisi Citra Digital.pptx
5-Proses-proses Akuisisi Citra Digital.pptx5-Proses-proses Akuisisi Citra Digital.pptx
5-Proses-proses Akuisisi Citra Digital.pptx
andani26
 
Top Vancouver Green Business Ideas for 2025 Powered by 4GoodHosting
Top Vancouver Green Business Ideas for 2025 Powered by 4GoodHostingTop Vancouver Green Business Ideas for 2025 Powered by 4GoodHosting
Top Vancouver Green Business Ideas for 2025 Powered by 4GoodHosting
steve198109
 
Best web hosting Vancouver 2025 for you business
Best web hosting Vancouver 2025 for you businessBest web hosting Vancouver 2025 for you business
Best web hosting Vancouver 2025 for you business
steve198109
 
Mobile database for your company telemarketing or sms marketing campaigns. Fr...
Mobile database for your company telemarketing or sms marketing campaigns. Fr...Mobile database for your company telemarketing or sms marketing campaigns. Fr...
Mobile database for your company telemarketing or sms marketing campaigns. Fr...
DataProvider1
 
Computers Networks Computers Networks Computers Networks
Computers Networks Computers Networks Computers NetworksComputers Networks Computers Networks Computers Networks
Computers Networks Computers Networks Computers Networks
Tito208863
 
Understanding the Tor Network and Exploring the Deep Web
Understanding the Tor Network and Exploring the Deep WebUnderstanding the Tor Network and Exploring the Deep Web
Understanding the Tor Network and Exploring the Deep Web
nabilajabin35
 
White and Red Clean Car Business Pitch Presentation.pptx
White and Red Clean Car Business Pitch Presentation.pptxWhite and Red Clean Car Business Pitch Presentation.pptx
White and Red Clean Car Business Pitch Presentation.pptx
canumatown
 
highend-srxseries-services-gateways-customer-presentation.pptx
highend-srxseries-services-gateways-customer-presentation.pptxhighend-srxseries-services-gateways-customer-presentation.pptx
highend-srxseries-services-gateways-customer-presentation.pptx
elhadjcheikhdiop
 
Reliable Vancouver Web Hosting with Local Servers & 24/7 Support
Reliable Vancouver Web Hosting with Local Servers & 24/7 SupportReliable Vancouver Web Hosting with Local Servers & 24/7 Support
Reliable Vancouver Web Hosting with Local Servers & 24/7 Support
steve198109
 
DNS Resolvers and Nameservers (in New Zealand)
DNS Resolvers and Nameservers (in New Zealand)DNS Resolvers and Nameservers (in New Zealand)
DNS Resolvers and Nameservers (in New Zealand)
APNIC
 
Determining Glass is mechanical textile
Determining  Glass is mechanical textileDetermining  Glass is mechanical textile
Determining Glass is mechanical textile
Azizul Hakim
 
project_based_laaaaaaaaaaearning,kelompok 10.pptx
project_based_laaaaaaaaaaearning,kelompok 10.pptxproject_based_laaaaaaaaaaearning,kelompok 10.pptx
project_based_laaaaaaaaaaearning,kelompok 10.pptx
redzuriel13
 
APNIC Update, presented at NZNOG 2025 by Terry Sweetser
APNIC Update, presented at NZNOG 2025 by Terry SweetserAPNIC Update, presented at NZNOG 2025 by Terry Sweetser
APNIC Update, presented at NZNOG 2025 by Terry Sweetser
APNIC
 
IT Services Workflow From Request to Resolution
IT Services Workflow From Request to ResolutionIT Services Workflow From Request to Resolution
IT Services Workflow From Request to Resolution
mzmziiskd
 
Perguntas dos animais - Slides ilustrados de múltipla escolha
Perguntas dos animais - Slides ilustrados de múltipla escolhaPerguntas dos animais - Slides ilustrados de múltipla escolha
Perguntas dos animais - Slides ilustrados de múltipla escolha
socaslev
 
Ad

Break out of The Box - Part 2

  • 1. Break out of The Box – Part 2 Integrate existing Domino Data with modern websites Karl-Henry Martinsson Demand Better Solutions, LLC
  • 2. I AM...  Swede living in Dallas, TX  Developer at Demand Better Solutions, LLC  Programming since 1982  Web developer since 1994  Notes/Domino developer since 1996  IBM Champion since 2014 http://www.demandbettersolutions.com http://www.texasswede.com http://blog.texasswede.com
  • 3. My Story  Old infrastructure • Domino 8.5.2 server and Notes 8.5.2 Basic client  Company unwilling to upgrade • Memory requirements for Standard client • Citrix environment – limited memory available • Upper management thinks Notes/Domino is legacy  Management requests • New web applications with modern look-and-feel • Future mobile support (phone/tablet)
  • 4. Bootstrap and jQuery to the Rescue!
  • 5. Why Not Xpages?  Infrastructure not supporting XPages (Domino 8.5)  No XPages development skills  Tight deadline – no time to learn  Better control of versions – not having to wait for IBM  Access to frameworks not yet in Domino (e.g. jQuery)  Use time-saving jQuery/Bootstrap plugins
  • 6. Why Integrate?  Limited or no migration options  Desire to modernize front-end  Code re-use  Take advantage of the power of Domino  Use existing skillset (Domino, Lotusscript)  Learn valuable new skills (Javascript/jQuery/Ajax)  No one will know you are using a Domino backend!
  • 7. How does it work? .NSF  HTML and CSS  jQuery (Javascript)  Choice of framework • Bootstrap • jQuery UI / jQuery Mobile • and many other...  Process Ajax from browser  Generate and return JSON • Lotusscript agents • XPages agents • ?ReadViewEntries • ExtLib REST Service control Ajax call JSON data
  • 8. Server – IBM Domino  Lotusscript agents  NSF databases  Existing business logic  Can use existing classes and script libraries Works on Domino version 5.0 and higher Update to recent version highly recommended
  • 9. Where does everything live?  HTML pages, CSS files and Javascript • Notes page element • Notes resources • CDN (.js and .css) • Server file system – in Data/Domino/HTML • Another web server  Lotusscript agents • .NSF database on Domino server
  • 10. Development Tools  Domino Designer  Browser with Dev Tools • Firefox with Firebug plugin • Internet Explorer Developer Tools (built-in) • Chrome Developer Tools (built-in)  Online resources • JSONLint • Stack Overflow • Google Search
  • 11. What is jQuery?  Fast, small and feature rich Javascript library  Simplify using Javascript on a web page  Available as CDN and as downloaded local files  Three code streams: • jQuery 1.x  Supporting all browsers • jQuery 2.x  Removed support for IE 8 and earlier  Smaller and faster • jQuery 3.x  Continuation of jQuery 2.x  Some breaking functionality – e.g. in Ajax calls  Only version to get new functionality  Free to use (MIT license)
  • 12. What is Bootstrap?  Developed by Twitter  Open source front-end framework  Mainly CSS, with some jQuery  Cross-browser  Responsive (out-of-the-box in version 3.0+)  Supports themes, color schemes and plugins  Available through CDN or as local files  Many 3rd party resources and plugins  Current version 3.3.7, version 4 is in early testing
  • 13. What does Bootstrap look like?  Attractive look out of the box  Themes used to modify colors and controls  Override with your own CSS for customization  Many free and premium add-ons available Bootstrap 2 using the theme “United”, with additional CSS for page curls. Bootstrap 3 using the default theme.
  • 14. How do you use jQuery and Bootstrap?  Link to .js and .css files in HTML header • Download files locally • Use CDN for easy linking – my preferred approach  Start writing your code! Tips:  Use // without protocol to use HTTP or HTTPS as needed.  ViewPort meta tag helps with scaling of page.  Never edit the Bootstrap CSS file (even if local), always override the CSS. <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Demo 1 - MWLUG 2016</title> <script src="//ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> <link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"> <link href="demo1.css" rel="stylesheet">
  • 15. Ajax – Asynchronous Javascript and XML  Asynchronous – call is processed in background  Result is passed back when done, then processed  Data can be returned in different formats: • XML – original format, rarely used anymore • JSON –now more common, easy to parse in Javascript • JSONP – JSON with Padding, when calling other servers • Can also return plain text or HTML  Using only a few lines of jQuery code  Supported as data source directly in many plugins
  • 16. Ajax call using jQuery  Arguments passed as JSON  cache: false – “cache buster” $.ajax({ url: '/websites/example.nsf/ajax_GetUserDetails?OpenAgent', data: {name: userName}, cache: false }).done(function(data) { // Process returned data here }).fail(function(e) { // Process failed call here }).always(function() { // This code will always execute }); or $.ajax({ url: '/websites/example.nsf/ajax_GetUserDetails?OpenAgent', data: {name: userName}, cache: false }).success(function(data) { // Process returned data here });
  • 17. JSON – JavaScript Object Notation  Describe data as Javascript objects  Preferred to XML in web applications • Less “chatty” (less bandwidth) • Very easy to access values directly in Javascript  Supports all Javascript data types  Can contain arrays of objects  Can be very complex if needed  Use JSONLint to validate!
  • 19. Generate JSON on Domino  ?ReadViewEntries&OutputFormat=JSON • Available in Domino 7.0.2+ • Can be hard to parse  Formula in Notes view • http://www.eknori.de/2011-07-23/formula-magic/  Lotusscript agent • Generate your own JSON • Test at JSONLint.com • Use JSON classes  Class.JSON (available in demo database)  JSON Lotusscript Classes by Troy Reimer (on OpenNTF.org)
  • 20. Generate JSON on Domino – Xpages Style  XPages agent (SSJS XAgent) • Domino 8.5.2 and XPages knowledge • Better performance than Lotusscript • http://www.wissel.net/blog/d6plinks/shwl-7mgfbn  REST Services control from Extension Library • Domino 8.5.2 and ExtLib on server
  • 21. Demo 1 Table using bootstrap-table plugin
  • 22. Bootstrap-table plugin  Plugin by @wenzhixin  Get it at http://bootstrap-table.wenzhixin.net.cn  CDN hosted version at CloudFlare.com  Minimal HTML markup  Javascript mainly to define columns and settings
  • 23. Bootstrap-table – Add to the webpage HTML <div id="tableToolbar"> <div class="toolbarText">My Contacts</div> </div> <table id="ContactTable"></table> jQuery (partial) $("#ContactTable").bootstrapTable({ url: 'ajax_Demo7_GetAllContacts?OpenAgent', search: true, showRefresh: true, pagination: true, pageSize: 25, classes: "table-condensed table-hover table-striped tableContent", toolbar: "#tableToolbar", columns: [{ field: 'FirstName', title: 'First Name', width: 80, sortable: true }, { field: 'LastName', title: 'Last Name', width: 90, sortable: true }, { … … …
  • 24. Bootstrap-table – Generate JSON data Lotusscript code (partial) '*** Get all documents in view to process Set db = session.CurrentDatabase Set view = db.GetView("(LookupContactsByLastName)") Set col = view.AllEntries '*** Start of JSON string jsonString = “” '*** Loop through all entries and build JSON to return Set entry = col.GetFirstEntry Do Until entry Is Nothing '*** Build JSON for each entry and add to string Set json = New JSONData() Call json.SetValue("LastName", CStr(entry.ColumnValues(0))) Call json.SetValue("FirstName", CStr(entry.ColumnValues(1))) Call json.SetValue("Company", CStr(entry.ColumnValues(2))) Call json.SetValue("Address", CStr(entry.ColumnValues(3))) Call json.SetValue("City", CStr(entry.ColumnValues(4))) Call json.SetValue("State", CStr(entry.ColumnValues(5))) Call json.SetValue("ZIP", CStr(entry.ColumnValues(6))) Call json.SetValue("DocUNID", CStr(entry.ColumnValues(9))) '*** Add new JSON to existing JSON string jsonString = jsonString + json.GetJSON() + "," + Chr$(13) Set entry = col.GetNextEntry(entry) Loop '*** Remove the trailing comma and line break if we have data If Len(jsonString) > 0 then jsonString = Left$(jsonString,Len(jsonString)-2) End If '*** Add brackets for array jsonString = "[ " + Chr$(13) + jsonString + Chr$(13) + “ ]“ '*** MIME Header to tell browser what kind of data we will send Print "content-type: application/json" '*** Send JSON back to browser Print jsonString
  • 27. Demo 2 Contact database using Bootstrap
  • 28. Contact database - Overview  Display contacts – use Demo 1 as base  Click on user in table to display details  Buttons • Edit • Save • New • Delete  Add refresh/reload of contacts when updated
  • 29. Contact database – Add elements  Lotusscript agents • ajax_GetAllContacts • ajax_GetContactDetails • ajax_SaveContact  If DocUNID is blank, create new contact  Otherwise update existing contact • ajax_DeleteContact  HTML page changes • Add section for contact details • Detect click on row to display details • Add buttons and jQuery code to call Lotusscript agents
  • 30. HTML – buttons <button class="btn btn-sm btn-primary" id="btnNewContact">New</button> <button class="btn btn-sm btn-primary" id="btnEditContact">Edit</button> <button class="btn btn-sm btn-success" id="btnSaveContact">Save</button> <button class="btn btn-sm btn-danger pull-right" id="btnDeleteContact">Delete</button> jQuery – Edit and New buttons //*** Button actions $("#btnEditContact").on("click", function(e) { setEditMode(); }); $("#btnNewContact").on("click", function() { setEditMode(); // Empty all input fields $('input[data-notesfield]').each( function() { $(this).val(""); }); // Empty hidden DocUNID field $("#docUNID").attr("data-UNID",""); // Hide ‘Delete’ button $("#btnDeleteContact").hide(); }); Contact database – New buttons
  • 31. Contact database – New buttons jQuery – Save button $("#btnSaveContact").on("click", function() { $("#btnSaveContact").hide(); var json = new Object(); // Store field values in JSON object var docunid = $("#docUNID").attr("data-UNID"); json["DocUNID"] = docunid; $('input[data-notesfield]').each( function() { var id = $(this).attr("id"); var notesfield = $(this).attr("data-notesfield"); json[notesfield] = $(this).val(); }); // Perform a call to the server to save values $.ajax({ url: "ajax_Demo8_SaveContact?OpenAgent", type: "POST", data: json }).done(function(data) { if (data.status=="error") { alert("Failure: " + data.msg); } else if (data.status=="success") { setReadMode(); // Convert INPUT back to DIV $("#contactTable").bootstrapTable("refresh", {silent: true}); }).fail( function(e) { alert("Failure!","Failed to save contact. Error: " + e.errorThrown); }); $("#btnEditContact").show(); });
  • 32. Contact database – New buttons jQuery – Delete button $("#btnDeleteContact").on("click", function(e) { var docunid = $("#docUNID").attr("data-UNID"); $.ajax({ url: "ajax_Demo8_DeleteContact?OpenAgent", type: "POST", data: {DocUNID: docunid } }).done(function(data) { if (data.status=="error") { alert("Failure: " + data.msg); } else if (data.status=="success") { $("#contactTable").bootstrapTable("refresh", {silent: true}); // Empty all input fields $('input[data-notesfield]').each( function() { $(this).val(""); }); // Empty all div with Notes data $('div[data-notesfield]').each( function() { $(this).html(""); }); // Empty hidden DocUNID storage $("#docUNID").attr("data-UNID","") $("#btnDeleteContact").hide(); $("#btnEditContact").hide(); } }).fail( function(e) { alert("Failure!","Failed to delete contact. Error: " + e.errorThrown); }); });
  • 33. Contact database – Detect click on row jQuery – Detect click on table row // Detect click on row in table $("#contactTable").on('click-row.bs.table', function (e, row, $element) { // Convert INPUT fields back to DIV just in case setReadMode(); // Hide save button if visible $("#btnSaveContact").hide(); // Get DocUNID value in table and load corresponding values from server var unid = row.DocUNID; displayDetails(unid); });
  • 34. Contact database – Load details jQuery – Load contact details from server and display on page // Get contact details from Domino server and populate fields // using the DocUIND value as lookup key function displayDetails(docunid) { $.ajax({ url: 'ajax_Demo8_GetContactDetails?OpenAgent', data: {DocUNID: docunid}, cache: false }).success(function(data) { if(data.status=="success") { // For each element with data-notesfield attribute $('div[data-notesfield]').each( function() { notesfield = $(this).attr("data-notesfield"); if (data[notesfield]!=null) { fieldvalue = data[notesfield]; $(this).html(fieldvalue); } }); // Store DocUNID in enmpty div for later use $("#docUNID").attr("data-UNID",data.DocUNID); // Display previously hidden editand delete buttons $("#btnEditContact").show(); $("#btnDeleteContact").show(); } }); }
  • 35. Contact database – Fancy stuff jQuery – Switch between DIV (plan text) and INPUT (editable) // Put contact details into edit mode by changing DIV to INPUT function setEditMode() { $("#btnEditContact").hide(); // Change all div with Notes data to input $('div[data-notesfield]').each( function() { var id = $(this).attr("id"); var notesfield = $(this).attr("data-notesfield"); var input = "<input class='jsonData inputNotesField form-control input-sm' id='" + id input = input + "' data-notesfield='" + notesfield + "' value='" + $(this).html() + "'></input>"; $(this).replaceWith(input) }); $("#btnSaveContact").show(); $("#btnEditContact").hide(); } // Put contact details into read mode by changing INPUT to DIV function setReadMode() { $('input[data-notesfield]').each( function() { var id = $(this).attr("id"); var notesfield = $(this).attr("data-notesfield"); var div = "<div class='jsonData displayNotesField' id='" + id div = div + "' data-notesfield='" + notesfield + "'>" + $(this).val() + "</div>"; $(this).replaceWith(div) }); }
  • 37. Demo 3 Contact database using jQuery Mobile
  • 38. jQuery UI and jQuery Mobile  UI Frameworks  jQuery UI – alternative to Bootstrap • Set of components  Widgets  Effects  Interactions • Built on top of jQuery  jQuery Mobile – emulates native mobile app look • Header/footer • Grid layout • Buttons • Listview widget • Forms • …and much more!
  • 39. Contact database – jQuery Mobile  Reuse agents from previous demo  New HTML code • Multi page application with two pages  Contact list using Listview widget  Contact details using form elements  New Javascript/jQuery • Some code can be reused!  Notification overlay when saved • Using notifIt! plugin • Can use other plugins, many available!
  • 40. Contact database – Android, iOS, WinMobile  Create native apps using PhoneGap  One source, multiple targets  Create folder structure on disk • .html, .css and .js • config.xml in root folder  Create ZIP file  Upload to PhoneGap Build  Download finished apps • Android • iOS • Windows Mobile
  • 41. Demo 4 Calendar using FullCalendar plugin
  • 42. FullCalendar plugin  Get it at http://fullcalendar.io  Lotusscript agents • ajax_Calendar_GetAllEvents  Returning events between specific days  Calendar automatically sends start and end date • ajax_Calendar_GetEventDetails • ajax_Calendar_UpdateEvent  Triggered when moving event or changing duration  Arguments: DocUNID, start date and end date
  • 43. FullCalendar plugin  Calendar points to JSON of event data  Automatically sends start and end dates  Agent returns only events within date range jQuery – Display calendar and load JSON of event data from server var eventSource = 'ajax_Calendar_GetAllEvents?OpenAgent'; $("#notesCalendar").fullCalendar({ events: eventSource });
  • 44. FullCalendar plugin Lotusscript agent ajax_Calendar_GetAllEvents '*** Local variables to hold arguments passed from URL Dim startdate As String Dim enddate As String '*** Other local variables Dim jsontext As String '*** Create new URLData object Set url = New URLData() '*** Create new JSONData object Set json = New JSONData() '*** Check start date and convert from ISO to US date format If url.IsValue("start") Then startdate = ISOtoUS(url.GetValue("start")) Else startdate = "01/01/1980" End If '*** Check end date and convert to US date format If url.IsValue("end") Then enddate = ISOtoUS(url.GetValue("end")) Else enddate = "12/31/2199" End If
  • 45. FullCalendar plugin Lotusscript agent ajax_Calendar_GetAllEvents (continued) '*** Send MIME header to browser Print "content-type: application/json" jsontext = "" Set db = session.CurrentDatabase Set view = db.GetView("Events") Set col = view.AllEntries Set entry = col.GetFirstEntry() Do Until entry Is Nothing If CDat(entry.ColumnValues(0))>=CDat(startdate) Then If CDat(entry.ColumnValues(0))<=CDat(enddate) Then Call json.SetValue("id", CStr(entry.ColumnValues(5))) Call json.SetValue("title",CStr(entry.ColumnValues(3))) Call json.SetValue("start", Format$(CDat(entry.ColumnValues(0)),"mm/dd/yyyy hh:nn ampm")) Call json.SetValue("end", Format$(entry.ColumnValues(1),"mm/dd/yyyy hh:nn ampm")) '*** Make the entry editable in calendar (allow changing date/time) Call json.SetBoolean("editable", True) End If End If jsontext = jsontext + json.GetJSON() + "," + Chr$(13) Set entry = col.GetNextEntry(entry) Loop If Len(jsontext)>4 Then jsontext = Left$(jsontext,Len(jsontext)-2) End If Print "[ " + jsontext + " ]"
  • 46. FullCalendar plugin FullCalendar plugin – Events triggered on click, resize and drop/move … eventClick: function(calEvent, jsEvent, view) { var unid = calEvent.id; displayEventDetails(unid); }, eventResize: function(event, delta, revertFunc) { if (!confirm(event.title + " will now end at " + event.end.format("h:mm a") + "nAre you sure?")) { revertFunc(); } else { var unid = event.id; updateEvent(unid,event.start.format("MM/DD/YYYY hh:mm a"),event.end.format("MM/DD/YYYY hh:mm a")); displayEventDetails(unid) } }, eventDrop: function(event, delta, revertFunc) { var prompt = event.title + "<br>was moved to " + event.start.format("MM/DD/YYYY") prompt = prompt + " at " + event.start.format("h:mm a"); bootbox.confirm(prompt + "<br>Are you sure you want to do that?", function(result) { if(result==true) { var unid = event.id; updateEvent(unid,event.start.format("MM/DD/YYYY hh:mm a"),event.end.format("MM/DD/YYYY hh:mm a")); displayEventDetails(unid) } else { revertFunc(); } }); } …
  • 47. FullCalendar plugin Javascript code – Send event update to server function updateEvent(docunid,startDT,endDT) { var json = new Object(); json["DocUNID"] = docunid; json["EventStart"] = startDT; json["EventEnd"] = endDT; // Perform a call to the server to save new event date/time $.ajax({ url: "ajax_Calendar_UpdateEvent?OpenAgent", type: "POST", data: json }).done(function(data) { if (data.status=="error") { bootstrapAlert(data.msg,"danger"); } else if (data.status=="success") { bootstrapAlert(data.msg,"success"); } }).fail( function(e) { bootstrapAlert("Failed to create progress note. Error: " + e.errorThrown,"danger"); }); }
  • 48. FullCalendar plugin Lotusscript agent – ajax_Calendar_UpdateEvent '--- Local variables Dim startDate As String Dim endDate As String '*** Get document Set db = session.CurrentDatabase If url.GetValue("DocUNID")<>"" Then Set doc = db.GetDocumentByUNID(url.GetValue("DocUNID")) End If '*** Check that we found a document, otherwise exit If doc Is Nothing Then Set json = New JSONData() json.success = False json.SetErrorMsg("Failed to locate document '" & url.GetValue("DocUNID")) Call json.SendToBrowser() Exit Sub End If Call doc.ReplaceItemValue("EventStart",CDat(url.GetValue("EventStart"))) Call doc.ReplaceItemValue("EventEnd",CDat(url.GetValue("EventEnd"))) Call doc.Save(True,False) Set json = New JSONData() json.success = True json.SetMsg("Updated '" & doc.GetItemValue("EventTitle")(0) & "' with new date/time") Call json.SendToBrowser()
  • 51. What have we seen?  Ajax/JSON – efficient way to access Domino data  CRUD using server based agents (Lotusscript)  jQuery and Bootstrap to speed up development Why learn this?  Quickly create attractive and modern web applications  Still access existing Domino data with ease  Acquire some new and easy-to-learn skills  Those skills are beneficial on other platforms as well  Many plugins available for free – less work for you!  Your customers and/or boss will love you!
  • 53. Thank you! Karl-Henry Martinsson Email: [email protected] Twitter, Skype: @texasswede http://www.linkedin.com/in/texasswede http://blog.texasswede.com

Editor's Notes

  • #48: When clicking on a calendar event, we want to display the details about the event, like title, description, location, etc. The function displayEventDetails() is very similar to the one in previous example and the agent called is almost identical, so we will not spend any time on it. The eventResize and eventDrop actions are more interesting. I have added two different ways to ask the user to confirm the change. Resize is using a Javascript confirmation box, a regular browser-generated dialog box with OK and Cancel buttons. Drop is using bootbox, a Bootstrap plugin to display pretty dialog and message boxes that matches the Bootstrap look. In both cases, if the user decides that it was a mistake, the revertFunc() function – a function in FullCalendar – is called to revert to the original values.
  • #49: When clicking on a calendar event, we want to display the details about the event, like title, description, location, etc. The function displayEventDetails() is very similar to the one in previous example and the agent called is almost identical, so we will not spend any time on it. The eventResize and eventDrop actions are more interesting. I have added two different ways to ask the user to confirm the change. Resize is using a Javascript confirmation box, a regular browser-generated dialog box with OK and Cancel buttons. Drop is using bootbox, a Bootstrap plugin to display pretty dialog and message boxes that matches the Bootstrap look. In both cases, if the user decides that it was a mistake, the revertFunc() function – a function in FullCalendar – is called to revert to the original values.
  • #50: When clicking on a calendar event, we want to display the details about the event, like title, description, location, etc. The function displayEventDetails() is very similar to the one in previous example and the agent called is almost identical, so we will not spend any time on it. The eventResize and eventDrop actions are more interesting. I have added two different ways to ask the user to confirm the change. Resize is using a Javascript confirmation box, a regular browser-generated dialog box with OK and Cancel buttons. Drop is using bootbox, a Bootstrap plugin to display pretty dialog and message boxes that matches the Bootstrap look. In both cases, if the user decides that it was a mistake, the revertFunc() function – a function in FullCalendar – is called to revert to the original values.