Как заставить jQuery Quicksearch принимать условия поиска в любом порядке?
На моем сайте Drupal 7 у меня есть страница обзора продукта, созданная с помощью Views. На этой странице у меня есть несколько флажков, которые можно нажимать в любом порядке. Для каждого установленного флажка соответствующий тег копируется в поле ввода текста. Это текстовое поле затем используется в качестве поля поиска для плагина jQuery Quicksearch. (Я заимствовал идею отсюда, но я использую новую версию плагина от deuxhuithuit).
Поскольку эти флажки можно щелкнуть в любом порядке, теги в поле поиска добавляются в любом порядке.
Затем у меня есть большое количество элементов, содержащих продукты, где у каждого продукта есть текстовое поле тега, в которое можно ввести несколько терминов тега, разделенных только пробелом, в зависимости от характеристик продуктов.
Есть ли способ заставить плагин Quicksearch принимать эти условия в любом порядке с помощью опций prepareQuery и / или testQuery? Если так, как это сделано? Я потратил много часов, пытаясь найти примеры того, как это сделать.
Если это невозможно, я думаю, что единственный вариант - создать функцию, которая будет сортировать теги в определенном фиксированном порядке в поле поиска, а затем всегда вводить термины тегов в правильном порядке для каждого продукта...
Так или иначе, вот как выглядит установка прямо сейчас:
$('#searchfield').quicksearch('.views-column .views-field-field-soktaggar', {
'delay': 100,
'selector': 'div.searchtags',
'loader': 'span.loading',
'noResults': '#noresults',
'bind': 'keyup',
'show': function () {
$(this).parent('.views-column').removeClass('hide');
$(this).parent('.views-column').addClass('show');
},
'hide': function () {
$(this).parent('.views-column').removeClass('show');
$(this).parent('.views-column').addClass('hide');
},
'prepareQuery': function (val) {
return new RegExp(val, "i");
},
'testQuery': function (query, txt, _row) {
console.log('query: ' + query + ' txt: ' + txt + ' _row: ' + _row);
return query.test(txt);
}
});
1 ответ
В конце концов я сам придумал решение. Хитрость заключалась в том, чтобы отсортировать запрос в том же порядке, в котором указаны теги для каждого продукта. Для этого я использовал функцию сортировки со ссылочным массивом (также теги должны быть введены в этом порядке в поле тега каждого продукта).
Следующая проблема заключалась в том, что совпадения были найдены только тогда, когда совпадающие теги были расположены рядом друг с другом. Например, если строка тега продукта была infrared logger ntc
и запрос был infrared ntc
нет совпадения было возможно. Итак, в этом случае тег logger
должен был быть удален из строки тега.
Теперь это полная рабочая функция:
$('#searchfield').quicksearch('.views-column .views-field-field-soktaggar', {
'delay': 100,
'selector': 'div.searchtags',
'loader': 'span.loading',
'noResults': '#noresults',
'bind': 'keyup',
'show': function () {
$(this).parent('.views-column').removeClass('hide');
$(this).parent('.views-column').addClass('show');
},
'hide': function () {
$(this).parent('.views-column').removeClass('show');
$(this).parent('.views-column').addClass('hide');
},
'prepareQuery': function (val) {
// turn query into array in order to allow sorting
var q = String(val).match(/("[^"]+"|[^"\s]+)/g);
// sort the tags in the query in the same order as in the reference array
var reference_array = [ 'ir', 'lowtemp', 'hightemp', 'logger', 'tek', 'tet', 'tes', 'tej', 'pt100', 'ntc', 'livs', 'fastighet' ];
if(q != null){
var result = q.sort(function(a, b) {
return reference_array.indexOf(a) - reference_array.indexOf(b);
});
var str = result.join(' ');
}
return new RegExp(str, "i");
},
'testQuery': function (query, txt, _row) {
// remove tags in txt that are not used in query
if(txt != ''){ // only process items with tags
// turn txt (tags from items) into array
var t = String(txt).match(/("[^"]+"|[^"\s]+)/g);
// remove leading '/' and trailing '/i' in query
var str = String(query).replace(/^\/|\/i$/g, '');
// turn query into array
var q = String(str).match(/("[^"]+"|[^"\s]+)/g);
// only show matching tags in txt, otherwise matching is not always possible
var res = t.filter(element => q.includes(element));
//turn tags array into string
var _txt = res.join(' ');
// use this alternative tag string from items
return query.test(_txt);
}
return query.test(txt);
}
});