
🔍 JQuery: miten löytää elementti tietyn tekstin perusteella
Kehittäjä luo tuotekorttiasettelua WooCommercessa. Kaikki sujuu suunnitelmien mukaan, kunnes hallintapaneelista tulee tehtävä: "poista Featured-merkki ja sen perässä oleva pilkku, mutta vain niiltä tuotteilta, jotka ovat holder-kategoriassa." Manuaalinen käsittely ei tule kysymykseen, tuotteita on satoja. Tarvitsemme skriptin, joka löytää itse "featured"-tekstin sisältävän lohkon, siirtyy sen yläelementtiin, nappaa viereisen span-elementin ja poistaa koko rakenteen.
Ja tässä kohtaa jQuery astuu kuvaan ketjutuksineen: .each() iteraatioon, .find() etsintään, :contains() tekstin perusteella suodattamiseen, .closest() yläelementtiin kiipeämiseen, .next() viereiseen elementtiin siirtymiseen ja .remove() siivoamiseen. Viisi metodia, ja tehtävä ratkeaa neljällä rivillä. Alla käyn läpi jokaisen vaiheen: valitsimesta lopulliseen siivoukseen, selittäen logiikan ja sudenkuopat.
💡 Pikakatsaus:
- Ensin etsimme tekstin sisältävän kohdelohkon contains-valitsimella ja kiipeämme sen yläelementtiin closestin avulla
- Sitten siirrymme viereiseen elementtiin nextin avulla ja poistamme molemmat lohkot tarkasti removella
- Lopuksi debuggaamme skriptin ja analysoimme tyypillisiä virheitä, jotka liittyvät kontekstin menetykseen ja ahneeseen nextiin
Tehtävä: mitä etsimme ja mitä poistamme
Alkuperäinen HTML-rakenne näyttää suunnilleen tältä:
1 <span class="tg-cats-holder"> 2 <a class="product_visibility" href="..."> 3 <span class="tg-item-term">featured</span> 4 </a> 5 <span>, </span> 6 <a class="product_visibility" href="..."> 7 <span class="tg-item-term">sale</span> 8 </a> 9 <span>, </span> 10 </span>
Keskeinen tavoite on löytää <span class="tg-item-term">, joka sisältää tekstin featured, kiivetä yläelementtiin <a class="product_visibility">, siirtyä sitten seuraavaan <span>-elementtiin (jossa on pilkku) ja poistaa se. Tämän jälkeen poista <a class="product_visibility"> ja itse merkki. Muut tunnisteet (sale jne.) säilyvät koskemattomina.
Valmis skripti
1 jQuery(document).ready(function($) { 2 $('span.tg-cats-holder').each(function() { 3 $(this) 4 .find('span.tg-item-term:contains("featured")') 5 .closest('a.product_visibility') 6 .next('span:contains(",")') 7 .remove(); 8 9 $(this) 10 .find('span.tg-item-term:contains("featured")') 11 .closest('a.product_visibility') 12 .remove(); 13 }); 14 });
Koodi on tarkoituksella jaettu kahteen ketjuun yhden sijaan. Syy on yksinkertainen: elementin .remove()-kutsun jälkeen ketju katkeaa, eikä jatkopaikkaa ole. Joten ensin siivoamme viereisen spanin pilkkuineen (ensimmäinen ketju), sitten poistamme itse lohkon (toinen).
Vaiheittainen erittely
Vaihe 1: käy läpi jokainen holder
1 $('span.tg-cats-holder').each(function() {
.each()-metodi käy läpi kokoelman jokaisen elementin, tässä tapauksessa kaikki sivun <span class="tg-cats-holder">-elementit. Jos holdereita on useita (eri tuotekategorioita), skripti toimii jokaisessa itsenäisesti. Takaisinkutsufunktion sisällä this viittaa kulloinkin käsiteltävään holderiin, ja kaikki jatkohaut lähtevät siitä.
Vaihe 2: etsi tekstin sisältävä lohko:contains()-valitsimella
1 .find('span.tg-item-term:contains("featured")')
:contains("featured")-valitsin löytää elementin, jonka sisällä (mukaan lukien lapsisolmut) on merkkijono "featured". Kolme tärkeää vivahdetta:
Kirjainkoko. Merkkijonot "Featured", "FEATURED" ja "featured" ovat eri asioita. Jos merkki on kirjoitettu hallintapaneelissa eri tavalla, lisää tarkistus
.filter()- ja.toLowerCase()-metodeilla, esimerkki UKK-osiossa.Haku kaikista jälkeläisistä.
:contains()tarkistaa sekä itse elementin että kaikkien sen lasten tekstisisällön. Jos<span class="tg-item-term">-elementin sisällä on toinen<strong>, myös sen sisällä oleva teksti lasketaan mukaan.Tämä ei ole suorituskyky-valitsin.
:contains()ei hyödynnä natiiviaquerySelectorAll-kiihdytystä, vaan jQuery käy läpi kaikki ehdokkaat ja lukee.textContent-ominaisuuden. Sivuilla, joilla on satoja elementtejä, on parempi rajata valintaa lisäluokalla tai -attribuutilla.
.find()-metodi rajoittaa haun nykyisen holderin jälkeläisiin, ei koko sivuun, mikä antaa sekä nopeusetua että suojaa vääriä positiivisia vastaan.
Vaihe 3: kiipeä yläelementtiin.closest()-metodilla
1 .closest('a.product_visibility')
.closest() kulkee puurakennetta ylöspäin löydetystä elementistä ja palauttaa lähimmän valitsinta vastaavan esivanhemman. Toisin kuin .parent(), se ei rajoitu yhteen tasoon, vaan se kiipeää aina <html>-elementtiin asti, kunnes löytää osuman tai saavuttaa juuren.
Jos olisimme käyttäneet .parent()-metodia .closest()-metodin sijaan, skripti hajoaisi heti, jos sisäkkäisyyttä olisi: <span class="tg-item-term"> → <strong> → <a class="product_visibility">, .parent() palauttaisi <strong>-elementin, ei tarvittua linkkiä. .closest() vakuuttaa tällaisia yllätyksiä vastaan.
Vaihe 4: hyppää viereiseen elementtiin.next()-metodilla
1 .next('span:contains(",")')
.next() ottaa välittömästi seuraavan sisaruselementin saman yläelementin alta. span:contains(",")-suodatin takaa, että otamme juuri pilkun sisältävän spanin, emme mitä tahansa seuraavaa elementtiä. Ilman suodatinta .next() nappaisi ensimmäisen saatavilla olevan sisarussolmun, esimerkiksi toisen <a class="product_visibility">-elementin seuraavalla tunnisteella.
Ero .next()- ja .nextAll()-metodien välillä: ensimmäinen ottaa täsmälleen yhden elementin, toinen kaikki seuraavat sisarukset. Tässä tarvitsemme tarkkaa iskua, joten .next().
Vaihe 5: poista
1 .remove();
.remove() leikkaa elementin kokonaan pois DOM-puusta, mukaan lukien tapahtumankäsittelijät ja jQuery-datan. Jos haluat vain piilottaa (mahdollisuudella palauttaa), käytä .hide()- tai .detach()-metodia. Mutta tehtävään "poista merkki pysyvästi" käy vain .remove().
Järjestyksellä on väliä: ensin poistamme viereisen spanin (ensimmäinen ketju), vasta sitten itse lohkon (toinen). Jos poistamme lohkon ensin, viereinen span menettää kontekstinsa, .next() toimii eri elementistä tai palauttaa tyhjän kokoelman.
Laajennettu esimerkki: kirjainkoosta riippumaton haku
Oikeassa projektissa tunnisteen teksti voi tulla eri kirjainkoossa: featured, Featured, FEATURED. Tavallinen :contains() ei käsittele tätä. Ratkaisu on .filter()-metodiin perustuva mukautettu valitsin:
1 $('span.tg-cats-holder').each(function() { 2 $(this).find('span.tg-item-term').filter(function() { 3 return $(this).text().toLowerCase().indexOf('featured') !== -1; 4 }).closest('a.product_visibility').each(function() { 5 $(this).next('span:contains(",")').remove(); 6 $(this).remove(); 7 }); 8 });
Tässä .filter() takaisinkutsufunktiolla tarkistaa jokaisen ehdokkaan tekstin pienaakkosin. Rivejä on hieman enemmän, mutta skripti ei ole riippuvainen siitä, miten teksti tarkalleen syötettiin hallintapaneelissa.
Vaihtoehto puhtaalla JavaScriptillä
Jos jQueryä ei käytetä projektissa lainkaan, sama logiikka kirjoitetaan vanilla JS:llä:
1 document.querySelectorAll('span.tg-cats-holder').forEach(function(holder) { 2 holder.querySelectorAll('span.tg-item-term').forEach(function(term) { 3 if (term.textContent.includes('featured')) { 4 const link = term.closest('a.product_visibility'); 5 const nextSpan = link.nextElementSibling; 6 if (nextSpan && nextSpan.matches('span') && nextSpan.textContent.includes(',')) { 7 nextSpan.remove(); 8 } 9 link.remove(); 10 } 11 }); 12 });
Sama algoritmi: holdereiden iterointi → tekstihaku .textContent.includes()-metodilla → yläelementtiin kiipeäminen natiivilla .closest()-metodilla → viereisen elementin tarkistus ja poisto → lohkon poisto. Natiivitoteutus on pidempi, mutta ei vedä jQuery-riippuvuutta mukanaan.
Lyhyt video aiheesta, :contains()-valitsimen ja navigointiketjujen erittely jQueryllä:
⁉️🤔 Usein kysytyt kysymykset
Miksi :contains() ei löydä tekstiä, jonka näen sivulla?
Todennäköisesti ongelma on kirjainkoossa tai välilyönneissä.
:contains("Featured")ei löydä tekstiä "featured", tämä on kirjainkoosta riippuvainen valitsin. Lisäksi selain saattaa normalisoida välilyönnit HTML:n sisällä eri tavalla kuin odotat. Tarkista tarkka sisältö komennollaconsole.log($('selector').text())ja kopioi merkkijono sellaisenaan:contains()-valitsimeen.
Voiko .closest() jättää pois ja käyttää kiinteää ketjua .parent().parent()?
Teknisesti kyllä. Käytännössä ei suositella. Kova ketju
.parent().parent()hajoaa heti, jos sisäkkäisyys muuttuu: lisättiin kääre, vaihdettiin teemaa, skripti lakkasi toimimasta..closest('a.product_visibility')on joustavampi: se etsii lähimmän vastaavan elementin miltä tahansa ylemmältä tasolta. Kirjoitetaan kerran, toimii rakenteesta riippumatta.
Skripti poistaa väärän spanin. Miten debuggaan?
Ensimmäinen askel: lisää
console.log()ennen jokaista.remove()-kutsua ja tarkista, mitä valintaan tarkalleen päätyy. Toiseksi: tarkenna.next()-valitsinta. Ilman suodatinta.next()ottaa minkä tahansa seuraavan elementin samalta tasolta, vaikka se olisi toinen<a>tai<div>. Lisääspan:contains(",")tai tarkempi luokka ja varmista, että viereinen elementti on todella oikea.
Pitääkö skripti kääriä jQuery(document).ready() -rakenteeseen?
Kyllä, jos skripti on
<head>-osiossa tai liitetään ennen DOM-puun renderöintiä.jQuery(document).ready(function($){ ... })-rakenne takaa, että koodi suoritetaan vasta DOM-puun täydellisen latautumisen jälkeen. Lisäksi$välitetään eksplisiittisesti takaisinkutsuun, mikä suojaa ristiriidoilta muiden kirjastojen kanssa, jotka saattavat myös vaatia$-merkkiä. Jos skripti on footerissa kaikkien elementtien jälkeen,.ready()ei ole muodollisesti pakollinen, mutta "aina käärimisen" kurinalaisuus säästää vaikeasti löydettäviltä bugeilta refaktoroinnin yhteydessä.
Kumpi on nopeampi: jQuery vai vanilla JS tällaiseen tehtävään?
Natiivi JavaScript voittaa kylmäkäynnistyksessä: ei tarvitse ladata, jäsentää ja kääntää jQueryä, ja tämä säästää kymmeniä kilotavuja liikennettä ja useita millisekunteja jäsennysaikaa. DOM-operaatioissa ero on vaatimattomampi, puhutaan millisekunnin murto-osista kutsua kohden. Tyypillisellä WordPress-sivustolla, jossa jQuery on jo teeman tai lisäosien puolesta käytössä, eroa ei huomaa, nelirivinen skriptisi ei muodostu pullonkaulaksi. Jos jQuery on jo projektissa, kirjoita jQueryllä, koodi on kompaktimpaa ja luettavampaa. Jos ei, ota vanilla JS, älä raahaa kirjastoa yhden käsittelijän takia.
Kannattaako jQueryä käyttää tekstihakuun vuonna 2026?
jQuery ei ole kadonnut minnekään. W3Techs-tilastojen mukaan kesäkuussa 2026 kirjasto on asennettuna 87,3%:lla sivustoista, joilla on tunnettu JavaScript-kirjasto (68,1% kaikista sivustoista), pääasiassa WordPressin ansiosta, jossa jQuery on ytimessä ja teemat ottavat sen automaattisesti käyttöön. WordPress-kehittäjälle jQuery on natiivi työkalu, joka on jo ladattu eikä aiheuta ylimääräisiä pyyntöjä.
Suorat vaihtoehdot, kuten Alpine.js tai HTMX, ratkaisevat eri tehtäviä (reaktiivisuus, osittaiset päivitykset) ja ovat ylimitoitettuja kertaluonteiseen DOM-skriptiin. Natiivi querySelectorAll + closest() + remove() on toimiva vaihtoehto ilman riippuvuuksia, mutta kutsuketjut pitenevät. Valinta kiteytyy yksinkertaiseen sääntöön: jQuery on jo projektissa, ota jQuery; projektissa ei ole jQueryä, ota vanilla JS.
Pääasia on, että tiedät nyt tarkan mekaniikan yhdistelmälle :contains() + .closest() + .next() + .remove(), ja millä murteella se kirjoitetaan, sen ratkaisee kulloinenkin projekti.



