You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Web-Dev-For-Beginners/translations/ro/3-terrarium/3-intro-to-DOM-and-closures
localizeflow[bot] 6602ddcc6a
chore(i18n): sync translations with latest source changes (chunk 1/1, 291 changes)
7 months ago
..
README.md chore(i18n): sync translations with latest source changes (chunk 1/1, 291 changes) 7 months ago
assignment.md chore(i18n): sync translations with latest source changes (chunk 1/1, 291 changes) 7 months ago

README.md

Proiectul Terariu Partea 3: Manipularea DOM și Închideri în JavaScript

journey
    title Călătoria ta JavaScript DOM
    section Bază
      Understand DOM: 3: Student
      Learn closures: 4: Student
      Connect elements: 4: Student
    section Interacțiune
      Setup drag events: 4: Student
      Track coordinates: 5: Student
      Handle movement: 5: Student
    section Finisare
      Add cleanup: 4: Student
      Test functionality: 5: Student
      Complete terrarium: 5: Student

DOM și o închidere

Sketchnote de Tomomi Imura

Bine ați venit la unul dintre cele mai atractive aspecte ale dezvoltării web - a face lucrurile interactive! Document Object Model (DOM) este ca un pod între HTML-ul tău și JavaScript, iar astăzi îl vom folosi pentru a da viață terariului tău. Când Tim Berners-Lee a creat primul browser web, și-a imaginat o web unde documentele pot fi dinamice și interactive - DOM face această viziune posibilă.

Vom explora, de asemenea, închiderile JavaScript, care la început pot părea intimidante. Gândește-te la închideri ca la crearea unor „buzunare de memorie” unde funcțiile tale pot reține informații importante. Este ca și cum fiecare plantă din terariul tău ar avea propriul său registru de date pentru a-și urmări poziția. Până la finalul acestei lecții, vei înțelege cât de naturale și utile sunt ele.

Iată ce construim: un terariu în care utilizatorii pot trage și plasa plante oriunde doresc. Vei învăța tehnicile de manipulare a DOM care stau la baza a tot, de la încărcarea fișierelor prin drag-and-drop până la jocuri interactive. Haide să dăm viață terariului tău.

mindmap
  root((DOM & JavaScript))
    DOM Tree
      Selecția Elementelor
      Accesul la Proprietăți
      Gestionarea Evenimentelor
      Actualizări Dinamice
    Events
      Evenimentele Pointer
      Evenimentele Mouse-ului
      Evenimentele Touch
      Ascultători de Evenimente
    Closures
      Variabile Private
      Domeniul Funcției
      Persistența Memoriei
      Gestionarea Stării
    Drag & Drop
      Urmărirea Poziției
      Matematica Coordonatelor
      Ciclu de Viață al Evenimentului
      Interacțiunea Utilizatorului
    Modern Patterns
      Delegarea Evenimentelor
      Performanță
      Cross-Device
      Accesibilitate

Test Prealabil Lecției

Test prealabil lecției

Înțelegerea DOM: Poarta ta către pagini web interactive

Document Object Model (DOM) este modul în care JavaScript comunică cu elementele tale HTML. Când browserul tău încarcă o pagină HTML, creează o reprezentare structurată a acelei pagini în memorie - asta este DOM-ul. Gândește-te la el ca la un arbore genealogic unde fiecare element HTML este un membru al familiei pe care JavaScript îl poate accesa, modifica sau rearanja.

Manipularea DOM transformă paginile statice în site-uri interactive. De fiecare dată când vezi un buton care își schimbă culoarea la trecerea mouse-ului, un conținut care se actualizează fără reîmprospătarea paginii, sau elemente pe care le poți trage în jur, asta este manipularea DOM în acțiune.

flowchart TD
    A["Document"] --> B["HTML"]
    B --> C["Antet"]
    B --> D["Corp"]
    C --> E["Titlu"]
    C --> F["Meta Tag-uri"]
    D --> G["H1: Terariul meu"]
    D --> H["Div: Container Pagină"]
    H --> I["Div: Container Stânga"]
    H --> J["Div: Container Dreapta"]
    H --> K["Div: Terariu"]
    I --> L["Elemente Plante 1-7"]
    J --> M["Elemente Plante 8-14"]
    
    L --> N["img#plant1"]
    L --> O["img#plant2"]
    M --> P["img#plant8"]
    M --> Q["img#plant9"]
    
    style A fill:#e1f5fe
    style B fill:#f3e5f5
    style D fill:#e8f5e8
    style H fill:#fff3e0
    style N fill:#ffebee
    style O fill:#ffebee
    style P fill:#ffebee
    style Q fill:#ffebee

Reprezentare arbore DOM

O reprezentare a DOM și a marcajului HTML care îl referențiază. De la Olfa Nasraoui

