Twitter typeahead在使用“预加载”时没有结果,但使用“远程”JSON却可以正常工作。

5

我整天都在苦苦挣扎。我的typeahead搜索表达式与远程json数据完美配合。但是当我尝试使用相同的json数据作为预取数据时,建议为空。在输入第一个字符后,对于空结果,我会收到预定义消息“无法找到任何东西...”。

这是我的脚本:

function initialTypeaheadTest(){
    var mo_selector = $('*[data-moT="mysearch"]');
    var engine = new Bloodhound({
        limit: 10
        ,prefetch: {url:'/api/action/getjsontest'}
        //,remote: {url:'/api/action/getjsontest'}
        ,datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name')
        ,queryTokenizer: Bloodhound.tokenizers.whitespace
    });
    engine.clearPrefetchCache(); //  only for test purposes
    engine.initialize();

    mo_selector.typeahead(
        {
            hint: true,
            highlight: true,
            minLength: 1
        }, {
        name: 'engine',
        displayKey: 'name',
        source: engine.ttAdapter(),
            templates: {
                empty: [
                    '<div class="empty-message">',
                    'unable to find anything that match the current query',
                    '</div>'
                ].join('\n'),
                suggestion: Handlebars.compile([
                        '<div id="{{value}}"><p style="max-height:100%;"><strong>{{title}}</strong></p>',
                        '<span style="font-size:12px;">{{year}}</span></div>'
                    ].join(''))
            }
    });
}

以下是我的JSON数据:

[{
"year":"02 Feb 2013 at 00:40 by anonymous",
"title":"JavaScript HTML DOM Changing HTML Content",
"value":"1",
"tokens":["JavaScript", "HTML", "DOM", "Changing", "HTML", "Content"]
},{
"year":"02 Feb 2013 at 00:42 by anonymous",
"title":"WDR.de",
"value":"2",
"tokens":["WDR.de"]
},{
"year":"02 Feb 2013 at 00:46 by anonymous",
"title":"Nachrichten, aktuelle Schlagzeilen und Videos - n-tv.de",
"value":"3",
"tokens":["Nachrichten", "aktuelle", "Schlagzeilen", "und", "Videos", "n", "tv.de"]
},{
"year":"02 Feb 2013 at 00:55 by anonymous",
"title":"JavaScript RegExp Object",
"value":"5",
"tokens":["JavaScript", "RegExp", "Object"]
},{
"year":"15 Feb 2013 at 23:24 by anonymous",
"title":"DotnetNuke Module Car Listing Module",
"value":"8",
"tokens":["DotnetNuke", "Module", "Car", "Listing", "Module"]
},{
"year":"08 Feb 2014 at 01:08 by advertiser",
"title":"Empfehlung",
"value":"1000",
"tokens":["Empfehlung"]
}]

原始路径:mattopen.com/api/action/getjsontest

对我来说,一切看起来都很好。JSON数据格式良好。所有字符串(例如tokens中的)都用双引号括起来。 为什么远程数据可以工作但预取不行呢?

有人能给我指点一下方向吗? 谢谢

1个回答

7
你的设置很好,除了tokenizer被设置的部分。因为你在data数组中返回了一个json对象类型,所以你必须指定要对json对象进行令牌化的属性/字段。在你的代码中,你指定了name,但是你的json类型不包含name。如果你将其从name更改为title,那么一切都会按预期工作,并且将搜索title字段。
更改行:
datumTokenizer: Bloodhound.tokenizers.obj.whitespace('name')

致:

datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title')

假设您想将字段“title”用作搜索索引。如果您希望搜索其他字段/属性,请将其更改为数组中列出的对象类型中存在的该字段/属性的名称。
如果您想使用提供的标记,则可以通过提供一个执行此操作的函数来实现。请将datumTokenizer这一行替换为以下内容:
,datumTokenizer: function (yourObj) {
    return yourObj.tokens; // returns the tokens array in your object
}

顺便提一下,默认的 Bloodhound.tokenizers.obj.whitespace 意味着它会尝试使用空格来分割字符串。这也是为什么在上一个 tokens 实现中你没有看到它,因为我假设你的 tokens 字段总是包含你想要的整个字符串。
来自Bloodhound文档

datumTokenizer - 一个带有签名 (datum) 的函数,将数据转换为字符串标记数组。必须。

我还添加了 sufficient 并将其设置为 1,这告诉引擎如果至少返回 1 个项(在这种情况下是从预取中返回),则不需要访问服务器。

sufficient - 如果内部搜索索引提供的数据数量小于 sufficient,则远程将用于填充由调用 #search 触发的搜索请求。默认值为5。

此外,为了测试,您可以在站点的根目录上创建一个磁盘文件(我们称其为 prefetchData.json),直接将列在您问题中的 json 数据文本复制到该文件中,然后更改 url 以直接指向它。
prefetch: {url:'/prefetchData.json'}

以下是完整的工作代码,其中包含上述更改。现在,如果您输入J,应返回2个结果。

function initialTypeaheadTest(){
    var mo_selector = $('*[data-moT="mysearch"]');
    var engine = new Bloodhound({
        limit: 10
        ,sufficient:1
        ,prefetch: {url:'/prefetchData.json'}
        //,remote: {url:'/api/action/getjsontest'} // left it commented out to prove it works
        ,datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title')
        ,queryTokenizer: Bloodhound.tokenizers.whitespace
    });
    engine.clearPrefetchCache(); //  only for test purposes
    engine.initialize();

    mo_selector.typeahead(
        {
            hint: true,
            highlight: true,
            minLength: 1
        }, {
        name: 'engine',
        displayKey: 'name',
        source: engine.ttAdapter(),
            templates: {
                empty: [
                    '<div class="empty-message">',
                    'unable to find anything that match the current query',
                    '</div>'
                ].join('\n'),
                suggestion: Handlebars.compile([
                        '<div id="{{value}}"><p style="max-height:100%;"><strong>{{title}}</strong></p>',
                        '<span style="font-size:12px;">{{year}}</span></div>'
                    ].join(''))
            }
    });
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接