Show-n-Tell Thursday

Tips for referencing elements in XPages JavaScript

I managed to hit a bit of a wall with my IdeaJam on XPages development this week. Up until now I haven't really needed to write any client side JavaScript which is impressive in itself compared to how much client side scripts we have in IdeaJam classic. But I have reached that point where I want to add some interactivity without round-tripping to the server.

In classic Domino it's very easy to write script that refers to specific elements of the HTML because you get to control the IDs of those elements. But with XPages it is not possible to predict what the name of an element will be when it reaches the browser. So you are provided with a couple of functions to help you out. When you're writing client side Javascript in an XPage client side event (like clicking a button) it's very easy, the syntax you use to reference an element is "#{id:myElement}" in place of the id. So for example you could use:

dojo.byId("#{id:myDiv}").style.display = "none";

But the thing that I didn't know about until John Mackey gave me some help was that there is a second way of getting the ID of an element. My specific problem was that I wanted to have a script run when the page finishes loading and that script needed to go and work on several different elements. It's easy enough to make a script run "onload". You can actually write JavaScript directly into the source XML of the XPage, so I have added, at the top of my XPage something like this:

<script language="Javascript">
XSP.addOnLoad(function () {
initLocal();
}
);
</script>

This will tell Dojo to call the function "initLocal()" when the page has finished loading, no problem there. But my initLocal function needs to reference an element on the page and I can't use the "#{id:myElement}" format as that only gets evaluated in events that are provided for you by the XPage, enter the "getClientId()" function. You can add a computed field to the XPage that has JavaScript embedded within it in the following format:

var out="<script language=\"Javascript\">\n";
out += "var myElementId = \"" + getClientId("myElement") + "\";\n";
out += "function initLocal(){\n";
out += "myFunction(myElementId);\n";
out += "}\n";
out += "</script>";
out

And by the time it makes it out the the browser it has been translated into:

<script language="Javascript">
var myElementId = "view:_id1:_id2:content:_id4:myElement";
function initLocal(){
myFunction(myElementId);
}
</script>

So in the initLocal function I call another function which is held in a Client Side JavaScript library and I pass in the element ID so that the function can reference the element on the page with proper separation between UI and business logic. So it's all a bit round the houses but this way of doing things does work well and hopefully you won't need to go through the pain that I have in working this stuff out.

Finally a big thanks to John Mackey for his help, this is when the Lotus community really proves it's worth