Jun 292007
 

In today’s three part tutorial I’m first going to show you how to create a sign in form directly on a Domino page. Secondly, I’m going to show how you can embed a Domino form, with security, directly into a floating pane and submit it using Ajax. Last I’m showing you some code how to display a Domino view on the page using JSON and give you some of the code we at SNAPPS used for the Lotus Quickr templates we developed, free for you to download.

I have also created a short Flash preview of what I’m going to show today. It’s a good idea to view that first to get an idea of what I’m trying to explain.

Prerequisites

To get this to work there are a few things that are required and you need a basic to medium skill-set of how JavaScript works inside Domino.

The Domino server has to be version 7.0.2 or later. This is because we are getting JSON from the view and this was introduced on that version of the Domino server.

We need to have the Dojo Toolkit library downloaded to our Domino server. Unfortunately, Domino on Windows has a problem. The file name Shadow.js cannot be used. The file just does not show up through the web server. I have created a Dojo version where Shadow.js is renamed to Shadow2.js and everywhere it’s being referenced is changed. This is the version of Dojo that IBM is using inside Lotus Quickr 8. You can download it here: [download#5#nohits]. Remember to put the “dojo” folder inside the “html” directory on your Domino server. If you have a Lotus Quickr 8 server, you don’t have to do this step, but you need to modify the “src=” of the JavaScript to “/qphtml/html/dojo/dojo.js”.

We also must have session based authentication on our Domino server for the Sign In form to work. If you don’t you can still use the other code in this tutorial.

You need to download the database with all the code in it, [download#6#nohits]. You don’t want to type it all yourself do you?

Embedded Sign In FormSign In Form on a Domino Page or Form

What I’m doing here is a sign in form that we can put directly on a Domino Page or Form to let the user sign in without leaving the page to go to the Domino log-in form that redirects us back to where we came from. There is not much code to it. Let’s start.

We start by looking at the “HTML Head Content” of the “Dojo Forms Submission” Page.

"<script type="text/javascript" src="/dojo/dojo.js"></script>" + @NewLine +
"<script>" + @NewLine +
"var dbURL = '/" + @WebDbName + "';" + @NewLine +
"</script>" + @NewLine +
"<style>" + @NewLine +
"body, td {
color:#333333;
font-family:Helvetica,Geneva,Arial,Verdana,Sans-Serif;
font-size: 0.9em;
}" + @NewLine +
"</style>" + @NewLine

All we are doing here is calling the Dojo JavaScript file, adding a variable for the database URL and adding some style to our page. Next we look at the “JS Header”. Inside here we have 239 lines of JavaScript code. Don’t worry, we are only going to use 14 of them for this first part of the tutorial. The function we are using for the sign in is “directLogin()”.

function directLogin(){
var poststring = "username=" + dojo.byId("Username").value + "&password=" + dojo.byId("Password").value;
var kw = {
url: "/names.nsf?Login",
postContent: poststring,
load: function(t, txt, e) {
location.href = location.href;
},
error: function(t, e) {
alert(e.message);
}
};
dojo.io.bind(kw);
}

As you can see we are constructing a string variable “poststring”, by adding the values of the “Username” and the “Password” fields to it. We are setting the “url” to “names.nsf?Login” and the “postContent” to our “poststring” variable. The “load” is what what we want to do after the Domino server returns that it was successful. All I do here is reload the page. We don’t have to that, we are actually signed in, but for the Hide-When formulas to take effect we need to in this case. More on this later. Dojo takes care of the rest by calling the “dojo.io.bind” and passing in the “kw” object.

Let’s look at the HTML part of our Domino Page. At the top of the Domino Page I have added some text to show who you are signed as and what access level you have. In a normal application, you would obviously not have those there.

<fieldset id="loginFieldset" style="padding-left:5px; padding-right:5px; padding-bottom:5px; width:200px;">
<legend style="font-weight:bold;"> Sign In </legend>
Name<br />
<input name="Username" id="Username" value="" maxlength=256 style="width:100%;" /><br />
Password</br>
<input name="Password" id="Password" value="" type=password maxlength=256 style="width:100%;" /><br /><br />
<input type="button" value="Sign In" onclick="directLogin()" />
</fieldset>

We make the form pretty by adding the “fieldset” and “label” HTML tags. The important parts of the HTML code are the two fields and the button. There is nothing special with the fields other than they need to be there and the only thing I added the call to our function. I have also added a Domino Hide-When formula to this text.

@TextToNumber(@UserAccess(@DbName ; [AccessLevel])) > 2

All that the above @Formula does is hide the HTML if we have a user access greater than 2. Which is Reader access. This is the Anonymous access to the database. Default is Author. That’s it, not to hard was it?

Embed Domino forms and submit them using Ajax

Now lets embed a Domino form inside a floating pane on our page. This is not done by any IFrames or pop-up windows. This is the actual HTML code of the form in question embedded onto our page. We will also submit this form using Dojo’s Ajax way.

The form we are going to embed is called “Favorites”. It is a very basic form with three Text fields, a Checkbox field and a Readers field together with two buttons.

I also created a view called “Favorites View” that contains the documents using the form. More on that later in the next part of the tutorial.

First we add some HTML to our Domino Page so that we can open up the form in the floating pane.

<a href="<Computed Value>">Sign Out</a> | <a href="javascript:createNewDocument();">New Document</a>

The first link is the “Sign Out” link. It’s only there so that we can sign out. (It really belongs to the previous section.) The second link is our link to create a new “Favorite” document. As you can see it calls the function “createNewDocument()”. Let’s take a look at that code inside the “JS Header” on our Domino Page.

function createNewDocument(){
if(!dojo.byId("ff-newdocument")){
var oDiv = document.createElement("div");
oDiv.innerHTML = "Loading...";
document.body.appendChild(oDiv);

var floatingPaneAttr = {
position: "absolute",
top: "100px",
left: "100px",
width: "300px",
height: "255px"
};

for(var s in floatingPaneAttr){
oDiv.style[s] = floatingPaneAttr[s];
}

var floatingPaneArgs = {
widgetId: "ff-newdocument",
title: "New Document",
href: dbURL + "/Favorites?OpenForm",
displayCloseAction: true,
toggle: "fade",
windowState: "normal",
cacheContent: false,
refreshOnShow: true,
hasShadow: true,
executeScripts: true
};

g_FloatingPane = dojo.widget.createWidget("FloatingPane", floatingPaneArgs, oDiv);
}else{
dojo.widget.byId("ff-newdocument").show();
}
}

First we check that we don’t already have an object named “ff-newdocument”. If we don’t we create a new Div element and append it to the document body. Then we add some style attributes to the Div. Here you see an example of how to use JSON directly in your JavaScript code. Then we create the “floatingPaneArgs” object. This is again Dojo and we are using a Dojo widget called “FloatingPane”.

The interesting part of the object is the “href” value. As you can see we are using the “dbURL” variable that we declared in the “HTML Head Content” area of our Page. If you recall, it was using an @Formula; @WebDbName. We then add the name of our form and the ?OpenForm to the string. What the other name-value pairs are I’m not going to go over here.

The last thing we do is to create our FloatingPane widget. We also have to declare to Dojo that we are going to use the FloatingPane widget, so we add this code to the top of our JavaScript.

dojo.require("dojo.widget.FloatingPane");

That’s all there is to it. You can see an example of what it looks like when we open the pane to the right.

As you can see, I have also added a Set Reader Access check-box on the form. If checked, only authenticated users can see the document.

If you open the “Favorites” form and examine the two buttons you’ll see that they both contain JavaScript calls. The Cancel button calls “cancelFavoritesForm();” and the Submit button calls “submitFavoritesForm();”.

These two JavaScript functions do not exist on the Domino Form. They are both in the “JS Header” on our Page. Another proof that we are not doing this by an IFrame or a pop-up window. These two functions looks like this:

function cancelFavoritesForm(){
if(dojo.widget.byId("ff-newdocument")){
dojo.widget.byId("ff-newdocument").closeWindow();
}
}

function submitFavoritesForm(){
var formObject = document.forms["_Favorites"];
var kw = {
formNode: formObject,
load: function(t, txt, e) {
dojo.widget.byId("ff-newdocument").closeWindow();
//Reload view
getDocumentViewJSON();
},
error: function(t, e) {
alert(e.message);
}
};
dojo.io.bind(kw);
}

The first function, “cancelFavoritesForm” is not to exciting, it just closes our Floating Pane. The same result as if you click the X at the top of the Pane. The “submitFavoritesForm” is much more interesting. In Domino all forms you open from the web gets a form tag with the name of the form with an _ (underscore) before it. So we create an object “formObject” by calling document.forms[“_Favorites”]. Now the fun begins. In dojo.io.bind we can declare a “formNode” value with the form object as it’s value. Dojo recognize that you are passing in a form and submits it using Ajax in the background. You can even have WebQuerySave agents run on the form and it will work. Really super cool.

Just as in our Sign-In JavaScript function, the “load” event is where we declare what will happen after the server returns that it was successfully loaded. Here we call “closeWindow” to close the Pane. We also call a function “getDocumentViewJSON()”. That is for the last part of this tutorial. You can see an example of much more complex Domino Form embedded into a web page by clicking the image on the left. This is from one of the Lotus Quickr templates that we have created, QContacts. It has a WebQuerySave agent, multiple tabs, attachment control and much more. There is also a function called “openDocument” where we just open documents after they have been saved. It looks a lot like the “createNewDocument” function I described earlier. We call this function inside our JSON function. Let’s jump to that.

Displaying a Domino View with JSON

The last part of today’s tutorial is all about Domino views, getting JSON from them and displaying the items on our Domino Page. First on our Page, we add a empty table to the HTML.

<table border=0 cellpadding=0 cellspacing=0 width="500">
<thead id="documentHead"></thead>
<tbody id="documentBody"></tbody>
</table>

This is where the documents show up when the JavaScript call is done. We also need to add some more functions to the “JS Header”. Don’t worry, it looks worse then it is.

function getDocumentViewJSON(){
var sURL = dbURL + '/favoritesview?ReadViewEntries&Outputformat=JSON';
sURL += '&Start=' + g_NumOfStartDoc;
sURL += '&Count=' + g_NumOfDocs;
dojoGetJSON(sURL, 'printDocumentTable');
}

dojo.addOnLoad(function(){
g_DocumentHead = dojo.byId("documentHead");
g_DocumentBody = dojo.byId("documentBody");
getDocumentViewJSON();
});

The bottom JavaScript, “dojo.addOnLoad” is a really handy way of not calling anything until we are sure that everything on our page has loaded in the browser window. All we do here is to assign two global variables for the table header and the table body and call the function above, “getDocumentViewJSON()”. That is also the function we called from within our submit function in the previous section. In that function, we create a URL string that we pass to the “dojoGetJSON” function. We also pass in a string “printDocumentTable” to that function. That is the name of the function that we want to call when the server has passed back the JSON to the”dojoGetJSON” function. The two functions “dojoGetJSON” and “returnJSONValue” I’m not going to examine in this tutorial, it would be to long. All I can say is that “dojoGetJSON” get JSON back from a server and “returnJSONValue” returns specific column values from a Domino View. Examine them and try them out. We at SNAPPS use them daily in our code. Let’s look at the “printDocumentTable” function instead.

function printDocumentTable(oJSON){
try{
var oRow, oCell;
if(oJSON["@toplevelentries"] && oJSON["@toplevelentries"] > 0){
var viewentries = oJSON.viewentry;
var n_viewentries = viewentries.length;
var unidAttr, entrydata, sTitle;

//Delete all rows in the table
var iRows = g_DocumentBody.rows.length;
for (var i = 0; i < iRows; i++){
g_DocumentBody.deleteRow(0);
}

if(n_viewentries > 0 && g_DocumentHead.rows.length < 1){
oRow = g_DocumentHead.insertRow(-1);

oCell = oRow.insertCell(-1);
oCell.style.fontWeight = "bold";
oCell.innerHTML = "Name";

oCell = oRow.insertCell(-1);
oCell.style.fontWeight = "bold";
oCell.innerHTML = "Pet";

oCell = oRow.insertCell(-1);
oCell.style.fontWeight = "bold";
oCell.innerHTML = "Color";
}

for (var i = 0; i < n_viewentries; i++){
unidAttr = viewentries[i]["@unid"];
entrydata = viewentries[i].entrydata;

oRow = g_DocumentBody.insertRow(-1);
oCell = oRow.insertCell(-1);
sTitle = returnJSONValue(entrydata[0]).items[0];
oCell.innerHTML = '<a href="javascript:openDocument('' + unidAttr + '', '' + sTitle + '');">' + sTitle + '</a>';

oCell = oRow.insertCell(-1);
oCell.innerHTML = returnJSONValue(entrydata[1]).items[0];
oCell = oRow.insertCell(-1);
oCell.innerHTML = returnJSONValue(entrydata[2]).items[0];
}
}
}catch(e){}
}

All I’m doing here is to create rows and cells with values for every document I get back from the call to the view. It might look like a lot of code but it is mostly repeated steps from creating rows and cells and adding values to them.

I will explain a few things though. “unidAttr” is just the UNID of the document. “entrydata” in the for loop represent all the column values that a document have. Calling returnJSONValue(entrydata[0]) returns an object with column type and an items array, even if there was only one value in the column for that document. Remember that a column can have multiple values for each document, a field with multiple values for instance. The function also returns the type of column the items come from, so that we can know what to do with the items. If for instance the column contains date strings we can parse them in the correct format for the application using JavaScript.

That’s if for this tutorial. I hope you have found it useful and maybe even learned something. As always please submit comments on the code and how I can do it better. Until next time. UPDATE! I have corrected some spelling errors. Why can’t everybody just learn Swedish?

Jun 042007
 

Several people have commented and emailed me wanting some sort of forum where I can post updates to code, examples and tutorials and where you can post your code variations, updates and ask questions to me and others.

So I have created eKrantz.com Forums where you can register and ask questions and write your comments about Dojo Calendar and Lotus Quickr code and tutorials. So go there now and register so we can get some good discussions going.

May 072007
 

Today I’m starting a new series of blog entries about extending the upcoming Lotus Quickr. The series will cover some of the new features, from a developers point-of-view, that will be available for you. You will be able to test most of them on upcoming beta releases, if you’re part of the beta program.

The tutorial today will show you a way of creating modal floating windows that can have any HTML you want in it. Click the thumbnail to see a larger image of what it looks like. The code is developed on top of the Dojo Toolkit that is now distributed as part of Lotus Quickr.

It is a modal window because the end user can not do anything else on the page until he clicks either of the buttons in the floating window or the close button in the top right corner of the floating window. (This “window” does not prevent the user from clicking the browsers back or close buttons.) It really is not a floating window. It’s not a window at all. It is a div object that is set to be on top of everything else on the web page when it is shown. The good thing about this is that we don’t have to worry about pop-up blockers. Another thing that the modal floating window does is that it darkens everything else on the web page to really focus in on the contents of the floating window. On to the tutorial.

First we create a new HTML page in our favorite editor. My new favorite is Eclipse Callisto with the Aptana plug in. Add a script tag inside the body tag. We have to add the script tag inside the body tag because Lotus Quickr will strip everything from our HTML code that is not within the body tag. So we have something like this:

<html>
<head>
</head>
<body>
<script type="text/javascript">
</script>
</body>
</html>

Time to add some functionality to our HTML code. First we add the reference to the ModalInput widget by adding the following code inside our script tag:

<script type="text/javascript">
dojo.require("dojowidgets.widget.ModalInput");
</script>

dojo.require is the Dojo way of referencing one of its JavaScript files. This happens to be a widget created by me and not by the Dojo developers but can still be called this way since it is referenced by its name space “dojowidgets”. Let’s not go in more on that. This tutorial would lose its focus very quickly, if I did that. If you want to read more about the Dojo Toolkit and how to create your own widgets please visit their website.

Next we want to add the button and the function that opens the floating window. Just before the end of the body tag we add:
<input name="mybutton" type="button" value="Open Modal" onclick="openMyModal()" />

Inside the script tag we add the function openMyModal:

function openMyModal(){
var sHTML = 'Your Name';
sHTML += '<br />';
sHTML += '<' + 'input type="text" id="modal_name" value="" style="width:95%;" />';
sHTML += '<br />';
sHTML += 'Your interests';
sHTML += '<br />';
sHTML += '<' + 'textarea rows="3" id="modal_interests" style="width:95%;"></textarea>';


var myModalParams = {
widgetId: "MyModalInput",
title: "My Custom Modal Form",
formText: sHTML,
submitFunction: "myModalSubmit"
};
var myModal = new dojowidgets.widget.ModalInput(myModalParams);
}

This function is what opens or show the “window” and whatever HTML we have chosen pass in. Let’s go over the function in more detail. The first part is where we declare a variable sHTML and add a string of the HTML that we want to show inside the floating window. As you can see we have a couple of labels, a text field and a text area field in the string representing the HTML. In the next part of the function we declare a variable myModalParams and add an object to it. This object represents the parameters that we pass into the floating window widget. More on these parameters in a moment. Last we call the ModalInput widget code and pass in our parameter object. We do this by setting a variable myModal.

Back to the parameter object that we created. As you can see we declared 4 properties to our object: widgetId, title, formText and submitFunction. These are not the only parameters that we can pass into the widget and all parameters, including these 4, are optional. Let’s go over them one by one.

  • widgetId:
    • Default: “modalInput” (string)
    • If you have more then one floating ModalInput on the page it is important to set their unique ID’s.
  • title:
    • Default: “” (string)
    • This is the title text in the window bar.
  • iconSrc:
    • Default: “information.gif” (string)
    • This is the image icon before the title in the window bar. Pass in the full URL to the image. The image should be 22×22 pixels.
  • formText:
    • Default: “” (string)
    • This is the HTML that you pass in to be displayed within the window.
  • width:
    • Default: “350px” (string)
    • The width of the window in pixels.
  • height:
    • Default: “250px” (string)
    • The height of the window in pixels.
  • resizable:
    • Default: false (boolean)
    • Should the window be re-sizable or not.
  • displayCloseAction:
    • Default: true (boolean)
    • Should we display a close button in the top right corner of the window.
  • submitFunction:
    • Default: “” (string)
    • The name of the function we should call when the Submit button is pressed. This function should return true or false if we should hide the window.
  • cancelFunction:
    • Default: “” (string)
    • The name of the function we should call if the Cancel button is clicked. This function should return true or false if we should hide the window. Use only if you need to have a Cancel function. I.E. you need to undo something when the user clicks Cancel.
  • submitValue:
    • Default: “Submit” (string)
    • The text inside the Submit button. Could be “OK” or “Yes”.
  • cancelValue:
    • “Cancel” (string)
    • The text inside the Cancel button. Could be “Close” or “No”.

Now we only need to add one more thing to our code to complete this tutorial, the function we call by clicking the “Submit” button inside our floating “window”. Inside our script tag we add:

function myModalSubmit(){
var sName = dojo.byId("modal_name").value;
var sInterests = dojo.byId("modal_interests").value;
if(sName == ""){
alert("FAILURE!nn" + sName + 'n' + sInterests);
return false;
}else{
alert("SUCCESS!nn" + sName + 'n' + sInterests);
}
return true;
}

We had added the value myModalSubmit to our submitFunction property above so we need to add a function with that name to our code. This function would in reality probably be much more complex than alerting “SUCCESS” or “FAILURE”. However in this basic demo that’s all we are doing. The function checks if you added a name in the field and alert result either way. If we did add a name it will close/hide our modal window by returning true, if not it will leave the window open by returning false. In the code you see that I’m using dojo.byId. That is just a more robust and shorter way of using document.getElementById.

Now all you have to do is to create a new “Imported Page” inside your Lotus Quickr place and select your HTML file as the file to import. Save and you will see the page with the button to click to open the modal floating window.

If you are lazy like me, and don’t want to create the file yourself, you can download the [download#3#nohits] zip file, unzip it and upload like above.

Now you can go and update the HTML to whatever you want and play with the widget parameters to suit your needs. In reality we would add this code to a custom HTML form and save our data down to regular or hidden fields on it. As an example I’ll show you a screen shot of the upcoming Lotus Quickr QMeeting template that we just finished.

If you have any comments about this tutorial, please submit them below. I will have a new tutorial for you as soon as I have another sleepless night.