Select2 – 按查询排序结果

我正在使用Select2版本4.0.0。

如果我的结果包含多个单词,并且用户输入其中一个单词,我想显示按输入单词在结果中的位置排序的结果。

例如,用户输入“apple”,我的结果是:

  1. “香蕉橙苹果”
  2. “香蕉苹果橙”
  3. “苹果香蕉橙”

然后“apple banana orange”应首先出现在select2结果列表中,因为这是“apple”最早出现在结果中的结果。 我不太关心过去的排序。

我可以覆盖或配置什么来获得这样的东西? 似乎matcher不处理排序,并且sorter器不包含查询数据。

您可以通过select2-search__field类识别它,从Select2生成的输入框的值中获取搜索查询。 这可能会打破各个版本,但由于他们没有提供钩子来获取查询,因此需要进行某种破解。 您可以提交一个问题 ,让他们在排序期间添加对访问查询的支持,特别是因为它似乎可以在Select2 3.5.2中使用。

 $('#fruit').select2({ width: '200px', sorter: function(results) { var query = $('.select2-search__field').val().toLowerCase(); return results.sort(function(a, b) { return a.text.toLowerCase().indexOf(query) - b.text.toLowerCase().indexOf(query); }); } }); 
     

这里的问题是,4.0.0版本中的Select2将结果查询与结果显示分开。 因此,通常用于对结果进行排序的sorter选项不会传递所做的查询(包括搜索项)。

因此,您需要找到一种方法来缓存所做的查询,以便在排序时使用它。 在我关于在结果中强调搜索词的回答中 ,我通过loading模板方法缓存查询,该方法在进行搜索时始终会触发。 这里也可以使用相同的方法。

 var query = {}; $element.select2({ language: { searching: function (params) { // Intercept the query as it is happening query = params; // Change this to be appropriate for your application return 'Searching…'; } } }); 

因此,现在您可以构建一个自定义sorter方法,该方法使用保存的query (并使用query.term作为搜索项)。 对于我的示例排序方法,我使用文本中搜索结果排序结果的位置。 这可能与您正在寻找的类似,但这是一种非常powershell的方法。

 function sortBySearchTerm (results) { // Don't alter the results being passed in, make a copy var sorted = results.slice(0); // Array.sort is an in-place sort sorted.sort(function (first, second) { query.term = query.term || ""; var firstPosition = first.text.toUpperCase().indexOf( query.term.toUpperCase() ); var secondPosition = second.text.toUpperCase().indexOf( query.term.toUpperCase() ); return firstPosition - secondPosition; }); return sorted; }; 

这将按照您希望的方式对事物进行排序。 您可以在下面找到所有连接在一起的部件的完整示例。 它使用了您在问题中提到的三个示例选项。

 var query = {}; var $element = $('select'); function sortBySearchTerm (results) { // Don't alter the results being passed in, make a copy var sorted = results.slice(0); // Array.sort is an in-place sort sorted.sort(function (first, second) { query.term = query.term || ""; var firstPosition = first.text.toUpperCase().indexOf( query.term.toUpperCase() ); var secondPosition = second.text.toUpperCase().indexOf( query.term.toUpperCase() ); return firstPosition - secondPosition; }); return sorted; }; $element.select2({ sorter: sortBySearchTerm, language: { searching: function (params) { // Intercept the query as it is happening query = params; // Change this to be appropriate for your application return 'Searching…'; } } }); 
     

无需保留期限:

 $element.select2({ sorter: function (data) { if(data && data.length>1 && data[0].rank){ data.sort(function(a,b) {return (a.rank > b.rank) ? -1 : ((b.rank > a.rank) ? 1 : 0);} ); } return data; } , matcher:function(params, data) { // If there are no search terms, return all of the data if ($.trim(params.term) === '') { return data; } // Do not display the item if there is no 'text' property if (typeof data.text === 'undefined') { return null; } // `params.term` should be the term that is used for searching // `data.text` is the text that is displayed for the data object var idx = data.text.toLowerCase().indexOf(params.term.toLowerCase()); if (idx > -1) { var modifiedData = $.extend({ // `rank` is higher when match is more similar. If equal rank = 1 'rank':(params.term.length / data.text.length)+ (data.text.length-params.term.length-idx)/(3*data.text.length) }, data, true); // You can return modified objects from here // This includes matching the `children` how you want in nested data sets return modifiedData; } // Return `null` if the term should not be displayed return null; } 

})