jquery - 使用 “prefetch” 时 Twitter 预输入没有结果,但使用 “remote” JSON 时

标签 jquery json bootstrap-typeahead twitter-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 数据格式良好。所有字符串(例如在标记中)也用双引号引起来。 为什么远程数据可以工作但预取却不能?

有人能指出我正确的方向吗? 谢谢

最佳答案

除了正在设置的标记器之外,您的设置中的一切都很好。因为您要在数据数组中返回 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 意味着它将尝试用空格分割字符串。这也是为什么您在最后一个 token 实现中看不到它的原因,因为我假设您的 tokens 字段将始终包含您想要的完整字符串。

来自Bloodhound Documentation

datumTokenizer – A function with the signature (datum) that transforms a datum into an array of string tokens. Required.

我还添加了 sufficient 并将其设置为 1,这告诉引擎如果至少返回 1 个项目(在本例中是从预取中返回的),则返回服务器不是必需的。

sufficient – If the number of datums provided from the internal search index is less than sufficient, remote will be used to backfill search requests triggered by calling #search. Defaults to 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(''))
            }
    });
}

关于jquery - 使用 “prefetch” 时 Twitter 预输入没有结果,但使用 “remote” JSON 时,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26534060/

相关文章:

json - 将特定 JSON 字段从 .responseText 提取到单个 Excel 单元格

vue.js - 使用 Vue.js 2.0 提前输入

javascript - angular.js ui + bootstrap typeahead + 异步调用

symfony - 在 Twig 内使用 Typeahead 模板

javascript - "infinite scroll"代码仅适用于顶部滚动

java - 解析另一个标签内的 json 标签

javascript - 如何从左侧切换 JQuery animate()?

javascript - JSON 空数组条目消失

javascript - jQuery 核心每个函数

javascript - jQuery 文件树 - 检测何时单击文件夹