Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Performace Problem with Filter and Keyboard Up/Down pressed. #359

Closed
oneff opened this issue Nov 26, 2014 · 4 comments
Closed

Performace Problem with Filter and Keyboard Up/Down pressed. #359

oneff opened this issue Nov 26, 2014 · 4 comments

Comments

@oneff
Copy link

oneff commented Nov 26, 2014

Hi,
respect, this is one of the best jquery plugins on the web..

I ran into performance problem with IE10 when the tree has 600 records and the filter is set
(hide mode) and 123 left.

image

If you try now to navigate with keyboard down arrow pressed, IE nearly crashes...

Problem seems to be navigation function is called too often recrusive

image

Maybe some debounce on calling or check to stop inner calls?

Cheers Otto.

@mar10
Copy link
Owner

mar10 commented Nov 26, 2014

Thanks! Could you help to set up a test scenario (a sample file or s.th.)?

@oneff
Copy link
Author

oneff commented Nov 26, 2014

Klar...
looks not a recrusive bug in the reproduction, more like keyboard isnt skipping the hidden by filter.
So the calls just happend in the background.

image

<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
    <title>Fancytree - Example: Filter</title>

    <script src="jquery-2.1.1.min.js" type="text/javascript"></script>
    <script src="jquery-ui.min.js" type="text/javascript"></script>

    <link href="../src/skin-win7/ui.fancytree.css" rel="stylesheet" type="text/css">
    <script src="../src/jquery.fancytree.js" type="text/javascript"></script>
    <script src="../src/jquery.fancytree.filter.js" type="text/javascript"></script>

    <!-- Start_Exclude: This block is not part of the sample code -->
    <link href="../lib/prettify.css" rel="stylesheet">
    <script src="../lib/prettify.js" type="text/javascript"></script>
    <link href="sample.css" rel="stylesheet" type="text/css">
    <script src="sample.js" type="text/javascript"></script>
    <!-- End_Exclude -->

<style type="text/css">
</style>

