Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Выборка элементов querySelectorAll (https://javascript.ru/forum/events/71107-vyborka-ehlementov-queryselectorall.html)

Nlk 26.10.2017 13:02

Выборка элементов querySelectorAll
 
Ребят, всем привет!
Пожалуйста укажите на ошибку в коде.
Почему при клике на выбранных элементах они не пропадают?
<h1 class="oli">вариант 1</h1>
<p class="sd">вариант 2</p>
<p class="oli">вариант 3</p>

var x = document.querySelectorAll('.oli');
document.x.addEventListener("click", myFunction);

function myFunction() {
	var i;
	for (i = 0; i < x.length; i++) {
		x[i].style.display = "none";
	}
}

рони 26.10.2017 13:11

Nlk,
что такое
Цитата:

Сообщение от Nlk
document.x

???
и на всякий случай у querySelectorAll нет метода addEventListener, нужен цикл по всем элементам для addEventListener

Nexus 26.10.2017 13:16

"x" - коллекция элементов, по сути массив.
У массива нет метода "addEventListener", а у "document" не появилось свойство "x" от того, что вы создали переменную.
Чтобы повесить обработчик на каждый элемент коллекции, нужно пробежаться по коллекции в цикле.
В обработчике события "this" - ссылка на элемент, на котором произошло событие.

var x = document.querySelectorAll('.oli');
for(var i=0;i<x.length;i++)
    x[i].addEventListener("click", myFunction);

function myFunction() {
    this.style.display = "none";
}

Nlk 26.10.2017 13:32

Всем огромное спасибо, особенно за столь подробные разъяснения.

Nlk 26.10.2017 15:48

А скобочки для цикла for можно и не ставить?

Nexus 26.10.2017 15:52

Nlk, лучше ставить.
Если в блоке только 1 операция, то скобки можно опустить.

Nlk 26.10.2017 17:09

Nexus,
Спасибо.
Простите за мою навязчивость, в цикле for переменную i вы внесли в цикл, а в каких случаях могло быть полезно объявлять переменную вне цикла?

Nexus 26.10.2017 17:28

Nlk, не знаю :)
Область видимости-то не поменяется от того, что переменная будет объявлена до объявления аргументов цикла.
Если циклов несколько и все юзают одну переменную, то её можно определить до создания цикла или в аргументах первого цикла, а в остальных циклах просто изменять её значение.
Т.е. так:
for(var i=0;i<10;i++){};
for(i=0;i<10;i++){};

Nlk 26.10.2017 18:45

Nexus,
Спасибо за ваши ответы, последний раз попрошу вашего внимания.
Скажите а можно реализовать выключение всех потомков схожим образом:
var x = document.querySelectorAll('.oli');
for(var i=0;i<x.length;i++)
    x[i].addEventListener("click", myFunction);

function myFunction() {
    this.childNodes.style.display = "none";
}

рони 26.10.2017 19:05

Цитата:

Сообщение от Nlk
выключение всех потомков

либо цикл по всем элементам, либо смена класса у родителя

Nlk 27.10.2017 12:58

рони,
Спасибо, касаемо варианта с классом, по css не могу сообразить как должно выглядеть.
function myFunction() {
    this.classList.add("disable");
}

.disable .submenu {display: none;}

Dilettante_Pro 27.10.2017 14:31

Не знаю, при чем тут .submenu, но
<style>
.disable, .submenu {display: none;}
</style>

<h1 class="oli">вариант 1</h1>
<p class="sd">вариант 2</p>
<p class="oli">вариант 3</p>

<script>
var x = document.querySelectorAll('.oli');
for(var i=0;i<x.length;i++)
    x[i].addEventListener("click", myFunction);

function myFunction() {
    this.classList.add("disable");
}
</script>

рони 27.10.2017 14:45

Цитата:

Сообщение от Nlk
по css не могу сообразить как должно

Цитата:

Сообщение от Nlk
.disable > .submenu {display: none;}

Знаете ли вы селекторы?

рони 27.10.2017 14:52

Nlk,
<meta charset="utf-8">
<style>
.oli {
  background-color: #EEE8AA;
   cursor: pointer;
}

.disable > .submenu {display: none;}
</style>

<div class="oli">вариант 1 <ul class="submenu"><li>test</li></ul></div>
<div class="sd">вариант 2</div>
<div class="oli">вариант 3 <ul class="submenu"><li>test</li></ul></div>

<script>
var x = document.querySelectorAll('.oli');
for(var i=0;i<x.length;i++)
    x[i].addEventListener("click", myFunction);

function myFunction() {
    this.classList.add("disable");
}
</script>

рони 27.10.2017 15:06

Цитата:

Сообщение от Nlk
Видимо classList не работает с nodeList если я правильно понимаю..

да
Цитата:

Сообщение от Nlk
Но я всё равно не могу захлопнуть меню по клику.

делайте макеты целиком!!!

Nlk 27.10.2017 15:26

Я вам всем ужасно благодарен на этом форуме! За ваше терпение и понимание.
А как мне реализовать переключение при повторном клике, как то так или использовать toggle?
function myFunction() {
	if (this.classList.add("disable")) {
		this.classList.remove("disable");
	}
}

или
this.classList.contains('show-submenu') ? hideSubMenu(el) : showSubMenu(el);

Nexus 27.10.2017 15:30

function myFunction() {
	this.classList.toggle("disable");
}

