Kendo TreeView搜索突出显示

时间:2014-09-02 20:31:02

标签: javascript jquery kendo-ui kendo-treeview

我有一个带spriteclass的KendoTreeview。我想用我的搜索词突出显示节点(根节点和子节点)。我已经实现了搜索功能。但是当我搜索它时的问题是突出显示节点中的术语但在第一次搜索后缺少节点中的SpriteClass。有什么想法吗?

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"
            }]
        }]
    }]
})

5 个答案:

答案 0 :(得分:2)

Kendo的树视图窗口小部件不喜欢它,如果您在其HTML中捣乱,所以我建议修改数据源(这将需要DS中所有项目的encoded选项。)

在keyup处理程序中,只要搜索清除突出显示,就重置DS,然后直接替换元素的HTML,设置模型的text属性:

$('#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));
        }
    });
});

树定义需要encoded选项才能生效:

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

答案 1 :(得分:0)

干得好的家伙,正是我所希望的!

使用你的代码我做了一个小调整(实际上只添加了两行jquery过滤),所以现在搜索关键字时,treeview只显示包含突出显示文本的分支。十分简单! :)

如果其他分支不包含突出显示的文本,则会隐藏它们。就这么简单。

这意味着我们现在有类似VisualStudio的树视图搜索(请参阅Visual Studio解决方案资源管理器搜索和过滤:http://goo.gl/qr7yVb)。

这是我在jsfiddle的代码和演示:http://jsfiddle.net/ComboFusion/d0qespaz/2/

<强> HTML:

<input id="treeViewSearchInput"></input>
<ul id="treeview">
    <li data-expanded="true">My Web Site
        <ul>
            <li data-expanded="true">images
                <ul>
                    <li>logo.png</li>
                    <li>body-back.png</li>
                    <li>my-photo.jpg</li>
                </ul>
            </li>
            <li data-expanded="true">resources
                <ul>
                    <li data-expanded="true">pdf
                        <ul>
                            <li>brochure.pdf</li>
                            <li>prices.pdf</li>
                        </ul>
                    </li>
                    <li>zip</li>
                </ul>
            </li>
            <li>about.html</li>
            <li>contacts.html</li>
            <li>index.html</li>
            <li>portfolio.html</li>
        </ul>
    </li>
    <li>Another Root</li>
</ul>

<强> CSS

span.k-in > span.highlight {
    background: #7EA700;
    color: #ffffff;
    border: 1px solid green;
    padding: 1px;
}

<强> JAVASCRIPT

function InitSearch(treeViewId, searchInputId) {

    var tv = $(treeViewId).data('kendoTreeView');

    $(searchInputId).on('keyup', function () {

        $(treeViewId + ' li.k-item').show();

        $('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;

        $(treeViewId + ' span.k-in').each(function (index) {
            var text = $(this).text();
            var html = '';
            var q = 0;
            var p;

            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) {
                    tv.expand($(this));
                    $(this).data('SearchTerm', term);
                });
            }
        });

        $(treeViewId + ' li.k-item:not(:has(".highlight"))').hide();

        $(treeViewId + ' li.k-item').expand(".k-item");
    });
}

var $tv = $("#treeview").kendoTreeView();

InitSearch("#treeview", "#treeViewSearchInput");

答案 2 :(得分:0)

我的另一个调整:)

我所做的是更改突出显示代码,以便保留节点html中可能存在的任何其他内容(例如精灵范围)。

我还将它实现为围绕TreeView的TypeScript类包装器。

如果你不想让TypeScript的东西只是复制代码,它应该工作正常:)

export class SearchableTreeView {
    TreeView: kendo.ui.TreeView;
    emphasisClass: string;

    constructor(treeView: kendo.ui.TreeView) {
        this.TreeView = treeView;
        this.emphasisClass = "bg-warning";
    }

