Tehnici DOM: părinte, copil și frați. Tehnici DOM: părinți, copii și frați Adăugarea și îndepărtarea copiilor

Aplicațiile web complexe și grele sunt obișnuite în zilele noastre. Bibliotecile încrucișate și ușor de utilizat, cum ar fi jQuery, cu funcționalitatea lor bogată, pot ajuta foarte mult la manipularea DOM-ului din mers. Prin urmare, nu este surprinzător faptul că mulți dezvoltatori folosesc astfel de biblioteci mai des decât lucrează cu API-ul DOM nativ, cu care au existat multe probleme. Și, deși diferențele de browser sunt încă o problemă, DOM este într-o formă mai bună acum decât acum 5-6 ani, când jQuery câștiga popularitate.

În acest articol, voi demonstra capacitățile de manipulare HTML ale DOM, concentrându-mă pe relațiile dintre părinți, copii și frați. În concluzie, voi oferi date despre suportul acestor caracteristici în browsere, dar rețineți că o bibliotecă precum jQuery este încă o opțiune bună datorită prezenței bug-urilor și a inconsecvențelor în implementarea funcționalității native.

Numărarea nodurilor copil

Voi folosi următorul markup HTML pentru demonstrație și îl vom schimba de mai multe ori pe parcursul articolului:

  • Exemplul unu
  • Exemplul doi
  • Exemplul trei
  • Exemplul patru
  • Exemplul cinci
  • Exemplul șase


Var myList \u003d document.getElementById ("lista mea"); console.log (myList.children.length); // 6 console.log (myList.childElementCount); // 6

După cum puteți vedea, rezultatele sunt aceleași, deși tehnicile sunt diferite. În primul caz, folosesc proprietatea pentru copii. Această proprietate este doar în citire și returnează colecția de elemente HTML care se află în elementul solicitat; pentru a număra câte, folosesc proprietatea lungime a acestei colecții.

În al doilea exemplu, folosesc metoda childElementCount, care mi se pare a fi un mod mai îngrijit și potențial mai ușor de întreținut (vom discuta mai detaliat acest lucru mai târziu, nu cred că veți avea probleme să înțelegeți ce face) .

Aș putea încerca să folosesc childNodes.length (în loc de children.length), dar uită-te la rezultat:

Var myList \u003d document.getElementById ("lista mea"); console.log (myList.childNodes.length); // 13

Se returnează 13 deoarece childNodes este o colecție de toate nodurile, inclusiv spațiile - luați în considerare acest lucru dacă vă pasă de diferența dintre nodurile copil și nodurile elementului copil.

Verificarea existenței nodurilor copil

Pentru a verifica dacă un element are noduri copil, pot folosi metoda hasChildNodes (). Metoda returnează o valoare booleană care indică prezența sau absența lor:

Var myList \u003d document.getElementById ("lista mea"); console.log (myList.hasChildNodes ()); // Adevărat

Știu că există noduri copil în lista mea, dar pot schimba codul HTML astfel încât să nu existe; acum marcajul arată astfel:



Și iată rezultatul unei noi runde de hasChildNodes ():

Console.log (myList.hasChildNodes ()); // Adevărat

Metoda revine în continuare adevărată. Deși lista nu conține niciun element, conține un spațiu, care este un tip de nod valid. Această metodă ia în considerare toate nodurile, nu doar nodurile elementelor. Pentru ca hasChildNodes () să returneze false, trebuie să schimbăm din nou marcajul:



Și acum rezultatul așteptat este tipărit pe consolă:

Console.log (myList.hasChildNodes ()); // fals

Desigur, dacă știu că aș putea întâlni un spațiu, atunci mai întâi verific existența nodurilor copil, apoi folosind proprietatea nodeType determinez dacă există noduri elemente printre ele.

Adăugarea și eliminarea copiilor

Există tehnici care pot fi utilizate pentru a adăuga și a elimina elemente din DOM. Cea mai faimoasă dintre acestea se bazează pe o combinație a metodelor createElement () și appendChild ().

Var myEl \u003d document.createElement ("div"); document.body.appendChild (myEl);

În acest caz, creez

folosind metoda createElement () și apoi adăugându-l la corp. Foarte simplu și probabil ați mai folosit această tehnică.