<!-- Add code to initialize the tree when the document is loaded: -->
<script type="text/javascript">
    $(function(){
        options = {}    
        options.enabledMultiselect = true;
        options.dataValueField = "VALUE";
        options.dataTextField = "TEXT";
        options.dataChildren = "CHILDREN";

        var createFancyTreeStructureRecrusive = function (parent) {
            if (this.options.dataChildren) {
                if (parent[this.options.dataChildren]) {
                    var sortField = this.options.dataSortField;
                    if (sortField) {
                        parent[this.options.dataChildren].sort(function (a, b) { return a[sortField] - b[sortField] });
                    }
                    var childs = [];
                    for (var k = 0; k < parent[this.options.dataChildren].length; k++) {
                        var c = parent[options.dataChildren][k];
                        var hbox = !this.options.enabledMultiselect;
                        var noselect = false;
                        if (this.options.itemSelectable) {
                            noselect = !this.options.itemSelectable(c);
                        }
                        if (noselect) {
                            hbox = true;
                        }
                        childs.push({
                            "title": c[options.dataValueField] + " - " + c[options.dataTextField],
                            "key": c[options.dataTextField],
                            "data": c,
                            "children": createFancyTreeStructureRecrusive(c),
                            "unselectable": noselect,
                            "hideCheckbox": hbox,
                            "selected": false
                        });
                    }
                    return childs;
                } else {
                    return null;
                }
            } else {
                return null;
            }
        };
        var createFancyTreeStructure = function (ds) {
            var hbox = !this.options.enabledMultiselect;
            var sortField = this.options.dataSortField;
            if (sortField) {
                ds.sort(function (a, b) { return a[sortField] - b[sortField] });
            }
            var rs = [];
            for (var i = 0; i < ds.length; i++) {
                var it = ds[i];
                var noselect = false;
                if (this.options.itemSelectable) {
                    noselect = !this.options.itemSelectable(it);
                }
                if (noselect) {
                    hbox = true;
                }
                rs.push({
                    "title": it[options.dataValueField] + " - " + it[options.dataTextField],
                    "key": it[options.dataTextField],
                    "data": it,
                    "children": createFancyTreeStructureRecrusive(it),
                    "unselectable": noselect,
                    "hideCheckbox": hbox,
                    "selected": false
                });
            }
            return rs;
        };


      // EXPERIMENTAL DATA
            var bomUsageExperimental = [{
                METADATA: "#AAA",
                SORT_KEY: "3",
                TEXT: "Quality 3",
                VALUE: "01",
                SELECTABLE: true,
                CHILDREN: null
            }, {
                METADATA: "#AAA",
                SORT_KEY: "1",
                TEXT: "Quality 1",
                VALUE: "03",
                SELECTABLE: true,
                CHILDREN: null
            }, {
                METADATA: "#AAA",
                SORT_KEY: "2",
                TEXT: "Quality 2",
                VALUE: "04",
                SELECTABLE: true,
                CHILDREN: null
            },
            {
                METADATA: "#CCC",
                SORT_KEY: "4",
                TEXT: "Lining 4",
                VALUE: "02",
                SELECTABLE: false,
                CHILDREN: [{
                    METADATA: "#BBB",
                    SORT_KEY: "B",
                    TEXT: "Jo Jo Child B",
                    VALUE: "02001",
                    SELECTABLE: true,
                    CHILDREN: [{
                        METADATA: "#CCC",
                        SORT_KEY: "2",
                        TEXT: "Na Na Child 2",
                        VALUE: "02003",
                        //SELECTABLE: null, //ERROR TO HANDLE
                        CHILDREN: null
                    }, {
                        METADATA: "#CCC",
                        SORT_KEY: "1",
                        TEXT: "No No Child 1",
                        VALUE: "02004",
                        SELECTABLE: true,
                        CHILDREN: [{
                            METADATA: "#CCC",
                            SORT_KEY: "1",
                            TEXT: "No No Child X",
                            VALUE: "02004007",
                            SELECTABLE: true,
                            CHILDREN: null
                        }]
                    },


                    {
                        METADATA: "#CCC",
                        SORT_KEY: "1",
                        TEXT: "Problem 01",
                        VALUE: "0200454777",
                        SELECTABLE: true,
                        CHILDREN: null
                    },

                    {
                        METADATA: "#CCC",
                        SORT_KEY: "1",
                        TEXT: "Problem 03",
                        VALUE: "02004545454",
                        SELECTABLE: true,
                        CHILDREN: null
                    }


                    ]
                }, {
                    METADATA: "#CCC",
                    SORT_KEY: "A",
                    TEXT: "Ja Ja Child A",
                    VALUE: "02002",
                    SELECTABLE: true,
                    CHILDREN: null
                }
                ]
            }];


       bomUsageExperimental[0].CHILDREN = [];

            for (var i = 0; i < 600; i++) {

                bomUsageExperimental[0].CHILDREN.push({
                    METADATA: "#CCC",
                    SORT_KEY: "D" + i,
                    TEXT: "Leave Node",
                    VALUE: "0000" + i,
                    SELECTABLE: true,
                    CHILDREN: null
                });

            }














        // Attach the fancytree widget to an existing <div id="tree"> element
        // and pass the tree options as an argument to the fancytree() function:
        $("#tree").fancytree({
            extensions: ["filter"],
            quicksearch: true,
            source: createFancyTreeStructure(bomUsageExperimental),
            filter: {
                mode: "hide",
                autoApply: true
            },
            activate: function(event, data) {
//              alert("activate " + data.node);
            },
            lazyLoad: function(event, data) {
                data.result = {url: "ajax-sub2.json"}
            }
        // }).on("keydown", function(e){
        //  var c = String.fromCharCode(e.which);
        //  if( c === "F" && e.ctrlKey ) {
        //      $("input[name=search]").focus();
        //  }
        });
        var tree = $("#tree").fancytree("getTree");


        tree.visit(function (node) {
                        if (node.unselectable) {
                            $(node.span).find(".fancytree-title").css("color", "#808080", "important");
                        }
                        node.setExpanded(true);
                    });
        /*
         * Event handlers for our little demo interface
         */
        $("input[name=search]").keyup(function(e){
            var n,
                leavesOnly = $("#leavesOnly").is(":checked"),
                match = $(this).val();

            if(e && e.which === $.ui.keyCode.ESCAPE || $.trim(match) === ""){
                $("button#btnResetSearch").click();
                return;
            }
            if($("#regex").is(":checked")) {
                // Pass function to perform match
                n = tree.filterNodes(function(node) {
                    return new RegExp(match, "i").test(node.title);
                }, leavesOnly);
            } else {
                // Pass a string to perform case insensitive matching
                n = tree.filterNodes(match, leavesOnly);
            }
            $("button#btnResetSearch").attr("disabled", false);
            $("span#matches").text("(" + n + " matches)");
        }).focus();

        $("button#btnResetSearch").click(function(e){
            $("input[name=search]").val("");
            $("span#matches").text("");
            tree.clearFilter();
        }).attr("disabled", true);

        $("input#hideMode").change(function(e){
            tree.options.filter.mode = $(this).is(":checked") ? "hide" : "dimm";
            tree.clearFilter();
            $("input[name=search]").keyup();
        }).prop("checked", true);
        $("input#leavesOnly").change(function(e){
            // tree.options.filter.leavesOnly = $(this).is(":checked");
            tree.clearFilter();
            $("input[name=search]").keyup();
        });
        $("input#regex").change(function(e){
            tree.clearFilter();
            $("input[name=search]").keyup();
        });

        addSampleButton({
            label: "Filter active branch",
            newline: false,
            code: function(){
                if( !tree.getActiveNode() ) {
                    alert("Please activate a folder.");
                    return;
                }
                tree.filterBranches(function(node){
                    return node.isActive();
                });
            }
        });
        addSampleButton({
            label: "Reset filter",
            newline: false,
            code: function(){
                tree.clearFilter();
            }
        });
    });
