Если кто-то может придумать более подходящее название для этого, пожалуйста, не стесняйтесь менять его.

Я новичок в jQuery и столкнулся с проблемой фильтрации элементов.

Я фильтрую DIVS с атрибутом data- через checkbox, используя функцию изменения.

Моя проблема в том, что если я фильтрую по одному атрибуту data (colour), а затем фильтрую по другому атрибуту (brand), все элементы скрыты. Но если я уберу галочку с одного из фильтров, элементы снова откроются, хотя они по-прежнему фильтруются другим атрибутом.

Могу ли я в любом случае остановить это?

Вот код.

<div data-brand="Nike" data-price="31" data-colour="Blue">Blue</div>
<div data-brand="Nike" data-price="31" data-colour="Red"> Red </div>
Colours:
Blue<input type="checkbox" id="BlueCB" checked>
Red<input type="checkbox" id="RedCB" checked>

Brand: Nike <input type="checkbox" id="NikeCB" checked>

<script>
    var BlueSelector = $('#BlueCB');

    BlueSelector.on("change", function(){
        if($(this).is(":checked"))
        {
            var divs = $("div[data-colour=Blue]");  
            divs.css("display",  "block");
        } else 
        {
            var divs = $("div[data-colour=Blue]");  
            divs.css("display",  "none");
        }
    });

    var RedSelector = $('#RedCB');

    RedSelector.on("change", function(){
        if($(this).is(":checked"))
        {
            var divs = $("div[data-colour=Red]");  
            divs.css("display",  "block");
        } else 
        {
            var divs = $("div[data-colour=Red]");  
            divs.css("display",  "none");
        }
    });

    var NikeSelector = $('#NikeCB');

    NikeSelector.on("change", function(){
        if($(this).is(":checked"))
        {
            var divs = $("div[data-colour=Nike]");  
            divs.css("display",  "block");
        } else 
        {
            var divs = $("div[data-brand=Nike]");  
            divs.css("display",  "none");
        }
    });
</script>

Чтобы повторить проблему, снимите флажок nike, затем снимите флажок синий и снова отметьте. Элемент выскочит обратно, что является проблемой.

Вот JSFIDDLE

Вероятно, это не самое лучшее объяснение, но у меня есть как можно лучше… ты поймешь после того, как поиграешь со скрипкой.

8
SK2017 16 Дек 2015 в 00:06

4 ответа

Лучший ответ

Очень позднее дополнение, но на заднем плане была на мгновение забытая скрипка. После письма от группы действий Forgotten Fiddle я все-таки решил опубликовать его.

Поскольку, как представляется, цель состоит в том, чтобы скрыть данные, относящиеся к непроверенным ячейкам, а не показывать какие-либо данные, для которых проверен какой-либо атрибут данных, вы можете создать черный список, для которого элементы данных должны быть скрыты. Как уже упоминалось в других ответах, я бы предпочел поместить все метаданные в теги (data), такие как <input type="checkbox" data-type="colour" data-value="Blue" checked>, но вместо того, чтобы хранить отдельные фильтры, создать комбинированный фильтр элементов, которые должны быть скрыты. Поскольку jquery может легко выбирать атрибуты элемента, функциональность jquery может использоваться для фильтрации.

Идея состоит в том, что, определяя фильтры, подобные этому, можно добавить любой новый атрибут данных (например, размер, который я позволил себе добавить в скрипку).

var $boxes = $('input[data-type]'), //all input boxes with data-type attribute
    $dataObjects =$(); //will be filled with all bound data elements
$boxes.each(function(ind, inp){     //create filter information
    var type = inp.dataset.type, value = inp.dataset.value; //for older browsers, use  $(inp).data('type')  
  var filter =  'div[data-' + type +'="' + value +'"]';     
  inp.dataset.filter = filter;
    $.merge($dataObjects,$(filter));
}); 

$boxes.change(function(){
    var blacklist = $boxes.filter(function(i,b){return !b.checked})
    .map(function(i,b){return b.dataset.filter}).toArray().join();
  $dataObjects.hide().not(blacklist).show();
});

Скрипка

2
Me.Name 16 Дек 2015 в 17:47

