Making Domino Behave Relationally, Part 2

Jake Howlett, 31 May 2004

Category: JavaScript; Keywords: popup dialog modal

This two-part set of articles aims to show a way to build pseudo-relational content in Domino. The first part described how to use a list of document IDs to dynamically build a set of links "on the fly" each time a document is opened. It used a looping @Formula to build the HTML at the server and send it to the browser. This all works fine when the document is in read-mode, but things get more complicated when the document is being edited and new links need to be added. This article aims to cover what's needed to maintain the list of links from within the browser. In short - a fair amount of JavaScript. Even if you're not interested in the approach of storing IDs of related article there's bound to be something of use for you in this article.

Overview:

Have you ever used a popup window to gather information from a user and then used it to populate a field on a form? Something like this method. It's fairly easy to do. What gets harder is when you want to update the actual HTML content of the parent window rather than simply the value of a field. This is what we want to do here. Whereas the Domino server builds the list of links for read-mode we need to do it using DHTML, without needing to return to the server each time we add a new link. To see how this works take a look at the example form. Use the "Add Link" button to add some new links and see how the list builds each time you add a new one. This is the code we are going to cover. Both how to launch the window and how to bring back the information needed to create the HTML.

There are four parts to this solution. We need an area within the page to display the links, a field to hold the link IDs, a view to select links from and a popup form to display the view.

How the parts fit:

In the first article we mentioned the multi-value field called RelatedArticles that holds the ID of the links. We covered how to generate the links from these IDs. Well, now we need to go over how to get the IDs in the field in the first place.

The first thing we need to do is hide this field. The last thing you want to see when editing the document is a list of document IDs. In the HTML Attributes section of the field add "type=\"hidden\"". Your user won't see the field but it will still be part of the form and available to JavaScript. You'll see why this is important later.

RelatedArticles Field

Notice below the field that we have a <div> called "related-articles". This is the area of the form where we are going to add the links, in edit mode, that Domino would normally produce at the server in read-mode. Again we will be using JavaScript to do this. In fact, this whole approach uses nothing but JavaScript.

Now all we need is a way of picking the documents that we want to add. To do this we need a view and a form for it to live in. The view is treated as HTML and creates a set of javascript links that call a function which adds the document to both the field and the div. The form simply holds this view and lives inside a popup window.

You should already have seen this in action in the demo form. Don't worry if things don't make sense. You can download a demo database at the end of the article and rip the design apart for yourself. Things always make more sense when you can get your hands on them, don't they.

Plugging it all together:

This first thing we need to do is open the popup dialog so the user can choose a link to insert. This is easy enough; just a simple JavaScript call to open a new window. Add something like this line of code to the onclick event of a button that says something like "Add Link" on it:

window.open("/related.nsf/LinkPick?OpenView","picker","width=450,height=350,resizable=yes,scrollbars=yes");return false;

In this code I have hard-coded the database name. You should never do this! It amazes me how many times I see this done. Instead, take a look at the design of the downloadable example db. You'll see a number of ways to avoid the need to hard-code.

When the user clicks this button a new window will appear that shows the view of all the documents they can choose to link to. Let's go over how the view works now.

If you are developing for IE you might to use modals dialogs instead.

All the view needs to do is display a list of documents. These documents will appear as links. When you click on any given link it calls a JavaScript function which adds that document to the list of related articles. Obviously it's not going to be a normal Notes view. Instead we are going to create a view which is treated as HTML. In the first (and only) column we add this code:

"<a href=\"JavaScript:doAddLink('" + Title + "', '" + @Text( @DocumentUniqueID ) + "' );\">" + Title + "</a><br />"

The result is a link in HTML that looks something like this:

<a href="JavaScript:doAddLink('Test Article', '212004813B779EA986256E840010FA3D');">Test Article</a><br />

All we need now is a form that this view can live on. Then we can open this form in our popup window and allow the user to select a document. The type of form we are creating is a $$ViewTemplate. We actually open the view but Domino uses this special form to display the view contents. On this form we can add any code needed, that can't traditionally be stored with the view.

I called the view "vwLinkPick" so I need to create a form called "$$ViewTemplate for vwLinkPick". It looks something like this:

$$ViewTemplate form

It's simply a view embedded on a form. There's a header that tells the user what they are expected to do and then the view. Notice however that there's a function in the JS Header. This is our doAddLink() function that's called by the links in the view. Here's the code in full:

function doAddLink(title, unid) {
//is it already linked to?
if (window.opener.document.forms0 ].RelatedArticles.value.indexOf(unid) >-1)
{
alert('This article is already linked to!');
return false;
} else {
window.opener.doAddLink(title, unid);
window.close();
}
}


Before we do anything at all we check whether the article is already in the list of links. If it is we alert the user and do nothing else. If the link is ok to be added we simply pass the argument to another function by the same name on the main form and close the popup window.

In JavaScript window.opener is an easy way to access the document from which a popup was spawned.

The function on the main form called doAddLink() is where all the hard work is done. It's where we need to both add the link to the hidden field and also add it to the list of links on the actual page. Here's the code:

function doAddLink(title, unid){

document.forms0 ].RelatedArticles.value+='; '+ unid;

var txt = document.createTextNode(title);
var lnk = document.createElement('a');

lnk.setAttribute('href', 'all/' + unid + '?OpenDocument');
lnk.setAttribute('title', title);
lnk.setAttribute('target', '_blank');
lnk.appendChild(txt);

var container = document.getElementById('related-articles');
container.appendChild( lnk );
}


For the sake of brevity I have removed some of the function. What's left are the important parts. From this you can get a grasp of the concept involved. If you want to see all the code then you'll have to delve in to the demo database.

First thing the function does is add the UNID of the document to the list in the hidden field. It uses the ";" as the delimiter so that Domino know this is a separate entry. Then the code adds another link to the list. To do this it creates the elements of the link within the Document Object Model (DOM) and adds it to the "container" - the DIV element where we display related articles. There are easier ways to do this in JavaScript but this is considered the "proper" way. In theory this approach is supposed to work in all types and versions of modern browsers.

Wrapping It All Up:

What I've covered so far should be all the essential elements of this solution. There are bits missing however and I've not covered it all in as much detail as it might require for those of you not comfortable with some of the more advanced JavaScript used. It's hard to cover it all in one article though. The reason I kept it as short as possible is that this is a case where you really need to get your hands on the finished design to see how it works. There's not really that much to it. Once you've seen it in Designer it should all make sense. If not, let me know and I'll try and explain in more detail.

Maybe you've got this far even though you have no need for a list of related articles or any interest in making Domino appear relational. If so there should be plenty for you to gain from looking in to the methods further. When you start working with complicated editing systems in the browser it's useful to know how to interact with popups and how to create HTML "on the fly". Hope you find it useful.