Search code examples
javascriptjquerykendo-uikendo-treeview

Kendo TreeView Search with Highlight


I have a KendoTreeview with spriteclass. I want to highlight the nodes (root as well as child nodes) with my search term. I have implemented the search functionality. But the issue when i search it is highlighting the term in the nodes but missing the SpriteClass in the nodes after first search. Any idea ?

jsFiddle code

$('#search-term').on('keyup', function () {
    $('span.k-in > span.highlight').each(function () {
        $(this).parent().text($(this).parent().text());
    });

    // ignore if no search term
    if ($.trim($(this).val()) == '') {
        return;
    }

    var term = this.value.toUpperCase();
    var tlen = term.length;

    $('#treeview-sprites span.k-in').each(function (index) {
        var text = $(this).text();
        var html = '';
        var q = 0;
        while ((p = text.toUpperCase().indexOf(term, q)) >= 0) {
            html += text.substring(q, p) + '<span class="highlight">' + text.substr(p, tlen) + '</span>';
            q = p + tlen;
        }

        if (q > 0) {
            html += text.substring(q);
            $(this).html(html);

            $(this).parentsUntil('.k-treeview').filter('.k-item').each(

            function (index, element) {
                $('#treeview-sprites').data('kendoTreeView').expand($(this));
                $(this).data('search-term', term);
            });
        }
    });

$("#treeview-sprites").kendoTreeView({
    dataSource: [{
        text: "My Documents",
        expanded: true,
        spriteCssClass: "rootfolder",
        items: [{
            text: "Kendo UI Project",
            expanded: true,
            spriteCssClass: "folder",
            items: [{
                text: "about.html",
                spriteCssClass: "html"
            }, {
                text: "index.html",
                spriteCssClass: "html"
            }, {
                text: "logo.png",
                spriteCssClass: "image"
            }]
        }, {
            text: "New Web Site",
            expanded: true,
            spriteCssClass: "folder",
            items: [{
                text: "mockup.jpg",
                spriteCssClass: "image"
            }, {
                text: "Research.pdf",
                spriteCssClass: "pdf"
            }, ]
        }, {
            text: "Reports",
            expanded: true,
            spriteCssClass: "folder",
            items: [{
                text: "February.pdf",
                spriteCssClass: "pdf"
            }, {
                text: "March.pdf",
                spriteCssClass: "pdf"
            }, {
                text: "April.pdf",
                spriteCssClass: "pdf"
            }]
        }]
    }]
})

;


Solution

  • Kendo's tree view widget doesn't like it if you muck around in its HTML, so I suggest modifying the data source instead (this will require the encoded option for all items in the DS).

    In the keyup handler, you reset the DS whenever you search to clear highlighting, then instead of replacing the element's HTML directly, you set the model's text property:

    $('#search-term').on('keyup', function () {
        var treeView = $("#treeview-sprites").getKendoTreeView();
        treeView.dataSource.data(pristine);
    
        // ignore if no search term
        if ($.trim($(this).val()) == '') {
            return;
        }
    
        var term = this.value.toUpperCase();
        var tlen = term.length;
    
        $('#treeview-sprites span.k-in').each(function (index) {
            var text = $(this).text();
            var html = '';
            var q = 0;
            while ((p = text.toUpperCase().indexOf(term, q)) >= 0) {
                html += text.substring(q, p) + '<span class="highlight">' + text.substr(p, tlen) + '</span>';
                q = p + tlen;
            }
    
            if (q > 0) {
                html += text.substring(q);
    
                var dataItem = treeView.dataItem($(this));
                dataItem.set("text", html);
    
                $(this).parentsUntil('.k-treeview').filter('.k-item').each(
    
                function (index, element) {
                    $('#treeview-sprites').data('kendoTreeView').expand($(this));
                    $(this).data('search-term', term);
                });
            }
        });
    
        $('#treeview-sprites .k-item').each(function () {
            if ($(this).data('search-term') != term) {
                $('#treeview-sprites').data('kendoTreeView').collapse($(this));
            }
        });
    });
    

    The tree definition needs the encoded option for this to work:

    var pristine = [{
        encoded: false,
        text: "Kendo UI Project",
        expanded: true,
        spriteCssClass: "folder",
        items: [{
            encoded: false,
            text: "about.html",
            spriteCssClass: "html"
        }, {
            encoded: false,
            text: "index.html",
            spriteCssClass: "html"
        }, {
            encoded: false,
            text: "logo.png",
            spriteCssClass: "image"
        }]
    }, {
        encoded: false,
        text: "New Web Site",
        expanded: true,
        spriteCssClass: "folder",
        items: [{
            encoded: false,
            text: "mockup.jpg",
            spriteCssClass: "image"
        }, {
            encoded: false,
            text: "Research.pdf",
            spriteCssClass: "pdf"
        }, ]
    }, {
        encoded: false,
        text: "Reports",
        expanded: true,
        spriteCssClass: "folder",
        items: [{
            encoded: false,
            text: "February.pdf",
            spriteCssClass: "pdf"
        }, {
            encoded: false,
            text: "March.pdf",
            spriteCssClass: "pdf"
        }, {
            encoded: false,
            text: "April.pdf",
            spriteCssClass: "pdf"
        }]
    }];
    
    $("#treeview-sprites").kendoTreeView({
        dataSource: [{
            text: "My Documents",
            expanded: true,
            spriteCssClass: "rootfolder",
            items: pristine
        }]
    });
    

    (demo)