是否可以合并使用具有不同来源的typeahead.js的多个输入?

时间:2015-06-22 13:38:13

标签: jquery twitter-bootstrap-3 typeahead.js

我有一个包含大量文本输入的表单,其中10个我想使用带有Bloodhound的typeahead.js。我有两个工作 - 它们都包括预取和远程数据源。但是,对于每个类型为/ / Bloodhound的实例,都有相当数量的jQuery代码,如果有人试图通过"泛化"那么我很好奇。 typeahead / Bloodhound处理多个不同的输入元素,每个元素都有不同的数据源?它可能比它的价值更麻烦,但我有点担心页面必须加载的代码量。

我的环境是Spring / MVC,Hibernate(Oracle db),Bootstrap。

这是一个typeahead / Bloodhound实例的样本。它是一个函数,因为我是动态添加行的输入所以我必须在添加新行后调用此函数以在该行的文本输入上启用typeahead。

function initIngredientsTA() {
    //set the options
    var ingredBH = new Bloodhound({
        limit: 20,
        datumTokenizer: function(datum) {
            return Bloodhound.tokenizers.whitespace(datum.name);
        },
        queryTokenizer: Bloodhound.tokenizers.whitespace,       
        prefetch: {
            url: '/myapp/resources/ingredients.json',
            cache: false,
            filter: function(data) {
                console.log("data: " + data.ingredients);
                return $.map(data.ingredients, function (ingredient) {
                    return {
                        id : ingredient.id,
                        name : ingredient.name
                    };
                });
            } 
        },
        remote: {
            url: '/myapp/recipe/addRecipe/getIngredients?searchStr=%QUERY',
            cache: false,
            wildcard: '%QUERY',
            filter: function(data) {
                console.log("data: " + data);
                return $.map(data, function (data) {
                    return {
                        id : data.id,
                        name : data.name
                    };
                });
            } 
        }
    });

    //initialize the suggestion Engine
    ingredBH.initialize();

    $('.ingredDesc').typeahead(
    {
        hint: true,
        highlight: true,
        minLength: 1
    },
    {
        name: 'ingredients',
        displayKey: 'name',
        limit: 20,
        source: ingredBH.ttAdapter(),
    })
};

编辑:我认为我真正要问的是,是否有人创建了一个"模板" typeahead / Bootstrap的版本,然后可以为每个单独的文本输入实例化。

2 个答案:

答案 0 :(得分:2)

很抱歉,如果这是一个有明显答案的问题,但我是Java,Spring / Hibernate,jQuery等的新手。使用Firebug我能够找出typeahead和Bloodhound所需的内容并提出以下内容:

//token and filter functions
function ingredDatumToken(datum) {
    return Bloodhound.tokenizers.whitespace(datum.name);
}

function ingredPrefetchFilter(data) {
    return $.map(data.ingredients, function (ingredient) {
        return {
            id : ingredient.id,
            name : ingredient.name
        };
    });
};

function ingredRemoteFilter(data) {
    return $.map(data, function (data) {
        return {
            id : data.id,
            name : data.name
        };
    });
};

//Bloodhound initialization
function initBloodhound(limit, cache, datumToken, queryToken,prefetchUrl,prefetchFilter, remoteUrl, wildcard, remoteFilter)
{
    var token = Bloodhound.tokenizers.whitespace; 

    var options = {};
    var prefetchOptions = {};
    var remoteOptions = {};

    prefetchOptions['url'] = prefetchUrl;
    prefetchOptions['cache'] = cache;
    prefetchOptions['filter'] = prefetchFilter;

    remoteOptions['url'] = remoteUrl;
    remoteOptions['cache'] = cache;
    remoteOptions['wildcard'] = wildcard; 
    remoteOptions['filter'] = remoteFilter;       

    options['limit'] = limit; 
    options['datumTokenizer'] = datumToken === null ? token : datumToken;
    options['queryTokenizer'] = queryToken === null ? token : queryToken;

    if (prefetchUrl != null)
        options['prefetch'] = prefetchOptions;

    if (remoteUrl != null)
        options['remote'] = remoteOptions;

    return new Bloodhound(options);
};

//create two Bloodhound engines
var ingredBH = initBloodhound(50,false,ingredDatumToken,null,'/myapp/resources/ingredients.json',ingredPrefetchFilter,'/myapp/recipeaddRecipe/getIngredients?searchStr=%QUERY','%QUERY',ingredRemoteFilter);
var measureBH = initBloodhound(20,false,null,null,'/myapp/resources/measures.json',null,null,null,null);
//add more Bloodhound engines here

//typeahead options
function initTypeaheadOptions(hint, highlight, minLength) {

    var options = {};

    options['hint'] = hint;
    options['highlight'] = highlight;
    options['minLength'] = minLength;

    return options;
}

//typeahead dataset
function initTypeaheadDataset(name, displayKey, limit, source) {

    var datasets = {};

    datasets['name'] = name;
    datasets['displayKey'] = displayKey;
    datasets['limit'] = limit;
    datasets['source'] = source;

    return datasets;
}

//initialize a typeahead control    
function initIngredientsTA() {

    var options = initTypeaheadOptions(true,true,1);
    var dataset = initTypeaheadDataset('ingredients', 'name', 20, ingredBH);

    $('.ingredDesc').typeahead(options,dataset);
};

//initialize a typeahead control
function initMeasuresTA() {

    var options = initTypeaheadOptions(true,true,1);
    var dataset = initTypeaheadDataset('measures', null, 20, measureBH);

    $('.ingredQtyType').typeahead(options,datasets);
};

