Select2 - 按查询排序结果
Select2 - Sorting results by query
我正在使用 Select2 版本 4.0.0。
如果我的结果包含多个词,并且用户输入其中一个词,我
想要显示按输入的词在结果中的位置排序的结果。
比如用户输入"apple",我的结果是:
- "banana orange apple"
- "banana apple orange"
- "apple banana orange"
那么 "apple banana orange" 应该首先出现在 select2 结果列表中,因为这是 "apple" 在结果中最早出现的结果。我不太关心过去的顺序。
我要重写或配置什么才能得到这样的东西? matcher
好像没有
处理排序,sorter
不包含查询数据。
您可以从 Select2 生成的输入框的值中获取搜索查询,方法是用 select2-search__field
class 标识它。这可能会跨越版本,但由于它们不提供挂钩来获取查询,因此需要某种黑客攻击。您可以 submit an issue 让他们添加对在排序期间访问查询的支持,特别是因为看起来它在 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);
});
}
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
<select id="fruit">
<option>Banana Orange Apple</option>
<option>Banana Apple Orange</option>
<option>Apple Banana Orange</option>
<option>Achocha Apple Apricot</option>
<option>Durian Mango Papaya</option>
<option>Papaya</option>
<option>Tomato Papaya</option>
<option>Durian Tomato Papaya</option>
</select>
这里的问题是Select2,在4.0.0版本中,将查询结果和显示结果分开了。因此,通常用于对结果进行排序的 sorter
选项不会传递所进行的查询(其中包括搜索词)。
因此您将需要找到一种方法来缓存所进行的查询,以便在排序时可以使用它。在我关于 underlining the search term in results 的回答中,我通过 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
作为搜索词)。对于我的示例排序方法,我使用文本中搜索结果所在的位置对结果进行排序。这可能与您正在寻找的类似,但这是一种非常蛮力的方法。
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…';
}
}
});
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js"></script>
<select style="width: 50%">
<option>banana orange apple</option>
<option>banana apple orange</option>
<option>apple banana orange</option>
</select>
无需留任:
$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;
}
})
我正在使用 Select2 版本 4.0.0。
如果我的结果包含多个词,并且用户输入其中一个词,我 想要显示按输入的词在结果中的位置排序的结果。
比如用户输入"apple",我的结果是:
- "banana orange apple"
- "banana apple orange"
- "apple banana orange"
那么 "apple banana orange" 应该首先出现在 select2 结果列表中,因为这是 "apple" 在结果中最早出现的结果。我不太关心过去的顺序。
我要重写或配置什么才能得到这样的东西? matcher
好像没有
处理排序,sorter
不包含查询数据。
您可以从 Select2 生成的输入框的值中获取搜索查询,方法是用 select2-search__field
class 标识它。这可能会跨越版本,但由于它们不提供挂钩来获取查询,因此需要某种黑客攻击。您可以 submit an issue 让他们添加对在排序期间访问查询的支持,特别是因为看起来它在 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);
});
}
});
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.min.js"></script>
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.min.css" rel="stylesheet" />
<select id="fruit">
<option>Banana Orange Apple</option>
<option>Banana Apple Orange</option>
<option>Apple Banana Orange</option>
<option>Achocha Apple Apricot</option>
<option>Durian Mango Papaya</option>
<option>Papaya</option>
<option>Tomato Papaya</option>
<option>Durian Tomato Papaya</option>
</select>
这里的问题是Select2,在4.0.0版本中,将查询结果和显示结果分开了。因此,通常用于对结果进行排序的 sorter
选项不会传递所进行的查询(其中包括搜索词)。
因此您将需要找到一种方法来缓存所进行的查询,以便在排序时可以使用它。在我关于 underlining the search term in results 的回答中,我通过 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
作为搜索词)。对于我的示例排序方法,我使用文本中搜索结果所在的位置对结果进行排序。这可能与您正在寻找的类似,但这是一种非常蛮力的方法。
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…';
}
}
});
<link href="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/css/select2.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/select2/4.0.0/js/select2.js"></script>
<select style="width: 50%">
<option>banana orange apple</option>
<option>banana apple orange</option>
<option>apple banana orange</option>
</select>
无需留任:
$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;
}
})