Znamy już różnicę pomiędzy Node (węzłem) a Elementem, teraz najwyższa pora poznać czym jest HTMLElement. Do dzieła.

Widzieliśmy już to w wersji HTMLUnknownElement:

function isValidTagname(tagname) {
    return document.createElement(tagname).toString() != "[object HTMLUnknownElement]";
  }

Widzieliśmy też inne, bardziej wyspecjalizowane dzieci HTMLElement, np. przy omawianiu web components:

class AnchorScroll extends HTMLAnchorElement {
    connectedCallback(){
        this.addEventListener("click", function(e){
            e.preventDefault();
            const anchor = this.getAttribute('href');
            document.querySelector(anchor).scrollIntoView({
                behavior: 'smooth'
            });
        });
    }
}

customElements.define('custom-anchor', AnchorScroll, {extends: 'a'});

Ale co to ten element? Cóż, dziedziczy z trzech rzeczy:

  • Node, czyli ma wszystkie properties z node
  • Element, czyli ma wszystkie properties z Element
  • EventTarget, ciekawa sprawa, bo EventTarget daje od siebie 3 metody:
    • addEventListener
    • removeEventListener
    • dispatchEvent

HTMLElement ma wszystkie te properties, które należą mu się z racji bycia elementem HTML, nie elementem w ogóle, elementem XML i tak dalej. Na przykład isContentEditable to property HTMLElement.

Zaś tagName, className, attributes, to wszystko properties Elementu. A textContent, nodeType, nodeName to properties klasy Node.

Z klasy Element pochodzi na przykład metoda hasAttribute, getAttribute, matches i tak dalej:

const birds = document.querySelectorAll("li");

for (const bird of birds) {
  if (bird.matches(".endangered")) {
    console.log(`The ${bird.textContent} is endangered!`);
  }
}

A metody cloneNode, appendChild i tak dalej, to metody klasy Node. Dodawnie/usuwanie event listenerów oraz emitowanie eventu, to metody klasy EventTarget.

I tu mamy odpowiedź, dlaczego cloneNode usuwa event listenery (w związku z tym jest dobre do usuwania listenerów):

  • cloneNode to metoda klasy Node, zaś node nie posiada listenerów
  • add/remove evt listener (oraz dispatch event) to metody klasy EventTarget
  • HTMLElement dziedziczy z Node, Element i EventTarget

Oczywiście dociekliwi mogą powiedzieć chwila chwila, node też dziedziczy po event target. To prawda, plus za dociekliwość w czytaniu dokumentacji.

Inne typy węzłów niż Elementy-HTMLElementy, mogą odpalać pewne eventy. Jest to trochę relikt przeszłości odkąd mamy mutation observery. Więcej o nich niedługo.