Почему это нужно знать?
Не знаю почему захотелось назвать так заголовок, но когда я делал свой проект и написал такой-то кусок кода, я встал в ступор. По началу я думал, что это баг javascript, потом думал, что это фича, шутка, нет конечно, я стал размышлять. После этого я стал больше понимать javascript, чисто логически, как-то осознал некоторые моменты, логику, да!
Задача
Допустим у нас появилась задача: клонировать все div-ы с классом newClass в объект с идентификатором inner.
Алгоритм вроде бы простой: Пройтись циклом от начала и до конца, клонировать-вставить. Клонирование в javascript осуществляется, не мне вас учить, посредством метода-свойства cloneNode, но, а если мы не знаем, что существует cloneNode, или вообще просто решили идти другим путем.
Приступаем к оформлению примера
Если хотите читать дальше, то сейчас мы с вами создадим бесконечный цикл, итак:
1. Создайте страницу index.htm (не важно как назовете, можно не только — index) и вставьте туда такой макет
<!DOCTYPE html>
<html>
<head>
<title>For</title>
</head>
<body>
<div id='inner'></div>
<div class='newClass'>1</div>
<div class='newClass'>2</div>
<div class='newClass'>3</div>
<div class='newClass'>4</div>
<div class='newClass'>5</div>
<div class='newClass'>6</div>
<script>
// здесь будем писать javascript
</script>
</body>
</html>
Рассмотрим такой алгоритм:
1. Делаем цикла от 1 до (Число всех элементов div.newClass), ну правда в программировании индексация смещена к нулю. Я имею ввиду, что первый элемент — это нулевой. Понятное дело, мы часто задаем такой цикл, во всяком случае, именно я, начинаю с j=0.
for(j = 0; j < (число всех элементов); j++) {}
2. В цилке нам нужно создавать div, в созданный div поместить внутренность div.newClass. По сути каждой итерации, свой div со своими внутренностями от div.newClass
3. Поместить, созданный, только что в итерации div, в общий и единый div с определенным идентификатором —
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Drag-and-Drop</title>
</head>
<body>
<div id='inner'></div>
<div class='newClass'>1</div>
<div class='newClass'>2</div>
<div class='newClass'>3</div>
<div class='newClass'>4</div>
<div class='newClass'>5</div>
<div class='newClass'>6</div>
<script>
var pan, taskElement = document.getElementsByClassName('newClass');
// почему taskElement? это не важно, взял за название общей коллекции, можете назвать и иначе, дело вкуса
for (var j = 0; j < taskElement.length; j++){
pan = document.createElement('div');
pan.innerHTML = taskElement[j].innerHTML;
document.getElementById('inner').appendChild(pan);
}
</script>
</body>
</html>
Казалось бы прототип алгоритма работает, остается только тем div-ам прописать тот же класс, который у оригинальных объектов div, я имею ввиду — newClass добавить им нужно
Кстати, если у кого не работает getElementsByClassName, то просто, где-нибудь, между тегами добавьте:
if (!document.getElementsByClassName) {
document.getElementsByClassName = function(search) {
var d = document, elements, pattern, i, results = [];
if (d.querySelectorAll) { // IE8
return d.querySelectorAll("." + search);
}
if (d.evaluate) { // IE6, IE7
pattern = ".//*[contains(concat(' ', @class, ' '), ' " + search + " ')]";
elements = d.evaluate(pattern, d, null, 0, null);
while ((i = elements.iterateNext())) {
results.push(i);
}
} else {
elements = d.getElementsByTagName("*");
pattern = new RegExp("(^|\\s)" + search + "(\\s|$)");
for (i = 0; i < elements.length; i++) {
if ( pattern.test(elements[i].className) ) {
results.push(elements[i]);
}
}
}
return results;
}
}
Продолжаем работать с прототипом
Если добавим такую строчку pan.setAttribute(«class», taskElement[j].className); — то есть как бы задаем нашему, созданному div, класс клонируемого элемента, вот тут-то и начинает бесконечная итерация… Цикл никогда не завершится
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Drag-and-Drop</title>
</head>
<body>
<div id='inner'></div>
<div class='newClass'>1</div>
<div class='newClass'>2</div>
<div class='newClass'>3</div>
<div class='newClass'>4</div>
<div class='newClass'>5</div>
<div class='newClass'>6</div>
<script>
var pan, taskElement = document.getElementsByClassName('newClass');
for (var j = 0; j < taskElement.length; j++){
pan = document.createElement('div');
pan.setAttribute("class", taskElement[j].className); // вот тут новая строчка
pan.innerHTML = taskElement[j].innerHTML;
document.getElementById('inner').appendChild(pan);
}
</script>
</body>
</html>
Дело в том, что до момента цикла taskElement = document.getElementsByClassName('newClass'); taskElement.length = 6 {6 элементов div};
А значит и в for(j=0; j < 6; j++) {}
Но так как в теле цикла for мы создаем с вами div, да еще и пишем туда класс newClass, то коллекция taskElement — автоматически увеличивается, так как при итерации создался новый идентичный элемент. То есть теперь for(j=0; j < 7; j++) {при первой итерации}. Откуда 7? А вот, с потолка взял, нет. В область определения for(..) тоже автоматически подставляется новое значение taskElement.length, которое равно 7 и при каждом проходе цифра будет расти и расти, и расти, вплоть до бесконечности. Казалось бы есть решение, но не тут то было…
Отменяем бесконечную итерацию
А делается это легко и просто. Нам нужно в область определения поставить не динамическую коллекцию, а статическую константу подставить, вот смотрите…
{ // 1-случай
var k = taskElement.length;
for (j = 0; j < k; j++) {}
}
{ // 2-случай
for (j = 0; j < taskElement.length; j++) {}
}
1 и 2 случай — совершенно разные, но при это совершенно одинаковые, при определенных условиях!
<!DOCTYPE html>
<html>
<head>
<title>HTML5 Drag-and-Drop</title>
</head>
<body>
<div id='inner'></div>
<div class='newClass'>1</div>
<div class='newClass'>2</div>
<div class='newClass'>3</div>
<div class='newClass'>4</div>
<div class='newClass'>5</div>
<div class='newClass'>6</div>
<script>
var pan, taskElement = document.getElementsByClassName('newClass');
var k = taskElement.length;
for (var j = 0; j < k; j++){
pan = document.createElement('div');
pan.setAttribute("class", taskElement[j].className);
pan.innerHTML = taskElement[j].innerHTML;
document.getElementById('inner').appendChild(pan);
}
</script>
</body>
</html>
Бесконечная итерация исчезла, но результат непредсказуемый!
Мы знаем, что в цикле создается div, но ему присваивается класс клонируемого объекта, коллекция newClass вновь обновляется и, только, что созданный элемент, встает впереди клонируемых, надеюсь я тут правильно рассуждаю. В общем и целом, эту задачу посредством такого алгоритма мне не удалось решить! Может это получится у вас!?
This entry passed through the Full-Text RSS service — if this is your content and you're reading it on someone else's site, please read the FAQ at http://ift.tt/jcXqJW.
Комментариев нет:
Отправить комментарий