Приведенный ниже код будет работать как для нескольких брендов, так и для нескольких цветов, что достигается наличием отдельного массива фильтров для брендов и цветов. Если флажок установлен, мы добавляем соответствующий массив фильтров, а затем, наконец, проверяем каждый {{X0 }} и проверьте, есть ли у него оба ключевых слова: бренд и цвет. Если встречаются оба, мы показываем (*) , иначе мы скрываем (*) это:

JS Fiddle

var Divs = $('.divs'),
  CheckBoxes = $('.chbx'),
  BlueSelector = $('#BlueCB'),
  RedSelector = $('#RedCB'),
  NikeSelector = $('#NikeCB'),
  Index, Colour, Brand;


CheckBoxes.on("change", function() {
  // Reset filters Arrays
  var ColoursFilters = [],
    BrandsFilters = [];

  // If Blue checkbox is checked, add it to colours array -
  // Otherwise it's unchecked, remove it from the colours array
  if (BlueSelector.is(":checked")) {
    ColoursFilters.push('Blue');
  } else if (BlueSelector.is(":checked") == false) {
    Index = ColoursFilters.indexOf('Blue');
    ColoursFilters.splice(Index, 'Blue');
  }

  // If Red checkbox is checked, add it to colours array -
  // Otherwise it's unchecked, remove it from the colours array
  if (RedSelector.is(":checked")) {
    ColoursFilters.push('Red');
  } else if (RedSelector.is(":checked") == false) {
    Index = ColoursFilters.indexOf('Red');
    ColoursFilters.splice(Index, 'Red');
  }

  // If Nike checkbox is checked, add it to brands array -
  // Otherwise it's unchecked, remove it from the brands array
  if (NikeSelector.is(":checked")) {
    BrandsFilters.push('Nike');
  } else if (NikeSelector.is(":checked") == false) {
    Index = BrandsFilters.indexOf('Red');
    BrandsFilters.splice(Index, 'Blue');
  }

  // Now we check for every colour and every brand -
  // If both conditions met, show the div, else hide it.
  Divs.each(function() {
    Colour = $(this).attr('data-colour');
    Brand = $(this).attr('data-brand');
    if ($.inArray(Colour, ColoursFilters) > -1) {
      if ($.inArray(Brand, BrandsFilters) > -1) {
        $(this).show();
      } else {
        $(this).hide();
      }
    } else {
      $(this).hide();
    }
  })
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div class="divs" data-brand="Nike" data-price="31" data-colour="Blue">
  Blue</div>
<div class="divs" data-brand="Nike" data-price="31" data-colour="Red">
  Red</div>
Colours: Blue
<input class="chbx" type="checkbox" id="BlueCB" checked>Red
<input class="chbx" type="checkbox" id="RedCB" checked>
<br>Brand: Nike
<input class="chbx" type="checkbox" id="NikeCB" checked>

ИЗМЕНИТЬ 1:

В случае, если вы хотите, чтобы состояние по умолчанию для всех флажков было снято, мы создаем функцию checkFilters() со всей логикой и вызываем ее при первой загрузке страницы, а также при каждом изменении состояния одного из флажков, как показано в этом JS Fiddle 2 .


ИЗМЕНИТЬ 2:

Код javascript все еще имеет избыточный код, и это только для 3-х флажков, предположим, что есть 10 брендов, и у вас есть 5 цветов для каждого бренда, тогда код будет выглядеть беспорядочным и повторяться с большим количеством ошибок, чтобы сделать код более надежным, гибким а также, намного короче, мы добавляем атрибуты data-type и data-keyword к каждому флажку, и в зависимости от значения атрибута data-type мы возвращаем соответствующий массив и помещаем значение {{ X3}} в соответствующий массив, поэтому он будет работать независимо от того, сколько цветов или флажков есть, как в этом < strong> JS Fiddle 3

Пример ввода :

<input class="chbx" type="checkbox" id="BlueCB" data-type="Colours" data-keyword="Blue" checked> Red

JS:

function checkFilters() {
    // Reset filters Arrays
    var ColoursFilters = [],
    BrandsFilters = [];

   CheckBoxes.each(function() {
       var $th = $(this), ArrayType, keyword;

       // Using ternary operator, we return the array that corresponds to the data-type
       ArrayType = $th.attr('data-type') == 'Colours' ? ColoursFilters : BrandsFilters;
       keyword = $th.attr('data-keyword');
       if ($th.is(':checked')) {
           ArrayType.push(keyword);
       } else if ($th.is(":checked") == false) {
           Index = ArrayType.indexOf(keyword);
           ArrayType.splice(Index, keyword);
       }
   });
   // ...  
}

* Обратите внимание, что jQuery .show() " примерно эквивалентно вызову .css( "display", "block") "while .hide() " примерно эквивалентно вызову .css( "display", "none") "

3
Mi-Creativity 15 Дек 2015 в 23:27

Добавьте в оператор if для селекторов цвета, чтобы определить, установлен ли флажок Nike.

Если флажок Nike не установлен, лично я сниму флажки и отключу флажки цвета.

https://jsfiddle.net/z9qbecLx/4/

var BlueSelector = $('#BlueCB');
var RedSelector = $('#RedCB');
var NikeSelector = $('#NikeCB');

BlueSelector.on("change", function(){
    if($(this).is(":checked") && NikeSelector.is(":checked"))
    {
        var divs = $("div[data-colour=Blue]");  
        divs.css("display",  "block");
    }
    else 
    {
        var divs = $("div[data-colour=Blue]");  
        divs.css("display",  "none");
    }
});

RedSelector.on("change", function(){
    if($(this).is(":checked") && NikeSelector.is(":checked"))
    {
        var divs = $("div[data-colour=Red]");  
        divs.css("display",  "block");
    }
    else 
    {
        var divs = $("div[data-colour=Red]");  
        divs.css("display",  "none");
    }
});

NikeSelector.on("change", function(){
  if($(this).is(":checked"))
  {
    RedSelector.prop('disabled', false);
    BlueSelector.prop('disabled', false);
    var divs = $("div[data-colour=Nike]");  
    divs.css("display",  "block");
  }
  else 
  {
    RedSelector.prop('checked', false).prop('disabled', true);
    BlueSelector.prop('checked', false).prop('disabled', true);
    var divs = $("div[data-brand=Nike]");  
    divs.css("display",  "none");
  }
});
0
xkcd149 15 Дек 2015 в 22:01

Вы можете использовать jQuery для добавления атрибута data-selected к отмеченным элементам. Я предполагаю, что элементы не выбраны по умолчанию. Используя свойство attr в выбранных элементах div, вы можете добавить такой атрибут. Чтобы убедиться, что при нажатии на флажок Nike отображаются только отфильтрованные селекторы, вы хотите добавить атрибут данных в селектор для этого события проверки, превратив его в $("div[data-brand=Nike][data-select=true]"). Кроме того, для краткости вы можете связать свойство attr и свойство css вместе.

https://jsfiddle.net/tfr9zh0w/

var BlueSelector = $('#BlueCB');

BlueSelector.on("change", function(){
if($(this).is(":checked"))
{
var divs = $("div[data-colour=Blue]");  
divs.attr('data-select', true).css("display",  "block");
} else 
{
var divs = $("div[data-colour=Blue]");  
divs.removeAttr('data-select').css("display",  "none");
}
});

var RedSelector = $('#RedCB');

RedSelector.on("change", function(){
if($(this).is(":checked"))
{
var divs = $("div[data-colour=Red]");  
divs.attr('data-select', true).css("display",  "block");
} else 
{
var divs = $("div[data-colour=Red]");  
divs.removeAttr('data-select').css("display",  "none");
}
});

var NikeSelector = $('#NikeCB');

NikeSelector.on("change", function(){
if($(this).is(":checked"))
{
var divs = $("div[data-brand=Nike][data-select=true]");  
divs.css("display",  "block");
} else 
{
var divs = $("div[data-brand=Nike]");  
divs.css("display",  "none");
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<div data-brand="Nike" data-price="31" data-colour="Blue">
Blue </div>
<div data-brand="Nike" data-price="31" data-colour="Red">
Red </div>
Colours:
Blue<input type="checkbox" id="BlueCB" checked>
Red<input type="checkbox" id="RedCB" checked>

Brand: Nike <input type="checkbox" id="NikeCB" checked>
0
litel 15 Дек 2015 в 22:22