Iată ce face DOM-ul puternic:

  • Oferă o modalitate structurată de a accesa orice element de pe pagina ta
  • Permite actualizări dinamice ale conținutului fără reîmprospătarea paginii
  • Îngăduie răspuns în timp real la interacțiunile utilizatorilor ca clicurile și tragerea
  • Creează fundamentul pentru aplicații web moderne și interactive

Închideri în JavaScript: Crearea de cod organizat și puternic

O închidere JavaScript este ca și cum ai da unei funcții propriul său spațiu de lucru privat cu memorie persistentă. Gândește-te cum finchii lui Darwin de pe Insulele Galápagos și-au dezvoltat fiecare ciocuri specializate în funcție de mediul lor specific - închiderile funcționează similar, creând funcții specializate care „își amintesc” contextul lor specific chiar și după ce funcția părinte s-a încheiat.

În terariul nostru, închiderile ajută fiecare plantă să-și amintească poziția în mod independent. Acest model apare frecvent în dezvoltarea profesională JavaScript, ceea ce îl face un concept valoros de înțeles.

flowchart LR
    A["dragElement(plant1)"] --> B["Creează Closure"]
    A2["dragElement(plant2)"] --> B2["Creează Closure"]
    
    B --> C["Variabile Private"]
    B2 --> C2["Variabile Private"]
    
    C --> D["pos1, pos2, pos3, pos4"]
    C --> E["funcția pointerDrag"]
    C --> F["funcția elementDrag"]
    C --> G["funcția stopElementDrag"]
    
    C2 --> D2["pos1, pos2, pos3, pos4"]
    C2 --> E2["funcția pointerDrag"]
    C2 --> F2["funcția elementDrag"]
    C2 --> G2["funcția stopElementDrag"]
    
    H["Planta 1 își amintește poziția"] --> B
    H2["Planta 2 își amintește poziția"] --> B2
    
    style B fill:#e8f5e8
    style B2 fill:#e8f5e8
    style C fill:#fff3e0
    style C2 fill:#fff3e0

💡 Înțelegerea închiderilor: Închiderile sunt un subiect important în JavaScript, iar mulți dezvoltatori le folosesc ani de zile înainte să înțeleagă pe deplin toate aspectele teoretice. Astăzi ne concentrăm pe aplicația practică - vei vedea cum închiderile apar natural pe măsură ce construim caracteristicile noastre interactive. Înțelegerea va crește pe măsură ce vezi cum rezolvă probleme reale.

Reprezentare arbore DOM

O reprezentare a DOM și a marcajului HTML care îl referențiază. De la Olfa Nasraoui

În această lecție, vom finaliza proiectul nostru interactiv de terariu prin crearea codului JavaScript care va permite unui utilizator să manipuleze plantele de pe pagină.

Înainte să începem: Pregătirea pentru succes

Ai nevoie de fișierele tale HTML și CSS din lecțiile anterioare despre terariu - suntem pe cale să facem designul static interactiv. Dacă vii pentru prima dată, parcurgerea acelor lecții mai întâi îți va oferi un context important.

Iată ce vom construi:

  • Tragere și plasare liniară pentru toate plantele din terariu
  • Urmărirea coordonatelor astfel încât plantele să-și amintească pozițiile
  • O interfață complet interactivă utilizând JavaScript simplu (vanilla)
  • Cod curat și organizat folosind modele de închidere

Configurarea fișierului JavaScript

Hai să creăm fișierul JavaScript care va face terariul tău interactiv.

Pasul 1: Creează fișierul script

În folderul terariului tău, creează un fișier nou numit script.js.

Pasul 2: Leagă JavaScript-ul de HTML-ul tău

Adaugă acest tag script în secțiunea <head> a fișierului index.html:

<script src="./script.js" defer></script>

De ce este important atributul defer:

  • Asigură că JavaScript-ul tău așteaptă până când tot HTML-ul este încărcat
  • Previne erorile când JavaScript caută elemente care încă nu sunt gata
  • Garantează că toate elementele tale de plante sunt disponibile pentru interacțiune
  • Oferă performanțe mai bune decât plasarea scripturilor la finalul paginii

⚠️ Notă importantă: Atributul defer previne probleme comune de sincronizare. Fără el, JavaScript-ul poate încerca să acceseze elemente HTML înainte să fie încărcate, cauzând erori.


Conectarea JavaScript la elementele tale HTML

Înainte să putem face elementele de tras, JavaScript trebuie să le localizeze în DOM. Gândește-te la asta ca la un sistem de catalogare a unei biblioteci - odată ce ai numărul de catalog, poți găsi exact cartea de care ai nevoie și accesa tot conținutul ei.

