Właściwości elementów

Jeżeli pobierzesz jakikolwiek element ze strony, będziesz mógł w konsoli wyświetlić jego właściwości i metody.
Najlepiej od razu odpal debugera F12 i zostaw konsole widoczną, bo jeszcze nam się przyda.

Pobrałem za ciebie powyższy przycisk. Otwórz debuger (F12) i rozwiń wypisany element.


const btn = document.querySelector('.button');
console.dir( btn );

Powyższy screen to tylko urywek całości.
Obiekt taki ma bardzo dużo właściwości i metod.
Część z nich wykorzystywana jest dla eventow takich jak kliknięcie, zaznaczenie, część pokazuje pozycję na stronie, typ elementu itp.
Większości z tych metod i właściwości na co dzień się nie wykorzystuje, ale jeżeli trafi się taka konieczność, wiedz po prostu gdzie szukać tego co cię interesuje (właśnie rozwijając pobrany element i wypisując go w konsoli).

Poniżej skupimy się na właściwościach i metodach, które są najczęściej wykorzystywane.

idzwraca id danego element
innerHTMLzwraca lub ustawia kod HTML danego element
outerHTMLzwraca lub ustawia kod HTML wraz z tagiem
innerTextzwraca lub ustawia tekst znajdujący się w elemencie (bez html)
tagNamezwraca nazwę tagu
setAttributeustawia atrybu
getAttributepobiera atrybu
datasetzwraca (obiekt) dataset, który przetrzymuje customowe atrybuty (data-...).

ID elementu

Czasami (choć wcale nie non stop) będziesz chciał pobrać ID danego elementu.

Możesz to zrobić za pomocą właściwości id lub korzystając z poniżej opisanego getAttribute

:

const btn = document.querySelector('.btn');

console.log(btn.id); //"" - bo nasz button nie ma ID

console.log(btn.getAttribute('id')); //null - bo jest puste

innerHTML i outerHTML

Właściwość innerHTML umożliwia odczyt i ustawianie html, jaki jest we wnętrzu danego elementu:


const btn = document.querySelector('.btn');

console.log( btn.innerHTML ); //<span>Kliknij mnie!</span>

btn.innerHTML = "<span>Nie klikaj mnie!</span>"

Nie jest to może najbezpieczniejsza metoda, ale skoro innerHTML umożliwia też ustawianie html w elemencie, tym samym pozwala tworzyć cały html dynamicznie:


document.querySelector('.button#test2').addEventListener('click', function() {
    let html = '';
    html += '<div class="module">';
    html += '   <div>To jest <strong>dynamicznie wstawiony html</strong>:</div>';
    html += '   <button class="button">Klik!</button>';
    html += '   <button class="button">Inny klik!</button>';
    html += '</div>';

    document.querySelector('.button#test3').innerHTML = html;
});
Tutaj zaraz coś wstawimy

Podobnie możemy też czyścić całe elementy:


document.querySelector('div.to-clean').innerHTML = "";

Podobną do innerHTML hest właściwość outerHTML, z tym, że zwraca także kod html samego elementu:


const btn = document.querySelector('.btn');
console.log(btn.outerHTML); //<button class="button" type="button"><span>Kliknij mnie</span></button>

innerText i textContent

Właściwości innerText i textContent działają podobnie do powyższej innerHTML, z tym że zwracają sam tekst, bez znaczników html:


const btn = document.querySelector('.btn');

console.log(btn.innerHTML); //<span>Kliknij mnie</span>

console.log(btn.innerText); //Kliknij mnie
console.log(btn.textContent); //Kliknij mnie

Podstawowa różnica między innerText a textContent jest taka, że innerText zwraca tekst po zaaplikowaniu stylów, a textContent pomija style. Co to oznacza? Jeżeli na jakiś element w tekście zostanie poprzez style nadade visibility:hidden lub display:none, wtedy innerText nie zwróci ukrytych części:


.button-text {}
.button-text-hide {
    visibility:hidden;
}
.button-text-none {
    display:none;
}