Dar, în loc să inserez un element special creat, pot folosi și appendChild () și doar să mut elementul existent. Să presupunem că avem următorul markup:

  • Exemplul unu
  • Exemplul doi
  • Exemplul trei
  • Exemplul patru
  • Exemplul cinci
  • Exemplul șase

Exemplu de text

Pot modifica locația listei cu următorul cod:

Var myList \u003d document.getElementById ("lista mea"), container \u003d document.getElementById ("c"); container.appendChild (lista mea);

DOM-ul rezultat va arăta astfel:

Exemplu de text

  • Exemplul unu
  • Exemplul doi
  • Exemplul trei
  • Exemplul patru
  • Exemplul cinci
  • Exemplul șase

Rețineți că întreaga listă a fost eliminată din locul său (deasupra paragrafului) și apoi inserată după ea, înainte de corpul de închidere. Deși metoda appendChild () este de obicei utilizată pentru a adăuga elemente create cu createElement (), poate fi folosită și pentru a muta elementele existente.

De asemenea, pot elimina complet copilul din DOM folosind removeChild (). Iată cum lista noastră este eliminată din exemplul anterior:

Var myList \u003d document.getElementById ("lista mea"), container \u003d document.getElementById ("c"); container.removeChild (lista mea);

Elementul a fost acum eliminat. Metoda removeChild () returnează elementul eliminat și îl pot salva în caz că am nevoie mai târziu.

Var myOldChild \u003d document.body.removeChild (myList); document.body.appendChild (myOldChild);

Există, de asemenea, metoda ChildNode.remove (), care a fost adăugată relativ recent la specificații:

Var myList \u003d document.getElementById ("lista mea"); MyList.remove ();

Această metodă nu returnează un obiect la distanță și nu funcționează în IE (numai Edge). Și ambele metode elimină nodurile text în același mod ca și nodurile elementelor.

Înlocuirea copiilor

Pot înlocui copilul existent cu unul nou, indiferent dacă acest element nou există sau l-am creat de la zero. Iată marcajul:

Text de exemplu

Var myPar \u003d document.getElementById ("par"), myDiv \u003d document.createElement ("div"); myDiv.className \u003d "exemplu"; myDiv.appendChild (document.createTextNode („Text element nou”)); document.body.replaceChild (myDiv, myPar);

Text cu element nou

După cum puteți vedea, metoda replaceChild () ia două argumente: elementul nou și elementul vechi pe care îl înlocuiește.

De asemenea, pot folosi această metodă pentru a muta un element existent. Aruncați o privire la următorul HTML:

Exemplu de text 1

Exemplu de text 2

Exemplu de text 3

Pot înlocui al treilea paragraf cu primul paragraf cu următorul cod:

Var myPar1 \u003d document.getElementById ("par1"), myPar3 \u003d document.getElementById ("par3"); document.body.replaceChild (myPar1, myPar3);

Acum, DOM-ul generat arată astfel:

Exemplu de text 2

Exemplu de text 1

Aducerea anumitor copii

Există mai multe moduri diferite de a selecta un anumit element. După cum s-a arătat mai devreme, pot începe folosind colecția pentru copii sau proprietatea childNodes. Dar să aruncăm o privire la alte opțiuni:

Proprietățile firstElementChild și lastElementChild fac exact ceea ce numele lor s-ar putea aștepta să facă: selectează primul și ultimul element secundar. Să revenim la marcajul nostru:

  • Exemplul unu
  • Exemplul doi
  • Exemplul trei
  • Exemplul patru
  • Exemplul cinci
  • Exemplul șase


Pot selecta primul și ultimul element folosind aceste proprietăți:

Var myList \u003d document.getElementById ("lista mea"); console.log (myList.firstElementChild.innerHTML); // „Exemplul unu” console.log (myList.lastElementChild.innerHTML); // „Exemplul șase”

De asemenea, pot folosi proprietățile previousElementSibling și nextElementSibling dacă doresc să selectez alte elemente copil decât primul sau ultimul. Acest lucru se realizează prin combinarea proprietăților firstElementChild și lastElementChild:

Var myList \u003d document.getElementById ("lista mea"); console.log (myList.firstElementChild.nextElementSibling.innerHTML); // „Exemplul doi” console.log (myList.lastElementChild.previousElementSibling.innerHTML); // „Exemplul cinci”