Vom folosi metoda document.getElementById() pentru a face aceste conexiuni. Este ca un sistem precis de arhivare - dai un ID și el găsește exact elementul de care ai nevoie în HTML-ul tău.

Activarea funcționalității de tragere pentru toate plantele

Adaugă acest cod în fișierul tău script.js:

// Activează funcționalitatea de drag pentru toate cele 14 plante
dragElement(document.getElementById('plant1'));
dragElement(document.getElementById('plant2'));
dragElement(document.getElementById('plant3'));
dragElement(document.getElementById('plant4'));
dragElement(document.getElementById('plant5'));
dragElement(document.getElementById('plant6'));
dragElement(document.getElementById('plant7'));
dragElement(document.getElementById('plant8'));
dragElement(document.getElementById('plant9'));
dragElement(document.getElementById('plant10'));
dragElement(document.getElementById('plant11'));
dragElement(document.getElementById('plant12'));
dragElement(document.getElementById('plant13'));
dragElement(document.getElementById('plant14'));

Iată ce face acest cod:

  • Localizează fiecare element plantă în DOM folosind ID-ul său unic
  • Recuperează o referință JavaScript către fiecare element HTML
  • Trimite fiecare element către o funcție dragElement (pe care o vom crea în continuare)
  • Pregătește fiecare plantă pentru interacțiunea de tragere și plasare
  • Leagă structura ta HTML de funcționalitatea JavaScript

🎯 De ce folosim ID-uri în loc de clase? ID-urile oferă identificatori unici pentru elementele specifice, în timp ce clasele CSS sunt gândite pentru a stiliza grupuri de elemente. Când JavaScript trebuie să manipuleze elemente individuale, ID-urile oferă precizia și performanța de care avem nevoie.

💡 Sfat profesionist: Observă cum apelăm dragElement() pentru fiecare plantă în parte. Această abordare asigură ca fiecare plantă să aibă comportamentul de tragere independent, esențial pentru o interacțiune lină cu utilizatorul.

🔄 Verificare pedagogică

Înțelegerea conexiunii DOM: Înainte de a trece la funcționalitatea de tragere, verifică dacă poți:

  • Explica cum localizează document.getElementById() elementele HTML
  • Înțelege de ce folosim ID-uri unice pentru fiecare plantă
  • Descrie scopul atributului defer în tagurile script
  • Recunoaște cum se conectează JavaScript-ul și HTML-ul prin DOM

Test rapid: Ce s-ar întâmpla dacă două elemente ar avea același ID? De ce getElementById() returnează doar un element? Răspuns: ID-urile trebuie să fie unice; dacă sunt duplicate, este returnat doar primul element


Construirea închiderii dragElement

Acum vom crea inima funcționalității noastre de tragere: o închidere care gestionează comportamentul de tras pentru fiecare plantă. Această închidere va conține mai multe funcții interne care lucrează împreună pentru a urmări mișcările mouse-ului și a actualiza pozițiile elementelor.

Închiderile sunt perfecte pentru această sarcină deoarece ne permit să creăm variabile „private” care persistă între apelurile funcțiilor, oferind fiecărei plante propriul sistem independent de urmărire a coordonatelor.

Înțelegerea închiderilor printr-un exemplu simplu

Hai să demonstrăm închiderile cu un exemplu simplu care ilustrează conceptul:

function createCounter() {
    let count = 0; // Acesta este ca o variabilă privată
    
    function increment() {
        count++; // Funcția internă își amintește variabila exterioară
        return count;
    }
    
    return increment; // Returnăm funcția internă
}

const myCounter = createCounter();
console.log(myCounter()); // 1
console.log(myCounter()); // 2

Ce se întâmplă în acest model de închidere:

  • Creează o variabilă privată count care există doar în cadrul acestei închideri
  • Funcția internă poate accesa și modifica acea variabilă externă (mecanismul închiderii)
  • Când returnăm funcția internă, ea își păstrează conexiunea cu acele date private
  • Chiar și după ce createCounter() se termină, count persistă și își amintește valoarea

De ce închiderile sunt perfecte pentru funcționalitatea de tragere

Pentru terariul nostru, fiecare plantă trebuie să-și amintească coordonatele poziției curente. Închiderile oferă soluția perfectă:

Beneficiile cheie pentru proiectul nostru:

  • Menține variabile private de poziție pentru fiecare plantă în mod independent
  • Păstrează datele coordonatelor între evenimentele de tragere
  • Previne conflictele de variabile între elemente diferite tragabile
  • Creează un cod curat și organizat

🎯 Obiectiv de învățare: Nu trebuie să stăpânești fiecare detaliu al închiderilor acum. Concentrează-te pe a vedea cum ne ajută să organizăm codul și să menținem starea pentru funcționalitatea de tragere.

