Как поддерживать правильное событие Javascript После использования cloneNode(true)

#javascript #events #dom #prototypejs #clonenode

Вопрос:

У меня есть элемент формы, содержащий несколько строк входных данных. Думайте о каждой строке как об атрибутах нового объекта, который я хочу создать в своем веб-приложении. И я хочу иметь возможность создавать несколько новых объектов в одном HTTP-сообщении. Я использую встроенный в Javascript метод cloneNode(true) для клонирования каждой строки. Проблема в том, что каждая строка ввода также имеет ссылку на удаление, прикрепленную к ее событию onclick:

 // prototype based
<div class="input-line">
    <input .../>
    <a href="#" onclick="$(this).up().remove();"> Remove </a>
</div>
 

При нажатии на ссылку удаления клонированной строки ввода также удаляются все строки ввода, которые были клонированы из одного и того же объекта dom. Можно ли повторно привязать объект «this» к соответствующему тегу привязки после использования cloneNode(true) в указанном выше элементе DOM?

Ответ №1:

Не ставьте обработчик на каждую ссылку (кстати, это действительно должна быть кнопка). Используйте пузырьковое событие для обработки всех кнопок одним обработчиком:

 formObject.onclick = function(e)
{
    e=e||event; // IE sucks
    var target = e.target||e.srcElement; // and sucks again

    // target is the element that has been clicked
    if (target amp;amp; target.className=='remove') 
    {
        target.parentNode.parentNode.removeChild(target.parentNode);
        return false; // stop event from bubbling elsewhere
    }
}
 
 <div>
  <input…>
  <button type=button class=remove>Remove without JS handler!</button>
</div>
 

Ответ №2:

Вы можете попробовать клонировать с помощью метода innerHTML или смеси:

 var newItem = $(item).cloneNode(false);
newItem.innerHTML = $(item).innerHTML;
 

Также: Я думаю, что cloneNode не клонирует события, зарегистрированные с помощью addEventListener. Но события прикрепления IE клонируются. Но я могу ошибаться.

Ответ №3:

Я протестировал это в IE7 и FF3, и это сработало, как и ожидалось, — должно быть, происходит что-то еще.

Вот мой тестовый сценарий:

 <div id="x">
    <div class="input-line" id="y">
        <input type="text">
        <a href="#" onclick="$(this).up().remove();"> Remove </a>
    </div>
</div>

<script>

$('x').appendChild($('y').cloneNode(true));
$('x').appendChild($('y').cloneNode(true));
$('x').appendChild($('y').cloneNode(true));

</script>
 

Ответ №4:

Чтобы отладить эту проблему, я бы завернул ваш код

 $(this).up().remove() 

в функции:

 function _debugRemoveInputLine(this) {
    debugger;
    $(this).up().remove();
} 

Это позволит вам узнать, какой $(этот) возвращается. Если он действительно возвращает более одного объекта (несколько строк), то вы определенно знаете, где искать-в коде, который создает элемент с помощью cloneNode. Вносите ли вы какие-либо изменения в результирующий элемент (т. е. меняете атрибут id)?

Если бы у меня была проблема, которую вы описываете, я бы рассмотрел возможность добавления уникальных идентификаторов к элементу запуска и элементу «линия».

Ответ №5:

Первый ответ-правильный.

Pornel неявно предлагает наиболее кроссбраузерное и не зависящее от фреймворка решение.

Я еще не тестировал его, но концепция будет работать в этих динамичных ситуациях, связанных с событиями.

Ответ №6:

Похоже, вы используете jQuery? В нем есть метод для клонирования элемента с событиями: http://docs.jquery.com/Manipulation/clone#true

ПРАВКА: Ой, я вижу, вы используете прототип.