Hi,
it's very easy to make a list of items scrollable - and it works like a charm.
Except one thing - the scroll position.
Assume the users scrolls down and selects an item.
Then he expands another group (SingleSelect mode is set).
Later he expands the previously selected group.
He sees the items list - but the selected one is "somewhere".
The same problem happens with data binding.
Assume a serverside selected item - way down in the scroll area.
So what the user gets is a "where is the item" situation.
My first thought was to use the "OnClientItemExpand" event.
The documentation says:
OnClientItemExpand occurs immediately after an item is expanded
But "after" is not really after as it looks.
My first approach was this:
Not really a problem - I locked the function like this:
This makes me think the event fires not "after" it is expanded.
My final approach is:
This works - but I'm not really happy with that approach.
Assume somebody decides to use a longer animation duration or something like this.
If I set "ExpandDelay" to (let's say) 500 - my workaround does no long work.
OnClientItemExpand fires as soon as I click the expand arrow - and not (as documented) "immediately after an item is expanded".
My Question - is there a better approach to solve this problem?
Or did I miss something in the documentation?
Manfred
it's very easy to make a list of items scrollable - and it works like a charm.
Except one thing - the scroll position.
Assume the users scrolls down and selects an item.
Then he expands another group (SingleSelect mode is set).
Later he expands the previously selected group.
He sees the items list - but the selected one is "somewhere".
The same problem happens with data binding.
Assume a serverside selected item - way down in the scroll area.
So what the user gets is a "where is the item" situation.
My first thought was to use the "OnClientItemExpand" event.
The documentation says:
OnClientItemExpand occurs immediately after an item is expanded
But "after" is not really after as it looks.
My first approach was this:
Snippet created with CBEnhancer
function OnExpand(sender, args) {
var iTem = args.get_item();
if (iTem.get_level() != 0) {
return; //only interest in top level items
}
var items = iTem.get_items();
for (var i = 0; i < items.get_count(); i++) {
if (items.getItem(i).get_selected()) {
items.getItem(i).focus();
return;
}
}
}
This results in a stack overflow - it seems setting the focus calls OnExpand again.function OnExpand(sender, args) {
var iTem = args.get_item();
if (iTem.get_level() != 0) {
return; //only interest in top level items
}
var items = iTem.get_items();
for (var i = 0; i < items.get_count(); i++) {
if (items.getItem(i).get_selected()) {
items.getItem(i).focus();
return;
}
}
}
Not really a problem - I locked the function like this:
Snippet created with CBEnhancer
var didFocus = false;
function OnExpand(sender, args) {
if (didFocus) {
return;
}
var iTem = args.get_item();
if (iTem.get_level() != 0) {
return; //only interest in top level items
}
var items = iTem.get_items();
for (var i = 0; i < items.get_count(); i++) {
if (items.getItem(i).get_selected()) {
didFocus = true;
items.getItem(i).focus();
didFocus = false;
return;
}
}
}
No more stack overflow - but an error message that an invisible item can't get the focus.var didFocus = false;
function OnExpand(sender, args) {
if (didFocus) {
return;
}
var iTem = args.get_item();
if (iTem.get_level() != 0) {
return; //only interest in top level items
}
var items = iTem.get_items();
for (var i = 0; i < items.get_count(); i++) {
if (items.getItem(i).get_selected()) {
didFocus = true;
items.getItem(i).focus();
didFocus = false;
return;
}
}
}
This makes me think the event fires not "after" it is expanded.
My final approach is:
Snippet created with CBEnhancer
var curSelItem;
function DoFocus() {
curSelItem.focus();
}
function OnExpand(sender, args) {
var iTem = args.get_item();
if (iTem.get_level() != 0) {
return;
}
var items = iTem.get_items();
for (var i = 0; i < items.get_count(); i++) {
if (items.getItem(i).get_selected()) {
curSelItem = items.getItem(i);
setTimeout("DoFocus()", 500);
return;
}
}
}
var curSelItem;
function DoFocus() {
curSelItem.focus();
}
function OnExpand(sender, args) {
var iTem = args.get_item();
if (iTem.get_level() != 0) {
return;
}
var items = iTem.get_items();
for (var i = 0; i < items.get_count(); i++) {
if (items.getItem(i).get_selected()) {
curSelItem = items.getItem(i);
setTimeout("DoFocus()", 500);
return;
}
}
}
This works - but I'm not really happy with that approach.
Assume somebody decides to use a longer animation duration or something like this.
If I set "ExpandDelay" to (let's say) 500 - my workaround does no long work.
OnClientItemExpand fires as soon as I click the expand arrow - and not (as documented) "immediately after an item is expanded".
My Question - is there a better approach to solve this problem?
Or did I miss something in the documentation?
Manfred