stateDiagram-v2
    [*] --> Ready: Încărcarea paginii
    Ready --> DragStart: Utilizator apasă jos (pointerdown)
    DragStart --> Dragging: Mișcare mouse/deget (pointermove)
    Dragging --> Dragging: Continuă mișcarea
    Dragging --> DragEnd: Utilizator eliberează (pointerup)
    DragEnd --> Ready: Resetare pentru următoarea tragere
    
    state DragStart {
        [*] --> CapturePosition
        CapturePosition --> SetupListeners
        SetupListeners --> [*]
    }
    
    state Dragging {
        [*] --> CalculateMovement
        CalculateMovement --> UpdatePosition
        UpdatePosition --> [*]
    }
    
    state DragEnd {
        [*] --> RemoveListeners
        RemoveListeners --> CleanupState
        CleanupState --> [*]
    }

Crearea funcției dragElement

Acum să construim funcția principală care va gestiona întreaga logică de tragere. Adaugă această funcție sub declarațiile elementelor plantelor:

function dragElement(terrariumElement) {
    // Inițializează variabilele de urmărire a poziției
    let pos1 = 0,  // Poziția anterioară a mouse-ului pe axa X
        pos2 = 0,  // Poziția anterioară a mouse-ului pe axa Y
        pos3 = 0,  // Poziția curentă a mouse-ului pe axa X
        pos4 = 0;  // Poziția curentă a mouse-ului pe axa Y
    
    // Configurează ascultătorul de evenimente de drag inițial
    terrariumElement.onpointerdown = pointerDrag;
}

Înțelegerea sistemului de urmărire a poziției:

  • pos1 și pos2: Stochează diferența dintre pozițiile vechi și noi ale mouse-ului
  • pos3 și pos4: Urmăresc coordonatele curente ale mouse-ului
  • terrariumElement: Elementul specific al plantei pe care îl facem tragabil
  • onpointerdown: Evenimentul care declanșează când utilizatorul începe să tragă

Cum funcționează tiparul închiderii:

  • Creează variabile private de poziție pentru fiecare element plantă
  • Menține aceste variabile pe tot parcursul ciclului de viață al tragerii
  • Asigură că fiecare plantă își urmărește coordonatele independent
  • Oferă o interfață curată prin funcția dragElement

De ce folosim evenimentele pointer?

Te-ai putea întreba de ce folosim onpointerdown în loc de mai familiarul onclick. Iată raționamentul:

Tip Eveniment Cel Mai Potrivit Pentru Partea Negativă
onclick Clicuri simple pe butoane Nu poate gestiona tragerea (doar clicuri și eliberări)
onpointerdown Mouse și touch Nou, dar bine suportat în zilele noastre
onmousedown Doar mouse desktop Exclude utilizatorii de pe mobil

De ce evenimentele pointer sunt perfecte pentru ce construim:

  • Funcționează bine indiferent dacă cineva folosește mouse, deget sau chiar un stylus
  • Se simte la fel pe laptop, tabletă sau telefon mobil
  • Gestionează mișcarea efectivă de tragere (nu doar clic și gata)
  • Creează o experiență lină pe care utilizatorii o așteaptă de la aplicațiile web moderne

💡 Pregătire pentru viitor: Evenimentele pointer sunt modul modern de a gestiona interacțiunile utilizatorilor. În loc să scrii cod separat pentru mouse și touch, le obții pe ambele gratuit. Destul de tare, nu?

🔄 Verificare pedagogică

Înțelegerea gestionării evenimentelor: Fă o pauză să confirmi dacă ai înțeles:

  • De ce folosim evenimente pointer în loc de evenimente mouse?
  • Cum persistă variabilele închiderii între apelurile funcțiilor?
  • Ce rol joacă preventDefault() pentru tragerea lină?
  • De ce atașăm ascultători la document în loc de elemente individuale?

Conexiune cu lumea reală: Gândește-te la interfețele drag-and-drop pe care le folosești zilnic:

  • Încărcări fișiere: Tragerea fișierelor într-o fereastră de browser
  • Table Kanban: Mutarea sarcinilor între coloane
  • Galerii foto: Reordonarea pozelor
  • Interfețe mobile: Glisarea și tragerea pe ecranele tactile

Funcția pointerDrag: Capturarea începerii unei trageri

Când un utilizator apasă pe o plantă (fie cu clic de mouse sau atingere cu degetul), funcția pointerDrag intră în acțiune. Această funcție capturează coordonatele inițiale și configurează sistemul de tras.

Adaugă această funcție în interiorul închiderii dragElement, imediat după linia terrariumElement.onpointerdown = pointerDrag;:

