Tehnici Web

DOM

Claudia Chiriță . 2023/2024

Window

  • orice tab al unui browser conține un obiect window al interfeței Window
node

Window

  • proprietatea document a obiectului window are ca valoare obiectul document asociat paginii web
    window.document // referința 
  • alte proprietăți: history, location, console, localStorage, sessionStorage

DOM (Document Object Model)

  • API web
  • JavaScript folosește DOM pentru accesarea și modificarea documentelor HTML
  • orice pagină web este reprezentată în DOM ca un arbore de obiecte și este accesată folosind variabila globală document

DOM (Document Object Model)

node

DOM - Noduri

node

DOM - Noduri

  • orice nod din arborele DOM are un tip
  • în funcție de elementul pe care îl reprezintă, obiectul corespunzator are proprietăți și metode specifice

DOM - Noduri

nodes
ierarhia tipurilor nodurilor din DOM

DOM vs. HTML

  • unui tag HTML îi corespunde un obiect (care implementează interfața Element)
  • unui atribut al unui tag HTML îi corespunde o proprietate a obiectului
  • atributele (generale) HTML id, class, style corespund proprietăților id, className, style ale obiectului corespondent

DOM vs. HTML

  • proprietățile obiectului style (care implementează interfața Style) asociat atributului HTML style corespund proprietăților de stilizare CSS pentru elementele HTML
/* element.style.proprietateCSS = valoare */
         
el.style.color = "red"
el.style.backgroundColor = "blue"

DOM vs. HTML - EXEMPLU

kitty
 obiect-Element-în-DOM = {tagName: "img", src: "cat.png", 
                          alt: "kitty", id: "catImg"}
function change(){
   var x = document.getElementById('catImg'); // obiect
   x.alt = "image of a soft warm happy kitty";
   x.style.border = "10px solid pink";
}

Load

  • elementul <script> din <head> este procesat înaintea elementului <body>
  • arborele DOM este creat mai apoi și deci elementele lui nu pot fi accesate
  • încărcarea paginii declanșează evenimentul load care are ca țintă obiectul window

Load

  • un handler pentru evenimentul load se înregistrează setând proprietatea onload pentru obiectul window
window.onload = function() { ... }
window.onload = myMain;
function myMain() { ... }

Load

Selectarea elementelor

document.getElementById(numeId) // un obiect
document.querySelector(selectorCSS) // primul obiect

colecții live

document.getElementsByClassName(numeClasa)
document.getElementsByTagName(numeTag)
document.getElementsByName(nume)

colecții statice

document.querySelectorAll(selectorCSS)

Colecții

  • colecții generice similare unui Array
  • au proprietatea length
  • metodele Array nu pot fi invocate direct
  • exercițiu:
    Afișați numărul elementelor <h1> care sunt descendenți direcți ai elementelor <section> cu clasa "special".

Colecții

  • colecții generice similare unui Array
  • au proprietatea length
  • metodele Array nu pot fi invocate direct
  • exercițiu:
    Afișați numărul elementelor <h1> care sunt descendenți direcți ai elementelor <section> cu clasa "special".
var col = document.querySelectorAll(“section.special > h1”);
alert(col.length);

Colecții

Colecții

Colecții - Quiz

Schimbarea numelui unei clase "old" în "new":

var colectie = document.getElementsByClassName("old");

for(var i = 0; i < colectie.length; i++)
   colectie[i].className = "new";
   
/* merge? */

Conținutul elementelor

accesarea și modificarea conținutului unui element HTML ca String folosind

  • innerHTML
    • întoarce un text HTML, adică un text cu marcaje
    • la setarea proprietății, browserul interpretează textul
<p>It was <i> the best </i> of times.</p>
<--! innerHTML --> 
It was <i> the best </i> of times.

Conținutul elementelor

accesarea și modificarea conținutului unui element HTML ca String folosind

  • textContent
    • întoarce text fără marcaje
    • are ca rezultat concatenarea conținuturilor
      descendenților de tip Text
<p>It was <i> the best </i> of times.</p>
<--! textContent --> 
It was the best of times.
        

Noduri DOM

tipuri de noduri:

  • un nod special numit document
  • noduri de tip Element (modelează tagurile HTML)
  • noduri de tip Text (modelează textul)

Noduri DOM

manipularea informației din noduri cu:

nodeValue /* pentru noduri Text, Comment
             pentru noduri Element = null */
