Поиск в li с несколькими критериями поиска

#jquery #search #criteria

#jquery #Поиск #критерии

Вопрос:

Несколько критериев поиска в списке

У меня есть список, как показано ниже

 <ul>
    <li>
        <dl class="p_list1">
            <dd id="name">
                <b>Car</b></dd>
            <dd id="company">
                Honda, Hyundai, Toyota, Suzuki</dd>
        </dl>
    </li>
    <li>
        <dl class="p_list2">
            <dd id="name">
                <b>Bike</b></dd>
            <dd id="company">
                Honda, Yamaha, Suzuki</dd>
        </dl>
    </li>
    <li>
        <dl class="p_list3">
            <dd id="name">
                <b>Truck</b></dd>
            <dd id="company">
                Tata, Volvo, Mahindra</dd>
        </dl>
    </li>
</ul>
  

Я использую два текстовых поля txtName и txtCompany для поиска в этом списке.
На основе одного значения текстового поля или обоих значений текстового поля мне нужно отобразить и скрыть список.

  1. Если пользователь выполняет поиск в txtName, например «c», он должен показывать элементы 1 и 3. (txtCompany пуст)
  2. Если пользовательский поиск в txtcompany похож на «Hon», он должен отображать первый и второй список. (txtname пусто)
  3. Если txtName похоже на «c» и поиск пользователя в txtCompany, то он должен выполнять поиск из списка с элементами 1-го и 3-го

Я использовал ниже jquery

 (
        function ($) {
            jQuery.expr[':'].Contains = function (a, i, m) {
                return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
            };
            function listFilter(list) {

                $('#txtName').change(function () {
                    var filter = $(this).val(); if (filter) { $(list).find("dd[id='name']:not(:Contains("   filter   "))").parent().parent().slideUp(); $(list).find("dd[id='name']:Contains("   filter   ")").parent().parent().slideDown(); }
                    else
                    { $(list).find("li").slideDown(); }
                    return false;
                }
               ).keyup(function () { $(this).change(); });


                $('#txtCompany').change(function () {
                    var filter = $(this).val(); if (filter) { $(list).find("dd[id='company']:not(:Contains("   filter   "))").parent().parent().slideUp(); $(list).find("dd[id='company']:Contains("   filter   ")").parent().parent().slideDown(); }
                    else
                    { $(list).find("li").slideDown(); }
                    return false;
                }
               ).keyup(function () { $(this).change(); });


            }



            $(function () {
                listFilter($("#list"));
            }
            );
        } (jQuery)); 
  

