Срабатывает только только else...
Добрый день!
Задача: - при нажатии на li или его дочерний <div class="filter__name filter__list"> блок li должен окрашивать границу в цвет activeColor - при повторном нажатии style по-умолчанию цвет становится (в коде - для проверки пока код пишется - сделал черный цвет, чтобы в глаза бросалось сразу отрабатывает ли, но не отрабатывает) - это справедливо для всех li, кроме последнего "CLEAR" - на нём ничего не происходит. Не могу понять почему блок if-else отрабатывает не верно - он красит в нужный цвет при первом нажатии, но при повторном не снимает окраску границы. Хочется понять в чем ошибка и узнать подсказки, а не готовое решение:) Подскажите, пожалуйста! P.S. если проще посмотреть на live версии, то могу залить HTML: <ul class="results__filter-inner dflex"> <!-- Блок конкретного фильтра. Далее каждая группа фильтров обозначена li id="название фильтра" --> <li id="gender"> <!--Блок названия группы фильтра и стрелочки --> <div class="filter__name filter__list"> <div>Gender</div> <i class="arrow down"></i> </div> <!--Раскрывающийся список группы --> <div class="filter__name__list-wrap dflex" style="display: none;"> <div class="name__list-inner"> <div class="name__list"> <input type="checkbox" id="chk_men" class="toggle" name="chk_men" value="Men"> <label for="chk_men" class="name__list-label">Men</label> </div> <div class="name__list"> <input type="checkbox" id="chk_women" class="toggle" name="chk_women" value="Women"> <label for="chk_women" class="name__list-label">Women</label> </div> </div> </div> </li> <li id="priority"> <div class="filter__name filter__list"> <div>Priority</div> <i class="arrow down"></i> </div> <div class="filter__name__list-wrap" style="display: none;"> <div class="name__list-inner"> <div class="name__list"> <input type="checkbox" id="chk_color" class="toggle" name="chk_color" value="Color"> <label for="chk_color" class="name__list-label">Color</label> </div> <div class="name__list"> <input type="checkbox" id="chk_style" class="toggle" name="chk_style" value="Style"> <label for="chk_style" class="name__list-label">Style</label> </div> </div> </div> </li> <li id="prod_type"> <div class="filter__name filter__list"> <div>Product type</div> <i class="arrow down"></i> </div> <div class="filter__name__list-wrap" style="display: none;"> <div class="name__list-inner"> <div class="name__list"> <input type="checkbox" id="chk_shirt" class="toggle" name="chk_shirt" value="Shirt"> <label for="chk_shirt" class="name__list-label">Shirt</label> </div> <div class="name__list"> <input type="checkbox" id="chk_blouse" class="toggle" name="chk_blouse" value="Blouse"> <label for="chk_blouse" class="name__list-label">Blouse</label> </div> <div class="name__list"> <input type="checkbox" id="chk_top" class="toggle" name="chk_top" value="Top"> <label for="chk_top" class="name__list-label">Top, T-shirt, Sweatshirt</label> </div> <div class="name__list"> <input type="checkbox" id="chk_sweater" class="toggle" name="chk_sweater" value="Sweater"> <label for="chk_sweater" class="name__list-label">Sweater</label> </div> </div> </div> </li> <li> <input type="checkbox" id="dublicate" class="toggle" name="dublicate"> <label for="dublicate">Remove dublicate</label> </li> <li> <div class="filter__name clear"> <div>Clear</div> </div> </li> </ul> JS: const buttons = document.querySelectorAll('.results__filter-inner>li'); const subMenuAll = document.querySelectorAll('.filter__name__list-wrap'); let activeBorderColor ='#ff7bac'; let activeColor = '#220718'; //функция HIDE всех нужных блоков по классу const dnoneStyle = () => { subMenuAll.forEach((dnone) => { dnone.style.display = "none"; }); } //Сброс цвета активного фильтра на "по-умолчанию" неактивный const resetColorBorder = () =>{ buttons.forEach((el) => { el.style.removeProperty('border-color'); }) } //Закрытие меню при клике вне меню const close = () => { document.addEventListener('click', e => { if(!buttons.target) { subMenuAll.forEach((e) => { dnoneStyle(); }) } }) } // Открытие/закрытие подменю при нажатии на название фильтра buttons.forEach((elem) => { let subMenu = elem.querySelector('.filter__name__list-wrap'); let clear = elem.querySelector('.clear'); subMenuAll.forEach( (chbx) => { let inputs = chbx.querySelectorAll('input'); for (let i=0; i<inputs.length; i++){ inputs[i].onchange = () =>{ let inputParent = chbx.parentNode; //обращаемся к родителю элемента if (inputs[i].checked){ inputParent.style.borderColor = activeBorderColor; inputParent.style.color = activeColor; } else { inputParent.style.removeProperty('border-color'); inputParent.style.removeProperty('color'); } } } }) //этот блок не работает - срабатывает только условие else почему-то. const notClear = () =>{ if (!clear){ if (elem.style.borderColor == activeBorderColor){ console.log('on') elem.style.borderColor='black'; elem.style.removeProperty('color'); } else { console.log('off') // filterButtons(); elem.style.borderColor = activeBorderColor; elem.style.color = activeColor; } } } //конец плохо работающего блока elem.addEventListener('click', (subElem) => { // elem.style.borderColor = activeBorderColor; const filterButtons = () => { subElem.stopPropagation(); if (subMenu){ //если имеется выпадающий список у фильтра if (subMenu.style.display != "block"){ dnoneStyle(); subMenu.style.display = "block"; //перебор checkbox, чтобы отмечался только один в фильтре let inputs= elem.getElementsByTagName('input'); for (var i = inputs.length-1; i >= 0; -- i) { inputs[i].onclick = function () { for (var j = inputs.length-1; j >= 0; -- j) { if (inputs[j] != this) inputs[j].checked = false; } } } activeFilter(); notClear(); //запрет на всплытие клика выше выпадающего списка, т.е. не будет срабатывать на родителе. subMenu.addEventListener('click', (g) => { g.stopPropagation(); }); } else { dnoneStyle(); } } else { //если нет выпадающего списка у фильтра notClear(); return; } } filterButtons(); }); }); close(); |
Aruta,
менять надо класс элемента, а не стили элемента!!! Цитата:
activeBorderColor не содержит нужный цвет, строки 3 и 4, нужно вычислять, писать функцию которая вернёт нужный "цвет", браузеры устанавливают цвет параметра в своих единицах измерения, независимо что было в параметре установки (строка 40 и 59)!!! поэтому лучше проверять класс элемента elem.classList.contains(), а ещё лучше не проверять а менять сразу elem.classList.toggle() и будет одна строка вместо строк 50 - 63. |
рони,
Цитата:
Цитата:
у меня же не все elem идут с классами - 2 шт без класса UPD. понял идею про classList, но он не подойдёт, т.к. если граница окрашены через функцию в 34 строке, то toggle будет их игнорировать и менять окраску, а этого не должно быть. |
Цитата:
он присваивает свой цвет а не ваш. |
Цитата:
|
Aruta,
фокус-покус :) <!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> </head> <body> <div id="elem"></div> <script> let activeColor = '#220718'; elem.style.color = activeColor; elem.innerHTML = elem.style.color; </script> </body> </html> |
Цитата:
|
Цитата:
Это к тому что должен выводиться именно #220718 а не RGB? |
Цитата:
|
Цитата:
|
Цитата:
Добавил 2 класса: active-show - активированный фильтр - просто когда нажали на фильтр, чтобы посмотреть какие параметры фильтра выбрать можно active - для активного фильтра с активным чекбоксом Работает почти всё - осталась одна мелочь и вот её я не понял как и куда надо впихнуть верное условие: if (click.target = любой соседний li || на самого себя || в любое другое место на document) { if (текущий активный li имеет class('active-show') ){ li.classList.remove('active-show') } } |
Aruta,
:-? |
Цитата:
|
Aruta,
<!DOCTYPE html> <html> <head> <title>Untitled</title> <meta charset="utf-8"> <style type="text/css"> ul{ list-style: none; } .filter__list{ display: flex; } li.active-show .filter__list{ color: #8B4513; font-weight: bold; } .filter__list + div{ display: none; } li.active-show .filter__list + div{ border: 1px solid #FF0000; display: block; } .filter__list:after{ content: "▼" } li.active-show .filter__list:after{ content: "▲" } </style> </head> <body> <ul class="results__filter-inner dflex"> <!-- Блок конкретного фильтра. Далее каждая группа фильтров обозначена li id="название фильтра" --> <li id="gender"> <!--Блок названия группы фильтра и стрелочки --> <div class="filter__name filter__list"> <div>Gender</div> </div> <!--Раскрывающийся список группы --> <div class="filter__name__list-wrap dflex"> <div class="name__list-inner"> <div class="name__list"> <input type="checkbox" id="chk_men" class="toggle" name="chk_men" value="Men"> <label for="chk_men" class="name__list-label">Men</label> </div> <div class="name__list"> <input type="checkbox" id="chk_women" class="toggle" name="chk_women" value="Women"> <label for="chk_women" class="name__list-label">Women</label> </div> </div> </div> </li> <li id="priority"> <div class="filter__name filter__list"> <div>Priority</div> </div> <div class="filter__name__list-wrap"> <div class="name__list-inner"> <div class="name__list"> <input type="checkbox" id="chk_color" class="toggle" name="chk_color" value="Color"> <label for="chk_color" class="name__list-label">Color</label> </div> <div class="name__list"> <input type="checkbox" id="chk_style" class="toggle" name="chk_style" value="Style"> <label for="chk_style" class="name__list-label">Style</label> </div> </div> </div> </li> <li id="prod_type"> <div class="filter__name filter__list"> <div>Product type</div> </div> <div class="filter__name__list-wrap" > <div class="name__list-inner"> <div class="name__list"> <input type="checkbox" id="chk_shirt" class="toggle" name="chk_shirt" value="Shirt"> <label for="chk_shirt" class="name__list-label">Shirt</label> </div> <div class="name__list"> <input type="checkbox" id="chk_blouse" class="toggle" name="chk_blouse" value="Blouse"> <label for="chk_blouse" class="name__list-label">Blouse</label> </div> <div class="name__list"> <input type="checkbox" id="chk_top" class="toggle" name="chk_top" value="Top"> <label for="chk_top" class="name__list-label">Top, T-shirt, Sweatshirt</label> </div> <div class="name__list"> <input type="checkbox" id="chk_sweater" class="toggle" name="chk_sweater" value="Sweater"> <label for="chk_sweater" class="name__list-label">Sweater</label> </div> </div> </div> </li> <li> <input type="checkbox" id="dublicate" class="toggle" name="dublicate"> <label for="dublicate">Remove dublicate</label> </li> <li> <div class="filter__name clear"> <div>Clear</div> </div> </li> </ul> <script> const ul = document.querySelector('.results__filter-inner'); let tempLi; document.addEventListener('click', event => { let filterUl = event.target.closest('ul'); let li = event.target.closest('li'); if (tempLi && li != tempLi) { tempLi.classList.remove('active-show'); tempLi = null; } if (filterUl == ul) { if (li.querySelector('.filter__list')) { tempLi = li; let input = event.target.closest('[type="checkbox"]'); if (input) li.querySelectorAll('[type="checkbox"]').forEach(el => el != input && (el.checked = false)); if (event.target.closest('.filter__list')) tempLi.classList.toggle('active-show'); } if (li.querySelector('.clear')) { ul.querySelectorAll(':checked').forEach(el => el.checked = false); } } }) </script> </body> </html> |
Цитата:
Добавляю код - дописал его всё же до конца и правильно работает:) :dance: const buttons = document.querySelectorAll('.results__filter-inner>li'); const subMenuAll = document.querySelectorAll('.filter__name__list-wrap'); let activeBorderColor ='rgb(255, 123, 172)'; let activeColor = 'rgb(34, 7, 24)'; //функция HIDE всех нужных блоков по классу const dnoneStyle = () => { subMenuAll.forEach((dnone) => { dnone.style.display = "none"; }); } const disActive = () =>{ for (let i=0; i<buttons.length; i++){ if (buttons[i].classList.contains('active-show')){ buttons[i].classList.remove('active-show'); } } } //Закрытие меню при клике вне меню const closeFilter = () => { document.addEventListener('click', e => { if(!buttons.target) { subMenuAll.forEach((e) => { dnoneStyle() }) } disActive() }) } // Открытие/закрытие подменю при нажатии на название фильтра buttons.forEach((elem) => { let subMenu = elem.querySelector('.filter__name__list-wrap'); let clear = elem.querySelector('.clear'); const activeFilter = () =>{ // elem.classList.toggle('active-show'); buttons.forEach( (chbx) => { let inputs = chbx.querySelectorAll('input'); for (let i=0; i<inputs.length; i++){ inputs[i].onchange = () =>{ let inputParent = chbx.closest('li'); //обращаемся к родителю элемента if (!inputs[i].checked){ inputParent.classList.remove('active-filter'); inputs[i].classList.remove('active_param'); } else { inputParent.classList.add('active-filter'); inputs[i].classList.add('active_param'); } } } }); } elem.addEventListener('click', (subElem) => { const filterButtons = () => { subElem.stopPropagation(); //если имеется выпадающий список у фильтра if (subMenu){ if (subMenu.style.display != "block"){ dnoneStyle(); subMenu.style.display = "block"; //перебор checkbox, чтобы отмечался только один в фильтре let inputs= elem.getElementsByTagName('input'); for (var i = inputs.length-1; i >= 0; -- i) { inputs[i].onclick = function () { for (var j = inputs.length-1; j >= 0; -- j) { if (inputs[j] != this) inputs[j].checked = false; } } } activeFilter(); //запрет на всплытие клика выше выпадающего списка, т.е. не будет срабатывать на родителе. subMenu.addEventListener('click', (g) => { g.stopPropagation(); }); } else { dnoneStyle(); } } else { //если нет выпадающего списка у фильтра dnoneStyle(); return; } } //снятие окраски фильтра, если он не активен или он не ракскрыт if (!clear){ for (let i = 0; i<buttons.length; i++){ if(!elem.classList.contains('active-show')){ elem.classList.toggle('active-show'); } else { disActive() } } } //применяем функцию фильтров filterButtons(); //сброс активных фильтра - CLEAR if (clear){ for (let i=0; i<buttons.length; i++){ buttons[i].classList.remove('active-filter'); buttons[i].classList.remove('active-show'); } buttons.forEach( (chbx) => { let inputs = chbx.querySelectorAll('input'); for (let i=0; i<inputs.length; i++){ inputs[i].classList.remove('active_param'); inputs[i].checked = false; } }) } }); }); closeFilter(); |
рони,
Цитата:
но он не работает у меня - ничего не происходит, а при нажатии на document вне фильтров иногда ошибка вылазит: Cannot read property 'querySelector' of null. Теперь интересно на сколько мой код мне сократить можно:write: |
const closeFilter = () => { document.addEventListener('click', e => { if(!buttons.target) { subMenuAll.forEach((e) => { dnoneStyle() }) } disActive() }) } Что такое buttons.target ? |
Цитата:
|
рони,
Понял почему не работает, но это уже в css надо лезть мне и пару примочек дописать, т.к. не всё работает как надо было, но нужная основа прописана получается в вашем коде. Но всё же поражаюсь - у меня ровно 100строк, а у вас 20 (или чуть больше если добавить всё что нужно) - снимаю шляпу просто и говорю огромное спасибо за показанное:) Один вопрос остался только по поводу кол-ва строк: - это у меня с логикой проблема и можно было строк в 50 уложиться (как для новичка) или это от незнания js и для обучающегося это нормальный код(мой)?:) |
Цитата:
|
Aruta,
код нормальный для начинающего, но почитайте про делегирование. |
Цитата:
|
Цитата:
const buttons = document.querySelectorAll('.results__filter-inner>li'); Это объект NodeList. Откуда у него появляется свойство target? |
Часовой пояс GMT +3, время: 20:00. |