//add more typeahead initialization functions here

//call the initialize functions
initIngredientsTA();
initMeasuresTA();
//call more initialize functions here

我仍然在努力使它更通用,而且我对Bloodhound初始化函数调用中的所有参数并不感到疯狂,但是因为我在页面上有大约10个或更多类型的控件启用它只需几行代码即可轻松添加其余部分。那些不是页面上动态创建的行的一部分的类型控件不需要单独的初始化函数,但可以用3行代码初始化。我绝对乐于接受任何改进意见或建议,包括任何想法,这是一个愚蠢的想法。

答案 1 :(得分:0)

我刚刚注意到这个问题上有一笔赏金,所以我想我会对原来的答案进行一些优化。

基本功能位于包含文件中:

<强> typeahead.js

FXCollections.sort()

初始化预取(json)typeahead:

function setBHPrefetchOpts(cache, prefetchUrl, prefetchFilter) {

    var prefetchOptions = {};

    prefetchOptions['url'] = prefetchUrl;
    prefetchOptions['cache'] = cache;
    prefetchOptions['filter'] = prefetchFilter;

    return prefetchOptions;
}

function setBHRemoteOpts(cache, wildcard, remoteUrl, remoteFilter) {

    var remoteOptions = {};

    remoteOptions['url'] = remoteUrl;
    remoteOptions['cache'] = cache;
    remoteOptions['wildcard'] = wildcard; 
    remoteOptions['filter'] = remoteFilter;

    return remoteOptions;
}

function setBHOptions(sufficient, datumToken, queryToken, prefetchOptions, remoteOptions) {

    var token = Bloodhound.tokenizers.whitespace; 

    var options = {};

    options['sufficient'] = sufficient; 
    options['datumTokenizer'] = datumToken === null ? token : datumToken;
    options['queryTokenizer'] = queryToken === null ? token : queryToken;

    if (prefetchOptions != null)
        options['prefetch'] = prefetchOptions;

    if (remoteOptions != null)
        options['remote'] = remoteOptions;

    return options;
}   

function initTypeaheadOptions(hint, highlight, minLength) {

    var options = {};

    options['hint'] = hint;
    options['highlight'] = highlight;
    options['minLength'] = minLength;

    return options;
};

function initTypeaheadDataset(name, displayKey, limit, source) {

    var dataset = {};

    dataset['name'] = name;
    dataset['displayKey'] = displayKey;
    dataset['limit'] = limit;
    dataset['source'] = source;

    return dataset;
};

初始化远程预先输入:

var prefetchOpts = setBHPrefetchOpts(false, '/recipe/resources/measures.json', null);
var bhOpts = setBHOptions(50, null, null, prefetchOpts, null);
var measureBH = new Bloodhound(bhOpts);

function initMeasuresTA() {

    var options = initTypeaheadOptions(true,true,1);
    var dataset = initTypeaheadDataset('measures', null, 50, measureBH);
    $('.ingredQtyType').typeahead(options,dataset);
};

在上述两个中,json由单个项组成,例如,

[&#34;杯&#34;&#34;杯&#34;&#34;盎司&#34;&#34;盎司&#34;&#34;英镑&#34;,& #34;磅&#34;&#34;茶匙&#34;&#34;茶匙&#34;&#34;汤匙&#34;&#34;汤匙&#34;]

使用更复杂的json初始化prefetch和remote:

{&#34;成分&#34;:[{&#34; ID&#34;:&#34; 142&#34;&#34;名称&#34;:&#34;面粉&#34; },{&#34; ID&#34;:&#34; 144&#34;&#34;名称&#34;:&#34;糖&#34;}]}

var remoteOpts = setBHRemoteOpts(false, '%QUERY', '/recipe/recipe/getQualifiers?searchStr=%QUERY', null);
var bhOpts = setBHOptions(50, null, null, null, remoteOpts);
var qualifierBH = new Bloodhound(bhOpts);   

function initQualifiersTA() {

    var options = initTypeaheadOptions(true,true,1);
    var dataset = initTypeaheadDataset('qualifiers', null, 50, qualifierBH);
    $('.ingredQual').typeahead(options,dataset);
};

动态查询的示例:

function ingredDatumToken(datum) {
    return Bloodhound.tokenizers.whitespace(datum.name);
};

function ingredPrefetchFilter(data) {
    return $.map(data.ingredients, function (ingredient) {
        return {
            id : ingredient.id,
            name : ingredient.name
        };
    });
};

function ingredRemoteFilter(data) {
    return $.map(data, function (data) {
        return {
            id : data.id,
            name : data.name
        };
    });
};

var prefetchOpts = setBHPrefetchOpts(false, '/recipe/resources/ingredients.json', ingredPrefetchFilter);
var remoteOpts = setBHRemoteOpts(false, '%QUERY', '/recipe/recipe/getIngredients?searchStr=%QUERY', ingredRemoteFilter);
var bhOpts = setBHOptions(50, ingredDatumToken, null, prefetchOpts, remoteOpts);
var ingredBH = new Bloodhound(bhOpts);

function initIngredientsTA() {

    var options = initTypeaheadOptions(true,true,1);
    var dataset = initTypeaheadDataset('ingredients', 'name', 50, ingredBH);
    $('.ingredDesc').typeahead(options,dataset);
};

过滤器可能也可以作为通用函数添加到typeahead.js中,但我只有一个数据集需要它们,所以我没有这样做。同样的替换&#39;选项。如前所述,我仍然是javascript / jQuery的新手,所以我确信这个解决方案可以改进,但它至少让我更容易设置打字。