How to auto-scroll an XUI listbox?

Keith Berard shows (among other things) how to auto-scroll an XUI listbox depending on the input in a textbox. Last Updated: 2006-10-24

=Question by N.N.=

Using ACL, I am setting the listitems using dlgitem_set_list_array:

$retvalue = dlgitem_set_list_array($win, "lstExpansion", $arr_expansion) $retvalue = dlgitem_set_refresh($win,"lstExpansion",1);

When the XUI is invoked I see all the list. I have seen code how to get the selected item from the user Group. I wonder if any one has a code, how to iterate through the existing listbox items and do autoscrolling.

I am using JavaScript as the language.

Is there a way that we can filter out only the events such as onkeypress events from the Domactivate event?

=Keith Berard answers=

As far as I know (at least as of 5.1M) the XUI controls do not throw any mouse events or the like. That said, I'm also pretty sure that DOM doesn't specifically handle keyboard clicks.

However, I know you can trap keyboard presses within Epic, and can control (for the most part) many parts of the XUI. Combining these two may be the answer.

Unfortunately, I'm not quite certain what you're trying to do. What do you mean by autoscrolling? From my experience, if I have a listbox that is very large (has a v scrollbar) it will auto scroll down if you programatically select an item in the box. We use this extensively to give context-specific information as the user mouses over various tags within the edit document.

That said, I believe it would be fairly trivial to trap navigation keys and select an item in the list based upon this. I can probably get an example together if this is what you mean... but I'll let you respond first.

=N.N. replies=

My requirement is I need to auto scroll based on the text user typed on a textbox. I need to iterate through the list, which I do not know how to do? Based on closest the user typed I need to select the listitem.

=Keith Berard answers=

Ok, I believe this does what you're asking for.

I'm not all the up on my javascript (primarily work in java) but it seems to work fine, I just may be checking for nulls when I don't need to.

Anyway, if you open this in Epic, and go to Tools -> View Dialog you should get a little popup with a text box and a list. The list is a bunch of fruit. If you type "p" it will select pear, "po" will select pomegranate, etc.

Let me know if this does the trick.

P.S. Not many bells and whistles... eg: it's case sensitive right now. You also may want to consider using some kind of regex for the match to avoid spacing issues. Also, someone may want to comment on my use of addlistener, since I always get the last boolean parameter wrong.

 <!DOCTYPE window PUBLIC "-//Arbortext//DTD XUI XML 1.0//EN"" xui.dtd">       <![CDATA[ var xuiwin = Application.event.target; var xuidoc = xuiwin.dialogView.document; var itemText = xuidoc.getElementById('myTextBox'); var itemList = xuidoc.getElementById('myListBox'); function handleEvent(e) { if ( e.type.equals('DOMSubtreeModified')) { if (itemText != null && itemText.hasChildNodes) { var matchVal = itemText.getFirstChild .getFirstChild.getNodeValue; if (matchVal != null && matchVal.length > 0) { var children = itemList.getChildNodes; for (var i = children.getLength - 1; i>=0; i--) { var curLabel = children.item(i).getAttribute("label"); if (curLabel.substring(0, matchVal.length).equals(matchVal)) { itemList.setAttribute("value",curLabel); }                   }                }            }        }    }    var o = { handleEvent: handleEvent }; var listener = Packages.org.w3c.dom.events.EventListener(o); itemText.addEventListener("DOMSubtreeModified", listener, false); ]]>

P.P.S One other thing... I just noticed that if you type more characters than the shortest item (in this case, pear, so 4) it will throw an exception. Just need to check that before doing:

curLabel.substring(0, matchVal.length )

Since in that case, the substring would be bigger than the actual item in the list.

=N.N. continues=

Is there a way that I get array values from ACL to XUI?

Inside XUI script code is like:

Var arr_list[]; var cmd="sis_bill::get_bill_array_list(arr_list)"; Acl.execute(cmd); ACL code: function get_bill_array_list(arr_list[]){ for ($i=1; $i<=100;$i++){ # I have some business logic routine here, but I modified this to get the list arr_list[$i]=$i; } }

I am able to generate the arr_list in ACL code and verified using responses that I got the arr_list.

After the call executed, in XUI I was thinking that the arr_list variable will fill up with the array list. I see always the count of the XUI array is 0.

Am I doing something weird?

=Keith Berard=

I'm afraid you're confusing ACL variables with javascript variables. They are distinct, and if you want to pass from one to the other you have to do so explicitly.

It's a little more challenging with arrays, because the types don't correspond directly. The usual way to handle this is to "encode" the ACL array to a delimited string and then "decode" the string in javascript. So, your code should look something like this:

var cmd="sis_bill::get_bill_array_list(arr_list)"; Acl.execute(cmd); // get arr_list as a string of the form "item 1,item 2,...,item x" var aclarray = Acl.eval("join(arr_list)"); // convert string back to an array var arr_list = aclarray.split(",");

=N.N. replies=

The code works great in setting the selected list item! Thanks for helping me out. But, the way we would like to implement is for example, if we see the Index tab under Epic Editor Help, when user types some word in the Type in the keyword to find: text box, the corresponding item is highlighted and moved to the top.

I looked into some of the XUL Listbox methods. It does provide some of the events SrollToIndex (Index). I tried using those methods like itemList.selectItem(itemList.item(bestScrollIndex)); and I receive a java method error.

=Keith Berard=

I think it's safe to say that you can pretty much ignore most of the XUL specific methods. Arbortext loves their W3C DOM, so unless it's in the DOM spec, I'd be very surprised to see it implemented. (Heck, mouse events aren't available and they _are_ a part of DOM)

Unfortunately, there's no way to force the box to scroll that I know of. You may be able to "hack" in a solution... for example, if you change the code I sent to:

if (curLabel.substring(0, matchVal.length ).equals(matchVal)) { itemList.setAttribute("value", children.item(children.getLength -1).getAttribute("label")); itemList.setAttribute ("value", ""); itemList.setAttribute("value",curLabel); }

What this does is first selects the bottom item, then none, then the item matched. This will force the item matched to go to the top. However, this will only work for items that aren't on the last page, so you may have to add empty items at the bottom to pad... ugh. (and ugly)

So I guess the short answer is no, it can't be done as far as I know... at least not with any consistency or without being annoying.

You'll probably find that you need to sacrifice some functionality for usability with XUI. I mentioned the above refresh example in your list. Likewise, when using a tree, refresh is horrible if you attempt to change the tree icons, whereas using the default [+] [-] refreshes beautifully.

I think XUI is certainly a powerful way to create interfaces using XML, however the implementation lacks many of the bells and whistles you might be accustomed to in other rich UIs. Hopefully Arbortext hasn't closed the door on making enhancements to XUI, but I wouldn't hold my breath.