dijit.form.ComboBox / dijit.form.FilteringSelect Subclass上的模糊匹配

时间:2012-06-26 02:47:05

标签: regex dojo dijit.form

我试图扩展dijit.form.FilteringSelect,要求它的所有实例都应该匹配输入,而不管输入文本中的字符在哪里,并且还应该忽略空格和标点符号(主要是句点和短划线)。 / p>

例如,如果选项是“J.P. Morgan”,我希望能够在输入“JP”或“P Morgan”后选择该选项。

现在我知道有关匹配字符串中任何位置的部分可以通过在创建实例时传入queryExpr: "*${0}*"来完成。

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

1 个答案:

答案 0 :(得分:0)

在这种情况下掌握的东西是商店获取查询字符串..它将调用附加商店中的一个函数来提取任何匹配项,所以如果你在自动填充输入字段中输入了一个值,它最终会结束与代码中的相似:

    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中进行更改

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函数而不是查询函数

看一下dojo / store / util下的SimpleQueryEngine.js文件。这基本上是对来自Array的给定String 查询上收到的FilteringSelect 进行过滤的内容。好的,它是这样的:

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(查询);

我没有测试环境,但找到上面的内联注释并开始使用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案例中,' Robert Din '..这将变得模糊,您可以自行填写正则表达式,这是从

开始的事情
 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 + '*';