<div class="test">
    <span class="button-text-none">Ukryty</span>
    <span>Obok mnie są dwa niewidoczne spany</span>
    <span class="button-text-hide">Niewidoczny</span>
</div>

<button class="button" type="button" id="test3">
    Kliknij
</button>

const btn = document.querySelector('.btn');
const divTest = document.querySelector('.test');

btn.addEventListener('click', function() {
    console.log('innerHTML: ', divTest.innerHTML);
    console.log('innerText: ', divTest.innerText);
    console.log('textContent: ', divTest.textContent);
});
Ukryty Obok mnie są dwa niewidoczne spany Niewidoczny

tagName

Właściwość tagName zwraca nam nazwę elementu np. h2, a, p itp.


const btn = document.querySelector('.btn');
console.log(btn.tagName);

Znowu - do czego to może się przydać? Bardzo często będziesz podpinał dane zdarzenie dla wielu typów elementów na raz. Po kliknięciu na taki element chcesz wiedzieć co kliknąłeś, by wykonać odpowiednie działania:


const elements = document.querySelector('div.test, .btn, h2.title');
for (let i=0; i<elements.length; i++) {
    elements[i].addEventListener('click', function() {
        console.log(this.tagName);
        if (this.tagName.toLowerCase() == 'button') {...}
        if (this.tagName.toLowerCase() == 'div') {...}
        if (this.tagName.toLowerCase() == 'h2') {...}
    });
}

getAttribute, setAttribute i removeAttribute

Metody setAttribute(nazwaAtrybutu) i getAttribute(nazwaAtrybutu, wartosc) służą do ustawiania i pobierania atrybutów danego znacznika.
Metoda removeAttribute(nazwaAtrybutu) służy do usunięcia atrybutu.

Metoda getAttribute(nazwaAtrybutu) wymaga tylko jednego atrybutu, którym jest nazwa pobieranego atrybutu. Jeżeli dany atrybut nie zostanie odnalezione, metoda zwróci null:


<form id="contactForm" class="form-contact" method="post" action="script.php">
    ...
</form>

const form = document.querySelector('.form-contact');

const formID = form.getAttribute('id');
const callType = form.getAttribute('method');
const callUrl = form.getAttribute('action');

Metoda getAttribute(nazwaAtrybutu, wartosc) wymaga podania zarówno nazwy atrybutu, jak i jego nowej wartości:


const submit = form.querySelector(':scope :submit');

submit.setAttribute('disabled', 'disabled');

Za pomocą tej metody nie musimy ustawiać tylko domyślnych atrybutów, ale i nasze własne:


const tooltip = document.querySelectorAll('.tooltip');

for (let i=0; i<tooltip.length; i++) {
    tooltip[i].setAttribute('data-text', tooltip[i].textContent);
}

Aby usunąć atrybut, skorzystamy z metody removeAttribute():


const inputText = document.querySelectorAll('[readonly]'); //pobieram pola readonly
inputText.removeAttribute('readonly'); //usuwam ten atrybut - od tej pory można je wypełniać

dataset

Właściwość dataset zwraca nam obiekt, który służy do manipulowania customowymi atrybutami (czyli takimi jaki ustawiliśmy przed chwilą dla tooltipów). Atrybuty takie zaczynają się od słowa data-


<span class="tooltip" data-default-text="..." data-position="top">
    Help
</span>

W powyższym przykładzie mamy 2 customowe atrybuty: data-default-text i data-position

Jeżeli teraz chcielibyśmy je odczytać użyjemy konstrukcji:


const tooltip = document.querySelector('.tooltip');
console.log(tooltip.dataset.defaultText);
console.log(tooltip.dataset.position);

Zauważ, jak odwołaliśmy się do nazw naszych parametrów.
Początek data- został pominięty, a zapis default-text zmieniliśmy na pisany stylem camelCase czyli defaultText. Podobna zamiana działa też przy stylach, gdzie dla przykładu background-color jest zamieniany na backgroundColor.


<div class="module"
    data-my-custom-data="..."
    data-style="..."
    data-module-type="..."
>
   ...
</div>

