Writing comboboxes on the fly
Writes comboboxes dynamically, by looking at a hidden field containing the data - a sort of pseudo-DBLookup in JavaScript
In the Notes client, you often have a series of comboboxes where the
value in one, determines the list of choices in the next, a common
example being "Main Category", "Sub Category1", "Sub Category 2".
When doing this on the Web, using the built-in "refresh fields on
keyword change etc" feature, it works, but can cause the screen to
jump around as all the fields are refreshed.
I had a user who didn't like this, so this is the solution I came up
with that writes comboboxes dynamically, by looking at a hidden
field containing the data - a sort of pseudo-DBLookup in
JavaScript.....
An alternative to using "refresh fields on keyword change" and
"refresh choices on document refresh" involves 4 parts
1) A Lookup view, that contains the values in a single column,
using a predefined separator - I use the pipe symbol |
2) A hidden lookup field on the form that does a dbcolumn on the above view
3) Some JavaScript to process the hidden field above
4) A field that contains the lookup value and a hotspot on the field
that triggers the above JavaScript
As follows
1) Create a view - for example, I called in "LookupStaffDivisions",
and it should have only one column, which contains multiple values
separated by a common separator. In my case I used the pipe symbol
'|' which is also in the JavaScript code. An e.g. of the column
contents is:
HR|Bob Jones
HR|Mike Smith
Admin|Sarah Joyce
Admin|Bill Clinton
2) Create a hidden field on the form that looks this up e.g.
<input type="hidden" name="lookupSomeValue"
value="[SOMECOMPUTEDFIELD]" >
Everything in the line above is passthru HTML. The
[SOMECOMPUTEDFIELD] is replaced with a field that is
computed when composed and contains a dbcolumn on some view. A
sample formula for the field is below:
(Note the space " " at the end of the value of t1 - this is needed
due to the counting starting at 0 in JavaScript)
Sample field value:
t1:=@DbColumn("":"Nocache" ;"" ; "LookupStaffDivisions" ; 1) : " "; @Text(t1)
3) The JavaScript code (in the JSHeader)
function getLookupList( key, fieldToChange, fieldLookupValues ){ //take a field containing the list values and add them //to an array var inVal=fieldLookupValues; var allValues=new Array(); var count=0; var beg=0; var end=0; while (end!=-1){ end=inVal.indexOf(";", beg); allValues[count]=inVal.substring(beg,end) beg=end+1 count++ } //get the number of documents in the array var numOfDocs = count var sLookupResult=""; var sCurrentValue=""; var k=0; var returnValues=new Array(); //now parse the array looking for the key for (i=0 ; i < numOfDocs ; i++ ){ sCurrentValue=allValues[i]; iFound=inStr(1, sCurrentValue.toLowerCase() , key.toLowerCase() ); if (iFound > 0 ){ sLookupResult=getEnd(sCurrentValue ,"|" ) returnValues[k]= sLookupResult; k++; } } //as we are working in base 0, subtract 1 from the total max=k-1 /*depending on the field type that is being changed, display the
output. So far it's only set to work with comboboxes, as well as a
straight dump to the document if the field isn't found */
if ( fieldToChange == null ) { //field not found, so output to the document - alternatively
you could //write an error message. Normally I write the result into an IFrame. document.open() document.write("<table cellpadding='0' cellspacing='0'
border='0' bgcolor='#FEFEFE'> ") for(k=0 ; k<max ; k++){ document.write( returnValues[k] ) } document.write("</table>") } else if ( inStr( 1, fieldToChange.type , "select" )) { //the field type is combo box (html SELECT statement) //reset the max number of options fieldToChange.options.length=null //update the combobox, check how many results are to be returned if (max<1){ fieldToChange.options.length=1 fieldToChange.options[0].text = "None available" }else{ //add 1 to max to allow the first item in the list to be
set to "Please select one" fieldToChange.options.length=max + 1 //set the first option in the list to be "Please select one" fieldToChange.options[0].text="Please select one" //now add the results to the end of the combobox for(k=0 ; k<max ; k++){ fieldToChange.options[k+1].text = returnValues[k] } } } } /* The below are various Javascript equivalent of LotusScript
functions, taken from various sources - mostly from the
"Javascript Bible 3rd edition" by Danny Goodman*/ function inStr(beginning, word1, word2) { check1 = new String(word2); returnInStr = word1.indexOf(word2, (beginning - 1)) + 1; return returnInStr; } function mid(inputMid, pos, l) { pos = pos - 1; if ((pos < inputMid.length) && ((pos + l) <= inputMid.length)) { returnMid = inputMid.substring(pos, pos + l); } else { returnMid = ""; } return returnMid; } function replaceSubstring (inputString, badString, goodString, caseSensitive) { fixedReplace = ""; UI = inputString; UB = badString; if ((caseSensitive != 1) && (caseSensitive != true)) { UI = inputString.toUpperCase(); UB = badString.toUpperCase(); } badEnd = -1; badLoc = UI.indexOf(UB); if (badLoc != -1) { for (x=1; (badLoc != -1); x++) { fixedReplace = fixedReplace + inputString.substring((badEnd + 1), badLoc) + goodString badEnd = badLoc + UB.length - 1; badLoc = UI.indexOf(UB, (badLoc + 1)); } fixedReplace = fixedReplace + inputString.substring((badEnd + 1), inputString.length); } else { fixedReplace = inputString; } return fixedReplace; } // similar to the StrLeft function function getFront(mainStr, searchStr ){ foundOffset = mainStr.indexOf(searchStr) if ( foundOffset == -1 ) { return null; } return mainStr.substring(0, foundOffset ); } // similar to the StrRight function function getEnd(mainStr, searchStr ){ foundOffset = mainStr.indexOf(searchStr) if ( foundOffset == -1 ) { return null; } return mainStr.substring( foundOffset + searchStr.length, mainStr.length); }
4) The code for the JavaScript hotspot, which causes the contents
of a combobox to be changed dynamically.
form=document.forms[0]; key=form.Division.options[form.Division.selectedIndex].text; getLookupList( key, form.StaffList, form.lookupSomeValue.value)
In the above code, Division is the name of the first combobox, which
when selected changes the contents of the 2nd combobox which is
called StaffList, providing a quick way of doing a dblookup without
the issues of the screen jumping around when a refresh occurs.