</script>
</head>
<body class="example">
    <h1>Example: 'filter' extension</h1>
    <div class="description">
        <p>
            Dynamic filter support.
        </p>
        <p>
            <b>Status</b>: beta
        </p>
    </div>
    <div>
        <label for="skinswitcher">Skin:</label> <select id="skinswitcher"></select>
    </div>
    <p>
        <label>Enter '02'</label>
        <input name="search" placeholder="Filter...">
        <button id="btnResetSearch">&times;</button>
        <span id="matches"></span>
    </p>
    <p>
        <label for="hideMode">
            <input type="checkbox" id="hideMode">
            Hide unmatched nodes
        </label>
        <label for="leavesOnly">
            <input type="checkbox" id="leavesOnly">
            Leaves only
        </label>

        <label for="regex">
            <input type="checkbox" id="regex">
            Regular expression
        </label>
    </p>
    <p id="sampleButtons">
    </p>
    <!-- Add a <table> element where the tree should appear: -->
    <div id="tree">
    </div>

    <!-- Start_Exclude: This block is not part of the sample code -->
    <hr>
    <p class="sample-links  no_code">
        <a class="hideInsideFS" href="https://github.com/mar10/fancytree">jquery.fancytree.js project home</a>
        <a class="hideOutsideFS" href="#">Link to this page</a>
        <a class="hideInsideFS" href="index.html">Example Browser</a>
        <a href="#" id="codeExample">View source code</a>
    </p>
    <pre id="sourceCode" class="prettyprint" style="display:none"></pre>
    <!-- End_Exclude -->
</body>
</html>

@mar10 mar10 closed this as completed in b7f4fb3 Nov 28, 2014
@mar10
Copy link
Owner

mar10 commented Nov 28, 2014

I noticed poor performance on IE, but I couldn't reproduce the crash.
Please let me know, if the patch fixes it for you.

@oneff
Copy link
Author

oneff commented Dec 5, 2014

Thanks a lot! 2.6.0 looks good now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants