Javascript-форум (https://javascript.ru/forum/)
-   Events/DOM/Window (https://javascript.ru/forum/events/)
-   -   обработчик событий для динамически добавленных элементов (https://javascript.ru/forum/events/52288-obrabotchik-sobytijj-dlya-dinamicheski-dobavlennykh-ehlementov.html)

Tecvid 11.12.2014 19:17

обработчик событий для динамически добавленных элементов
 
доброго времени суток всем, на jquery есть метод .on() который вешает обрабочик даже на динамически созданные элементы, как это сделать на чистом javascript? копал в сторону addEventListener, но почему-то не срабатывает
var modify = document.querySelectorAll('.modify');
for (var i = 0; i < mod2.length; i++) {
    mod2[i].addEventListener('click', function() {
        alert(1);
    });
}
// правильно ли навешал обработчик на элементы с одинаковым классом ?


подумал реализовать через так: при добавлении нового элемента удалить обработчик через removeEventListener, потом снова добавить на все, но не знаю правильно ли так сделать, если нет, то как правильнее? если да, то покажите как правильно реализовать это с ремувом, благодарю заранее)

krutoy 11.12.2014 19:31

Цитата:

Сообщение от Tecvid
// правильно ли навешал обработчик на элементы с одинаковым классом ?

Нет конечно
<html>
<head>
</head>
<body>

<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>

<script>

var mod2 = document.querySelectorAll('.modify');
for (var i = 0; i < mod2.length; i++) {
    mod2[i].addEventListener('click', function() {
        alert(1);
    });
}
</script>
</body>
</html>

И, кстати, при таокм раскладе лучше делать вот так
<html>
<head>
</head>
<body>

<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>
<div class="modify">div</div>

<script>

f=function(){alert(1)}
var mod2 = document.querySelectorAll('.modify');
for (var i = 0; i < mod2.length; i++) {
    mod2[i].addEventListener('click', f);
}
</script>
</body>
</html>

дабы не засирать память бестолку

krutoy 11.12.2014 19:33

Цитата:

Сообщение от Tecvid
даже на динамически созданные элементы

Какая разница как элементы созданы? К моменту невешивания обработчиков, никакой разницы нет. Разница будет только если ты пытаешься повесить на еще не созданные элементы.

Tecvid 11.12.2014 19:45

Цитата:

Сообщение от krutoy
И, кстати, при таокм раскладе лучше делать вот так

ага понятно, спасибо большое, хотел убедиться что навешивание в цикле не является плохим)
Цитата:

Сообщение от krutoy
Разница будет только если ты пытаешься повесить на еще не созданные элементы.

я как это имел ввиду, наверное неверно выразился;
кстати, за это время попробад сделать вот так для не ещё несозданных элементов:
function modify() {
    alert(1);
}
    
function addModEvent() {
    var mod = document.querySelectorAll('.modify');
    for (var i = 0; i < mod.length; i++) {
        mod[i].addEventListener('click', modify);
    }
}
addModEvent(); // для уже сущесвующих
    
function removeModEvent() {
    var mod = document.querySelectorAll('.modify');
    for (var i = 0; i < mod.length; i++) {
        mod[i].removeEventListener('click', modify);
   }
}

// для ещё не созданных
parentElem.appendChild(newElem); // ну условно
removeModEvent();
addModEvent();

рони 11.12.2014 19:48

Tecvid,
Цитата:

Сообщение от Tecvid
на jquery есть метод .on()

Цитата:

Сообщение от Tecvid
как это сделать на чистом javascript?

http://learn.javascript.ru/event-delegation

Tecvid 11.12.2014 19:53

рони,
я как раз перед этим вопросом прочитал этот урок) но либо он не подходит для моей задачи, либо я не смог адаптировать его под неё

задача такая, есть один контейнер - див, в нём множество одинаковых дивов с одинаковым классом, и каждый из них имеет кнопку (див) с классом modify, без какого либо id или ещё что-то который уникален, то есть мне кажется что по любому надо перебирать в цикле, либо я что-то недопонял

рони 11.12.2014 19:58

Tecvid,
подходит именно делегирование под условие вашей задачи. ставите на контейнер клик в клике определяите источник -- если источник имеет класс modify запускаите функцию

