Фильтр блоков на чистом JS

112
07 мая 2021, 19:50

У меня есть код, который фильтрует блоки по выбранному цвету:

var filter_button_el = document.getElementById('filter'); 
var items_el = document.getElementById('items'); 
 
filter_button_el.onclick = function() { 
  console.log(this.value); 
  var items = items_el.getElementsByClassName('item'); 
  for (var i = 0; i < items.length; i++) { 
    if (items[i].classList.contains(this.value)) { 
      items[i].style.display = 'block'; 
    } else { 
      items[i].style.display = 'none'; 
    } 
  } 
} 
 
var filter_select_el = document.getElementById('filter1'); 
var items_el = document.getElementById('items'); 
 
filter_select_el.onclick = function() { 
  console.log(this.value); 
  var items = items_el.getElementsByClassName('item'); 
  for (var i = 0; i < items.length; i++) { 
    if (items[i].classList.contains(this.value)) { 
      items[i].style.display = 'block'; 
    } else { 
      items[i].style.display = 'none'; 
    } 
  } 
}
#items { 
  margin-top: 100px; 
} 
 
.item { 
  float: left; 
  width: 50px; 
  height: 50px; 
  margin: 1px; 
} 
 
.red { 
  background: #cf2624; 
} 
 
.blue { 
  background: #2478cf; 
} 
 
.green { 
  background: #24cf7c; 
} 
 
.orange { 
  background: #cf7c24; 
} 
 
.yellow { 
  background: #f1e81f; 
}
<select id="filter1"> 
  <option value="">Сбросить</option> 
  <option value="item">все</option> 
  <option value="red">красный</option> 
  <option value="blue">синий</option> 
  <option value="green">зелёный</option> 
  <option value="orange">оранжевый</option> 
  <option value="yellow">жёлтый</option> 
</select> 
 
<button id="filter" value="red">Красный</button> 
 
<div id="items"> 
  <div class="item red">1</div> 
  <div class="item blue">2</div> 
  <div class="item red">3</div> 
  <div class="item green">4</div> 
  <div class="item red">5</div> 
  <div class="item orange">6</div> 
  <div class="item green">7</div> 
  <div class="item yellow">8</div> 
  <div class="item green">9</div> 
  <div class="item orange">10</div> 
  <div class="item yellow">11</div> 
  <div class="item blue">12</div> 
  <div class="item green">13</div> 
  <div class="item orange">14</div> 
  <div class="item blue">15</div> 
  <div class="item orange">16</div> 
  <div class="item red">17</div> 
  <div class="item yellow">18</div> 
</div>

По отдельности всё работает (список фильтрует, кнопка то же).

Не понимаю как сделать фильтр вроде чекбоксов. То есть, при выборе в списке "Синий" - остаются все синие блоки, при нажатии на кнопку "Красный" - добавляются красные блоки. Нужно, что бы принцип работы был следующий: список воспринимался - чекбоксом, а кнопки - "радио".

Answer 1

( JsFiddle )

var radio = document.getElementById('radio'); // селект - псевдорадио 
var check = document.querySelectorAll('.check'); // кнопки - псевдочекбоксы 
var items = document.getElementById('items'); // цветные квадратики 
 
radio.addEventListener('change', function() { 
  var val = this.value; 
  var item = items.querySelectorAll('.item'); 
  for ( var i = 0; i < item.length; i++ ) { 
    if (item[i].classList.contains( val )) { 
      item[i].style.display = "block"; 
    } else { 
      item[i].style.display = "none"; 
    } 
  } 
  for( i = 0; i < check.length; i++ ){ 
    var ch = check[i]; 
    if( ch.value === val || this.value === "item" ){ 
      ch.classList.add('checked'); // Класс-индикатор отмеченности 
      ch.chosen = true; 
    } else {		   
      ch.classList.remove('checked'); 
      ch.chosen = false; 
    } 
  } 
}); 
 
for (var i = 0; i < check.length; i++) { 
  check[i].chosen = true; // Изначально все показаны 
  check[i].addEventListener('click', function() { 
    this.chosen = !this.chosen; // Значение переключается, как у обычных чекбоксов 
    this.classList.toggle('checked'); 
    var item = items.querySelectorAll('.' + this.value);  
    for( var u = 0; u < item.length; u++ ){ 
      item[u].style.display = this.chosen ? 'block' : 'none'; 
    } 
  }); 
}
#items { 
  margin-top: 100px; 
} 
 
.item { 
  float: left; 
  width: 50px; 
  height: 50px; 
  margin: 1px; 
} 
 
.red { 
  background: #cf2624; 
} 
 
.blue { 
  background: #2478cf; 
} 
 
.green { 
  background: #24cf7c; 
} 
 
.orange { 
  background: #cf7c24; 
} 
 
.yellow { 
  background: #f1e81f; 
} 
 
.check::before { 
  content: "• "; 
  color: #999; 
} 
.checked::before { 
  color: red; 
}
<select id="radio"> 
  <option value="">Сбросить</option> 
  <option value="item">все</option> 
  <option value="red">красный</option> 
  <option value="blue">синий</option> 
  <option value="green">зелёный</option> 
  <option value="orange">оранжевый</option> 
  <option value="yellow">жёлтый</option> 
</select> 
 
<button class="check checked" value="red">Красный</button> 
<button class="check checked" value="green">Зеленый</button> 
 
<div id="items"> 
  <div class="item red">1</div> 
  <div class="item blue">2</div> 
  <div class="item red">3</div> 
  <div class="item green">4</div> 
  <div class="item red">5</div> 
  <div class="item orange">6</div> 
  <div class="item green">7</div> 
  <div class="item yellow">8</div> 
  <div class="item green">9</div> 
  <div class="item orange">10</div> 
  <div class="item yellow">11</div> 
  <div class="item blue">12</div> 
  <div class="item green">13</div> 
  <div class="item orange">14</div> 
  <div class="item blue">15</div> 
  <div class="item orange">16</div> 
  <div class="item red">17</div> 
  <div class="item yellow">18</div> 
</div>

P.s. float-left надо бы заменить на display: inline-block; А образовавшиеся пробелы можно убрать, если удалить пробелы между элементами, так:

<div> ... </div
><div> ... </div
><div> ... </div>
READ ALSO
Использование Auth0 в России

Использование Auth0 в России

В своем сервисе использую авторизацию через Auth0

111
Анимация вращения на CSS

Анимация вращения на CSS

Хочу сделать такую же анимацию вращения с помощью CSS, но у меня получается она только в одну сторону

90
Вывод 2D с поворотом в Irrlicht

Вывод 2D с поворотом в Irrlicht

Возможно ли это?

71