function pointerDrag(e) {
    // Previne comportamentul implicit al browserului (precum selecția textului)
    e.preventDefault();
    
    // Capturează poziția inițială a mouse-ului/touch-ului
    pos3 = e.clientX;  // Coordonata X unde a început tragerea
    pos4 = e.clientY;  // Coordonata Y unde a început tragerea
    
    // Configurează ascultători de evenimente pentru procesul de tragere
    document.onpointermove = elementDrag;
    document.onpointerup = stopElementDrag;
}

Pas cu pas, ce se întâmplă aici:

  • Previne comportamentele implicite ale browserului care s-ar putea interfera cu tragerea
  • Înregistrează coordonatele exacte unde utilizatorul a început gestul de tragere
  • Stabilește ascultători de evenimente pentru mișcarea continuă a tragerii
  • Pregătește sistemul pentru a urmări mișcarea mouse-ului/degetului peste întreg documentul

Înțelegerea prevenirii evenimentelor

Linia e.preventDefault() este crucială pentru o tragere lină:

Fără prevenire, browserele ar putea:

  • Selecta textul când se trage peste pagină
  • Declanșa meniuri contextuale la tragere cu clic dreapta
  • Interfera cu comportamentul personalizat de tragere
  • Crea artefacte vizuale în timpul operației de tragere

🔍 Experiment: După ce termini această lecție, încearcă să elimini e.preventDefault() și vezi cum afectează experiența de tragere. Vei înțelege rapid de ce această linie este esențială!

Sistemul de urmărire a coordonatelor

Proprietățile e.clientX și e.clientY ne oferă coordonatele precise ale mouse-ului/atingerii:

Proprietate Ce măsoară Utilizare
clientX Poziția orizontală relativă la fereastra vizuală Urmărirea mișcării stânga-dreapta
clientY Poziția verticală relativă la fereastra vizuală Urmărirea mișcării sus-jos
Înțelegerea acestor coordonate:
  • Oferă informații de poziționare pixel-perfect
  • Se actualizează în timp real pe măsură ce utilizatorul își mișcă cursorul
  • Rămâne consecvent pe diferite dimensiuni de ecran și niveluri de zoom
  • Permite interacțiuni de drag lineare și responsive

Configurarea ascultătorilor de evenimente la nivel de document

Observă cum atașăm evenimentele de mișcare și oprire întregului document, nu doar elementului plantei:

document.onpointermove = elementDrag;
document.onpointerup = stopElementDrag;

De ce facem atașarea la document:

  • Continuă urmărirea chiar și când mouse-ul părăsește elementul plantei
  • Previne întreruperea tragerii dacă utilizatorul se mișcă rapid
  • Oferă o tragere fluidă pe întreg ecranul
  • Gestionează cazurile speciale în care cursorul iese în afara ferestrei browserului

Notă despre performanță: Vom curăța acești ascultători la nivel de document când tragerea se oprește pentru a evita scurgerile de memorie și probleme de performanță.

Completarea sistemului de tragere: Mișcare și curățare

Acum vom adăuga cele două funcții rămase care se ocupă de mișcarea efectivă a tragerii și de curățarea când tragerea încetează. Aceste funcții lucrează împreună pentru a crea o mișcare fluidă și responsive a plantei prin terrariul tău.

Funcția elementDrag: Urmărirea mișcării

Adaugă funcția elementDrag imediat după acolada de închidere a funcției pointerDrag:

function elementDrag(e) {
    // Calculează distanța parcursă de la ultimul eveniment
    pos1 = pos3 - e.clientX;  // Distanța orizontală parcursă
    pos2 = pos4 - e.clientY;  // Distanța verticală parcurse
    
    // Actualizează urmărirea poziției curente
    pos3 = e.clientX;  // Noua poziție curentă pe axa X
    pos4 = e.clientY;  // Noua poziție curentă pe axa Y
    
    // Aplică mișcarea la poziția elementului
    terrariumElement.style.top = (terrariumElement.offsetTop - pos2) + 'px';
    terrariumElement.style.left = (terrariumElement.offsetLeft - pos1) + 'px';
}

Înțelegerea matematicii coordonatelor:

  • pos1 și pos2: Calculează cât de mult s-a mișcat mouse-ul de la ultima actualizare
  • pos3 și pos4: Stochează poziția curentă a mouse-ului pentru următorul calcul
  • offsetTop și offsetLeft: Obțin poziția curentă a elementului în pagină
  • Logica scăderii: Mută elementul cu aceeași distanță cu care s-a mișcat mouse-ul
