Как сохранить правильное событие Javascript после использования cloneNode(true)
У меня есть элемент формы, который содержит несколько строк ввода. Думайте о каждой строке как об атрибутах нового объекта, который я хочу создать в своем веб-приложении. И я хочу иметь возможность создавать несколько новых объектов в одном HTTP POST. Я использую встроенный в 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?
6 ответов
Не помещайте обработчик на каждую ссылку (это действительно должна быть кнопка, кстати). Используйте всплывающее окно событий для обработки всех кнопок одним обработчиком:
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 && 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>
Я проверил это в 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>
Чтобы устранить эту проблему, я бы обернул ваш код
$(this).up().remove()
в функции:
function _debugRemoveInputLine(this) {
debugger;
$(this).up().remove();
}
Это позволит вам узнать, что возвращает $(this). Если он действительно возвращает более одного объекта (несколько строк), то вы точно знаете, где искать - в коде, который создает элемент с использованием cloneNode. Делаете ли вы какие-либо изменения в результирующем элементе (т.е. меняете атрибут id)?
Если бы у меня возникла проблема, которую вы описываете, я бы подумал о добавлении уникальных идентификаторов к инициирующему элементу и элементу "line".
Первый ответ правильный.
Pornel неявно предлагает наиболее кросс-браузерное и фреймворк-независимое решение.
Не проверял, но концепция будет работать в этих динамических ситуациях, связанных с событиями.
Вы можете попробовать клонирование с помощью метода innerHTML или смеси:
var newItem = $(item).cloneNode(false);
newItem.innerHTML = $(item).innerHTML;
Также: я думаю, что cloneNode не клонирует события, зарегистрированные с помощью addEventListener. Но события attachEvent в IE клонируются. Но я могу ошибаться.
Похоже, вы используете JQuery? У него есть метод для клонирования элемента с событиями: http://docs.jquery.com/Manipulation/clone
РЕДАКТИРОВАТЬ: Ой я вижу, что вы используете Prototype.