Tworzenie i usuwanie elementów

Potrafimy już poruszać się po elementach, potrafimy je pobrać, przechodzić z jednego na drugi itp. Czas zacząć je tworzyć a potem usuwać. Nie jest to wcale takie trudne. Wystarczy, że skorzystamy z kilku podstawowych metod oferowanych przez Javascript.

Tworzenie obiektu za pomocą createElement

Aby utworzyć nowy element na stronie korzystamy z metody document.createElement(typ). Po utworzeniu nowego elementu musimy ustawić jego właściwości. Ale to nie wszystko. Utworzony w ten sposób element jest dostępny dla skryptu, ale nie ma go jeszcze w drzewie dokumentu. Musimy go tam wstawić metodą parentNode.appendChild(nowy_obiekt):


var element = document.createElement('div'); //tworzymy nowego Diva
element.id = 'bloczek';
element.style.width = '400px';
element.style.height = '200px';
element.style.backgroundColor = '#FF6633';

var body = document.getElementsByTagName('body')[0]; //pobieramy body
body.appendChild(element); //wstawiamy element do drzewa dokumentu

Po dodaniu elementu do drzewa pojawi się on na stronie.


Do wstawiania nodów w drzewo strony możemy też skorzystać z metody parentNode.insertBefore(element, beforeNode), która do parentNode wstawia element element przed elementem beforeNode:


    <p id="beforeTest">
        <strong>Jestem pierwszym nodem</strong>
    </p>

function insertBefore() {
      var p = document.getElementById('beforeTest'); //pobieramy element <p>
      var strong = p.firstChild; //pobieramy pierwsze dziecko p czyli element <strong>
      var newNode = document.createTextNode('Jestem innym nodem, '); //tworzymy nowy nod z tekstem
      p.insertBefore(newNode, strong); //wstawiamy go przed <strong>
}

document.addEventListener("DOMContentLoaded", function() {
    document.getElementById('guzik').addEventListener('click', wstawPrzed);
});

Jestem pierwszym nodem

Czasami chcemy zamiast przed obiektem, wstawić coś za nim. Javascript nie posiada metody do tego służącej (appendChild wstawia element na końcu danej listy dzieci), więc musimy ją napisać sami:


Node.prototype.insertAfter = function(newNode) {
    if(this.nextSibling) { //jeżeli dany element ma za sobą jakiś obiekt
        return this.parentNode.insertBefore(newNode, this.nextSibling); //to wstawiamy przed tym obiektem nasz element
    } else {
        return this.parentNode.appendChild(newNode);
    }
}

Od tej chwili możemy wstawiać nowe obiekty za elementem:


var p = document.getElementById('akapit');
p.insertAfter(document.createTextNode('...');

Tworzenie fragmentów dokumentu

Korzystając z powyższych metod z łatwością możemy tworzyć różne skomplikowane kawałki drzewa. Możemy do tego celu wykorzystać także metodę createDocumentFragment(), która tworzy fragment dokumentu. Fragment taki jest "zbiornikiem", podobnym do zwykłego diva, jednak przy wstawianiu go do odokumentu, wstawiane zostają tylko jego dzieci.

Przypuśćmy, że stworzymy fragment, do którego wrzucimy 10 paragrafów. Podczas dołączania tego fragmentu do drzewa dokumentu, wstawione zostaną tak naprawdę tylko te paragrafy.


var fragment = document.createDocumentFragment();
for (var i=0; i<10; i++ ) {
    var p = document.createElement('p');
    p.appendChild(document.createTextNode('Akapit '+(i+1)));
    fragment.appendChild(p);
}
document.body.appendChild(fragment); //wstawiamy 10 paragrafów

Korzystanie z takich pseudo kontenerów przy manipulacji większą liczbą nodów jest dobrą techniką i pozytywnie wpływa na szybkość naszego skryptu (w powyższym przykładzie drzewo dokumentu jest odświeżane 1 raz zamiast 10)

Usuwanie elementu

Element, który istnieje w drzewie dom, możemy z niego usunąć korzystając z metody parentNode.removeChild(element). Metoda ta usuwa element "obiekt_usuwany" oraz wszystkie jego dzieci:

Przypuśćmy, że z paragrafu z poprzedniego rozdziału chcemy usunąć pogrubiony tekst (czyli usunąć znacznik strong):


<p id="paragraf">To jest <strong>bardzo</strong> ważny tekst</p>

Kod, który usunie znacznik strong może mieć postać:


var p = document.getElementById('paragraf'); //pobieramy nasz paragraf
var strong = p.getElementsByTagName('strong')[0]; //pobieramy 1 strong z paragrafu
p.removeChild(strong); //usuwamy strong z paragrafu

//lub
var strong = p.getElementsByTagName('strong')[0];
strong.parentNode.removeChild(strong);

Aby usunąć wszystkie dzieci danego elementu - czyli go wyczyścić, powinniśmy wykonać pętlę po jego dzieciach i wszystkie pousuwać. Musimy dodatkowo sprawdzić, czy dany element w ogóle ma dzieci:


Node.prototype.empty = function() {
    while (this.firstChild) {
        this.removeChild(this.firstChild);
    }
}

var ul = document.getElementById('lista');
ul.empty(); //czyścimy cały akapit

Pętlę wykonujemy od końca. Gdybyśmy robili ją od początku, wówczas usuwanie elementów zmieniało by indeksację kolejnych dzieci, które nie były by pobierane w kolejnych iteracjach pętli.

innerHTML

Javascript udostępnia nam właściwość innerHTML, która służy do pobierania i ustawiania kodu html w danym elemencie.

    var html = '';
    html += '<article class="news">';
    html += '<h3 class="title">Przykładowy tytuł</h3>';
    html += '<time datetime="2010-10-12">Utworzono: 12 października 2010</time>';
    html += '</article>';

    div.innerHTML = html;

    console.log(div.innerHTML);

Jest to bardzo łatwa i przyjemna metoda do wstawiania całych fragmentów kodu. Wadą tego sposobu jest to, że nie mamy referencji do wstawianych elementów. Dlatego po wstawieniu takiego html, musimy potem wstawione elementy pobrać za pomocą JS.

Za jej pomocą wyczyszczenie danego elementu staje się o wiele łatwiejsze niż wcześniej:

    var ul = document.getElementById('lista');
    ul.innerHTML = '';