Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #11 (permalink)  
Старый 21.10.2020, 13:55
Аспирант
Отправить личное сообщение для Aruta Посмотреть профиль Найти все сообщения от Aruta
 
Регистрация: 08.07.2019
Сообщений: 85

Сообщение от рони Посмотреть сообщение
Aruta,
менять надо класс элемента, а не стили элемента!!!

потому-что if (elem.style.borderColor == activeBorderColor)
activeBorderColor не содержит нужный цвет, строки 3 и 4, нужно вычислять, писать функцию которая вернёт нужный "цвет", браузеры устанавливают цвет параметра в своих единицах измерения, независимо что было в параметре установки (строка 40 и 59)!!!

поэтому лучше проверять класс элемента elem.classList.contains(), а ещё лучше не проверять а менять сразу elem.classList.toggle() и будет одна строка вместо строк 50 - 63.
Цвета пока не трогал, но переписал код.
Добавил 2 класса:
active-show - активированный фильтр - просто когда нажали на фильтр, чтобы посмотреть какие параметры фильтра выбрать можно
active - для активного фильтра с активным чекбоксом

Работает почти всё - осталась одна мелочь и вот её я не понял как и куда надо впихнуть верное условие:
if (click.target =  любой соседний li || на самого себя || в любое другое место на document) {  
    if (текущий активный li имеет class('active-show') ){ 
        li.classList.remove('active-show')
    }
}

Последний раз редактировалось Aruta, 21.10.2020 в 13:58.
Ответить с цитированием
  #12 (permalink)  
Старый 21.10.2020, 14:37
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,064

Aruta,
Ответить с цитированием
  #13 (permalink)  
Старый 21.10.2020, 14:48
Аспирант
Отправить личное сообщение для Aruta Посмотреть профиль Найти все сообщения от Aruta
 
Регистрация: 08.07.2019
Сообщений: 85

Сообщение от рони Посмотреть сообщение
Aruta,
Да... забыл код добавить завтра докину
Ответить с цитированием
  #14 (permalink)  
Старый 21.10.2020, 16:06
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,064

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>
Ответить с цитированием
  #15 (permalink)  
Старый 22.10.2020, 05:43
Аспирант
Отправить личное сообщение для Aruta Посмотреть профиль Найти все сообщения от Aruta
 
Регистрация: 08.07.2019
Сообщений: 85

Сообщение от рони Посмотреть сообщение
Aruta,
Неделю делал это... фуууф.
Добавляю код - дописал его всё же до конца и правильно работает

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();

Последний раз редактировалось Aruta, 22.10.2020 в 09:19.
Ответить с цитированием
  #16 (permalink)  
Старый 22.10.2020, 05:46
Аспирант
Отправить личное сообщение для Aruta Посмотреть профиль Найти все сообщения от Aruta
 
Регистрация: 08.07.2019
Сообщений: 85

рони,
Сообщение от рони
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);
        }
    }
})
я в шоке от лаконичности кода
но он не работает у меня - ничего не происходит, а при нажатии на document вне фильтров иногда ошибка вылазит:
Cannot read property 'querySelector' of null.

Теперь интересно на сколько мой код мне сократить можно

Последний раз редактировалось Aruta, 22.10.2020 в 07:52.
Ответить с цитированием
  #17 (permalink)  
Старый 22.10.2020, 08:24
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,693

const closeFilter = () => {
    document.addEventListener('click', e => {
        if(!buttons.target) {
            subMenuAll.forEach((e) => {
                dnoneStyle()   
            }) 
        }
        disActive()
    })
}


Что такое buttons.target ?
Ответить с цитированием
  #18 (permalink)  
Старый 22.10.2020, 08:52
Аватар для рони
Профессор
Отправить личное сообщение для рони Посмотреть профиль Найти все сообщения от рони
 
Регистрация: 27.05.2010
Сообщений: 33,064

Сообщение от Aruta
Cannot read property 'querySelector' of null.
допишите if(li && li.querySelector... строки 12 и 18 пост #16
Ответить с цитированием
  #19 (permalink)  
Старый 22.10.2020, 09:54
Аспирант
Отправить личное сообщение для Aruta Посмотреть профиль Найти все сообщения от Aruta
 
Регистрация: 08.07.2019
Сообщений: 85

рони,
Понял почему не работает, но это уже в css надо лезть мне и пару примочек дописать, т.к. не всё работает как надо было, но нужная основа прописана получается в вашем коде.
Но всё же поражаюсь - у меня ровно 100строк, а у вас 20 (или чуть больше если добавить всё что нужно) - снимаю шляпу просто и говорю огромное спасибо за показанное
Один вопрос остался только по поводу кол-ва строк:
- это у меня с логикой проблема и можно было строк в 50 уложиться (как для новичка) или это от незнания js и для обучающегося это нормальный код(мой)?

Последний раз редактировалось Aruta, 22.10.2020 в 10:12.
Ответить с цитированием
  #20 (permalink)  
Старый 22.10.2020, 10:07
Аспирант
Отправить личное сообщение для Aruta Посмотреть профиль Найти все сообщения от Aruta
 
Регистрация: 08.07.2019
Сообщений: 85

Сообщение от voraa
Что такое buttons.target ?
voraa, проверка условия "если клик не по одному из элементов массива buttons"

Последний раз редактировалось Aruta, 22.10.2020 в 10:10.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
mouseover срабатывает только для первого тега Julia1991 jQuery 4 23.06.2019 20:16
Listener's - срабатывает только последний __Alex__ Events/DOM/Window 7 31.08.2018 18:04
setInterval срабатывает только по клику yaparoff Общие вопросы Javascript 2 16.01.2018 16:03
Событие срабатывает только 1 раз mazahaler Events/DOM/Window 4 24.12.2017 13:00
Событие click срабатывает только при повторном нажатии (через ON) loko jQuery 8 16.01.2014 10:35