nodeName // numele tagului
nodeType /* Document=9, Element=1,
            Text=3, Comment=8 */ 

Navigarea în arbore

navigare arbore
node.parentNode // un obiect
node.childNodes // obiect NodeList 
node.firstChild // un obiect
node.lastChild // un obiect
node.nextSibling // un obiect
node.previousSibling // un obiect 

Navigarea în arbore

Navigarea în arborele de elemente

node.parentNode       |   node.parentElement
node.childNodes       |   node.children
node.firstChild       |   node.firstElementChild
node.lastChild        |   node.lastElementChild
node.nextSibling      |   node.nextElementSibling
node.previousSibling  |   node.previousElementSibling 

putem defini metode noi

function secondChild(e){
   return e.firstElementChild.nextElementSibling;
};

Navigarea în arborele de elemente

Navigarea în arbore - QUIZ

  • o funcție find(e, className) care pentru un element e din DOM, întoarce primul strămoș care conține clasa className
function find(e, className) {
   var p = e.parentElement;
   while (p != document.documentElement) {
      if(p.classList.contains(className))
         return p;
      p = p.parentElement;
      }
   return null;
}

Navigarea în arbore - QUIZ

  • o funcție frati(e) care pentru un element e din DOM, calculează numărul
    fraților de același tip
function frati(e) {
   var nr = -1;
   var p = e.parentElement;
   var copii = p.children;
   for(var i = 0; i < copii.length; i++) {
      if(e.nodeName == copii[i].nodeName) nr++;
   }
   return nr;
}

Operații cu elemente

crearea unui element

document.createElement("tag")
document.createTextNode("text")

inserarea unui element

parinte.appendChild(copil)
// dacă nodul copil există în arbore, doar mută nodul    
parinte.insertBefore(CopilNou, CopilVechi)

ștergerea / înlocuirea unui element

parinte.removeChild(copil)
parinte.replaceChild(CopilNou, CopilVechi)

Operații cu elemente

Modificarea atributelor

  • atributele elementelor HTML devin proprietăți ale obiectelor corespunzatoare
  • pot fi accesate prin
    • numele proprietății
    • metode specifice
    • proprietatea attributes

Modificarea atributelor

  • proprietăți: el.id, el.className, el.alt, el.href, el.src
  • metode:
  • el.getAttribute("nume-atribut")
    // întoarce un string (valoarea atributului specificat)
    
    el.setAttribute("nume-atribut", "valoare")
    // adaugă un atribut și valoarea lui
    
    el.hasAttribute("nume-atribut") // întoarce boolean
    el.removeAttribute("nume-atribut") // șterge atributul 
    
el.proprietateNoua = valoare // adăugare de proprietăți noi

Modificarea atributelor

Modificarea atributelor

  • proprietatea el.attributes întoarce un obiect
    array-like cu atributele elementului
    attrs = element.attributes;
    // attrs[i].name
    // attrs[i].value
    // attrs.length - număr de atribute
    
    var output = "";
    for (var i = 0; i < attrs.length; i++) { 
       output += attrs[i].name + " -> " + 
                 attrs[i].value + " // ";
    }
    alert(output);

JavaScript + CSS = STYLE

  • orice obiect asociat unui element HTML (interfața Element) are proprietatea style, a cărei valoare este un obiect care implementează CSSStyleDeclaration
  • proprietăților CSS le corespund proprietăți ale obiectului style
  • schimbarea stilului unui element HTML:
    element.style.proprietate = stil nou
    

JavaScript + CSS = STYLE

JavaScript + CSS : Clase

  • clasele asociate unui element pot fi accesate folosind proprietatea classList, care implementează DOMTokenList
  • lista claselor elementului:
    ecl = element.classList

JavaScript + CSS : Clase


</head>
<body>

Hakuna Matata!

JavaScript + CSS : Clase

ecl = element.classList;
       
ecl.length // nr. de clase asociate elementului
ecl.item(i) // numele clasei cu indexul i (i = 0,..)
ecl.add("clasa1","clasa2",...)
ecl.remove("clasa1","clasa2",...) 
ecl.contains("clasa") // returns boolean

ecl.toggle("clasa", expresie) 
/* șterge clasa dacă aceasta există, altfel o adaugă;
   expresie => boolean: if true, se adaugă clasa,
                        if false, se șterge clasa */

            /\_____/\
           /  o   o  \
          ( ==  v  == )
           )         (               întrebări?
          (           )
         ( (  )   (  ) )
        (__(__)___(__)__)