Search code examples
javascriptasp.netperformancetelerikradtreeview

Telerik RadTreeView And Client-Side Expand/Collapse


I'm following this approach to expanding and collapsing all nodes in client JavaScript: http://www.telerik.com/help/aspnet/treeview/tree_expand_client_side.html

However, it's taking a REALLY long time to process this, and after expanding then collapsing, I get the "script unresponsive" error, so I was wondering if there was a way to speed this up for a rather large tree? Is there a better way to parse it? Currently, the tree is 4 levels deep.

Thanks.


Solution

  • I got around the "script unresponsive" errors by expanding and collapsing the tree asynchronously. In addition, I expand from the bottom (so you can see the nodes expand) and collapse from the top, but only when it gets to the last node in each branch, so visually it's far more interesting to the user. They can actually see it happen, and if it's not fast (IE7 and before is particularly slow), it's at least entertaining while they wait.

    var treeView, nodes;
    
    function expandAllNodesAsynchronously() {
        if (<%= expandedLoaded.ToString().ToLower() %>) {
            treeView = $find("<%= tv.ClientID %>");
            nodes = treeView.get_allNodes();
            if (nodes.length > 1) {
                doTheWork(expandOneNode, nodes.length);
            }
            return false;
        } else
            return true;
    }
    
    function expandOneNode(whichNode) {
        var actualNode = nodes.length - whichNode;
        if (nodes[actualNode].get_nextNode() == null) {
            nodes[actualNode].get_parent().expand();
        }
    }
    
    function collapseAllNodesAsynchronously() {
        treeView = $find("<%= tv.ClientID %>");
        nodes = treeView.get_allNodes();
        if (nodes.length > 1) {
            doTheWork(collapseOneNode, nodes.length);
        }
    }
    
    function collapseOneNode(whichNode) {
        if (nodes[whichNode].get_nextNode() == null && nodes[whichNode].get_parent() != nodes[0]) {
            nodes[whichNode].get_parent().collapse();
        }
    }
    
    function doTheWork(operation, cycles) { //, callback
        var self = this, // in case you need it
            cyclesComplete = 1,
            batchSize = 10; // Larger batch sizes will be slightly quicker, but visually choppier
    
        var doOneBatch = function() {
            var c = 0;
            while(cyclesComplete < cycles) {
                operation(cyclesComplete);
                c++;
                if(c >= batchSize) {
                    // may need to store interim results here
                    break;
                }
                cyclesComplete++;
            }
            if (cyclesComplete < cycles) {
                setTimeout(doOneBatch, 1); // "1" is the length of the delay in milliseconds
            }
            else {
                // Not necessary to do anything when done
                //callback(); // maybe pass results here
            }
        };
    
        // kickoff
        doOneBatch();
        return null;
    };