Tecvid 11.12.2014 20:00

рони,
хм понятно, спасибо большое)

рони 11.12.2014 20:00

Tecvid,
для вашей задачи цикл ненужен

Tecvid 11.12.2014 20:10

рони,
тогда получается что target нужно вставить внутри handler при addEventListener?

function hasClass(elem, cls) {
    // ...
    return true;
}

function modify() {
    var event = e || window.event;
    var target = event.target || event.srcElement;
    if (hasClass(target, 'modify')) {
        addModEvent();
    }
}
    
function addModEvent() {
    parentElem.addEventListener('click', modify);
}
addModEvent();


так верно будет?

рони 11.12.2014 20:29

Tecvid,
проверяйте ...
если класс один то можно так
if (target.className == 'modify')

Tecvid 11.12.2014 20:39

рони,
я не про способ проверки, но не важно) разобрался) спасибо большое, всё теперь работает ка надо :)

andrey3681 16.07.2016 11:35

Помогите плиз с помощью ajax добавляю ссылку на открытие модального окна:
//Модальное окно ДОБАВИТЬ
$(document).ready(function() { // запускаем скрипт после загрузки всех элементов
    /* засунем сразу все элементы в переменные, чтобы скрипту не приходилось их каждый раз искать при кликах */
    var overlay = $('#overlay'); // подложка, должна быть одна на странице
    var open_modal = $('.open_add'); // все ссылки, которые будут открывать окна
    var close = $('.modal_close, #overlay'); // все, что закрывает модальное окно, т.е. крестик и оверлэй-подложка
    var modal = $('.modal_add'); // все скрытые модальные окна

     open_modal.click( function(event){ // ловим клик по ссылке с классом open_modal
         event.preventDefault(); // вырубаем стандартное поведение
         var div = $(this).attr('href'); // возьмем строку с селектором у кликнутой ссылки
         overlay.fadeIn(400, //показываем оверлэй
             function(){ // после окончания показывания оверлэя
                 $(div) // берем строку с селектором и делаем из нее jquery объект
                     .css('display', 'block') 
                     .animate({opacity: 1, top: '50%'}, 200); // плавно показываем
         });
     });

     close.click( function(){ // ловим клик по крестику или оверлэю
            modal // все модальные окна
             .animate({opacity: 0, top: '45%'}, 200, // плавно прячем
                 function(){ // после этого
                     $(this).css('display', 'none');
                     overlay.fadeOut(400); // прячем подложку
                 }
             );
     });
});


Не открывается до обновления страницы

рони 16.07.2016 17:22

Цитата:

Сообщение от andrey3681
помощью ajax добавляю ссылку

добавили ссылку поставили клик на ссылку или поставили клик на body изначально

$('body').on('click' , '.open_add', function(event){ })

andrey3681 17.07.2016 11:18

Цитата:

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

Подскажите пожалуйста куда или вместо чего вставить приведенный код?
Так как в JavaScript только начинаю разбиратся:blink:

Дбавляю ссылку ajax:
function call() {
 	  var msg   = $('#Vhod').serialize();
        $.ajax({
          type: 'POST',
          url: 'logIn.php',
          data: msg,
		  
          success: function(data) {
			  var responseData = jQuery.parseJSON(data);
			switch(responseData.status){
                        case 'error':
							$('#logIn').html(responseData.message)
                        break;
                        case 'success':
							$('#logIn').html(responseData.message),
							$('#overlay').trigger('click'),
							$('#logInHeader').html(responseData.statusLogin);
                        break; 
                    }
          },
          error:  function(xhr, str){
	    alert('Возникла ошибка: ' + xhr.responseCode);
          }
        });
    };

рони 17.07.2016 11:33

