Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   Привязка одного события к многим однотипным элементам (https://javascript.ru/forum/events/65390-privyazka-odnogo-sobytiya-k-mnogim-odnotipnym-ehlementam.html)

Rostik 16.10.2016 11:36

Привязка одного события к многим однотипным элементам
 
Всем привет! Начал изучать js совсем не давно и естественно возникли некоторые сложности.
Нужно чтобы при первом нажатии на блок он развернулся, а при втором нажатии на него - свернулся.
Проблема в том что все работает только с последним блоком. И когда нажимаю на первый или второй блок, все равно действия происходит над 3-м.
Хотелось бы чтобы действия происходили над блоком с классом "post" и не задавать для этого блока артибут onClick.

вот моя попытка это сделать:
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>LoL</title>
	<style>
        .post{
            width: 500px;
            height: 40px;
            background: #666;
            margin-top: 10px;
        }
	</style>
</head>
<body>
    <div class="post"></div>
    <div class="post"></div>
    <div class="post"></div>
    <script>
        
        var post;
        var i = 0;
        var post = document.querySelectorAll(".post");
        while(document.querySelectorAll(".post")[i]){
            post[i].onclick = Post(post[i]); // здесь проблемка. походу обработчик вешается только на последний элемент
            i++;
        }
        function Post(mythis){
            $this = mythis;
            var startH = mythis.clientHeight;
            var tumbler = false;
            var n = 0;
            var tname;
            return function(){
                h = $this.clientHeight;
                tumbler = !tumbler;
                n++;
                if(tumbler){
                    clearTimeout(tname);
                    tname = setInterval(function(){
                        if(100 <= h) clearTimeout(tname); 
                        $this.style.height = h+"px";
                        h +=1;
                    },10);
                }else{
                    clearTimeout(tname);
                    tname = setInterval(function(){
                        if(startH >= h) clearTimeout(tname); 
                        $this.style.height = h+"px";
                        h -=1;
                    },10);
                }
            }  
        };
        
    </script>
</body>
</html>

destus 16.10.2016 13:46

Rostik,
как вариант...
<style>
        .post{
            width: 500px;
            height: 40px;
            background: #666;
            margin-top: 10px;
            transition: height .5s ease-in;
        }
        .post.active{
            height: 140px;
        }
</style>
<div class="post"></div>
    <div class="post"></div>
    <div class="post"></div>
    <script>
		[].forEach.call(document.querySelectorAll('.post'), function(div){
			div.addEventListener('click', function(){
				this.classList.toggle('active');
			})
		})
    </script>

рони 16.10.2016 13:58

Rostik,
Цитата:

Сообщение от Rostik
здесь проблемка. походу обработчик вешается только на последний элемент

Пример ошибочного использования
Цитата:

Такой глюк возник из-за того, что все функции div[i].onclick получают значение i ... на момент активации onclick ... последнее значение i когда цикл завершился
решение либо замыкание, либо forEach вместо for, либо нужное значение хранить в самом элементе.

рони 16.10.2016 14:05

Rostik,
пост выше для развития , а у вас просто var не хватает в строках 29 и 35

warren buffet 16.10.2016 14:09

Здесь проблемка в лобовом решении. Есть чуть более вбок, но тоже хрестоматийное. Меняем хтмл

<div class="posts"></div>
   <div></div>
   <div></div>
   <div></div>
</div>


Правила применяем к posts так

.posts > div {}

чтобы дивы следующего порядка не затрагивались

и вешаем на этот родительский див 1 листенер и 1 обработчик

document.querySelector('posts').addEventListener('click',togPost);

function togPost(ev){
  
  var el = ev.target;
  if(el===this) return;
  /* могут быть еще проверки, ну и пользуешься el для скрытия-раскрытия */

}


Канонично все.

Rostik 16.10.2016 14:09

Всем большое спасибо! вижу многому нужно еще учится))

я тут похимичил и вот что в итоге получилось...
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>LoL</title>
	<style>
        .post{
            width: 500px;
            height: 40px;
            background: #666;
            margin-top: 10px;
        }
	</style>
</head>
<body>
    <div class="post"></div>
    <div class="post"></div>
    <div class="post"></div>
    <script>
        
        var post;
        var i = 0;
        var post = document.querySelectorAll(".post");
        while(document.querySelectorAll(".post")[i]){
            post[i].myClick = new Post(post[i]);
            post[i].onclick = post[i].myClick.do();
            i++;
        }
        function Post($this){
            this.do = function(){
                var startH = $this.clientHeight;
                var tumbler = false;
                var n = 0;
                var tname;
                return function(){
                    h = $this.clientHeight;
                    tumbler = !tumbler;
                    n++;
                    if(tumbler){
                        clearTimeout(tname);
                        tname = setInterval(function(){
                            if(100 <= h) clearTimeout(tname); 
                            $this.style.height = h+"px";
                            h +=1;
                        },10);
                    }else{
                        clearTimeout(tname);
                        tname = setInterval(function(){
                            if(startH >= h) clearTimeout(tname); 
                            $this.style.height = h+"px";
                            h -=1;
                        },10);
                    }
                }  
        };
        };
        
    </script>
</body>
</html>

warren buffet 16.10.2016 14:14

Цитата:

Сообщение от Rostik
многому нужно еще учится

Вот именно. Чем меньше знаешь, тем больше плодишь лишних сущностей. Простейшую переключалку ты превратил в какое-то монструозное угребище.

warren buffet 16.10.2016 14:17

Причем они почему-то с нуля начинают с лишней сущности под названием JQuery. Капец блин этим дерьмом народу мозг как законопатили. В свое время я тоже подозревал, что Жикверя - это язык.)

warren buffet 16.10.2016 14:20

Причем можно вообще без js обойтись для решения такой задачи, если не брезговать дополнительными чекбоксами. Через CSS правила для чекнутого бокса применяются к непосредственному соседу и все раскрывается и скрывается без скриптов.

Способ не очень, но рабочий.

destus 16.10.2016 14:43

Цитата:

Причем можно вообще без js обойтись для решения такой задачи
как-то так?
<style>
        .post{
            width: 500px;
            height: 40px;
            background: #666;
            margin-top: 10px;
			transition: height .5s ease-in;
        }
		
		input[type=checkbox]{
			display: none;
		}
		
		label > input[type='checkbox']:checked ~ .post{
			height: 100px;
		}
		
	</style>
	<label><input type="checkbox"><div class="post"></div></label>
    <label><input type="checkbox"><div class="post"></div></label>
	<label><input type="checkbox"><div class="post"></div></label>


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