JS Looped appendChild производит странное поведение - PullRequest
0 голосов
/ 01 июля 2011

У меня есть эта функция:

//add links to called classes
function addLinks () {
    var classElements = [];
    var idElements = [];
    var finalRender;
    var expand = document.createTextNode("+");
    var contract = document.createTextNode("-");
    var elementsList = [];
    var count = 0;

    //create the dom nodes
    renderPElements = document.createElement ("p");

        renderAElements = document.createElement ("a");
        renderAElements.setAttribute("href", "#");
        renderAElements.setAttribute("class", "expander");
        renderAElements.appendChild(expand);
        finalRender = renderPElements.appendChild(renderAElements);


    //get arrays of elements with class or id set to provided string
    for (var i = 0; i< show_hide_class_selectors.length; i++) {
        classElements[i] = document.getElementsByClassName(show_hide_class_selectors[i]);

        //if prevents null value appearing in array and freezing script
        if (document.getElementById(show_hide_class_selectors[i])) {
        idElements[i] = document.getElementById (show_hide_class_selectors[i]);
        }
    }

    //loop though selected id's / classes and generate a single array of selected elements
    for (var i = 0; i< idElements.length; i++) {
        elementsList[count] = idElements[i];
        count = count +1;
    }

    //must loop twice as variable is 2 dimensional i=class name y=elements of that class
    for (var i = 0; i< classElements.length; i++) {
        for (var y = 0; y< classElements[i].length; y++) {
        elementsList[count] = classElements[i][y];
        count = count +1;
        }
    }

    //render
    for (var i = 0; i< elementsList.length; i++) {
        alert ("render");
        elementsList[i].parentNode.firstChild.appendChild(finalRender);

        alert (elementsList[i]);
    }
}

Что подразумевает использование массива классов / идентификаторов, предоставляемых в качестве глобальных переменных, и создание массива, который содержит все запрошенные элементы. Затем предполагается добавить дочерние узлы (в данном случае ссылки) в узлы-братья, выполняя цикл по сгенерированному массиву с использованием appendchild.

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

Я не могу найти объяснения этому поведению или кому-то с похожей проблемой.

1 Ответ

2 голосов
/ 01 июля 2011

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

elementsList[i].parentNode.firstChild.appendChild(finalRender.cloneNode(true));

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

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

elementList = idElements;
for (var i=0; i<classElements.length; ++i)
    elementList = elementList.concat(classElements[i]);

Или, что еще лучше, просто создайте elementList непосредственно в первом цикле, чтобы не создавать кучу массивов, которые вы на самом деле не используете позже, или даже лучше, просто сделайте добавление прямо в первом цикл.

...