andrey3681,
//Модальное окно ДОБАВИТЬ
$(function() { // запускаем скрипт после загрузки всех элементов
    /* засунем сразу все элементы в переменные, чтобы скрипту не приходилось их каждый раз искать при кликах */
    var overlay = $('#overlay'); // подложка, должна быть одна на странице
    $('body').on('click' , '.open_add', function(event){ // ловим клик по ссылке с классом open_modal
         event.preventDefault(); // вырубаем стандартное поведение
         var div = $(this).attr('href'); // возьмем строку с селектором у кликнутой ссылки
         overlay.fadeIn(400, //показываем оверлэй
             function(){ // после окончания показывания оверлэя
                 $(div) // берем строку с селектором и делаем из нее jquery объект
                     .css('display', 'block')
                     .animate({opacity: 1, top: '50%'}, 200); // плавно показываем
         });
     });

    $('body').on('click' , '.modal_close, #overlay', function(){ // ловим клик по крестику или оверлэю
            $('.modal_add') // все модальные окна
             .animate({opacity: 0, top: '45%'}, 200, // плавно прячем
                 function(){ // после этого
                     $(this).css('display', 'none');
                     overlay.fadeOut(400); // прячем подложку
                 }
             );
     });
});

andrey3681 17.07.2016 11:53

рони,
Все по прежнему, не работает:cray:

andrey3681 17.07.2016 11:58

рони,
Большущее спасибо! Разобрался, в ссылке изменил class на open_add, и все заработало!!!:dance: Все моя невнимательность:(

alecto 25.06.2018 11:48

Друзья, помогите пожалуйста разобраться, почему-то не снимается событие.
Проверил - условие выполняется.

var items = document.querySelector('.page-content');

var fnCounter = function (e) {
  var target = e.target;

  if (target.classList.contains('item-actions__cart')) {
    items.removeEventListener('click', fnCounter);
  }
};

items.addEventListener('click', {handleEvent: fnCounter, e: event});

Dilettante_Pro 25.06.2018 12:07

alecto,
А что такое items ?

alecto 25.06.2018 12:19

var items = document.querySelector('.page-content');

я вешаю обработчик на родителя, затем ловлю на каком элементе происходит событие.
когда событие наступает - нужно снять обработчик.
а он не снимается.
подозреваю, что проблема в передаче функции через handler в addEventLiustener.

рони 25.06.2018 12:53

Dilettante_Pro,
строка 1 и строка 5 ???

alecto 25.06.2018 12:55

Dilettante_Pro,

я и не передаю, всего лишь отслеживаю на каком элементе произошло событие, и при всплытии срабатывает обработчик.
на этом этапе у меня все работает.
проблема только в снятии события.

пример выше у меня не работает ни на сайте, ни после перетягивания в редактор :(
стурктура элементов в вашем примере была правильная
page-content - родитель
item-actions__cart - вложенные элементы

Dilettante_Pro 25.06.2018 12:56

рони, спасибо, я уже заметил.
Не снимается.
<div class = 'page-content'>page-content
   <div >Content</div>
   <div class = 'item-actions__cart'>Content Cart</div>
   <div >Content</div>
</div>
<script>
var fnCounter = function (e) {
  var target = e.target;
  alert(target.textContent);
  if (target.classList.contains('item-actions__cart')) {
    items.removeEventListener('click', fnCounter);
  }
};


var items = document.querySelector('.page-content');
items.addEventListener('click', {handleEvent: fnCounter, e: event});

</script>

Dilettante_Pro 25.06.2018 12:58

Вот так снимается
<div class = 'page-content'>page-content
   <div >Content</div>
   <div class = 'item-actions__cart'>Content Cart</div>
   <div >Content</div>
</div>
<script>
var fnCounter = function (e) {
  var target = e.target;
  alert(target.textContent);
  if (target.classList.contains('item-actions__cart')) {
    items.removeEventListener('click', fnCounter);
  }
};


var items = document.querySelector('.page-content');
items.addEventListener('click', fnCounter);

</script>

Очевидно, EventListener считает, что fnCounter и handleEvent: fnCounter - разные функции

alecto 25.06.2018 12:58

Dilettante_Pro,
да, у меня тоже самое происходит.
событие срабатывает, но снять его не могу.

Dilettante_Pro 25.06.2018 13:15

alecto,
Пост 25 видели?

alecto 25.06.2018 13:36

да, теперь увидел.
решение оказалось очень простым.
спасибо огромное, ваш сайт просто незаменимый ресурс по JS!

Dilettante_Pro 25.06.2018 13:49

alecto,
Цитата:

Сообщение от alecto
ваш сайт просто незаменимый ресурс по JS!

Он точно так же и ваш!


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