Există, de asemenea, proprietăți similare firstChild, lastChild, previousSibling și nextSibling, dar țin cont de toate tipurile de noduri, nu doar de elemente. De regulă, proprietățile care consideră doar nodurile elementelor sunt mai utile decât cele care selectează toate nodurile.

Inserarea conținutului în DOM

Am analizat deja modalități de a insera elemente în DOM. Să trecem la un subiect asociat și să aruncăm o privire asupra noilor opțiuni de inserare a conținutului.

În primul rând, există o metodă simplă insertBefore (), care este foarte asemănătoare cu replaceChild (), acceptă două argumente și, în același timp, funcționează atât cu elemente noi, cât și cu cele existente. Iată marcajul:

  • Exemplul unu
  • Exemplul doi
  • Exemplul trei
  • Exemplul patru
  • Exemplul cinci
  • Exemplul șase

Exemplu de paragraf

Observați paragraful, îl voi elimina mai întâi și apoi îl voi introduce înaintea listei, totul dintr-o dată:

Var myList \u003d document.getElementById ("lista mea"), container \u003d document.getElementBy ("c"), myPar \u003d document.getElementById ("par"); container.insertBefore (myPar, myList);

În HTML rezultat, paragraful va fi înaintea listei și acesta este un alt mod de a înfășura elementul.

Exemplu de paragraf

  • Exemplul unu
  • Exemplul doi
  • Exemplul trei
  • Exemplul patru
  • Exemplul cinci
  • Exemplul șase

La fel ca replaceChild (), insertBefore () ia două argumente: elementul de adăugat și elementul înaintea căruia dorim să îl inserăm.

Această metodă este simplă. Să încercăm acum un mod mai puternic de inserare: metoda insertAdjacentHTML ().

De obicei, dezvoltatorii folosesc jQuery atunci când trebuie să facă ceva cu DOM. Cu toate acestea, aproape orice manipulare DOM poate fi făcută în JavaScript pur folosind API-ul DOM.

Să aruncăm o privire mai atentă la acest API:

La final, veți scrie propria bibliotecă DOM simplă pe care o puteți folosi în orice proiect.

Solicitări DOM

Interogările DOM sunt făcute utilizând metoda .querySelector (), care ia ca argument un selector CSS arbitrar.

Const myElement \u003d document.querySelector ("# foo\u003e div.bar")

Se va returna primul articol care se potrivește. Alternativ, puteți verifica dacă un element se potrivește cu un selector:

MyElement.matches ("div.bar") \u003d\u003d\u003d adevărat

Dacă doriți să obțineți toate elementele care se potrivesc cu un selector, utilizați următoarea construcție:

Const myElements \u003d document.querySelectorAll (". Bar")

Dacă știți ce părinte să faceți referință, puteți căuta pur și simplu printre copiii săi, în loc să căutați peste tot codul:

Const myChildElemet \u003d myElement.querySelector ("input") // În loc de: // document.querySelector ("# foo\u003e div.bar input")

Se pune întrebarea: de ce să folosim apoi alte metode mai puțin convenabile precum .getElementsByTagName ()? Există o mică problemă - ieșirea ieșirii .querySelector () nu este actualizată, iar când adăugăm un element nou (vezi) nu se modifică.

Const elements1 \u003d document.querySelectorAll ("div") const elements2 \u003d document.getElementsByTagName ("div") const newElement \u003d document.createElement ("div") document.body.appendChild (newElement) elements1.length \u003d\u003d\u003d elements2.length // fals

De asemenea, querySelectorAll () colectează totul într-o singură listă, ceea ce îl face să nu fie foarte eficient.

Cum lucrez cu listele?

În plus, .querySelectorAll () are două mici nuanțe. Nu puteți apela doar la metode pentru rezultate și așteptați ca acestea să se aplice fiecăruia dintre ele (așa cum s-ar putea să vă obișnuiți cu jQuery). În orice caz, va trebui să iterați pe toate elementele din buclă. În al doilea rând, obiectul returnat este o listă de elemente, nu o matrice. Prin urmare, metodele matrice nu vor funcționa. Desigur, există metode pentru liste, ceva de genul .forEach (), dar, din păcate, nu sunt potrivite pentru toate cazurile. Deci, este mai bine să convertiți lista într-o matrice:

