#javascript #html #javascript-events
#javascript #HTML #dom-события
Вопрос:
Я использую простой старый JavaScript (без jQuery или другого).
У меня есть приложение HTML5, в котором я хочу удалить холст из элемента раздела:
<section id="thumbnails">
<h1>My Bookmarks:</h1>
<canvas height="60px" width="100px" data-time="2.1167500019073486"></canvas>
<canvas height="60px" width="100px" data-time="3.60492205619812"></canvas>
<canvas height="60px" width="100px" data-time="4.558893203735352"></canvas>
<canvas height="60px" width="100px" data-time="5.411310195922852"></canvas>
</section>
Код, который я использую, следующий:
document.getElementById('videos').addEventListener('change',function(e){
var canvasElements=document.getElementById('thumbnails').getElementsByTagName('canvas');
for(var i=0;i<canvasElements.length;i ){
document.getElementById('thumbnails').removeChild(canvasElements[i]);
console.log('removed canvas');
}
},true);
Однако, когда выполняется код, не все canvas удаляются из этого раздела, и я даже не вижу инструкции log в консоли.
Перейдите на эту страницу, сделайте несколько эскизов, затем переключитесь на другое видео: http://laurent-tonon.com/VideoFinal /
Я действительно не понимаю…
Ответ №1:
Проблема в том, что getElementsByTagName
возвращает динамический список узлов, который изменится под вами при удалении элементов. Вы можете обойти это, обработав массив в обратном порядке, чтобы единственная часть списка узлов, которая изменяется при удалении элемента, — это та часть, которую вы уже обработали, а не та, которую вам еще предстоит выполнить:
document.getElementById('videos').addEventListener('change',function(e){
var canvasElements=document.getElementById('thumbnails').getElementsByTagName('canvas');
for (var i = canvasElements.length - 1; i >= 0; i--) {
canvasElements[i].parentNode.removeChild(canvasElements[i]);
console.log('removed canvas');
}
},true);
Обработка его в прямом порядке, как вы это делали, приводит к удалению всех остальных элементов и оставляет половину элементов. Вы удаляете первый элемент. Он удаляется из списка узлов, перемещая каждый элемент в списке узлов вниз на один слот. Затем вы повышаете свой индекс до [1] и удаляете то, что изначально было третьим элементом (но теперь находится во 2-м слоте в массиве). Элемент, который изначально был вторым элементом, теперь находится в первом слоте в массиве, и вы никогда не сможете его удалить.
Изменение порядка обработки списка узлов позволяет обойти эту проблему, поскольку те, которые удаляются из массива, находятся в конце и не меняют положение тех, которые вам еще предстоит обработать.
Я знаю, что это не был вопрос jQuery, и он прекрасно решаем с помощью приведенного выше простого javascript, но в такие моменты мне напоминают, насколько просты некоторые вещи в jQuery:
$("#thumbnails canvas").remove();
Ответ №2:
Поскольку вы уже используете браузер с поддержкой html5, почему бы не использовать некоторые обновленные методы:
[].slice.call( document.querySelectorAll( "#thumbnails canvas" ) ).forEach(
function(v){
v.parentNode.removeChild(v);
}
);
Ответ №3:
Я считаю, что проблема заключается getElementsByTagName()
в том, что возвращает значение live nodeList
, что вызывает проблемы, когда вы удаляете элементы и ссылаетесь на них по их индексу.
Попробуйте это…
while(canvasElements.length) {
canvasElements[0].parentNode.removeChild(canvasElements[0]);
console.log('removed canvas');
}
Ответ №4:
Почему так сложно? Как насчет того,
document.getElementById('videos').addEventListener('change',function(e){
var canvasElements=document.getElementById('thumbnails');
while (canvasElements.hasChildNodes())
{
canvasElements.removeChild(canvasElements.lastChild);
}
});
или, еще проще
document.getElementById('videos').addEventListener('change',function(e){
document.getElementById('thumbnails').innerHTML = '';
});
?
Комментарии:
1. У
canvasElements
них не будетhasChildNodes()
метода.2. @alex хотите уточнить? Имейте в виду тот факт, что мое именование переменных немного сбивает с толку, поскольку я просто копирую / вставляю фрагменты кода OP.
canvasElements
относится к окружающему div.3. Это также удаляет закладки
<h1>
, которые код OP не пытается выполнить.4. @vzwick: О, подождите, да, я понимаю. Это действительно смутило меня. Тем не менее, похоже, что OP хочет сохранить
h1
элемент.5. Могу ли я утверждать, что простое перемещение
<h1>
внешнего элемента было бы гораздо менее хлопотным?