I've built a library for my xPage apps that includes functions like 'gotoPage', 'returnToPage', 'callToPage', and 'returnFromCall'. These 4 functions form the basis of my navigation engine and work in all clients. They all rely on a fifth function named 'getUrl' that does most of the work. I've posted the 'getUrl' function code below for reference. It was ripped from my library, so there is some dependant code missing.
var MIS_CLIENT_IS_NOTES:boolean = (@ClientType() == 'Notes');
var MIS_CURRENT_PROTOCOL:string = MIS_CLIENT_IS_NOTES ? 'notes' : 'http';
getUrl: function(page:string, target, setReturnUrl:boolean, setSaveUrl:boolean, readOnly:boolean, parameters:java.util.HashMap, forceExternal:boolean){
if (typeof setReturnUrl === 'undefined') setReturnUrl = false;
if (typeof setSaveUrl === 'undefined') setSaveUrl = false;
if (typeof readOnly === 'undefined') readOnly = false;
if (typeof parameters === 'undefined') parameters = null;
if (typeof forceExternal === 'undefined') forceExternal = false;
// handle custom @Functions
var fn:Array = MisUtil.parseLotusFunction(page);
if (fn != null){
switch(fn[0]){ // custom @Function name
case 'ExternalPage': // @ExternalPage("SettingsFieldName", "pageName.xsp")
target = MisApp.openSettingsDb(fn[1]);
var pn:string = fn[2];
if (pn.endsWithIgnoreCase('.xsp')){
page = pn;
}else{
page = MisApp.getSetting(pn);
}
break;
default:
exception('MisApp.getUrl: Invalid custom @Formula: ' + fn[0] + '!');
}
}
// determine context
var targetDoc:NotesDocument = null;
var targetDb:NotesDatabase = null;
switch(typeof target){
case 'lotus.domino.local.Document':
targetDoc = target;
break;
case 'NotesXspDocument':
case 'com.ibm.xsp.model.domino.wrapped.DominoDocument':
targetDoc = target.getDocument();
break;
case 'lotus.domino.local.Database':
case 'com.ibm.domino.xsp.module.nsf.NSFComponentModule$XPagesDatabase':
targetDb = target;
break;
case 'NotesXspViewEntry':
targetDoc = target.getDocument();
break;
case 'string':
if (target.length() == 32){
targetDoc = database.getDocumentByUNID(target);
}else{
targetDoc = database.getDocumentByID(target);
}
break;
case 'undefined':
break;
default:
exception('MisApp.getUrl - target type is not recognized: [' + typeof target + ']!');
}
if (targetDoc != null) targetDb = targetDoc.getParentDatabase();
if (targetDb == null) targetDb = session.getCurrentDatabase();
// construct url
var isExternal:boolean = page.startsWithIgnoreCase('http://') || page.startsWithIgnoreCase('notes://');
var url:Array = [];
if ((!isExternal && !MisUtil.dbIsCurrent(targetDb)) || forceExternal){
url.push(MIS_CURRENT_PROTOCOL);
url.push('://');
url.push(MisUtil.getUrlHost(targetDb));
url.push('/');
url.push(MisUtil.getUrlFilePath(targetDb));
url.push('/');
isExternal = true;
}else{
if (page.endsWithIgnoreCase('.xsp') && !page.startsWith('/')) url.push('/');
}
url.push(page);
if (page.endsWithIgnoreCase('.xsp')) url.push('?OpenXPage');
// add document id
if (targetDoc != null){
url.push('&documentId=');
url.push(targetDoc.getNoteID());
url.push('&action=');
if (readOnly){
url.push('openDocument');
}else{
url.push('editDocument');
}
}
// add return URLs
var returnUrl:string = '';
if (setReturnUrl || setSaveUrl) returnUrl = MisApp.getUrl(MisApp.getPageName(), targetDoc, false, false, false, null, isExternal);
if (setReturnUrl){
url.push('&returnUrl=');
url.push(urlEncode(returnUrl));
}
if (setSaveUrl){
url.push('&saveUrl=');
url.push(urlEncode(returnUrl));
}
// add custom parameters
if (parameters != null){
for (paramName in parameters.keySet()){
url.push('&');
url.push(paramName);
url.push('=');
url.push(parameters.get(paramName));
}
}
return url.join('');
}