If you've ever built Domino applications for the web, chances are you've had to face the problem of getting something out of the Name and Address Book
(that's the Domino Directory to you newbies). For whatever reason, an easy way to access the NAB isn't a part of the core Domino developers' package even though there's a pretty good one in the iNotes mail package.
So, we're left to roll our own.
There are a number of fair, even some good, solutions floating around out there, including one we built many years ago and which has been included for years in our ProcessIt! workflow tool. If you were at Lotus Advisor Live last summer, you may have downloaded a copy of ours along with my session demos.
While ours was pretty good, it was a bit slow--particularly on really big NABs--and it had a whole lot of pieces and parts needed to make it work. Well, that's been solved thanks to some very smart (and amazingly compact) coding by Matt White. Matt used AJAX, the smorgasbord of technologies that's popping up everywhere these days to set down the basis needed to build a great NAB picker.
His, which you can try out here, is actually more flexible than we need for just a NAB picker. It can work against more or less any database and more or less any view which could be amazingly useful in the right applications but is unnecessary for a strictly NAB-picking application.
And, while it is blazingly fast, it lacks some of the more mundane user requirements. You can't change between address books, for instance, and there is a little too much clicking around required for a really spectacular user experience. But it is close, man. Really close.
All it needs is a little polishing, which I've been busy doing. You can download a copy of mine (pictured above) here (instructions for installation are in the Help About document, and a demo Page you can use to try it out on your server is included).
You're welcome to use this in your own applications but please retain the copyright statements for both Matt White and Teamwork Solutions. And, if you add some new enhancements, please share them with the rest of us.
I bring this up for several reasons: First, a good NAB picker is something we all need and too good a thing to keep to ourselves, particuarly when we didn't write the original code. More importantly, the process I've gone through to convert Matt's starting model into my finished version is pretty typical of the work developers need to do all the time (but often don't) in trying to anticipate users' needs.
Henry Newberry and I are doing both a Best Practices session and a hands-on lab at Lotusphere 2006 on the subject of making Domino applications that don't look or work like Domino, and this will probably be a part of that discussion.

I thought you might be at least a teench interested in the before-and-after differences because while they are simple at one level, the devil is in the details and the net result is--in my opinion at least--a much improved user experience.
What Matt built was brilliant and amazingly fast, but it had a few issues. First, as a system-like tool, it did not look, well, boring enough. Conservative might be a better word than boring. It wasn't conservative enough. You can see his above. Compare it to the way mine (at the top of the page) looks.
Now, you may like the white and blue of Matt's better than the subtle grays of mine. That's OK but, at the risk of sounding like an old prude, having a lot of color in things like this is almost never a good thing. Boring is beautiful. On the whole, there are very few instances when dialog boxes (such as a NAB picker) should not look like they came from IE or Firefox or whatever platform you're using. And, generally that means gray backgrounds, black type, and simple, consistently-named and -placed user choices.
In addition to the obvious color differences, notice a few other things that have been changed:
- There is now a drop-down to choose from the various address books available to you.
- There is a search function. Actually, Matt's included a search function, too, except you had to type in some letters and hit the Go button. In mine, it searches on each keystroke, making it feel all the faster.
- The page loads with the cursor already in the search field and ready to go. You can immediately start typing without first needing to click.
- Hitting Enter after a search chooses the top name on the list. In the single-name picker, it enters that name into your field and closes the window. In the multi-name picker, it adds the top name to your list of names. Either way, you'll find it is a very fast and surprisingly satisfying way to get names out of the picker and onto your form.
I've included images here of the multi-name pickers, too, both before and after, so you can see what they look like.

What's funny about this is the new ones do the same things as the old ones except for a handful of subtle differences: a click less here, a faster call for a search there. Pretty soon, with just a little extra work you go from a terrific solution to an even more terrific solution--and one you like to use, to boot.
It's a subtle but important difference. If you hope to have your Domino applications treated like mission critical software, they need to look and act like it. It's not enough to have good code--that's a given--you need to have a compelling and easy-to-use interface, too. It's a part of your application's credibility.