// Utilizarea Array.from () Array.from (myElements) .forEach (doSomethingWithEachElement) // Sau prototip Array (pre ES6) Array.prototype.forEach.call (myElements, doSomethingWithEachElement) // Mai simplu: .forEach.call (myElements) , faceSomethingWithEachElement)

Fiecare element are câteva proprietăți care se referă la „familie”.

MyElement.children myElement.firstElementChild myElement.lastElementChild myElement.previousElementSibling myElement.nextElementSibling

Deoarece interfața Element este moștenită de la interfața Node, sunt prezente și următoarele proprietăți:

MyElement.childNodes myElement.firstChild myElement.lastChild myElement.previousSibling myElement.nextSibling myElement.parentNode myElement.parentElement

Primele proprietăți se referă la element, iar ultima (cu excepția .parentElement) poate fi listă cu orice tip de element. În consecință, puteți verifica tipul elementului:

MyElement.firstChild.nodeType \u003d\u003d\u003d 3 // acest element va fi un nod text

Adăugarea de clase și atribute

Adăugarea unei clase noi este foarte simplă:

MyElement.classList.add ("foo") myElement.classList.remove ("bar") myElement.classList.toggle ("baz")

Adăugarea unei proprietăți unui element este exact la fel ca pentru orice obiect:

// Obțineți valoarea atributului const value \u003d myElement.value // Setați atributul ca proprietate a elementului myElement.value \u003d "(! LANG: foo" // Для установки нескольких свойств используйте.Object.assign() Object.assign(myElement, { value: "foo", id: "bar" }) // Удаление атрибута myElement.value = null !}

Puteți utiliza metodele .getAttibute (), .setAttribute () și .removeAttribute (). Acestea vor schimba imediat atributele HTML ale elementului (spre deosebire de proprietățile DOM), ceea ce va face ca browserul să fie redesenat (puteți vedea toate modificările examinând elementul utilizând instrumentele de dezvoltare ale browserului). Astfel de redesenări nu numai că necesită mai multe resurse decât setarea proprietăților DOM, dar pot duce și la erori neașteptate.

De obicei, acestea sunt utilizate pentru elemente care nu au proprietăți DOM corespunzătoare, cum ar fi colspan. Sau dacă utilizarea lor este cu adevărat necesară, de exemplu, pentru proprietățile HTML în moștenire (vezi).

Adăugarea stilurilor CSS

Acestea sunt adăugate în același mod ca și alte proprietăți:

MyElement.style.marginLeft \u003d "2em"

Unele proprietăți specifice pot fi setate folosind .style, dar dacă doriți să obțineți valorile după unele calcule, este mai bine să utilizați window.getComputedStyle (). Această metodă ia un element și returnează o declarație CSSStyleDeclaration care conține stilurile atât ale elementului în sine, cât și ale părintelui său:

Window.getComputedStyle (myElement) .getPropertyValue („margin-left”)

Schimbarea DOM

Puteți muta elemente:

// Adăugați element1 ca ultimul element al elementului2 element1.appendChild (element2) // Introduceți elementul2 ca element secundar al elementului 1 înainte de elementul3 element1.insertBefore (element2, element3)

Dacă nu doriți să vă mutați, dar trebuie să inserați o copie, utilizați:

// Creați o clonă const myElementClone \u003d myElement.cloneNode () myParentElement.appendChild (myElementClone)

Metoda .cloneNode () ia ca argument o valoare booleană, dacă este adevărată, sunt clonate și elementele copil.

Desigur, puteți crea elemente noi:

Const myNewElement \u003d document.createElement ("div") const myNewTextNode \u003d document.createTextNode ("ceva text")

Și apoi introduceți-le așa cum se arată mai sus. Nu veți putea șterge un element direct, dar îl puteți face prin elementul părinte:

MyParentElement.removeChild (myElement)

De asemenea, puteți aplica indirect:

MyElement.parentNode.removeChild (myElement)

Metode pentru elemente

Fiecare element are proprietăți precum .innerHTML și .textContent, conțin codul HTML și, în consecință, textul în sine. Următorul exemplu schimbă conținutul unui element:

// Schimbă HTML myElement.innerHTML \u003d `

Conținut nou

beep boop beep boop

