views:

171

answers:

5

EDIT2:
I omitted the line that updates the UI "urrentNode.set_checked(checked);", and it run amazingly fast. Apparently this is the reason of that performance bottleneck, what do you guys suggest?

Hello SO,

In short, I'm dealing with Telerik's RadTreeView, and I want enable checking all the child nodes if the user checked the parent node. Simple enough! OK here's my code that handles OnClientNodeChecked event of the TreeView:

function UpdateAllChildren(nodes, checked) {

            var i;
            for (i = 0; i < nodes.get_count(); i++) {
                var currentNode = nodes.getNode(i);
                currentNode.set_checked(checked);                    
                if (currentNode.get_nodes().get_count() > 0) {
                   UpdateAllChildren(currentNode.get_nodes(), checked);                   
                }
            }
        }       

        function ClientNodeChecked(sender, eventArgs) {
            var node = eventArgs.get_node();         
            UpdateAllChildren(node.get_nodes(), node.get_checked());
        }

And here's the TreeView's markup:

<telerik:RadTreeView ID="RadTreeView1" runat="server" CheckBoxes="True" OnClientNodeChecked="ClientNodeChecked"></telerik:RadTreeView>

The tree contains quite a lot of nodes, and this is causing my targeted browser (ehm, that's IE7) to really slow down while running it. Furthermore IE7 displays an error message asking me to stop the page from running scripts as it's might make my computer not responsive (yeah, scary enough). So what do you guys propose to optimize this code?
EDIT: Runs pretty fast in firefox and chrome of course. Needles to say, hah?

Thanks in advance

+3  A: 

For sure save your objects for reuse:

var i;
for (i = 0, n=nodes.get_count(); i < n; i++) {
  var currentNode = nodes.getNode(i);
  currentNode.set_checked(checked);
  var curNodes = currentNode.get_nodes();
  if (curNodes.get_count() > 0) {
    UpdateAllChildren(curNodes, checked);                   
  }
}
mplungjan
PS: What does set_checked and UpdateAllChildren do?
mplungjan
mplungjan: The set_checked method sets the checked property of the node. The UpdateAddChildren function is the recursive function that you just suggested changes for.
Guffa
@mplungjan yeah, sure. Done that, however, I didn't notice any difference.
Galilyou
+2  A: 

Avoid repeating calls to the objects. Get the value in a variable and reuse the variable. You don't need to check if the node collection is empty before calling the function, as the function already does that (in the loop condition).

function UpdateAllChildren(nodes, checked) {
  var cnt = nodes.get_count();
  for (var i = 0; i < cnt; i++) {
    var currentNode = nodes.getNode(i);
    currentNode.set_checked(checked);
    UpdateAllChildren(currentNode.get_nodes(), checked);                   
  }
}
Guffa
Please check my edits
Galilyou
Does the `set_checked` call cause the `ClientNodeChecked` event to trigger so that you are updating the children twice (and four times on the next level and so on)? Put a breakpoint or an alert in it to check it. In that case you wouldn't need the recursive call in the function, the event would make it recursive.
Guffa
NO it's not. I checked this and console.log it and, yeah, it was called one time only.
Galilyou
A: 

Profile it in a proper browser to see where it's spending most of its time.

Like @mplungjan says, reuse objects.

It seems unlikely the get_count call is expensive, but if it is you can drop the check before recursing down.

If the library is slow you could possibly cheat and simulate click events yourself.

wombleton
Nope, get_count() is not the expensive part, plz check my edit.
Galilyou
Assume you've tried this: http://www.telerik.com/help/aspnet-ajax/troubleshooting-treeview-script-causes-ie-run-slowly.html
wombleton
Thank you for the link, actually this helped resolving IE's problem dialog. Still no noticeable performance gain, though.
Galilyou
Have you profiled set_checked to see where it's spending most of its time? There might be something in the library you could fix for IE. (hell if I know though)
wombleton
A: 

It's a guess, but I believe that set_checked calls ClientNodeChecked. This is why it's called many more times than it needs to be.

The easiest way to make sure of this is to run it in FF with Firebug, and use console.log to see how it's called exactly.

Mohammad Tayseer
Tayseer, thanks for your answer. I checked with firebug's console, the event is raised only once.
Galilyou
A: 

OK, apparently the problem is that the call to set_checked() is the most expensive part. I omitted it from the code and the recursive call went pretty fast. I also modified the ScriptMode property on the script manager to be "release" and this helped get rid of IE's annoying dialog, but the performance is still as slow. Case closed.

Galilyou