    search(term: string): void {
        var treeElement: JQuery = this.TreeView.element;
        var tv: kendo.ui.TreeView = this.TreeView;
        var emphClass = this.emphasisClass;

        this.resetHighlights();

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

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

        $('span.k-in', treeElement).each(function (index) {
            // find all corresponding nodes
            var node = $(this);
            var htmlContent = node.html();
            var text = node.text();

            var searchPosition = text.toUpperCase().indexOf(term);
            if (searchPosition === -1) {
                // continue
                return true;
            }

            var generatedHtml = '<span class="highlight-container">' + text.substr(0, searchPosition) + '<span class="' + emphClass + '">' + text.substr(searchPosition, tlen) + '</span>' + text.substr(searchPosition + tlen) + '</span>';

            htmlContent = htmlContent.replace(text, generatedHtml);
            node.html(htmlContent);

            node.parentsUntil('.k-treeview').filter('.k-item').each(
                function (index, element) {
                    tv.expand($(this));
                    $(this).data('search-term', term);
                }
            );

        });

        $('.k-item', treeElement).each(function () {
            if ($(this).data('search-term') != term) {
                tv.collapse($(this));
            }
        });
    }

    resetHighlights(): void {
        this.TreeView.element.find("span.k-in:has('." + this.emphasisClass + "')")
            .each(function () {
                var node = $(this);
                var text = node.text();
                $(".highlight-container", node).remove();
                node.append(text);
            });
    }
}

答案 3 :(得分:0)

   $("#textBox").on("input", function () {

    var query = this.value.toLowerCase();
    var dataSource = $("#Treeview").data("kendoTreeView").dataSource;

    filter(dataSource, query);
   });


  function filter(dataSource, query) {
        var uidData = [];
        var data = dataSource instanceof kendo.data.DataSource && dataSource.data();
        for (var i = 0; i < data.length; i++) {
            var item = data[i];
            var text = item.text.toLowerCase();
            var isChecked = item.checked;
            var itemVisible =
                query === true 
                || query === "" 
                || text.indexOf(query) >= 0; 

            uidData.push({ UID: item.uid, Visible: itemVisible });

        }

        if (query != "") {
            $.each(uidData, function (index, datavalue) {
                if (datavalue.Visible) {
                    $("li[data-uid='" + datavalue.UID + "']").addClass("highlight");
                }
                else {
                    $("li[data-uid='" + datavalue.UID + "']").removeClass("highlight");
                }

            });
        }
        else {
            $.each(uidData, function (index, datavalue) {
                $("li[data-uid='" + datavalue.UID + "']").removeClass("highlight");

            });
        }
    }

CSS:

.highlight {
    background:#0fa1ba;
    color:white;
}

答案 4 :(得分:0)

对于Angular 2+,您需要为此功能创建一个管道。

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer } from '@angular/platform-browser';
import { NGXLogger } from 'ngx-logger';

@Pipe({
    name: 'highlight'
})

export class TypeaheadHighlight implements PipeTransform {
    constructor(private readonly _sanitizer: DomSanitizer, private readonly logger: NGXLogger) { }
    transform(matchItem: any, query: any): string {
        let matchedItem: any;
        if (matchItem) {
            matchedItem = matchItem.toString();
        }
        if (this.containsHtml(matchedItem)) {
            this.logger.warn('Unsafe use of typeahead please use ngSanitize');
        }
        matchedItem = query ? ('' + matchedItem).replace(new RegExp(this.escapeRegexp(query), 'gi'), '<strong>$&</strong>') : matchedItem; // Replaces the capture string with a the same string inside of a "strong" tag

        if (!this._sanitizer) {
            matchedItem = this._sanitizer.bypassSecurityTrustHtml(matchedItem);
        }

        return matchedItem;
    }

    escapeRegexp = (queryToEscape) => queryToEscape.replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');

    containsHtml = (matchItem) => /<.*>/g.test(matchItem);

} 

在html模板中使用此管道。     

            <input name="searchTerm" type="text" [(ngModel)]="searchTerm" (keyup)='onkeyup(searchTerm)'
             />
        </div>

        <div style="height: 70vh;overflow: auto">
            <kendo-treeview style="margin-top: 50px" id="availableColumns" [nodes]="availableColumns"
                textField="displayName" kendoTreeViewExpandable kendoTreeViewFlatDataBinding idField="id"
                parentIdField="parentId">
                <ng-template kendoTreeViewNodeTemplate let-dataItem>
                    <span [tooltip]="dataItem.columnDescription"
                        [innerHtml]="dataItem.displayName | highlight:searchTerm "></span>
                </ng-template>
            </kendo-treeview>
        </div>