const tooltip = document.querySelector('.module');
console.log(tooltip.dataset.myCustomData);
console.log(tooltip.dataset.style);
console.log(tooltip.dataset.moduleType);

tooltip.style.backgroundColor = "red";

Jeżeli teraz chcielibyśmy ustawić jakiś własny customowy atrybut, lub zmienić istniejący, wystarczy że ustawimy im nową wartość:


tooltip.dataset.myCustomData = "nowa wartość"; //utworzy w elemencie atrybut data-my-custom-data="nowa wartość"
tooltip.dataset.style = "primary"; //utworzy atrybut data-style="primary"
tooltip.dataset.moduleType = "big" //utworzy atrybut data-module-type="big"

tooltip.dataset.title = "important"; //data-title
tooltip.dataset.footerStyle = "bottom"; //data-footer-style

//to samo możemy uzyskać za pomocą getAttribute i setAttribute (mini-mini wolniejsze)
tooltip.getAttribute('data-style');
tooltip.setAttribute('data-title', "important");
tooltip.setAtribute('data-footer-style', "bottom");

Użycie konstrukcji element.dataset.footerStyle="bottom" utworzy w takim elemencie atrybut data-footer-style, co jest równoznaczne z zastosowaniem konstrukcji element.setAttribute('data-footer-style', 'bottom')

Charakterystyczną rzeczą jest to, że atrybuty w znacznikach html są stringami. Tak więc cokolwiek byśmy nie przetrzymywali w dataset, staje się to stringiem:


<button type="button" id="myButton" data-id="23" data-ob='{"name":"John"}'>
    Kliknij mnie
</button>

typeof myButton.dataset.id === 'string' //true
typeof myButton.dataset.ob === 'string' //true

Można to obchodzić przez zastosowanie odpowiednich metod konwertujących takich jak Number czy JSON.parse:


const ob = JSON.parse(myButton.dataset.ob);
const id = Number(myButton.dataset.id);

Jeżeli chcielibyśmy przechowywać w dataset obiekt, wtedy musimy skorzystać z JSON.stringfity:


const ob = {
    name : "Marcin",
    lastname : "Domanski"
}

myButton.dataset.ob === JSON.stringfity(ob);

Trening czyni mistrza

Poniżej zamieszczam kilka zadań, które w ramach ćwiczenia możesz wykonać:

  1. Ściągnij sobie przykładową stronę klikając prawym przyciskiem tutaj i wybierając zapisz jako.
    Zadania wykonuj w skryptach inline pisanych na dole kodu strony.
  2. Pobierz listę .list i podstaw ją pod zmienną.
  3. Korzystając z powyższej zmiennej dodaj liście klasę preety
  4. Pierwszemu LI listy dodaj klasę first
    Ostatniemu LI listy dodaj klasę last
    
                const list = document.querySelector('.list');
                list.classList.add('preety');
    
                const li = list.querySelectorAll('li');
                li[0].addClass('first');
                li[li.length-1].addClass('last');
    
                //lub
                list.firstElementChild.addClass('first');
                list.lastElementChild.addClass('last');
            
  5. Po najechaniu na każde LI listy wyświetl tooltip, który będzie zawierał tekst z środka. Dla tooltipa wykorzystaj atrybut title
    
                    const list = document.querySelector(".list");
                    list.classList.add("preety");
    
                    const li = list.querySelectorAll("li");
                    [].forEach.call(li, function(el) {
                        list.setAttribute("title", el.innerText);
                    });
                
  6. Trzeciemu elementowi w liście ustaw czerwone tło. Wykorzystaj do tego właściwość style. Jeżeli nie wiesz jak tego użyć, poszukaj w internecie, lub zbada dany element w debugerze.
    
                    const list = document.querySelector(".list");
                    const li = list.querySelectorAll("li");
    
                    li[2].style.setProperty("background-color", "red");
                    //lub
                    li[2].style.backgroundColor = "red";
                
  7. Trzeciemu elementowi ustaw text na "Jestem czerwonym elementem"
    
                    const list = document.querySelector(".list");
                    const li = list.querySelectorAll("li");
                    li[2].innerText = "Jestem czerwonym elementem";