sequenceDiagram
    participant User
    participant Mouse
    participant JavaScript
    participant Plant
    
    User->>Mouse: Începe tragerea la (100, 50)
    Mouse->>JavaScript: eveniment pointerdown
    JavaScript->>JavaScript: Stochează poziția inițială (pos3=100, pos4=50)
    JavaScript->>JavaScript: Configurează ascultători pentru mutare/eliberează
    
    User->>Mouse: Mută la (110, 60)
    Mouse->>JavaScript: eveniment pointermove
    JavaScript->>JavaScript: Calculează: pos1=10, pos2=10
    JavaScript->>Plant: Actualizează: left += 10px, top += 10px
    Plant->>Plant: Redă în noua poziție
    
    User->>Mouse: Eliberează la (120, 65)
    Mouse->>JavaScript: eveniment pointerup
    JavaScript->>JavaScript: Elimină ascultătorii
    JavaScript->>JavaScript: Resetează pentru următoarea tragere

Iată o defalcare a calculelor de mișcare:

  1. Măsoară diferența între vechile și noile poziții ale mouse-ului
  2. Calculează cât trebuie mutat elementul pe baza mișcării mouse-ului
  3. Actualizează proprietățile CSS de poziționare ale elementului în timp real
  4. Stochează noua poziție ca referință pentru următorul calcul de mișcare

Reprezentare vizuală a matematicii

sequenceDiagram
    participant Mouse
    participant JavaScript
    participant Plant
    
    Mouse->>JavaScript: Mută de la (100,50) la (110,60)
    JavaScript->>JavaScript: Calculează: mutat 10px la dreapta, 10px în jos
    JavaScript->>Plant: Actualizează poziția cu +10px la dreapta, +10px în jos
    Plant->>Plant: Redă la noua poziție

Funcția stopElementDrag: Curățarea

Adaugă funcția de curățare după acolada de închidere a funcției elementDrag:

function stopElementDrag() {
    // Elimină ascultătorii de evenimente la nivel de document
    document.onpointerup = null;
    document.onpointermove = null;
}

De ce este esențială curățarea:

  • Previne scurgerile de memorie cauzate de ascultătorii de evenimente rămași
  • Oprește comportamentul de tragere când utilizatorul eliberează planta
  • Permite altor elemente să fie trase independent
  • Resetează sistemul pentru următoarea operațiune de tragere

Ce se întâmplă fără curățare:

  • Ascultătorii de evenimente continuă să ruleze după ce tragerea se oprește
  • Performanța degradează pe măsură ce ascultătorii nefolosiți se acumulează
  • Comportament neașteptat la interacțiunea cu alte elemente
  • Resursele browserului sunt risipite pe gestionarea evenimentelor inutile

Înțelegerea proprietăților CSS de poziționare

Sistemul nostru de tragere manipulează două proprietăți CSS cheie:

Proprietate La ce controlează Cum o folosim
top Distanță față de marginea de sus Poziționare verticală în timpul tragerii
left Distanță față de marginea din stânga Poziționare orizontală în timpul tragerii

Informații cheie despre proprietățile offset:

  • offsetTop: Distanța curentă față de partea de sus a elementului părinte poziționat
  • offsetLeft: Distanța curentă față de partea stângă a elementului părinte poziționat
  • Contextul poziționării: Aceste valori sunt relative la cel mai apropiat strămoș poziționat
  • Actualizări în timp real: Se schimbă imediat ce modificăm proprietățile CSS

🎯 Filosofia designului: Acest sistem de tragere este intenționat flexibil nu există „zone de plasare” sau restricții. Utilizatorii pot așeza plante oriunde, având control creativ complet asupra designului terariului.

Punând totul cap la cap: Sistemul tău complet de tragere

Felicitări! Tocmai ai construit un sistem sofisticat de drag-and-drop folosind JavaScript simplu. Funcția ta completă dragElement conține acum un closure puternic care gestionează:

Ce realizează closure-ul tău:

  • Menține variabile private de poziție pentru fiecare plantă independent
  • Gestionează întreg ciclul de viață al tragerii de la început la sfârșit
  • Oferă o mișcare fluidă și responsive pe întreg ecranul
  • Curăță resursele corespunzător pentru a preveni scurgeri de memorie
  • Creează o interfață intuitivă și creativă pentru designul terariului

Testarea terariului tău interactiv

Acum testează-ți terariul interactiv! Deschide fișierul index.html într-un browser web și încearcă funcționalitățile:

  1. Fă click și ține apăsat pe orice plantă pentru a începe tragerea
  2. Mişcă mouse-ul sau degetul și urmărește cum planta urmează fluid mișcarea
  3. Eliberează pentru a plasa planta în noua poziție
  4. Experimentează cu diferite aranjamente pentru a explora interfața

🥇 Realizare: Ai creat o aplicație web complet interactivă folosind concepte de bază pe care dezvoltatorii profesioniști le folosesc zilnic. Funcționalitatea de drag-and-drop utilizează aceleași principii din spatele upload-urilor de fișiere, tablourilor kanban și multor alte interfețe interactive.

🔄 Verificare pedagogică

