This tutorial will showcase a simple NotesDocument auto-save engine for an example NotesDatabase using the Domino CRUD API. The desired user experience will have the user's non-submitted NotesDocument auto-save after an admin-defined interval. To ensure a seamless user experience, I will continually - via a JavaScript timer - submit the "uidoc" via HTTP POST through AJAX to the Domino CRUD API to create (or update) a "temp" NotesDocument. We will create a custom response message to the HTTP POST and return the "temp" NotesDocument Unique ID (UNID), which we will use to update the "uidoc" HTML Form Processing Agent.
Prerequisites
There are several prerequisite technologies, development environment considerations, and a few things you should be aware of before beginning the tutorial.
- Lotus Domino Application Server (Release 6.5 or later).
- Lotus Domino Designer (Release 6.5 or later).
- Understanding the Domino CRUD API
Understanding the Domino CRUD API - the Basics (http://www.dominoguru.com/pages/crud_1.html)
Understanding the Domino CRUD API - $$Return Basics (http://www.dominoguru.com/pages/crud_2.html)
Understanding the Domino CRUD API: $$Return and Smart Landing Pages (http://www.dominoguru.com/pages/crud_3.html)
Understanding the Domino CRUD API: non-Domino Form CRUD Basics - Part 1 (http://www.dominoguru.com/pages/crud_4.html)
System requirements
To view the demos included in this tutorial, JavaScript must be enabled in your browser and Macromedia Flash Player 6 or higher must be installed. You can download the latest Flash Player at http://www.macromedia.com/go/getflashplayer/.
NotesDatabase Build
Page Design Elements
To create a visual container for the example Domino Web Application, I will create the following Page Design Elements:
index.html
editor.html
UNID
The index.html Page Design Element will act as the Default Launch Object for our Domino Web-Enabled NotesDatabase. It will also act as the redirect location for our editor.html HTML Form Element after a successful HTTP POST. This Page Design Element will contain an embedded View Design Element as well as various Computed Text instances to complete the dashboard-like user experience.
The editor.html Page Design Element will house the HTML Form Element used to submit our document NotesDocument to the Domino CRUD API. I will discuss the HTML Field Elements further in the tutorial, and this HTML Form Element will both contain the title and body HTML Field Elements designed to the referenced "Understanding the Domino CRUD API: non-Domino Form CRUD Basics - Part 1" article in the Prerequisites section of this tutorial.
Simply put: editor.html will create a new NotesDocument while editor.html?open&UNID= will populate the HTML Form Element Fields and Processing Agent with NotesDocument data.
The UNID Page Design Element - Content Type text/plain - will act as the Smart Landing Page post-HTTP POST Submission of our temp Form Design Element. This will make sense further in this tutorial.
Form Design Elements
I will create two forms to handle our Domino CRUD API calls:
document
temp
Since both of these Form Design Elements will house like-content Fields, we will create and include a Subform Design Element named notesitems, which will house the following Editable Text Fields:
title
body
To handle each HTTP POST to the temp and document Form Design Elements, I will add a unique $$Return Computed For Display Field.
The document Form Design Element's $$Return Computed For Display Field will contain the following Formula:
"[http://" + @GetHTTPHeader("HOST") + "/" + @WebDbName + "/index.html]"
The temp Form Design Element's $$Return Computed For Display Field will contain the following Formula:
"[http://" + @GetHTTPHeader("HOST") + "/" + @WebDbName + "/UNID?Open&UNID=" + @Text(@DocumentUniqueID) + "]"
Post-successful HTTP POST Submission to the Domino CRUD API, the document $$Return will return the user to the index.html Page Design Element. This is a fairly standard user experience, and something that I will maintain in the example Domino Web-Enabled NotesDatabase.
Post-successful HTTP POST Submission to the Domino CRUD API, the temp $$Return will return the user to the UNID Page Design Element and pass a Query String parameter of UNID with the submitted NotesDocument Unique ID as the value. I will use this returned NotesDocument Unique ID for the Auto-Save engine, but first will confirm the HTML Form functionality.
Once I have confirmed that our edit.html Page Design Element can create and update NotesDocuments via the Domino CRUD API, I will add the Auto-Save feature to the HTML Form.
Script Libraries
I have chosen to keep things simple, and thus have written the entire auto-save function into a single Script Library Design Element named autosave.js. Consisting of a mere 6 JavaScript functions, autosave.js is an extremely straight-forward and easy to understand construct. To really showcase just how simple it is to leverage the Domino CRUD API in combination with custom Domino Web Development to achieve more advanced functionality, I opted to include JavaScript functions that I found via internet searches.
I will detail each JavaScript function in the autosave.js below:
function trim(stringToTrim) {
return stringToTrim.replace(/^\s+|\s+$/g,"");
}
The trim() function is used on the returned NotesDocument Universal ID to ensure that there are no trailing spaces retrieved from the UNID Form Design Element. Certain browsers, such as Google Chrome, would append a non-breaking space at the end of the returned value, which would cause the NotesDocument Auto-Save engine to fail. The trim() function quickly addresses the cross-browser compatability issues I ran into with the build.
var http_request = false;
function makePOSTRequest(url, parameters) {
http_request = false;
if (window.XMLHttpRequest) { Mozilla, Safari,...
http_request = new XMLHttpRequest();
if (http_request.overrideMimeType) {
set type accordingly to anticipated content type
http_request.overrideMimeType('text/xml');
http_request.overrideMimeType('text/html');
}
} else if (window.ActiveXObject) { IE
try {
http_request = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
http_request = new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {}
}
}
if (!http_request) {
alert('Cannot create XMLHTTP instance');
return false;
}
http_request.onreadystatechange = alertContents;
http_request.open('POST', url, true);
http_request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
http_request.setRequestHeader("Content-length", parameters.length);
http_request.setRequestHeader("Connection", "close");
http_request.send(parameters);
}
A very basic AJAX-style JavaScript function, makePostRequest() handles the AJAX HTTP POST submission of the NotesDocument to the Domino CRUD API.
function alertContents() {
if (http_request.readyState == 4) {
if (http_request.status == 200) {
result = http_request.responseText;
document.getElementById('UNID').value = trim(result);
} else {
alert('There was a problem with the request.');
}
}
}
The alertContents() function is simply an extended handler function for the AJAX HTTP POST response.
function save() {
var poststr = "title=" + encodeURI( document.getElementById("title").value ) + "&body=" + encodeURI( document.getElementById("body").value );
var UNID = document.getElementById('UNID').value;
if (UNID == "") {
var URL = 'temp?createdocument';
} else {
var URL = '0/' + UNID + '?SaveDocument';
}
makePOSTRequest(URL, poststr);
}
This save() function pulls the HTML Field values from the editor.html HTML Form Element, checks the value of the UNID HTML Field to see if it will create or update via the Domino CRUD API, and submits the HTML Form Element contents to the desired URL. This is the NotesDocument Auto-Save, and is purposefully written as simply as possible; thus illustrating the power and flexibility of the IBM Lotus Domino development platform.
function validate(obj) {
var UNID = document.getElementById('UNID').value;
if (UNID == "") {
return true;
} else {
obj.action = 'documents/' + UNID + '?SaveDocument';
}
}
The validate() function is used - in the NotesDocument Auto-Save Example Domino Web Application - in the editor.html HTML Form Element's onsubmit event. Checking the value of the UNID HTML Field, the application logic states that if this field value is blank, then you area submitting a new NotesDocument - thus proceed with said HTML Form Element's Processing Agent. If UNID is populated, I first change the HTML Form Element (passed into the function as obj) Processing Agent to submit the NotesDocument to 'documents/' + UNID + '?SaveDocument'.
function autosave(flag) {
if (flag) {
asTimer = setInterval ( "save()", 5000 );
} else {
clearTimeout ( asTimer );
}
}
The last function - autosave() - is specific to the example; I wanted to provide the user with the ability to enable or disable the NotesDocument Auto-Save feature on the editor.html HTML Form Element. In the example, I call the save() function every 5 seconds once the user has enabled the NotesDocument Auto-Save feature. Once disabled, I simply terminate the repeated call.
View Design Elements
The save() and validate() JavaScript functions both show the usage of the Update State of the Domino CRUD API. Each function either calls an existing View Design Element (documents/) or a non-existing View Design Element (0/).The reason for this is simple: View Design Element Form Formulas and the Domino CRUD API.
If I create a NotesDocument via the Domino CRUD API based on the following criteria, I will get the following result:
temp?CreateDocument A new NotesDocument with a NotesItem named "Form" containing the value temp.
document?CreateDocument A new NotesDocument with a NotesItem named "Form" containing the value document.
0/?SaveDocument An updated NotesDocument, maintaining the NotesItem "Form" value.
documents/?SaveDocument An updated NotesDocument, updating the NotesItem named "Form" with the value defined in the View Design Element's Form Formula.
The documents View Design Element is used by the NotesDocument Auto-Save Example Domino Web Application to change the value of the temp NotesDocument "Form" NotesItem from temp to document. I have designed the NotesDocument Auto-Save engine this way to ensure that application logic and workflow designed for the target document NotesDocuments are not initiated when we create or update a temp NotesDocument in the target NotesDatabase.
This separation from the document NotesDocument until said NotesDocument has been submitted to the NotesDatabase should allow you to easily implement the NotesDocument Auto-Save engine into your existing Domino Web Applications, and provide your users with functionality that they expect in more advanced and feature-rich web-based applications.
Conclusion
The NotesDocument Auto-Save engine was specifically designed to allow you to "bolt on" this feature to your enterprise-level Domino Web Applications with minimal impact and revision, while additionally showcasing what functionality can be achieved using platform capabilities available to Domino Web Application Developers from as far back as Domino R5. The aforementioned Example can be found online at http://domino1.clearframe.net/autosave.nsf/index.html or available for download at http://www.dominoguru.com/pages/autosave_example.html. I encourage you to download and rip apart this NotesDatabase, and leverage whatever possible therein to provide your users with feature-rich enterprise applications.