Go back and look at the graphics above one more time. If I told you two of these came out of the box with Domino and two were built downstairs in your shop by one of the application developers, which would you say was which? If you had to put both in front of the CEO of your organization, which do you think he would consider the better, more robust, piece of software?
You and I know the underpinnings are virtually the same but, the catch is, the rest of the world--including those who (think they) matter most in our organizations--don't. They know what they see, and what they touch. Make sure the people who matter at your company see and touch the right kinds of things.
1. Matt White11/09/2005 04:51:10 AM
Homepage: http://www.11tmr.com
Good work Scott.
I actually tend to agree with you on the color scheme and general look and feel. In my case I tailored it to match a suite of applications which I look after. The one issue with the whole thing which I am not happy with is how to handle text wrapping. If you have a person in the NAB with a spectacularly long name (which is bound to happen when there are more than 100,000 people in the company) my picker just wraps down to the next line (hence the nasty white space at the bottom of the window).
Anyway, thanks for complimentary words, see you at Lotusphere!
2. Scott Good11/09/2005 09:09:56 AM
Homepage: http://www.scottgood.com
Matt,
Thanks for your note. BTW, I didn't mean my comments to be criticism of your implementation. I'm a bit in awe of what you built, frankly. We've tried it on a NAB of more than 80,000 names and the response time is more or less the same as when I'm hitting our 131-name NAB. Amazing.
What I'd hoped to show here was how you can take anything--even great code--and take it up another notch from a user's (and manager's) perspective by making some simple but important adjustments. It's like BASF: I didn't write the code; I just helped make the code better.
As to the wrapping, you're right. That remains an issue. You can get around it if you're smart enough to re-size the window but that's a hack at best.
I actually had a version where the two tables of names were scrollable. That solved the problem (and let you return a lot more names in each search) but I couldn't keep it from having scroll bars on both the right and bottom, which I didn't like.
The other problem I haven't solved yet is correctly alphabetizing the names. I'm pulling my name list from ($VIMPeopleByLastName) which, while sorted by last name, is NOT sorted by first name or, for that matter, middle initial. That means the docs come up in creation order within common last names--not an ideal solution. I sorted the first name column in that view in our NAB but that's not likely to be an acceptable solution at, say, DaimlerChrysler or the US Army where mere developers May Not Touch The NAB.
So, we need a bit more sorting there that I've just not taken the time to write yet.
My final whine has to do with the highlighting of selected names. When you run your cursor over the table of names they get highlighted as it passes over. I'd really like to have the top choice automatically highlighted when you do a search so it's a little more obvious that an ENTER command will do something with it. That's easy enough to do, of course, but I'm still scheming on how to efficiently get rid of that highlight when you start running the cursor over something else on the page. As in every application, it seems, there are always more things that can be done to make it better.
Any takers?
Scott
3. Mark Barton11/21/2005 10:34:29 AM
Homepage: http://www.markbarton.com
Scott,
Its a bit scrappy but I changed the JS to create an associative array (with a custom object_ using the fullname as the key, I then had a seperate fullname array which I sorted on. It does mean 2 loops but seems fast enough.
Mark
function displayData(xmlDoc) {
// get areas which we are going to write results into
var namelist = document.getElementById("namelist");
var countlist = document.getElementById("countlist");
//Add new Object Array
var personObjArray=new Array();
var fullnameArray=new Array();
try {
namelist.innerHTML = "Please Wait...";
//Open the XML Document
var root = xmlDoc.documentElement;
results = root.getElementsByTagName("viewentry");
//Get the toplevelentries value each time in case it changes
viewTotalDocs = parseInt(root.attributes[0].value, 10);
for(k=0;k<results.length;k++){
var fullname = getInnerText(results[k].getElementsByTagName("entrydata")[returnColumn]);
var displayColumns=new Array();
for (iCol=0; iCol < columns.length; iCol++) {
//Write each cell of the current row
var text;
try {
text = getInnerText(results[k].getElementsByTagName("entrydata")[parseInt(columns[iCol], 10)]);
}
catch (e) {
text =+ e. message + " (" + e.name + ")";
}
displayColumns[displayColumns.length]= text ;
}
personObjArray[fullname]=new personObj(fullname,displayColumns);
fullnameArray[fullnameArray.length]=fullname;
}
fullnameArray.sort();
var strHTML = "<table width=\"100%\" id=\"nameChoicesTable\">";
for (i=0; i<fullnameArray.length; i++) {
//Get the value which the row will return if clicked
var returnText = fullnameArray;
//Write the tr tag
if (i % 2 == 0){
strHTML += "<tr class=\"normal1 " + escape(returnText) + "\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal1'\" name=" + escape(returnText) + " onClick=\"storeValue('" + escape(returnText) + "');\">";
} else {
strHTML += "<tr class=\"normal2 " + escape(returnText) + "\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal2'\" name=" + escape(returnText) + " onClick=\"storeValue('" + escape(returnText) + "');\">";
}
for (iCol=0; iCol < personObjArray[returnText].displayColumns.length; iCol++) {
//Write each cell of the current row
var text;
try {
text = personObjArray[returnText].displayColumns[iCol];
}
catch (e) {
text =+ e. message + " (" + e.name + ")";
}
strHTML += "<td>" + text + "</td>";
}
strHTML += "</tr>";
}
strHTML += "</table>";
// output the document count details
countlist.innerHTML = results[0].attributes[0].value + " to " + results[results.length - 1].attributes[0].value + " of " + viewTotalDocs + " records";
// output the table HTML
namelist.innerHTML = strHTML;
}
catch (e) {
namelist.innerHTML = errormessage + e. message + " (" + e.name + ")";
}
}
function personObj(fullname,displayColumns){
this.fullname=fullname;
this.displayColumns=displayColumns;
}
4. owen01/04/2006 06:51:15 PM
This is truly a fantastic piece of work from all of you!
Greatly appreciated and an excellent learning tool.
Just one dumb question if I may:
I have test implemented your NAB lookup in a Domino.Doc. library in an R5 environment. It is used to select multiple reviewers of the attached document.
When saved the selected names are held in a Reviewers field
On editing the document and clicking the selectmultiple names button all of the previously names are lumped together into a single entry in the dialog box.
I have tried various field types, imploding and exploding etc to deliver separate entries.
Current solution is to implode around ; on save and use a display field with new line.
But when editing all of the selections are displayed a single line running off to the right.
Is there a simple way of dealing with this so that WYSIWYG layout applies without rewriting the jscript code?
The jscript code in the name picker form seems set up to deal with various field input types but I cant easily debug it as the "try" and "catch" functions are reserved in R5 and I cant add alert/debug code to track the process.
I know this is a "backwards" facing question, specially since R7 is here, but any advice would be appreciated.
Thanks
5. Andrew Tetlaw01/25/2006 12:33:59 AM
Homepage: http://tetlaw.id.au
What an awsome name picker!
I have done an implementation which was a breeze except for 2 problems:
1. The URL params are transformed to lowercase here:
var strQueryString = "&" + strHref.substr(strHref.indexOf("?") + 1).toLowerCase();
Firefox 1.5 did not like that because the field name had capitals; "FieldName" (and my id's matched the field names). So I removed the toLowerCase():
var strQueryString = "&" + strHref.substr(strHref.indexOf("?") + 1);
2. The return value for each name was preceded by a line feed character,which meant the return value for multiple names was truncated at the first line feed when setting a text field in Firefox 1.5. So I added a trim() function:
function trim(str) {
return str.replace(/^\s+|\s+$/g,'');
}
and modified displayData(xmlDoc) to read:
var returnText = trim(getInnerText(results.getElementsByTagName("entrydata")[returnColumn]));
After that it worked like a charm in FF1.5 and IE6.
Again, great piece of work.
6. Tricia Short03/06/2006 10:10:44 AM
GREAT!! Beautiful! Lightening fast! I have one simple question. I'm using the single-name picker. Once a name is selected, how do I get the web page to refresh? I need my form to recalculate values based on the newly-selected name. Any help on the javascript to use is much appreciated!
7. Scott Good03/06/2006 11:35:01 AM
Homepage: http://www.scottgood.com
Hm. Good question, Tricia. The idea here, of course, is to try to NOT make your form have to refresh, at least in the sense that it has to go back to the server for more information.
If you absolutely need the form to do a refresh (like the ones you get when you set a keyword field to refresh the form when the value changes),you'll need to call the same function they do. That function is something like this:
_doClick('$Refresh', this, '_self', '#_RefreshKW_Applications')
You may have to fool around with this a bit to get it to work, and you'll have to call it from the OK button in the NAB picker, so it will be more like this:
window.opener._doClick('$Refresh', this, '_self', '#_RefreshKW_Applications')
The "this" in the code above is a reference to the checkbox field this came from, so you probably have to include a reference to an object on your form there. Possibly, you can leave it blank (I'm not sure without messing around with it). Send me an e-mail if you get stuck and I'll try to help.
HAVING SAID ALL THAT, a better approach than forcing the refresh, if you can do it in your application, is to write some Javascript do do the refreshing for you.
If you're resetting fields or other values with things that are known to you already in the form (as opposed to having to go out and look things up from somewhere else), that's clearly the way to go. It's vastly faster and much more satisfying to the user.
If you simply have to go out and look one or more values up, I'd suggest either calling an agent (through an embedded iFrame, possibly) or, better yet, using a little AJAX to do it all in the background for you.
Let me know if you need some help.
Scott
8. Scott Good03/07/2006 01:34:07 PM
Homepage: http://www.scottgood.com
FWIW, I just got a note from a friend who implemented this date picker into an environment with over 168,000 names in the NAB and he tells me it is still very fast.
What a cool little bit of technology.
Scott
9. Jim Sasso03/29/2006 12:44:58 PM
This thing is really sweet. Runs amazingly fast. There are about 25,000 entries in the address book. I got it to work on Firefox with the changes above. Has it been tried on Safari? It pops up the window and allows me to select names but never returns them to the field. I have tinkered with the Javascript in the header of the form but have not gotten it to work.
10. Scott Good03/29/2006 02:06:27 PM
Homepage: http://www.scottgood.com
Jim,
I have not tried it in Safari. If you get it working there, please send me a copy and I'll update the version here.
Thanks,
Scott
11. Jim Sasso03/30/2006 11:53:48 AM
Scott,
Thanks for your quick reply. I was mistaken. When you make all the changes listed by Andrew Tetlaw above that fix firefox they also seem to fix the Safari issues. It now works across all three browsers. It is so much nicer than the one we had pulled from the mail file.
Thanks Again - Jim
12. Scott 04/11/2006 01:41:16 PM
This is a very nice picker and works very fast on our 2800 list address book. I was just wondering if you were planning on incorporating a SendTo, CopyTo, BlindCopyTo in the same pop-up instead of having a seperate button for each of them. This is just something I was looking forward to and I would love to keep this picker because it's a very nice one. Good work on it!
13. Scott Good04/11/2006 02:36:23 PM
Homepage: http://www.scottgood.com
Interesting. I hadn't thought of that but probably we won't do it just because it would suddenly become a whole lot less generic with those fields on it. It wouldn't be TOO much harder to do it though...why not take a shot yourself?
14. Roman Kopac05/04/2006 10:24:37 AM
Homepage: http://www.flopi.si
Excelent work from both Mike and Scott. This is a very useful solution. There is however a small bug. It happens only if you have small views to pick from - views that have document count less than initial start parameter. Next and Last buttons raise an error. I this case you get an error in js functions nextPage() and lastPage() because the calculated start parameter is negative. Something like this should solve it:
function nextPage() {
try {
// work out where the next page starts
var lastMax = parseInt(results[results.length - 1].attributes[0].value, 10);
var start = lastMax + 1;
if ((start > (viewTotalDocs - (count - 1))) && ((viewTotalDocs - (count - 1)) > 0)){
start = viewTotalDocs - (count - 1);
} else{
start = 1;
}
.
.
.
function lastPage() {
try {
// work out where the last page starts
start = viewTotalDocs - (count - 1);
if (start < 0) start = 1;
.
.
.
15. Scott Good05/04/2006 01:02:51 PM
Homepage: http://www.scottgood.com
Thanks!
16. Roman Kopac05/05/2006 05:08:20 AM
Homepage: http://www.flopi.si
Bah, the 'if' check in lastPage() should be
if (start < 1)
start = 1;,
just as in previousPage().
17. Patrick Niland05/19/2006 07:34:12 AM
Hi,
Great work. Just wondering have you tried getting it to include "Groups" or a User's contacts? Also, have you tried putting it into a modal dialog (i.e. for Internet Explorer).
I'm currently attempting to do the above. Just wondering whether you know of any funnies i should watch out for.... (e.g. like excluding "Access Only Groups", etc...).
Thanks
Patrick Niland
18. Scott Good05/19/2006 08:45:55 AM
Homepage: http://www.scottgood.com
Hi Patrick,
I've not tried either groups or modal dialogs, but neither should be hard to do. Getting groups should simply be a matter of pointing to a different view that includes them, and the modal dialog is a tweak to the call.
Let us know how it turns out (and feel free to share code and/or samples).
Thanks,
Scott
19. Fernando Ferrandini07/07/2006 05:17:01 PM
Well finally im starting to get it to work in here...
i have to change smalls details...
This NAB is very cool and so light.. but... i know it could be a little bit better... my suggestions for next "version":
1. Server should be a parameter too... cause, as my case, others might passed through it too, is the fact that the names.nsf to be accessed isnt in the same server from the App running the NAB.
2. Support for multiple names.nsf using notes.ini or Directory Assistance(in my case i use DA... )
Im working on it, right now im trying to add the server parameter.
but a support for multiple names.nsf using notes.ini or DA , hmmm im affraid i wont be able to do it myself. on monday i will work on it.
what iīve done far now:
1. var urlArray = document.location.href.split("/"); // already exists
2. var dbServer = urlArray[2]; // server default . can be overriden with server parameter
3. changed URLPrefix = urlArray[0] + "//" + urlArray[2]; to URLPrefix = urlArray[0] + "//" + dbServer;
4. added code to retrieve from query_String the serverīs param(below the URLPrefix ):
if (getURLParam("server") != ""){
dbServer = getURLParam("server");
URLPrefix = urlArray[0] + "//" + dbServer;
}
i did my first test and as usual, didnt work hehe =/
i get namelist.innerHMTL :
There has been an error displaying the data:
'null' é nulo ou não é um objeto (TypeError)
But if i take out the &server=blabla added to URL that opens NAB, it means that it will search for the localserverīs names.nsf and it works just fine.
is there any limitation on accessing external domino servers with the techniques used in the NAB code?
Lets share our experience and make this NAB-AJAX become 100% like the
NAB from notes client. !!!
20. Scott Good07/10/2006 08:44:39 AM
Homepage: http://www.scottgood.com
Hi Fernando,
One of the security limitations of AJAX is it cannot access data from servers other than the one it's running on. So, therefore, if you hit ServerA and hope to read some .ini variables which you'll then use to hit ServerB, that won't work. You could probably make a work-around of sorts with a Notes agent, though. It's a pretty simple thing to write an agent that returns XML to you (I cover it in the July 2006 Advisor article). You might be able to do something with this.
I love your idea of putting a few heads together to build an even better NAB picker...it's about the biggest hole out there in Domino development (at least as far as I can tell). I'll be happy to act as the coordination/distribution point for such an effort. Please let us know how you do on your efforts...
Thanks,
Scott
21. fernando ferrandini07/11/2006 04:34:08 PM
hi scott!
as im not a guru =/ only couple of months working with notes...
As you told me to do, i found this sample LS agent that uses XML... for solving the cross-domain ajax problem...
Sub Initialize
Dim s As New NotesSession
Dim doc As NotesDocument
Dim xml As Variant
Dim temp As String
Set doc = s.DocumentContext
temp = Strright(doc.Query_String_Decoded(0),"url=")
Set xml = CreateObject("Microsoft.XMLHTTP")
Call xml.Open("GET", temp , False)
Call xml.Send
Print "Content-Type:text/html"
Print "Cache-Control:NoCache"
Print Cstr(xml.ResponseText)
Set xml = Nothing
End Sub
Well very simple... but the person who coded it, didnt show any example...
HE says only:
Finally, you create an AJAX call on your page that calls the agent you created and pass the URL you want to retrieve as a query string parameter. That's all it takes to basically have one AJAX call access another AJAX call to get data from some other domain.
as my problems are with NAB,DA ... will this work at first?
if yes, could you open my mind with some examples of retrieving others serverīs names.nsf?
TIA
/ fferrandini
22. Michael Sobczak07/18/2006 11:20:09 AM
Homepage: http://www.punkdbynotes.com
Hey Scott,
I want to clarify the following statement:
"One of the security limitations of AJAX is it cannot access data from servers other than the one it's running on."
In IE, if you set the "Access data sources across domains" Security setting to "Enable", doing what Fernando describes will work. In fact, I've just done exactly that, and it works fine.
However, I heard that Mozilla doesn't having a setting like this at all, making this development option prohibitive for that browser (and all its derivitives). Has this been your experience as well?
FWIW, I'll probably be going the agent route described above, as I don't think I'll be able to get my company to sign off on changing that browser setting.
23. M D McNamara07/31/2006 12:06:18 PM
"However, I heard that Mozilla doesn't having a setting like this at all, making this development option prohibitive for that browser (and all its derivitives)."
You know, there's probably a reaaaaaal good reason for that...
24. Luis09/05/2006 11:18:08 AM
Very interresting work !
In my case i have just a little problem with multi selection, when i select more people than parameter the buttons for navigation go down.
25. Dave Navarre10/10/2006 03:08:42 PM
Homepage: http://www.centretek.net
My co-worker, Elvis Lezcano, found this and did some good work to implement it in some of our applications. I made one relevant modification that handles the lack of proper sorting of names you mentioned.
We wanted to allow the user could get to the name by typing in LastName, FirstName. So, we created a view of the names with the first sorted column as LastName[space][comma][space]FirstName so that all names would be sorted correctly. The second column displays it the way the user would like to see it - without the extra space before the comma. So, when we have the picker call it, we use columns=1. The trouble is, that with the sort being with the space, we had to translate any user input to re-insert that space.
function doSearch() {
try {
var search = document.getElementById("search").value;
//no space before or after the comma
var commaspot = search.indexOf(",");
//no space before or after the comma
var namessplit = search.split(",");
if ( commaspot != -1 ) {
//there is a space before the comma, but not after
search = namessplit[0] + " ," + namessplit[1];
alert ( search );
}
if (search != "") {
var xmlDoc = doXMLHTTPGet(URLPrefix + "/" + dbPath + "/" + view + "?readviewentries&startkey=" + escape(search) + "&count=" + count);
} else {
var xmlDoc = doXMLHTTPGet(URLPrefix + "/" + dbPath + "/" + view + "?readviewentries&startkey=a&count=" + count);
}
}
catch (e) {
document.getElementById("namelist").innerHTML = errormessage + e. message + " (" + e.name + ")";
}
}
This way, the user gets a list sorted correctly by last name and first name, while dsiplaying without extraneous spaces AND can type as he sees it in the search box.
We're using the single picker for both name lookups (against the NAB and against a list of approvers in a different db) and selection of items from a list (so, we're using it a lot - thanks!)
Hopefully, that helps you with your hurdle.
Dave Navarre
Centretek
26. Aigars10/17/2006 10:17:31 AM
Found one small bug... any ideas how to solve?
If I choose large set of users then bottom of dialog box start disaper.
http://img373.imageshack.us/img373/5238/bugsn7.jpg
27. Scott Good10/24/2006 10:29:40 AM
Homepage: http://www.scottgood.com
Interesting point. OK, the trick here is to use a little CSS to handle the overflow. On the NAB picker form, add this to the CSS already there:
#selectedVals {
height: 280px;
overflow-y: scroll;
}
Then, in the JS Header, change the displayCurrentValues() function to read like this:
function displayCurrentValues() {
aValues.sort();
var storedlist = document.getElementById("storedlist");
var strHTML = "<div id=\"selectedVals\"><table width=\"100%\">";
if (aValues.length > 0) {
for (var iValue=0; iValue<aValues.length; iValue++) {
strHTML += "<tr class=\"normal\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal'\" onClick=\"removeValue(" + iValue + ");\">";
strHTML += "<td>" + unescape(aValues[iValue]) + "</td>";
strHTML += "</tr>"
}
} else {
strHTML += "<tr class=\"normal\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal'\">";
strHTML += "<td>Click any name to add it to this list</td></tr>";
}
strHTML += "</table></div>";
storedlist.innerHTML = strHTML;
}
That should make it scroll vertically once you have too many names.
The only problem? It only works in IE.
Scott
28. Lomix10/25/2006 03:12:11 AM
10x! Now it works on my FF 1.5.0.7 and IE 6.0
Best regards ;)
29. Haseeb Iqbal03/05/2007 11:24:06 PM
I've installed the script as directed.
In the pick list where the names should appear, give following error message There has been an error displaying the data:
'null' is null or not an object (TypeError)
What I am really doing wrong?
Thanks in advance.
30. Scott Good03/11/2007 01:18:40 PM
Homepage: http://www.scottgood.com
Haseeb,
You aren't logged in. Almost certainly your NAB does not allow Anonymous access.
Scott
31. Sean McKendall03/27/2007 10:29:43 AM
Scott,
I'm seeing the same error as Haseeb, although it depends on the role I give the user. Also, I only see the error when I try typing a name in Search box. Any suggestions?
- Sean
32. Scott Good03/27/2007 12:27:39 PM
Homepage: http://www.scottgood.com
Hm. The only time I've seen this error (and I have seen it), is when the user doesn't have the authority to access the data. I've never seen an instance where logging in wouldn't solve the problem, assuming that I'm allowed into the NAB (or wherever you're searching).
Scott
33. Sean McKendall03/27/2007 12:35:11 PM
So my issue really is that many of my users aren't authorized to access the NAB. This is the way I'd prefer it. Should I really use this NAB picker if my authenticated users don't have access to the NAB?
- Sean
34. Scott Good03/27/2007 02:09:11 PM
Homepage: http://www.scottgood.com
If your users don't have access to the NAB, there's no way this will work. It IS possible to take this picker and point it at another database, though. I don't have it right here in front of me but I believe this is documented on the NAB picker form somewhere. You can add parameters to the URL to go to a different database/view and look up values from there. This, too, is subject to what your users are allowed to see/do.
Scott
35. Simon Brown03/28/2007 11:46:43 AM
Homepage: http://www.simes.org/
I had this exact same problem but worked around it by creating an agent which duplicates the relevant functionality of ReadViewEntries. If you sign the agent with an ID which has access to the appropriate views in the NAB, the users don't need to be able to access the NAB for the name picker to work.
It's still less secure than no access to the NAB at all, obviously, as savvy people can launch the agent and read the contents of the view that way, but it might be an acceptable compromise.
It's here: http://www.simes.org/?p=124
(apologies for the slightly dodgy formatting in the displayed code, the new template I am using isn't quite optimised for code display)
36. Kurt04/25/2007 04:17:07 PM
Hey Mark,
In the post where you say you "changed the JS to create an associative array", I have tried replacing the portion of the JS header where that code seems to fit. However, I am now getting an error:
There has been an error displaying the data:
'displayColumns' is null or not an object (TypeError)
Any suggestions? Was the code posted complete?
37. Scott Good04/25/2007 05:24:20 PM
Homepage: http://www.scottgood.com
Kurt,
Your error sounds like what you get if you aren't logged in properly.
FWIW,
Scott
38. Mark Holloway04/25/2007 06:09:10 PM
great picker... just what i've been looking for...(javascript newbie)
just one problem i am having ..
Browser JS error "Error : 'isNewDoc' is undefined
i have the computed text and it is show as true ???
i am truing the single & multiple options
any ideas
Thanks
39. Mark Holloway04/25/2007 06:25:21 PM
solved it....
i didnt have pass through html on the computed text ...
now its great
40. Kim Holschuh04/25/2007 06:42:17 PM
Hi Scott,
I think this NAB picker is amazing! I am really NEW at lotus notes and web databases (only been doing this for 2 months) and I'm having a problem with saved documents. I got it working on NEW documents and it's brilliant. If I create a new document, the picker works like a charm. The problem happens if I open a saved document to edit it and try to select a new name or select a name for a field that was left empty the picker gives me the error, "Page cannot be displayed". Can you help me with this?
Thanks so much,
Kim
41. Mark Holloway04/25/2007 07:51:38 PM
Scottm
I too have a problem.... the picker works great... and form is saved.
but i need to use the data saved in the fields these values arent saved..
what am i missing to save the data in a field for later use...
Thanks Mark
42. Scott Good04/26/2007 08:51:35 AM
Homepage: http://www.scottgood.com
Mark/Kim,
The problem you're having is one of realms (at least that's the most likely source). When you have a new document, it has a URL more or less like this:
http://yourServer/yourDB.nsf/formName?Open
After you have saved the document and then re-open it from a view, there's an additional level in the URL, like this:
http://yourServer/yourDB.nsf/THEVIEW/documentKey?Open
If you are using a referential URL to call the NAB picker--that is, a shortened URL--then you have to account for the extra level in the URL. So, for instance, if you're calling it from a new document with something like this...
window.open('NABPickerMulti?open&returnfield=...
...to get to the same place from a document opened from a view you would need to do this...
window.open('../NABPickerMulti?open&returnfield=...
I frankly don't remember exactly what code is out here but we have a function we call when we use the AJAX NAB Picker that accounts for this based on the isNewDoc JS variable. Another approach would be to use @WebDbName in some computed text to work out the right URL. That would be more like this:
window.open('/<ComputedText>/NABPickerMulti?open&returnfield=...
...with the <ComputedText> item having a formula of @WebDbName. Almost certainly this is what's causing your problem(s).
Scott
43. Kim Holschuh04/26/2007 09:35:38 AM
Thanks Scott,
I understand better now and I was able to fix it by hard coding the URL into the window.open and it looks like this...
http://server/Database.nsf/NABPickerMulti?open&returnfield=...
I was not able to get the computedfield to work, I'm not sure of the correct syntax but I tried this.....
window.open('/ComputedFieldName/NABPickerMulti?open&returnfield=...
and this...
window.open('/+ComputedFieldName+/NABPickerMulti?open&returnfield=...
but this URL would not return the value in the field.
Sorry to be asking such basic questions, I'm kinda embarrassed at my lack of skill right now.
Kim
44. Scott Good04/26/2007 11:10:41 AM
Homepage: http://www.scottgood.com
No problem. Keep in mind what we're doing here is using @Formulas to generate JavaScript code. The problem is, JavaScript knows absolutely nothing about @Formulas...so we need to cheat.
If this were the formula language, you could do something like your example...
window.open('/+ComputedFieldName+/NABPickerMulti?open&returnfield=...
...but that won't work here. In my example, I showed <ComputedText>. My (unstated) assumption was that your code was actually ON the form, inside <script> tags, so you could put a ComputedText object right there in the middle of the code. I could have explained that better.
If your call is in the JS Header or other place where you can put JavaScript code (a button, for instance), my example won't work. On the other hand, what you CAN do is make a JavaScript variable on your form. Again, it has to be inside <script> tags. It might look like this:
<script>
var databasePath = "<ComputedText>";
</script>
Again, the formula for the Computed Text is simply @WebDbName. Then, given that, you can use this variable in your code by doing this:
window.open('/' + databasePath + '/NABPickerMulti?open&returnfield=...
It's pretty easy (once you get the whole story on how to do it). More importantly, it keeps you from hard-coding values into your applications. Hard-coding is almost universally a bad idea.
45. Kurt04/26/2007 03:10:06 PM
Hey Scott,
Thanks for the reply, but I am in fact logged in, I wouldn't even be able to access the db containing the code if I weren't. Your original code works with no problems, it is when I try to incorporate the sorting code posted by Mark that the problem occurs. I was hoping he could confirm that it is complete, and/or point out anything I need to know. Have you tried it?
46. Scott Good04/26/2007 03:36:31 PM
Homepage: http://www.scottgood.com
I haven't had a chance to try it yet. Sorry.
47. Kim Holschuh04/27/2007 03:31:03 PM
Hi Scott,
Thank you so much for your explanation. I really appreciate your help, it works now without hardcoding it.
Kim
48. Chuck Carter05/03/2007 12:06:40 PM
Homepage: http://www.ebsbuild.com
Hi Scott,
This NAB lookup is great. Unfortunately, it looks like I have a problem similar to Kim Holschuh and I don't have enough experience to figure it out. If I create a new 'timesheet' from an embedded view, the NAB lookup works great. If I select an existing timesheet from the embedded view, the form is read-only. When I choose the action to 'Edit' the timesheet, the NAB lookup gives me HTTP 404 - File not found Internet Explorer.
I have the following HTML passthru code at the top of my Timesheet form:
<script language="Javascript" type="text/javascript">
var isNewDoc = "<Computed Value>";
function getSingleName(returnField, specialParameters, isNewDoc) {
if (isNewDoc){
setTimeout("window.open('NABPickerSingle?open&returnfield=" + returnField + specialParameters + "', 'popupWindow', 'toolbar=no,directories=no,status=no,scrollbars=auto,resizable=yes,resize=yes,menubar=no,height=410,width=320')", 1);
} else {
setTimeout("window.open('/<Computed Value>/NABPickerSingle?open&returnfield=" + returnField + specialParameters + "', 'popupWindow', 'toolbar=no,directories=no,status=no,scrollbars=auto,resizable=yes,resize=yes,menubar=no,height=410,width=320')", 1);
}
}
</script>
The first Computed Value = @If(@IsNewDoc; "true"; "false"). The second Computed Value = @WebDbName. I have a button on the form with the value = getSingleName("STManager", "", isNewDoc).
Any help is greatly appreciated.
49. Chuck Carter05/03/2007 03:36:31 PM
Homepage: http://www.ebsbuild.com
Update: Found a solution.
I put a Computed Text (or Value) after both "window.open"s. The value for both = "//"+ @GetHTTPHeader("Host") + "/" + @WebDbName
If you have a better solution, please advise. Thank you.
50. Kathy Street05/30/2007 12:07:30 PM
Scott, thank you for the first NAB picker I took this code and added some things. 1) we use this for all of our file picking. 2) we do a call back function(javascript) so we can split data from the user's one click and prefill fields. 3) I also do a RestrictToCategory - so I can pair down entries per a previous selection.
Just some of the ways we have extended your code. Thanks, appreciate it.
51. Mike Hunter06/11/2007 07:05:42 AM
Scott/Matt, this is fantastic! Thank you!
I have one query, when I add in the changes suggested by Mark Barton to sort the first name column, I start getting errors such as "There has been an error displaying the data:
'displayColumns' is null or not an object (TypeError)".
This seems odd since it works fine (user can access the NAB) before I add that code, anyone got any ideas?
Mike
52. Mark Barton06/11/2007 08:54:35 AM
Error in my sorting code.
Slipped through the QA
There was an idex missing when setting a variable - the following code should work fine:
function displayData(xmlDoc) {
// get areas which we are going to write results into
var namelist = document.getElementById("namelist");
var countlist = document.getElementById("countlist");
//Add new Object Array
var personObjArray=new Array();
var fullnameArray=new Array();
try {
namelist.innerHTML = "Please Wait...";
//Open the XML Document
var root = xmlDoc.documentElement;
results = root.getElementsByTagName("viewentry");
//Get the toplevelentries value each time in case it changes
viewTotalDocs = parseInt(root.attributes[0].value, 10);
for(k=0;k<results.length;k++){
var fullname = getInnerText(results[k].getElementsByTagName("entrydata")[returnColumn]);
var displayColumns=new Array();
for (iCol=0; iCol < columns.length; iCol++) {
//Write each cell of the current row
var text;
try {
text = getInnerText(results[k].getElementsByTagName("entrydata")[parseInt(columns[iCol], 10)]);
}
catch (e) {
text =+ e. message + " (" + e.name + ")";
}
displayColumns[displayColumns.length]= text ;
}
personObjArray[fullname]=new personObj(fullname,displayColumns);
fullnameArray[fullnameArray.length]=fullname;
}
fullnameArray.sort();
var strHTML = "<table width=\"100%\" id=\"nameChoicesTable\">";
for (i=0; i<fullnameArray.length; i++) {
//Get the value which the row will return if clicked
var returnText = fullnameArray;
//Write the tr tag
if (i % 2 == 0){
strHTML += "<tr class=\"normal1 " + escape(returnText) + "\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal1'\" name=" + escape(returnText) + " onClick=\"storeValue('" + escape(returnText) + "');\">";
} else {
strHTML += "<tr class=\"normal2 " + escape(returnText) + "\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal2'\" name=" + escape(returnText) + " onClick=\"storeValue('" + escape(returnText) + "');\">";
}
for (iCol=0; iCol < personObjArray[returnText].displayColumns.length; iCol++) {
//Write each cell of the current row
var text;
try {
text = personObjArray[returnText].displayColumns[iCol];
}
catch (e) {
text =+ e. message + " (" + e.name + ")";
}
strHTML += "<td>" + text + "</td>";
}
strHTML += "</tr>";
}
strHTML += "</table>";
// output the document count details
countlist.innerHTML = results[0].attributes[0].value + " to " + results[results.length - 1].attributes[0].value + " of " + viewTotalDocs + " records";
// output the table HTML
namelist.innerHTML = strHTML;
}
catch (e) {
namelist.innerHTML = errormessage + e. message + " (" + e.name + ")";
}
}
function personObj(fullname,displayColumns){
this.fullname=fullname;
this.displayColumns=displayColumns;
}
53. Mark H06/27/2007 05:46:41 AM
Homepage: http://www.stirnpanzer.com
hi,
great nab picker....
would make it even greater if it could be used to extract say the "internet address" etc ...
is this possible ??
Mark
54. Scott Good06/27/2007 07:52:29 AM
Homepage: http://www.scottgood.com
Hi Mark,
It could probably be made to do that. The way it works right now, though, is by reading views. If you look in the form itself you'll see there's some documentation of extra parameters you can use on the URL to determine which view you look at and which columns are shown and returned. If you can find (or build) a view with the information you want, you could use it that way.
Scott
55. Mark H07/02/2007 09:50:31 AM
Homepage: http://www.stirnpanzer.com
hi Scott,
Still a little confused , i am at the stage where i am using the singlename picker, which displays the:
"lastname" | "firstname" | "internet address"
I select one and it populates a name field,
but i'm at a loss as how to return value of column 3 "internet address" and populate a field (email) with it ??
i'm confused with the "special parameters"
56. Todd Phillips07/03/2007 09:43:08 AM
Hi Scott, I was wondering if you had ever thought about addressing the very small bug (not really) with this relating to duplicate entries?
I have been using the original version of this tool that Matt White wrote for a little more than a year now. I have adapted it to work with other databases, but have ran into a problem. My users are requesting that I eliminate the "names" appearing twice in the list.
Have you noticed this and thought about a solution?
I have been battling it for several days now, but can't seem to come up with a solution that doesn't break anything else.
57. Scott Good07/09/2007 08:17:01 AM
Homepage: http://www.scottgood.com
Todd,
I didn't know there was a problem with duplicate entries.
I didn't know there was a problem with duplicate entries.
Seriously, I haven't really seen probl...oh...I get it...you're pulling values from databases other than the NAB which could have duplicate entries. I can see how that could happen as it's just reading a portion of a view without regard to the actual values of the entries.
We mostly use this for the NAB so it's not really a problem for us. What you could do if this is a problem for you is write a little test in the loop that parses the XML to see if the current value is the same as the one immediately before it and, if so, ignore it. You'll need to get it to return more than 16 values from the initial lookup so you have enough once you discard some of them.
Good luck!
Scott
58. Todd Phillips07/09/2007 10:25:33 AM
Thanks Scott,
I had already taken the step of eliminating the duplicates when parsed, but I couldn't address the Next and Previous button problem. I'll take your suggestion and see if I can't force it to work with me.
Again, thanks for your quick response.
59. Scott Good07/09/2007 01:24:49 PM
Homepage: http://www.scottgood.com
Todd...
You'll have to do something to keep track of which was the last displayed value. In other words, let's say you bring back 25 rows with each query in an effort to get 16 unique values. Sometimes you'll use numbers 1-16 (when there are no duplicates) but others you'll have to dig deeper into the choices.
What you need to know for the Next button is where to start. With the current application it's the 16th (17th?) item. If you may be skipping some because of duplicates you'll need to track which is actually the last one. Sounds like a JS variable to me.
Scott
60. Tomas Bartek10/24/2007 02:13:54 AM
Hi Scott/Matt,
this picklist is amazing, really love it. However, do you know about any way how to return two variables into two fields. I'm using your picklist in the form where users need to decide some values from a view and need use their decision to be linked with an another document. I hope that you know what I mean, I try to solve the classic lotus notes non relational database problem. I want to store in one field a value which a user has chosen and in the other hidden field I want to store a value of the chosen document UNID. Any help with this?
61. Scott Good10/24/2007 06:50:11 AM
Homepage: http://www.scottgood.com
Tomas,
At the end of the day, all this is doing is returning a value from a view. I can think of several ways to do what you're talking about.
Probably the easiest way, if you're allowed to modify the view you're looking up to, is to add a second parameter to the value you get back. In other words, instead of returning "John Doe," your view would return something like "John Doe~93877633:098367B65."
Then, in the storeValue() function (in the JS Header), the function that actually updates the underlying form, you would change the line that reads like this:
fieldReturn.value = unescape(newValue);
...to be more like this...
var nVal = unescape(newValue.split("~"));
fieldReturn.value = nVal[0];
document.forms[0].OtherFieldName.value = nVal[1];
Alternatively, if you're not permitted to mess with the view (as is probably the case in the NAB, for instance), in that same general part of storeValue() you could trigger another AJAX lookup which could get the Document UNID. Remember, though, if you're doing that and want the dialog to close, the AJAX request will have to be called from the underlying form and NOT the NAB-picker dialog.
Let me know how it works out.
Scott
62. Tomas Bartek10/25/2007 11:48:28 AM
Hi Scott, i did it as you suggested and it works awesome. I also created a parameter for the url so it works only for picklists in which I want them to work. However, I made it only for the single selection picklist and tomorrow I'd like to do the same for the multiple selection picklist and I let you know If I come across to any problems. Thank a lot for the hint, which really made my day.
T.
63. Arnaud Rajeanne01/17/2008 06:29:15 PM
Hi Scott
Really great job.
Where can we specify the return value type?
I mean actually it's returning cannonicalize, how do we return the common name?
Got a hidden field that use @name([cn]... but need to save the document for it to get the correct value
64. Annon04/09/2008 02:11:34 PM
can anybody post how they got rid of duplicate names?
65. Anonymous04/18/2008 12:26:55 AM
I'm curious to see Tomas Bartek's solution to his dilemma, I'm lacking some experience and I'm trying to populate an entire Form from the picker. BTW, is there a way to somhow use "twistes" in the view? Embedding a view in a modal window never seems to work out well when doing the NAB, at least for me it doesn't.
66. Q White03/17/2009 12:38:21 PM
Great tool Scott; it is exactly what I need and returns our nab w/15,000 entires in seconds.
I am getting a prompt when using the multi=name selection. Any advice on how I can get rid of it? When I click the button to pick names for the multi field I get a box that says &open&returnfield=MultiNames I click ok about 5 times then it goes away and the multi name selector works fine.
Any way to get rid of this prompt? thanks so much for such a cool tool and time saver.
67. Scott Good03/17/2009 01:11:00 PM
Homepage: http://www.scottgood.com
Hm. I know I've seen this. I'm tempted to say your url is &Open when it should be ?Open. If that's not it, you might take a swim through the comments above because I'm pretty sure somebody has had this problem before.
Send me a note if neither of those works and I'll give it a better try!
Scott
68. Q White03/19/2009 02:20:14 PM
The resolution to the prompt I was getting w/the multi button was to comment out the line alert(strQueryString) in the jsheader of the from AJAX NAB Picker Multi.
69. Kelly Kerr03/23/2009 09:53:38 AM
Hi Scott.. (New to lotus development) I need to integrate iNotes (Forms85)calendar Name Picker with a lagacy DB2 name and address database. Would AjaxNab be a candidate for ths application? Essentially from the Calendar entry form there is an Invite: button that pop's up a page for selection of users. I would like to replace this page with your selection page but access my DB2 name and address database. Any comments would be appreciated.. Thanks
70. Scott Good03/23/2009 12:06:55 PM
Homepage: http://www.scottgood.com
Hi Kelly,
Interesting problem. This NAB picker uses a background agent (called via AJAX) to actually go and retrieve data from the address book. I don't know why you couldn't tweak the agent to retrieve it from DB2.
Sounds do-able to me.
Scott
71. john brooks04/06/2009 11:05:57 AM
Hi Scott,
I am using the single picker to populate an "internet address" field from a customised version of ($VIMPeopleByLastName) whichj is working perfectly. I am a novice at this and would like to populate a second field from another column in the same view but it is beyond me how I can pass the second field parameter and modify the code to acheive this. Any advice you can give will be greatly appreciated.
Thanks in advance.
72. Scott Good04/07/2009 07:03:47 AM
Homepage: http://www.scottgood.com
John,
I think you're probably going to have to tweak the code a bit to do that. I don't have it in front of me right now but if you look at the OK button you'll see the function that's called there. You can go into that function and make it do what you want it to do.
I'm pretty sure the NAB picker only returns one value the way it's set up now so the easiest way to get two is probably to combine them in the column you're currently looking the e-mail address up from. For instance, if you wanted to get the e-mail and phone number you might combine them like 614-555-1212~jdoe@acme.com and then in your JavaScript do a .split() on the tilde and get two elements which you can then put into your two fields.
Hope this helps.
Scott
73. Alyn07/01/2009 09:44:39 AM
Mark,
There is no difference in the second block of code you posted for fixing the displayColumns error. Still receive this error with the second block.
Any ideas?
74. Alyn07/01/2009 11:19:14 AM
Correction should be this...
for (iCol=0; iCol < personObjArray[returnText].displayColumns.length; iCol++) {
//Write each cell of the current row
var text;
try {
text = personObjArray[returnText].displayColumns[iCol];
}
catch (e) {
text =+ e. message + " (" + e.name + ")";
}
75. Alyn07/01/2009 11:21:36 AM
Looks like this forum is converting the SQUARE BRACKET i SQUARE BRACKET to italics.
Where the XXX is you need to put SQUARE BRACKET i SQUARE BRACKET
for (iCol=0; iCol < personObjArray[returnTextXXX].displayColumns.length; iCol++) {
//Write each cell of the current row
var text;
try {
text = personObjArray[returnTextXXX].displayColumns[iCol];
}
catch (e) {
text =+ e. message + " (" + e.name + ")";
}
76. Alyn07/01/2009 11:24:43 AM
Code needs to be like this. Replaced i with j to make it clearer!!
function displayData(xmlDoc) {
// get areas which we are going to write results into
var namelist = document.getElementById("namelist");
var countlist = document.getElementById("countlist");
//Add new Object Array
var personObjArray = new Array();
var fullnameArray = new Array();
try {
namelist.innerHTML = "Please Wait...";
//Open the XML Document
var root = xmlDoc.documentElement;
results = root.getElementsByTagName("viewentry");
//Get the toplevelentries value each time in case it changes
viewTotalDocs = parseInt(root.attributes[0].value, 10);
for(k = 0; k < results.length; k++) {
var fullname = getInnerText(results[k].getElementsByTagName("entrydata")[returnColumn]);
var displayColumns = new Array();
for (iCol = 0; iCol < columns.length; iCol++) {
//Write each cell of the current row
var text;
try {
text = getInnerText(results[k].getElementsByTagName("entrydata")[parseInt(columns[iCol], 10)]);
}
catch (e) {
text =+ e. message + " (" + e.name + ")";
}
displayColumns[displayColumns.length] = text ;
}
personObjArray[fullname] = new personObj(fullname, displayColumns);
fullnameArray[fullnameArray.length] = fullname;
}
fullnameArray.sort();
var strHTML = "<table width=\"100%\" id=\"nameChoicesTable\">";
for (j = 0; j < fullnameArray.length; j++) {
//Get the value which the row will return if clicked
var returnText = fullnameArray;
//Write the tr tag
if (j % 2 == 0) {
strHTML += "<tr class=\"normal1 " + escape(returnText) + "\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal1'\" name=" + escape(returnText) + " onClick=\"addValue('" + escape(returnText) + "');\">";
}
else {
strHTML += "<tr class=\"normal2 " + escape(returnText) + "\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal2'\" name=" + escape(returnText) + " onClick=\"addValue('" + escape(returnText) + "');\">";
}
//for (iCol = 0; iCol < personObjArray[returnText].displayColumns.length; iCol++) { // Its bailing out here
for (iCol = 0; iCol < personObjArray[returnText[j]].displayColumns.length; iCol++) { // Its bailing out here
//Write each cell of the current row
var text;
try {
text = personObjArray[returnText[j]].displayColumns[iCol];
}
catch (e) {
text =+ e. message + " (" + e.name + ")Inside loop";
}
strHTML += "<td>" + text + "</td>";
}
strHTML += "</tr>";
}
strHTML += "</table>";
// output the document count details
countlist.innerHTML = results[0].attributes[0].value + " to " + results[results.length - 1].attributes[0].value + " of " + viewTotalDocs + " records";
// output the table HTML
namelist.innerHTML = strHTML;
}
catch (e) {
namelist.innerHTML = errormessage + e. message + " (" + e.name + ")";
}
}
function personObj(fullname, displayColumns) {
this.fullname = fullname;
this.displayColumns = displayColumns;
}
77. Scott Good07/01/2009 11:30:28 AM
Homepage: http://www.scottgood.com
Alyn,
Thanks much for posting this. I've been slammed with a big project for the last couple months and haven't had much of a chance to figure out what's going on here. One of the guys in my office was going to take a look at this later today so--thanks--I'm sure you've saved him a lot of trouble!
Scott
78. Alyn07/01/2009 04:26:28 PM
Hmmmm had me puzzled for quite a while!! I figured out the missing index so decided to post it here! Found it really strange when it just dissappeared, then noticed the UUB code!!!
One guy at the office said to me, "another reason not to use 'i' as an array accumulator!" lol
I have found the sorting to be not quite how I want it, so might have a play to adjust it slighty.
Thanks for this anyway, It's absolutely brilliant!
For your info, I've actually ported the code over to a classic ASP application whereby there was a requirement to access a Domino Address Book to pick names. Needless to say, it works perfectly, and lightning fast!!
Cheers!
79. Scott Good07/01/2009 05:04:20 PM
Homepage: http://www.scottgood.com
That's cool! Thanks for sharing.
80. Alyn07/02/2009 03:53:44 AM
There is another small bug caused by the forum stripping out the accumulator. I figured when I selected names it was putting the whole array in, instead of the selected value.
This should fix it.
//Write the tr tag
if (j % 2 == 0) {
strHTML += "<tr class=\"normal1 " + escape(returnText[j]) + "\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal1'\" name=" + escape(returnText[j]) + " onClick=\"addValue('" + escape(returnText[j]) + "');\">";
}
else {
strHTML += "<tr class=\"normal2 " + escape(returnText[j]) + "\" onMouseOver=\"this.className='highlight'\" onMouseOut=\"this.className='normal2'\" name=" + escape(returnText[j]) + " onClick=\"addValue('" + escape(returnText[j]) + "');\">";
}
81. James Sanders09/08/2009 04:25:46 PM
Bug report
One of the other guys here at Teamwork was recently implementing this NAB picker into an app he's working on. While doing that he noticed a bug with the display of the "1 to 16 of 162" (basically the page count). His app was showing "1 to 16 of 20090909...." (a time stamp).
It turns out that the issue came from a change in the Domino server from R7 to R8 and the ReadViewEntries of the related view from the NAB. Looking at the display of the returned XML it appears Lotus added a new attribute to the viewentries node... and since the nab picker references the array index of the toplevelentries attribute we had a problem. Here's some sample XML:
R8:
-<viewentries timestamp="2009..." toplevelentries="162">
R7:
-<viewentries toplevelentries="162">
Solution
1. Open the "(AJAX NAB picker single)" and "(AJAX NAB picker multi)" form designs and go to the displayData function in the JSHeader.
2. Change the following line of code from:
viewTotalDocs = parseInt(root.attributes[0].value, 10);
to:
viewTotalDocs = parseInt(root.attributes.toplevelentries.value, 10);
82. James Sanders09/10/2009 01:44:36 PM
One minor correction to the previous post to make things cross browser compatible. The posted code works in Firefox but not in IE.
Use this line of code for script code at step 2:
viewTotalDocs = parseInt(root.getAttribute('toplevelentries'), 10);
83. Vinay Shindre11/26/2010 06:19:43 AM
We are getting the error 'Problem retrieving XML data:Internal Server Error' while using the Ajax NAB picker. any clue on debugging this issue. i can also paste the screen shot of the error...but not sure how i can attach it here.
Thanks in advance,
Vinay
84. Scott Good11/26/2010 08:28:59 AM
Homepage: http://www.scottgood.com
Hi Vinay,
What server version are you using? Is it possible there's some kind of security setting preventing you from doing this?
You can contact me directly at my regular e-mail address if that's simpler (which it probably is). sgood AT teamsol DOT com.
Scott

