Înțelegerea completă a sistemului: Verifică-ți stăpânirea asupra întregului sistem de tragere:

  • Cum mențin closure-urile un stat independent pentru fiecare plantă?
  • De ce este necesar calculul matematic al coordonatelor pentru o mișcare fluidă?
  • Ce se întâmplă dacă uităm să curățăm ascultătorii de evenimente?
  • Cum se poate scala acest model pentru interacțiuni mai complexe?

Reflecție asupra calității codului: Revizuiește soluția ta completă:

  • Design modular: Fiecare plantă are propria instanță de closure
  • Eficiență a evenimentelor: Configurare și curățare corectă a ascultătorilor
  • Suport cross-device: Funcționează pe desktop și pe mobil
  • Conștientizare a performanței: Fără scurgeri de memorie sau calcule redundante

terrariu finalizat


Provocarea GitHub Copilot Agent 🚀

Folosește modul Agent pentru a completa următoarea provocare:

Descriere: Extinde proiectul terrariului adăugând o funcție de resetare care readuce toate plantele la pozițiile lor inițiale cu animații line.

Prompt: Creează un buton de reset care, la clic, animează toate plantele înapoi la pozițiile lor inițiale din bara laterală folosind tranziții CSS. Funcția ar trebui să stocheze pozițiile inițiale când se încarcă pagina și să tranziționeze lin plantele înapoi la acele poziții în decurs de 1 secundă când butonul de reset este apăsat.

Află mai multe despre modul agent aici.

🚀 Provocare suplimentară: Extinde-ți abilitățile

Ești gata să duci terrariul tău la un nou nivel? Încearcă să implementezi aceste îmbunătățiri:

Extensii creative:

  • Dublu click pe o plantă pentru a o aduce în față (manipulare z-index)
  • Adaugă feedback vizual precum o strălucire subtilă când plasezi cursorul peste plante
  • Implementează limite pentru a preveni tragerea plantelor în afara terariului
  • Creează o funcție de salvare care reține pozițiile plantelor folosind localStorage
  • Adaugă efecte sonore pentru ridicarea și plasarea plantelor

💡 Oportunitate de învățare: Fiecare dintre aceste provocări te va învăța noi aspecte ale manipulării DOM, gestionării evenimentelor și designului experienței utilizatorului.

Test post-lectură

Test post-lectură

Recapitulare & Studiu individual: Adâncirea înțelegerii

Ai stăpânit fundamentele manipulării DOM și closures, dar întotdeauna există mai mult de explorat! Iată câteva căi pentru a-ți extinde cunoștințele și abilitățile.

Alternative pentru Drag and Drop

Am folosit evenimentele pointer pentru flexibilitate maximă, dar web development oferă multiple abordări:

Abordare Potrivit pentru Valoare educațională
API-ul HTML Drag and Drop Upload-uri de fișiere, zone formale de drag Înțelegerea capacităților native ale browserului
Evenimente Touch Interacțiuni specifice pe mobil Modele de dezvoltare mobile-first
Proprietăți CSS transform Animații fluide Tehnici de optimizare a performanței

Subiecte avansate de manipulare DOM

Pașii următori în călătoria ta de învățare:

  • Delegare de evenimente: Gestionarea eficientă a evenimentelor pentru multiple elemente
  • Intersection Observer: Detectarea când elementele intră sau ies din viewport
  • Mutation Observer: Monitorizarea schimbărilor în structura DOM
  • Componente Web: Crearea de elemente UI reutilizabile și încapsulate
  • Concepte Virtual DOM: Înțelegerea modului în care framework-urile optimizează actualizările DOM

Resurse esențiale pentru învățare continuă

Documentație tehnică:

Compatibilitatea browserelor:

Oportunități practice:

  • Construiește un joc puzzle folosind mecanisme similare de tragere
  • Creează un panou kanban cu gestionare drag-and-drop a sarcinilor
  • Design o galerie foto cu aranjamente dragabile
  • Experimentează gesturile touch pentru interfețele mobile

🎯 Strategie de învățare: Cea mai bună metodă de a fixa aceste concepte este prin practică. Încearcă să construiești variații de interfețe dragabile fiecare proiect îți va arăta ceva nou despre interacțiunea utilizatorului și manipularea DOM.

Ce poți face în următoarele 5 minute

  • Deschide DevTools în browser și tastează document.querySelector('body') în consolă
  • Încearcă să schimbi textul unei pagini folosind innerHTML sau textContent
  • Adaugă un ascultător pentru evenimentul click pe orice buton sau link de pe o pagină web
  • Inspectează structura DOM folosind panoul Elements