`// Aceasta elimină conținutul myElement.innerHTML \u003d null // Adăugați la HTML myElement.innerHTML + \u003d` continuați să citiți ...

Schimbarea HTML este de fapt o idee proastă, deoarece pierde orice modificare făcută anterior și, de asemenea, suprasolicită gestionarele de evenimente. Este mai bine să utilizați această metodă numai aruncând complet HTML și înlocuindu-l cu o copie de pe server. Asa:

Const link \u003d document.createElement ("a") const text \u003d document.createTextNode ("continuați să citiți ...") const hr \u003d document.createElement ("hr") link.href \u003d "foo.html" link.appendChild ( text) myElement.appendChild (link) myElement.appendChild (hr)

Cu toate acestea, acest lucru va implica două redesenări în browser, în timp ce .innerHTML va avea ca rezultat doar unul. Puteți rezolva acest lucru adăugând mai întâi totul la DocumentFragment, apoi adăugând fragmentul dorit:

Fragment const \u003d document.createDocumentFragment () fragment.appendChild (text) fragment.appendChild (hr) myElement.appendChild (fragment)

Manipulatori de evenimente

Unul dintre cei mai simpli manipulatori:

MyElement.onclick \u003d funcție onclick (eveniment) (console.log (event.type + "a fost concediat"))

Dar, de regulă, ar trebui evitată. Aici .onclick este o proprietate a unui element și, teoretic, îl puteți schimba, dar nu puteți adăuga alți manipulatori folosind o altă funcție care se referă la cea veche.

Este mai bine să utilizați .addEventListener () pentru a adăuga handlers. Este nevoie de trei argumente: tipul evenimentului, o funcție care va fi apelată ori de câte ori este declanșată și un obiect de configurare (vom reveni la aceasta mai târziu).

MyElement.addEventListener ("clic", funcție (eveniment) (console.log (event.type + "a fost concediat"))) myElement.addEventListener ("clic", funcție (eveniment) (console.log (event.type + ") am fost concediat din nou ")))

Proprietatea event.target se referă la elementul la care este atașat evenimentul.

Și astfel puteți accesa toate proprietățile:

// Proprietatea `forms` este o matrice care conține referințe la toate formularele const myForm \u003d document.forms const myInputElements \u003d myForm.querySelectorAll (" input ") Array.from (myInputElements) .forEach (el \u003d\u003e (el.addEventListener (" schimbare ", funcție (eveniment) (console.log (event.target.value)))))

Prevenirea acțiunilor implicite

Pentru aceasta, se utilizează metoda .preventDefault (), care blochează acțiunile standard. De exemplu, va bloca trimiterile de formulare dacă autorizarea de la client nu a avut succes:

MyForm.addEventListener ("trimiteți", funcție (eveniment) (const name \u003d this.querySelector ("# name") if (name.value \u003d\u003d\u003d "(! LANG: Donald Duck") { alert("You gotta be kidding!") event.preventDefault() } }) !}

Metoda .stopPropagation () vă va ajuta dacă aveți un anumit handler de eveniment atașat la elementul copil și un al doilea handler pentru același eveniment atașat la părinte.

După cum sa menționat mai devreme, metoda .addEventListener () ia un al treilea argument opțional, un obiect de configurare. Acest obiect trebuie să conțină oricare dintre următoarele proprietăți booleene (în mod implicit, toate false):

  • captură: evenimentul va fi atașat acestui element înainte de orice alt element de mai jos în DOM;
  • o dată: evenimentul poate fi fixat o singură dată;
  • pasiv: event.preventDefault () va fi ignorat (excepție în momentul erorii).

Cea mai comună proprietate este .capture și este atât de obișnuită încât există o cale scurtă de a o nota: în loc să o treceți într-un obiect de configurare, trebuie doar să specificați valoarea acesteia aici:

MyElement.addEventListener (tip, ascultător, adevărat)

Handlerele sunt eliminate folosind metoda .removeEventListener (), care ia două argumente: tipul evenimentului și o referință la handler de eliminat. De exemplu, proprietatea odată poate fi implementată astfel:

MyElement.addEventListener ("modificare", funcție de ascultare (eveniment) (console.log (event.type + "a fost declanșat pe" + aceasta) this.removeEventListener ("modificare", ascultător)))

Moştenire

