0

我试图扩展dijit.form.FilteringSelect它的所有实例都应该匹配输入的要求,无论字符在输入文本中的位置,并且还应该忽略空格和标点符号(主要是句点和破折号)。

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

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

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

4

1 回答 1

0

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

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

因此,当您定义选择时,覆盖 _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]);或者可能更容易理解;item[searchAttr].matches(query);

我没有测试环境,但是找到上面的内联注释并开始使用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 + '*';
于 2012-06-26T03:49:06.063 回答