🎯 Ce poți realiza în această oră

  • Completează quiz-ul post-lectură și recapitulează conceptele manipulării DOM
  • Creează o pagină web interactivă care răspunde la click-uri
  • Exersează gestionarea evenimentelor cu tipuri diferite (click, mouseover, keypress)
  • Construiește o listă simplă de sarcini sau un contor folosind manipularea DOM
  • Explorează relația dintre elementele HTML și obiectele JavaScript

📅 Călătoria ta JavaScript săptămânală

  • Completează proiectul terrarium interactiv cu funcționalitate drag-and-drop
  • Stăpânește delegarea evenimentelor pentru o gestionare eficientă
  • Învață despre event loop și JavaScript asincron
  • Exersează closures construind module cu stare privată
  • Explorează API-uri moderne DOM precum Intersection Observer
  • Construiește componente interactive fără a utiliza framework-uri

🌟 Maestria ta JavaScript lunară

  • Creează o aplicație complexă SPA folosind JavaScript pur
  • Învață un framework modern (React, Vue, sau Angular) și compară-l cu manipularea DOM vanilla
  • Contribuie la proiecte open source JavaScript
  • Stăpânește concepte avansate precum web components și elemente customizate
  • Construiește aplicații web performante cu modele DOM optime
  • Predă altora despre manipularea DOM și fundamentele JavaScript

🎯 Cronologia ta pentru stăpânirea DOM în JavaScript

timeline
    title Progresul în Învățarea DOM & JavaScript
    
    section Fundament (15 minute)
        Înțelegerea DOM: Metode de selecție a elementelor
                         : Navigarea structurii arbore
                         : Modele de accesare a proprietăților
        
    section Manipularea Evenimentelor (20 minute)
        Interacțiunea Utilizatorului: Bazele evenimentelor pointer
                                   : Configurarea ascultătorilor de evenimente
                                   : Compatibilitate între dispozitive
                                   : Tehnici de prevenire a evenimentelor
        
    section Închideri (25 minute)
        Gestionarea Domeniului: Crearea variabilelor private
                              : Persistența funcțiilor
                              : Modele de gestionare a stării
                              : Eficiența memoriei
        
    section Sistemul de Drag (30 minute)
        Funcționalități Interactive: Urmărirea coordonatelor
                                   : Calculul poziției
                                   : Matematica mișcării
                                   : Proceduri de curățare
        
    section Modele Avansate (45 minute)
        Abilități Profesionale: Delegarea evenimentelor
                              : Optimizarea performanței
                              : Tratarea erorilor
                              : Considerații de accesibilitate
        
    section Înțelegerea Framework-ului (1 săptămână)
        Dezvoltare Modernă: Concepte Virtual DOM
                           : Biblioteci de gestionare a stării
                           : Arhitecturi de componente
                           : Integrarea uneltelor de build
        
    section Nivel Expert (1 lună)
        API-uri Avansate DOM: Intersection Observer
                            : Mutation Observer
                            : Elemente Personalizate
                            : Componente Web

🛠️ Rezumatul trusei tale de instrumente JavaScript

După completarea acestei lecții, ai acum:

  • Stăpânire DOM: Selecția elementelor, manipularea proprietăților și navigarea în arbore
  • Experiență cu evenimente: Gestionarea interacțiunilor cross-device folosind pointer events
  • Înțelegere a closure-urilor: Administrarea stării private și persistența funcțiilor
  • Sisteme interactive: Implementarea completă a drag-and-drop de la zero
  • Conștientizare a performanței: Curățare corectă a evenimentelor și managementul memoriei
  • Modele moderne: Tehnici de organizare a codului folosite în dezvoltarea profesională
  • Experiență utilizator: Crearea de interfețe intuitive și responsive

Abilități profesionale dobândite: Ai construit funcționalități folosind aceleași tehnici ca:

  • Trello/tablouri Kanban: Tragerea cardurilor între coloane
  • Sisteme de upload fișiere: Manipulare drag-and-drop a fișierelor
  • Galerii foto: Interfețe de aranjare a fotografiilor
  • Aplicații mobile: Modele de interacțiune bazate pe touch

Nivel următor: Ești pregătit să explorezi framework-uri moderne precum React, Vue sau Angular care se bazează pe aceste concepte fundamentale de manipulare DOM!

Temă

Lucrează puțin mai mult cu DOM-ul


Declinarea răspunderii: Acest document a fost tradus folosind serviciul de traducere AI Co-op Translator. Deși ne străduim pentru acuratețe, vă rugăm să țineți cont că traducerile automate pot conține erori sau inexactități. Documentul original în limba sa nativă trebuie considerat sursa autorizată. Pentru informații critice, se recomandă traducerea profesională realizată de un specialist uman. Nu ne asumăm responsabilitatea pentru eventualele neînțelegeri sau interpretări greșite cauzate de utilizarea acestei traduceri.