Să presupunem că aveți un element și doriți să adăugați un gestionar de evenimente pentru toți copiii acestuia. Apoi, va trebui să le parcurgeți folosind metoda myForm.querySelectorAll („input”) așa cum se arată mai sus. Cu toate acestea, puteți adăuga elemente la formular și puteți verifica conținutul acestora folosind event.target.

MyForm.addEventListener ("schimbare", funcție (eveniment) (const target \u003d event.target if (target.matches ("input")) (console.log (target.value))))

Și încă un avantaj al acestei metode este că gestionarul se va lega automat de elementele copil noi.

Animaţie

Cel mai simplu mod de a adăuga animație este utilizarea CSS cu proprietatea de tranziție. Dar pentru mai multă flexibilitate (cum ar fi jocul) JavaScript este mai potrivit.

Apelarea metodei window.setTimeout () până la finalizarea animației nu este o idee bună, deoarece aplicația dvs. poate îngheța, în special pe dispozitivele mobile. Mai bine să utilizați window.requestAnimationFrame () pentru a salva toate modificările până la următoarea redesenare. Are o funcție ca argument, care, la rândul său, primește un timestamp:

Const start \u003d window.performance.now () const duration \u003d 2000 window.requestAnimationFrame (function fadeIn (now)) (const progress \u003d now - start myElement.style.opacity \u003d progres / durata if (progres< duration) { window.requestAnimationFrame(fadeIn) } }

Se realizează astfel o animație foarte lină. În articolul său, Mark Brown discută acest subiect.

Scrierea bibliotecii

Faptul că în DOM trebuie să iterați elemente tot timpul pentru a efectua orice operații pe ele poate părea destul de plictisitor în comparație cu sintaxa jQuery $ (". Foo"). Css ((culoare: "roșie")). Dar de ce nu scrieți câteva dintre propriile metode pentru a ușura această sarcină?

Const $ \u003d funcție $ (selector, context \u003d document) (const elements \u003d Array.from (context.querySelectorAll (selector)) return (elements, html (newHtml) (this.elements.forEach (element \u003d\u003e (element.innerHTML \u003d newHtml)) returnează acest lucru), css (newCss) (this.elements.forEach (element \u003d\u003e (Object.assign (element.style, newCss))) returnează acest lucru), pe (eveniment, handler, opțiuni) (this.elements .forEach (element \u003d\u003e (element.addEventListener (eveniment, handler, opțiuni))) returnează acest lucru)))



Pseudo cod

