dijit.form.ComboBox / dijit.form.FilteringSelect子类的模糊匹配 [英] Fuzzy Matches on dijit.form.ComboBox / dijit.form.FilteringSelect Subclass

查看:319
本文介绍了dijit.form.ComboBox / dijit.form.FilteringSelect子类的模糊匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试扩展 dijit.form.FilteringSelect ,要求其所有实例应与输入匹配,而不管输入的文本中的字符位于何处,应该也可以忽略空格和标点符号(主要是期间和破折号)。

I am trying to extend dijit.form.FilteringSelect with the requirement that all instances of it should match input regardless of where the characters are in the inputted text, and should also ignore whitespace and punctuation (mainly periods and dashes).

例如,如果一个选项是JP Morgan,我希望能够在输入 JP或P Morgan。

For example if an option is "J.P. Morgan" I would want to be able to select that option after typing "JP" or "P Morgan".

现在我知道在字符串中任何地方匹配的部分可以通过传入 queryExpr: * $ {0} *在创建实例时。

Now I know that the part about matching anywhere in the string can be accomplished by passing in queryExpr: "*${0}*" when creating the instance.

我还没有想到的是如何使它忽略空白,期间,和破折号。我有一个例子,我在这里 - http://jsfiddle.net/mNYw2/2/。任何帮助将不胜感激。

What I haven't figured out is how to make it ignore whitespace, periods, and dashes. I have an example of where I'm at here - http://jsfiddle.net/mNYw2/2/. Any help would be appreciated.

推荐答案

在这种情况下掌握的东西是存储fetch querystrings ..它会调用一个函数在附加的商店中拉出任何匹配的项目,所以如果您在自动填充输入字段中输入了一个值,则最终将在代码中与此类似:

the thing to master in this case is the store fetch querystrings.. It will call a function in the attached store to pull out any matching items, so if you have a value entered in the autofilling inputfield, it will eventually end up similar to this in the code:

    var query = { this.searchAttr: this.get("value") }; // this is not entirely accurate
    this._fetchHandle = this.store.query(query, options);
    this._fetchHandle.then(  showResultsFunction  );

所以,当你定义select时,重写_setStoreAttr以便在商店查询api

So, when you define select, override the _setStoreAttr to make changes in the store query api

dojo.declare('CustomFilteringSelect', [FilteringSelect], {
    constructor: function() {
        //???
    },
    _setStoreAttr: function(store) {
          this.inherited(arguments); // allow for comboboxmixin to modify it
          // above line eventually calls this._set("store", store);
          // so now, 'this' has 'store' set allready
          // override here
          this.store.query = function(query, options) {
               // note that some (Memory) stores has no 'fetch' wrapper
          };
    }
});

编辑:覆盖queryEngine功能而不是查询功能

EDIT: override queryEngine function as opposed to query function

查看dojo / store / util下的SimpleQueryEngine.js文件。这实际上是在给定的 String 查询中过滤收到的数组 项目 FilteringSelect 。好的,它就像这样:

Take a look at the file SimpleQueryEngine.js under dojo/store/util. This is essentially what filters the received Array items on the given String query from the FilteringSelect. Ok, it goes like this:

var MyEngine = function(query, options) {
        // create our matching query function
        switch(typeof query){
                default:
                        throw new Error("Can not query with a " + typeof query);
                case "object": case "undefined":
                       var queryObject = query;
                        query = function(object){
                                for(var key in queryObject){
                                        var required = queryObject[key];
                                        if(required && required.test){
                                                if(!required.test(object[key])){
                                                        return false;
                                                }
                                        }else if(required != object[key]){
                                                return false;
                                        }
                                }
                                return true;
                        };
                        break;
                case "string":
  /// HERE is most likely where you can play with the reqexp matcher.
                        // named query
                        if(!this[query]){
                                throw new Error("No filter function " + query + " was found in store");
                        }
                        query = this[query];
                        // fall through
                case "function":
                        // fall through
        }
        function execute(array){
                // execute the whole query, first we filter
                var results = arrayUtil.filter(array, query);
                // next we sort
                if(options && options.sort){
                        results.sort(function(a, b){
                                for(var sort, i=0; sort = options.sort[i]; i++){
                                        var aValue = a[sort.attribute];
                                        var bValue = b[sort.attribute];
                                        if (aValue != bValue) {
                                                return !!sort.descending == aValue > bValue ? -1 : 1;
                                        }
                                }
                                return 0;
                        });
                }
                // now we paginate
                if(options && (options.start || options.count)){
                        var total = results.length;
                        results = results.slice(options.start || 0, (options.start || 0) + (options.count || Infinity));
                        results.total = total;
                }
                return results;
        }
        execute.matches = query;
        return execute;
};

new Store( { queryEngine: MyEngine });

当execute.matches设置在此函数的底部时,会发生什么是字符串被调用在每个项目。每个项目都有一个属性 - Select.searchAttr - 由RegExp测试,如下所示: new RegExp(query).test(item [searchAttr]); 或者可能有点简单理解项目[searchAttr] .matches(query);

when execute.matches is set on bottom of this function, what happens is, that the string gets called on each item. Each item has a property - Select.searchAttr - which is tested by RegExp like so: new RegExp(query).test(item[searchAttr]); or maybe a bit simpler to understand; item[searchAttr].matches(query);

我没有测试环境,但找到上面的内联注释,并开始使用console.debug ..

I have no testing environment, but locate the inline comment above and start using console.debug..

示例:

Stpre.data = [ 
   { id:'WS', name:  'Will F. Smith' },
   { id:'RD', name:'Robert O. Dinero' },
   { id:'CP', name:'Cle    O. Patra' }
];
Select.searchAttr = "name";
Select.value = "Robert Din"; // keyup->autocomplete->query

Select.query将成为 select.queryExp.replace($ {0],Select.value),在你的简单的queryExp的情况下,'@ em'Robert Din '..这将变得模糊和这将由你填写正则表达式,这里有一些开始于

Select.query will become Select.queryExp.replace("${0]", Select.value), in your simple queryExp case, 'Robert Din'.. This will get fuzzy and it would be up to you to fill in the regular expression, here's something to start with

 query = query.substr(1,query.length-2); // '*' be gone
 var words = query.split(" ");
 var exp = "";
 dojo.forEach(words, function(word, idx) {
    // check if last word
    var nextWord = words[idx+1] ? words[idx+1] : null;
    // postfix 'match-all-but-first-letter-of-nextWord'
    exp += word + (nextWord ? "[^" + nextWord[0] + "]*" : "");
 });
 // exp should now be "Robert[^D]*Din";
 //  put back '*'
 query = '*' + exp + '*';

这篇关于dijit.form.ComboBox / dijit.form.FilteringSelect子类的模糊匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