рони 27.10.2017 15:31

Nlk,
:-?
function myFunction() {
			this.classList.toggle("disable");
	
}

Nlk 27.10.2017 16:48

Спасибо большое всё работает)
Как завершу выложу попрошу проверить.

А не могли бы рассказать про данную альтернативную реализацию меню.
[].slice.call(document.querySelectorAll('.dropdown .nav-link')).forEach(function(el){
    el.addEventListener('click', onClick, false);
});

Как я понимаю:
[].slice - в пустой массив производится копирование
call - посредством контекста
(document.querySelectorAll('.dropdown .nav-link')) - из nodeList'а
.forEach - который посредством метода forEach делает полноценный массив из классов.

рони 27.10.2017 16:52

Nlk,
коллекции-не-массивы

рони 27.10.2017 16:55

Цитата:

Сообщение от Nlk
[].slice.call

создание массива, методом slice из списка элементов (лишнее звено, можно сразу [].forEach.call)
Цитата:

Сообщение от Nlk
forEach

цикл по созданному массиву

Nlk 30.10.2017 15:08

рони,
Спасибо, скажите а элементы классов .dropdown и .nav-link оказываются в одном массиве?

Nexus 30.10.2017 15:18

Nlk,
document.querySelectorAll('.dropdown .nav-link')

Если вопрос по этой выборке, то "querySelectorAll" вернет коллекцию элементов с классом "nav-link", которые являются детьми для элементов с классом "dropdown".
Родители при таком селекте в коллекцию не попадут.

Nlk 30.10.2017 15:33

Nexus,
Теперь всё ясно, а я голову ломал. Огромнейшее Вам спасибо!

Nlk 30.10.2017 15:40

Выпадающее меню работу которого вы мне сейчас объяснили https://codepen.io/ryanmorr/pen/LVzYmx

Nlk 31.10.2017 11:16

А можно в дальнейшем ещё вопросы в этой ветке задавать, без прямой связи с темой?

В данном отрывке кода не могу понять как метод contains используется? Ведь он призван проверять присутствие класса в элементе!?
container.addEventListener('click', function(e){
    if(isShowingSidebar() && main.contains(e.target)){
        e.preventDefault();
        hideSidebar();
    }
}, true);

Nexus 31.10.2017 11:19

Nlk,
https://learn.javascript.ru/compare-document-position

Nlk 31.10.2017 12:15

Nexus,
Спасибо за ссылку, ознакомился.
Но не могу понять, метод contains необходим для проверки вложенности элементов. А в данном случае используется проверка на событие, так?

Nexus 31.10.2017 12:20

Nlk, нет.
Цитата:

Сообщение от learn.javascript.ru
event.target – это исходный элемент, на котором произошло событие, в процессе всплытия он неизменен.

https://learn.javascript.ru/event-bu...-event-target

Nlk 31.10.2017 12:49

Nexus,
извините за мою тупость, но я не понимаю что в данной строке кода происходит? Что e.target событие понятно.
main.contains(e.target)

Nexus 31.10.2017 12:54

Цитата:

Сообщение от Nlk
Что e.target событие понятно.

Объект события - "e", "e.target" - HTMLElement, на котором произошло событие "e.type".
В этой строке проверяется является ли элемент, на котором произошло событие дочерним по отношению к элементу main или элемент "main" и есть тот элемент, на котором это событие произошло.

Nlk 31.10.2017 15:02

Nexus,
огромное спасибо, что разъяснили столь подробно.

Nlk 20.11.2017 13:55

Скажите метод matches подходит для проверки класса по которому было произведено событие?
window.onclick = function(event) {
  if (event.target.matches('.dropbtn')) {}

рони 20.11.2017 14:12

Цитата:

Сообщение от Nlk
matches подходит для проверки класса

а самому проверить? да, но возможно лучше будет closest

Nlk 20.11.2017 15:14

рони,
Спасибо за ответы, я знал что пример рабочий, просто хотел уточнить возможные нюансы. Как к примеру вы упомянули про closest, я в первые про него слышу. В остальном постараюсь понапрасну не писать.

Nlk 27.11.2017 15:52

Скажите пожалуйста, у меня такой вопрос.
Есть модальное окно, при его всплытии работает скролл сайта.
Могу ли я от него избавиться, таким путем задав body class или id, и впоследствии в момент всплытия popup-окна добавить ему данный класс. К примеру:
.popup-active. classBody {
     overwlov:hidden;
}

Nlk 27.11.2017 16:05

Или это может вообще считается не очень хорошей практикой body задавать класс?

Nexus 27.11.2017 16:15

Nlk, нормальная практика.
У вас css малость кривоват.
body.popup-active{overflow:hidden;}

Nlk 27.11.2017 16:41

Nexus,
в данном случае если я не ошибаюсь overflow:hidden мы задаём классу .popup-active, а мне нужно overflow:hidden задать body чтобы при всплытии моего popup-окна прокрутка сайта исчезла. Или я чего -то не понимаю..

Nexus 27.11.2017 16:45

Nlk, нельзя добавить класс дочернему элементу, а свойство объявить его родителю, поэтому когда popup показывается тэгу body добавляете класс "popup-active".
У body с классом "popup-active" скроллбары отключаем (код я привел выше).

Тут вроде бы адекватное описание селекторов:
https://misha.blog/css/selektoryi.html


Часовой пояс GMT +3, время: 18:27.