$ (". rightArrow"). click (function () (rightArrowParents \u003d this.dom (); //. dom (); este pseudo funcția ... ar trebui să afișeze întreaga alertă (rightArrowParents);));

Mesajul de alarmă va fi:

corp div.lol a.rightArrow

Cum pot obține acest lucru folosind javascript / jquery?

Folosind jQuery astfel (urmat de o soluție care nu folosește jQuery, cu excepția unui eveniment, cu atât mai puține apeluri funcționale dacă asta contează):

Exemplu live:

$ (". rightArrow"). click (function () (var rightArrowParents \u003d; $ (this) .parents (). addBack (). not ("html"). each (function () (var entry \u003d this.tagName .toLowerCase (); if (this.className) (entry + \u003d "." + this.className.replace (/ / g, ".");) rightArrowParents.push (entry);)); alert (rightArrowParents.join ("")); returnează fals;));

Click aici

(În exemple live, am actualizat atributul de clasă de pe div pentru a fi lol multi înainte de a demonstra gestionarea mai multor clase.)

Iată o soluție pentru a se potrivi exact cu articolul.

Este important să înțelegem că selectorul ( nu este real) care arată instrumentele cromate nu identifică în mod unic un element din DOM. ( de exemplu, nu va face distincția între o listă de elemente consecutive. Fără informații de poziționare / indexare)

$ .fn.fullSelector \u003d function () (var path \u003d this.parents (). addBack (); var quickCss \u003d path.get (). map (function (item) (var self \u003d $ (item), id \u003d item .id? "#" + item.id: "", clss \u003d item.classList.length? item.classList.toString (). split ("") .map (function (c) (return "." + c; )). join (""): "", name \u003d item.nodeName.toLowerCase (), index \u003d self.siblings (name) .length? ": nth-child (" + (self.index () + 1) + ")": ""; if (nume \u003d\u003d\u003d "html" || nume \u003d\u003d\u003d "corp") (returnează numele;) returnează numele + index + id + clss;)). join ("\u003e") ; returnează quickCss;);

Și îl puteți folosi astfel:

Console.log ($ ("some-selector"). FullSelector ());

Am mutat un fragment din T.J. Strângeți un mic plugin jQuery. Am folosit versiunea jQuery, chiar dacă el este corect că este complet inutil, dar îl folosesc doar în scopuri de depanare, deci nu-mi pasă.

Folosind:

Zonă cuibărită
Durată simplă
Pre


// result (array): ["body", "div.sampleClass"] $ ("span"). getDomPath (false) // result (string): body\u003e div.sampleClass $ ("span"). getDomPath ( ) // result (array): ["body", "div # test"] $ ("pre"). getDomPath (false) // result (string): body\u003e div # test $ ("pre"). getDomPath ()

Var obj \u003d $ ("# show-editor-button"), cale \u003d ""; while (typeof obj.prop ("tagName")! \u003d "undefined") (if (obj.attr ("class")) (path \u003d "." + obj.attr ("class"). replace (/ \\ s / g, ".") + cale;) if (obj.attr ("id")) (cale \u003d "#" + obj.attr ("id") + cale;) cale \u003d "" + obj.prop ( "TagName"). toLowerCase () + cale; obj \u003d obj.parent ();) console.log (cale);

salut această funcție rezolvă eroarea legată de elementul curent care nu este afișat în cale

Verifica acum

$ j (". wrapper"). click (function (event) (selectedElement \u003d $ j (event.target); var rightArrowParents \u003d; $ j (event.target) .parents (). not ("html, body")) .each (function () (var entry \u003d this.tagName.toLowerCase (); if (this.className) (entry + \u003d "." + this.className.replace (/ / g, ".");) else if (this.id) (entry + \u003d "#" + this.id;) entry \u003d replaceAll (entry, "..", "."); rightArrowParents.push (entry);)); rightArrowParents.reverse (); //if(event.target.nodeName.toLowerCase()\u003d\u003d"a "|| event.target.nodeName.toLowerCase () \u003d\u003d" h1 ") (var entry \u003d event.target.nodeName.toLowerCase (); if (event.target.className) (entry + \u003d "." + event.target.className.replace (/ / g, ".");) else if (event.target.id) (entry + \u003d "#" + event.target.id;) rightArrowParents.push (entry); //)

Unde $ j \u003d jQuery Variable

rezolvați și problema cu .. în numele clasei

iată funcția de înlocuire:

Funcția escapeRegExp (str) (return str.replace (/ ([. * +? ^ \u003d !: $ () () | \\ [\\] \\ / \\\\]) / g, "\\\\ $ 1");) funcție replaceAll (str, find, replace) (return str.replace (new RegExp (escapeRegExp (find), "g"), replace);)

Iată o versiune nativă JS care returnează calea jQuery. De asemenea, adaug ID-uri pentru elemente, dacă există. Acest lucru vă va oferi posibilitatea de a face cea mai scurtă cale dacă vedeți id-ul în matrice.

Var cale \u003d getDomPath (element); console.log (path.join ("\u003e"));

Corp\u003e secțiune: eq (0)\u003e div: eq (3)\u003e secțiunea # conținut\u003e secțiunea # firehose\u003e div # firehoselist\u003e articolul # firehose-46813651\u003e header\u003e h2\u003e span # title-46813651

Iată funcția.

Funcția getDomPath (el) (var stack \u003d; while (el.parentNode! \u003d Null) (console.log (el.nodeName); var sibCount \u003d 0; var sibIndex \u003d 0; for (var i \u003d 0; i< el.parentNode.childNodes.length; i++) { var sib = el.parentNode.childNodes[i]; if (sib.nodeName == el.nodeName) { if (sib === el) { sibIndex = sibCount; } sibCount++; } } if (el.hasAttribute("id") && el.id != "") { stack.unshift(el.nodeName.toLowerCase() + "#" + el.id); } else if (sibCount > 1) (stack.unshift (el.nodeName.toLowerCase () + ": eq (" + sibIndex + ")");) else (stack.unshift (el.nodeName.toLowerCase ());) el \u003d el.parentNode ; ) return stack.slice (1); // elimină elementul html)