Помогите подправить поиск на сайте
Есть у меня скрипт для сортировки и поиска элементов на странице.
Поиск учитывает последовательность слов в запросе. Тоисть если у меня элемент называется Samsung Galaxy и я делаю поиск по запросу Galaxy Samsung то ничего не находит, а запрос Samsung находит элемент. Помогите поправить скрипт что-бы он не учитывал последовательность слов. Вот кусок кода отвечающего за поиск:
SLS.isearch.on('keyup',function(){
var results = [];
var toSearch = SLS.isearch.val();
if(toSearch=='') {
SLS.prod = products;
}else{
for(var i=0; i<SLS.sproducts.length; i++) {
if(SLS.sproducts[i].name.toLowerCase().indexOf(toSearch.toLowerCase())!=-1) {
results.push(SLS.sproducts[i]);
}
}
SLS.prod = results;
}
SLS.page=1;
SLS.products.html('');
SLS.sorta(SLS.isort);
});
|
Alexko64,
вы что-то не договариваите ...
alert("Samsung Galaxy".toLowerCase().indexOf("Galaxy".toLowerCase()) != -1);
|
В каком смысле? Я не автор скрипта, что не так?
Скинул часть, вроде она отвечает за поиск, там еще кусок для сортировки. Нужен целиком? |
Alexko64,
могу только гадать, возможно в name продукта есть только Samsung SLS.sproducts[i].name, Samsung Galaxy в другом месте. |
Цитата:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<div>Search: <input type="search" class="simple-input" id="isearch" placeholder="Start typing...">
</div>
<br><br><br>
<div id="products"></div>
<script>
var products = [
{name:'Samsung Galaxy s9',
html:'<div>Samsung Galaxy S9</div>'
},
{name:'Galaxy S9 Samsung',
html:'<div>Galaxy S9 Samsung</div>'
},
];
</script>
<script>
var SLS = {
products: $('#products'),
plow:$('#plow'),
phigh:$('#phigh'),
isearch:$('#isearch'),
prod:products,
sproducts: products,
page:1,
limit:12,
isort:0,
init:function(){
SLS.pload(SLS.page,SLS.limit);
SLS.events();
},
pload:function(page,limit){
for(var i=((page-1)*limit);i<(limit*page);i++){
if(SLS.prod[i])
SLS.products.append($(SLS.prod[i].html));
}
},
sorta:function(type){
var byPrice = SLS.prod.slice(0);
byPrice.sort(function(a,b) {
return a.price - b.price;
});
if(type==1)
byPrice=byPrice.reverse();
SLS.prod=byPrice;
SLS.page=1;
SLS.products.html('');
SLS.pload(SLS.page,SLS.limit);
},
events:function(){
$(window).on('scroll',function(){
if($(this).scrollTop()+250>=($(document).height() - window.innerHeight-$('footer').height())){
SLS.page++;
SLS.pload(SLS.page,SLS.limit);
}
});
SLS.plow.on('click',function(){
SLS.isort=0;
SLS.sorta(SLS.isort);
});
SLS.phigh.on('click',function(){
SLS.isort=1;
SLS.sorta(SLS.isort);
});
SLS.isearch.on('keyup',function(){
var results = [];
var toSearch = SLS.isearch.val();
if(toSearch=='') {
SLS.prod = products;
}else{
for(var i=0; i<SLS.sproducts.length; i++) {
if(SLS.sproducts[i].name.toLowerCase().indexOf(toSearch.toLowerCase())!=-1) {
results.push(SLS.sproducts[i]);
}
}
SLS.prod = results;
}
SLS.page=1;
SLS.products.html('');
SLS.sorta(SLS.isort);
});
}
};
SLS.init();
</script>
</div>
|
Цитата:
|
Alexko64,
<script>
function escapeRegExp(string){
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function fnSearch(arr, pattern) {
pattern = escapeRegExp(pattern);
pattern = new RegExp("^(" + pattern.trim().replace(/\s+/g, "|") + ")", "i");
return arr.filter(function(el) {
return Object.values(el).some(function(val) {
return pattern.test(val)
})
})
};
var products = [
{name:'Samsung Galaxy s9',
html:'<div>Samsung Galaxy S9</div>'
},
{name:'Galaxy S9 Samsung',
html:'<div>Galaxy S9 Samsung</div>'
},
];
</script>
<script>
var SLS = {
products: $('#products'),
plow:$('#plow'),
phigh:$('#phigh'),
isearch:$('#isearch'),
prod:products,
sproducts: products,
page:1,
limit:12,
isort:0,
init:function(){
SLS.pload(SLS.page,SLS.limit);
SLS.events();
},
pload:function(page,limit){
for(var i=((page-1)*limit);i<(limit*page);i++){
if(SLS.prod[i])
SLS.products.append($(SLS.prod[i].html));
}
},
sorta:function(type){
var byPrice = SLS.prod.slice(0);
byPrice.sort(function(a,b) {
return a.price - b.price;
});
if(type==1)
byPrice=byPrice.reverse();
SLS.prod=byPrice;
SLS.page=1;
SLS.products.html('');
SLS.pload(SLS.page,SLS.limit);
},
events:function(){
$(window).on('scroll',function(){
if($(this).scrollTop()+250>=($(document).height() - window.innerHeight-$('footer').height())){
SLS.page++;
SLS.pload(SLS.page,SLS.limit);
}
});
SLS.plow.on('click',function(){
SLS.isort=0;
SLS.sorta(SLS.isort);
});
SLS.phigh.on('click',function(){
SLS.isort=1;
SLS.sorta(SLS.isort);
});
SLS.isearch.on('keyup',function(){
var results = [];
var toSearch = SLS.isearch.val();
if(toSearch=='') {
SLS.prod = products;
}else{
SLS.prod = fnSearch(SLS.sproducts, toSearch);
}
SLS.page=1;
SLS.products.html('');
SLS.sorta(SLS.isort);
});
}
};
SLS.init();
</script>
|
Цитата:
|
пока писал ответ не увидел что уже ответили )
|
рони, надо бы наверное trim() для входного значения, и \s более одного?
Видимо перепил, trim есть. :) |
laimas,
если работает(сработает) лучше не трогать :) |
рони, ну если ввод к примеру будет таким
' Galaxy samsung ', то шаблон получится такой 'Galaxy| samsung'. |
Цитата:
Не работает, при поиске Samsung, второй вариант что начинается на Galaxy уже не находит |
Цитата:
var s = 'Samsung Galaxy', //в чем ищем
v = ' Galaxy samsung ', //пусть ввели так
r = new RegExp(v.trim().replace(/\s+/, '|'), 'gi'); //определяем шаблон поиска
alert(r.test(v)) //есть совпадение?
И если строка в которой ищем будет 'Galaxy Samsung', все равно будет найдено совпадение. PS. рони подправил код, а вы скопировали до правки, проверьте еще раз, может в этом причина. |
Цитата:
Вот залил на тест хост http://mobidor.zzz.com.ua/test.php |
Цитата:
|
Ну какая тайна, разбираем-же пример. не работает, на хостинге можно проверить где я залил
http://mobidor.zzz.com.ua/test.php |
А так:
pattern = new RegExp(pattern.trim().replace(/\s+/g, "|"), "gi");
return arr.filter(function(el) {
//return Object.values(el).some(function(val) {
return pattern.test(Object.values(el)[0])
//})
})
А отображать и надо одно совпадение, которое начинается с первого введенного в поиске? |
Alexko64,
замените
function fnSearch(arr, pattern) {
pattern = escapeRegExp(pattern);
pattern = new RegExp("(" + pattern.trim().replace(/\s+/g, "|") + ")", "i");
return arr.filter(function(el) {
pattern.lastIndex = 0;
return pattern.test(el.name)
})
};
|
Цитата:
попробуйте найти Galaxy, Samsung note 6 (его там и в помине нет но поиск выдает результат) Добавил RAM для отличий между вариантами. Отображать надо все совпадения которые подходят под шаблон, как в любом поиске |
Цитата:
|
function fnSearch(arr, pattern) {
var parts = pattern.trim().toLowerCase().split(/\s+/);
return arr.filter(function(product) {
return parts.every(function(part) {
return product.name.toLowerCase().includes(part)
});
});
}
Кстати вы можете менять some на every, посмотрите, может вам нужен такой эффект! |
Цитата:
Перезалил на хост. При поиске Samsung 2GB находит все где есть слово samsung и все где есть 2GB. Я так понимаю что алгоритм поиска должен быть такой: Показывать все результаты где было совпадение всех слов введенных в запросе но не обращать внимание на порядок слов в искомой строке. |
НУ может быть тогда такое как Malleys написал?
|
Цитата:
|
Цитата:
|
Залил на хостинг вариант с правкой Malleys
Не работает поиск совсем http://mobidor.zzz.com.ua/test.php |
Последний раз редактировалось Malleys, Сегодня в 13:05. Причина: Если вы смотрели решение до 10:56 по Гринвичу, то посмотрите ещё раз.
|
Alexko64,
function fnSearch(arr, pattern) {
return arr.filter(function(product) {
return pattern
.trim()
.toLowerCase()
.split(/\s+/)
.every(function(p) {
return product.name.toLowerCase().includes(p)
});
});
}
var products = [
{name:'Samsung Galaxy s9',
html:'<div>Samsung Galaxy S9</div>'
},
{name:'Galaxy S9 Samsung',
html:'<div>Galaxy S9 Samsung</div>'
},
];
</script>
<script>
var SLS = {
products: $('#products'),
plow:$('#plow'),
phigh:$('#phigh'),
isearch:$('#isearch'),
prod:products,
sproducts: products,
page:1,
limit:12,
isort:0,
init:function(){
SLS.pload(SLS.page,SLS.limit);
SLS.events();
},
pload:function(page,limit){
for(var i=((page-1)*limit);i<(limit*page);i++){
if(SLS.prod[i])
SLS.products.append($(SLS.prod[i].html));
}
},
sorta:function(type){
var byPrice = SLS.prod.slice(0);
byPrice.sort(function(a,b) {
return a.price - b.price;
});
if(type==1)
byPrice=byPrice.reverse();
SLS.prod=byPrice;
SLS.page=1;
SLS.products.html('');
SLS.pload(SLS.page,SLS.limit);
},
events:function(){
$(window).on('scroll',function(){
if($(this).scrollTop()+250>=($(document).height() - window.innerHeight-$('footer').height())){
SLS.page++;
SLS.pload(SLS.page,SLS.limit);
}
});
SLS.plow.on('click',function(){
SLS.isort=0;
SLS.sorta(SLS.isort);
});
SLS.phigh.on('click',function(){
SLS.isort=1;
SLS.sorta(SLS.isort);
});
SLS.isearch.on('keyup',function(){
var results = [];
var toSearch = SLS.isearch.val();
if(toSearch=='') {
SLS.prod = products;
}else{
SLS.prod = fnSearch(SLS.sproducts, toSearch);
}
SLS.page=1;
SLS.products.html('');
SLS.sorta(SLS.isort);
});
}
};
SLS.init();
|
Урааа) заработало
Вы лучшие. Плюсики в карму всем кто старался. Залил на хост рабочий вариант, можете глянуть |
Парни, упустил один момент. В тексте по которому идет поиск, присутствуют html теги, соответственно поиск их учитывает, попытался решить проблему вот так
function fnSearch(arr, pattern) {
return arr.filter(function(product) {
return pattern
.replace(/\<.*?>/g, "")
.trim()
.toLowerCase()
.split(/\s+/)
.every(function(p) {
return product.html.toLowerCase().includes(p)
});
});
}
не помогло, потом вот так
function fnSearch(arr, pattern) {
return arr.filter(function(product) {
return pattern
.text()
.trim()
.toLowerCase()
.split(/\s+/)
.every(function(p) {
return product.html.toLowerCase().includes(p)
});
});
}
не сработало Подсобите еще разок? |
Alexko64,
name чем не устроило? |
Alexko64,
function fnSearch(arr, pattern) {
return arr.filter(function(product) {
return pattern
.trim()
.toLowerCase()
.split(/\s+/)
.every(function(p) {
return $("<div/>", {html : product.html}).text().toLowerCase().includes(p)
});
});
}
|
Цитата:
|
Нашел баг или вернее специфику работы скрипта. Он не учитывает место нахождения первой буквы из запроса.
Если есть такие вариенты на сайте: Samsung Galaxy Note 5 4GB RAN 64GB ROM Samsung Galaxy Note 6 2GB RAM 128 ROM Samsung Galaxy Note 7 4GB RAM 256 GB ROM SAmsung Galaxy Note 8 6GB RAM 512 GB ROM И поискать Samsung Galaxy Note 6, то скрипт покажет все результаты, потому-что везде есть цифра 6 и не важно в каком месте она находится. Аналогично скрипт покажет все результаты на любой из следующих запросов: sung alaxy, laxy 6 и тд... Для наглядности залил пример на хостинг http://mobidor.zzz.com.ua/test.php |
Alexko64,
|
Alexko64, ну тут палка о двух концах, если говорить о цифрах.
Samsung Galaxy Note 5 4GB RAN 64GB ROM - здесь 6, но это размер и полный 64 Samsung Galaxy Note 6 2GB RAM 128 ROM - здесь 6, но модель Как понять при вводе чего ищет пользователь - модель или размер. Пусть угадали, размер, но и 64 не равно 64GB. К тому же размер ведь не только у ROM, но и RAM, что нужно возвращать если не указано GB (128 ROM) - нет или где попадется подходящее? Вообще все это похоже на фильтр, вот только фильтр всегда определяет не только значения, но и какому параметру они принадлежат, в строке же искать такое задача нелегкая. PS. Да еще если строки имеют ошибки, как у вас, не обязательно, что это так и есть, но от них никто не застрахован. |
Alexko64,
function escapeRegExp(string){
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}
function fnSearch(arr, pattern) {
return arr.filter(function(product) {
var text = $("<div/>", {html : product.html}).text().toLowerCase();
return pattern
.trim()
.toLowerCase()
.split(/\s+/)
.every(function(p) {
p = escapeRegExp(p);
p = new RegExp("(^|\\s)" + p, "i");
return p.test(text)
});
});
}
|
Цитата:
|
Цитата:
Уж тогда организовывать на клиенте фильтр, как это бы был запрос в базу по параметрам. Искать не в строке, а объектах:
{
brand: "Samsung",
line: "Galaxy Note",
model: 5,
ram: 4,
rom: 64
},
....
Тогда проблем с подбором не будет. Главная проблема, это сделать интерактивное поле для поиска (если поиск, а не фильтр с выбором параметров), которое бы по мере ввода предлагало выбор следующего параметра, следующего, сопоставляя каждый ввод с предложенным параметром, и так до завершения ввода. В итоге нужно искать среди параметров объектов совпадения из полученного при вводе объекта. |
| Часовой пояс GMT +3, время: 17:18. |