теперь проблема в том, что когда я начинаю поиск с одного текстового поля, он работает нормально, когда я использую оба критерия поиска, тогда он начнет поиск на основе текущего нажатия клавиши текстового поля.
Я знаю, что это потому, что я написал событие изменения для текстового поля, и оно не учитывает другие значения текстового поля: (

Вот ссылка на созданный мной тест

Комментарии:

1. спасибо за помощь 🙂 Мне нужен поиск «и», т.Е. Если имя начинается с «c», а компания похожа на «h», тогда она должна показывать первый список. Я работаю над кодом, чтобы решить эту проблему 🙂

2. Тогда это просто: взяв мой ответ за отправную точку, вы должны инвертировать то, что вы делаете с условиями для slideUp и slideDown . В частности, напишите две инструкции для двух условий в slideUp, чтобы при совпадении с одним из них элемент был скрыт, и только один для slideDown, чтобы он отображался только в том случае, если выполнены оба условия. смотрите Код в моем ответе

3. спасибо @mlr за помощь, это решило мою проблему 🙂

4. Добро пожаловать: D Возможно, вы хотели бы отметить мой ответ как принятый? Спасибо

Ответ №1:

Этот код должен сделать свое дело:

РЕДАКТИРОВАТЬ: этот код фильтрует элементы в соответствии с a ИЛИ комбинацией двух условий.

  (
        function ($) {
            jQuery.expr[':'].Contains = function (a, i, m) {
                return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
            };
            var nameFilter, companyFilter;    //store their values

            function onConditionChange (nameFilter, companyFilter) {

                     var hideCondition =  "dd"   (companyFilter ? "[id='company']:not(:Contains("   companyFilter   "))" : "")   (nameFilter ? "[id='name']:not(:Contains("   nameFilter   "))" : "");

                    if (nameFilter || companyFilter) { 

                        $(list).find(hideCondition).parent().parent().slideUp();
                        if (nameFilter) {
                                                    $(list).find("dd[id='name']:Contains("   nameFilter   ")").parent().parent().slideDown();
                                                }
                                                if (companyFilter) {
                                                        $(list).find("dd[id='company']:Contains("   companyFilter   ")").parent().parent().slideDown();                         
                                                }                        
                    } else { 
                        $(list).find("li").slideDown(); 
                    }
                    return false;
                }            

            function listFilter(list) {

                $('#txtName').change(function() {
                    nameFilter = $(this).val();
                    onConditionChange(nameFilter, companyFilter);
                }
               ).keyup(function () { $(this).change(); });


                $('#txtCompany').change(function() {
                    companyFilter = $(this).val();
                    onConditionChange(nameFilter, companyFilter);
                }
               ).keyup(function () { $(this).change(); });


            }



            $(function () {
                listFilter($("#list"));
            }
            );
        } (jQuery)); 
  

Я разветвил вашу скрипку, чтобы вы могли увидеть ее в действии здесь

По сути, вы отслеживаете оба условия и используете их для фильтров, если они не равны нулю (или хотя бы одно из них не равно нулю).

Я попытался применить более сухую версию с меньшим количеством дублированного кода. Тем не менее, его можно еще улучшить, но это должно решить вашу проблему.

Редактировать

После прочтения комментария, вот версия, которая фильтрует элементы, помещая два условия поиска в И .

  (
    function ($) {
        jQuery.expr[':'].Contains = function (a, i, m) {
            return (a.textContent || a.innerText || "").toUpperCase().indexOf(m[3].toUpperCase()) >= 0;
        };
        var nameFilter, companyFilter;    //store their values

        function onConditionChange (nameFilter, companyFilter) {

                 var showCondition =  "dd"   (companyFilter ? "[id='company']:Contains("   companyFilter   ")" : "")   (nameFilter ? "[id='name']:Contains("   nameFilter   ")" : "");

                if (nameFilter || companyFilter) { 
                    if (nameFilter) {                        
                        $(list).find("dd[id='name']:not(:Contains("   nameFilter   "))").parent().parent().slideUp();
                    }
                    if (companyFilter) {
                        $(list).find("dd[id='company']:not(:Contains("   companyFilter   "))").parent().parent().slideUp();                            
                    }

                    $(list).find(showCondition).parent().parent().slideDown();

                } else { 
                    $(list).find("li").slideDown(); 
                }
                return false;
            }            

        function listFilter(list) {

            $('#txtName').change(function() {
                nameFilter = $(this).val();
                onConditionChange(nameFilter, companyFilter);
            }
           ).keyup(function () { $(this).change(); });


            $('#txtCompany').change(function() {
                companyFilter = $(this).val();
                onConditionChange(nameFilter, companyFilter);
            }
           ).keyup(function () { $(this).change(); });


        }



        $(function () {
            listFilter($("#list"));
        }
        );
    } (jQuery)); 
  

Ответ №2:

Вы столкнулись с проблемой, потому что вы используете один и тот же идентификатор для нескольких элементов DOM, что недопустимо. Попробуйте назначить классы вместо идентификаторов, если вы хотите вызвать одну и ту же функцию jquery для нескольких элементов DOM.

Я отмечаю проблемы в вашей разметке:

 <ul>
    <li>
        <dl class="p_list1">
            <dd id="name"> <!--OK to have an ID here---->
                <b>Car</b></dd>
            <dd id="company"><!--OK to have an ID here---->
                Honda, Hyundai, Toyota, Suzuki</dd>
        </dl>
    </li>
    <li>
        <dl class="p_list2">
            <dd id="name"><!--ID repeated, jquery function won't run for this event---->
                <b>Bike</b></dd>
            <dd id="company"><!--ID repeated, jquery function won't run for this event---->
                Honda, Yamaha, Suzuki</dd>
        </dl>
    </li>
    <li>
        <dl class="p_list3">
            <dd id="name"><!--ID repeated, jquery function won't run for this event---->
                <b>Truck</b></dd>
            <dd id="company"><!--ID repeated, jquery function won't run for this event---->
                Tata, Volvo, Mahindra</dd>
        </dl>
    </li>
</ul>