Skip to content

Alt om WordPress, webutvikling — og mer til

🔍 JQuery: hvordan finne et element med spesifikk tekst

🔍 JQuery: hvordan finne et element med spesifikk tekst

En utvikler lager et produktkort-oppsett i WooCommerce. Alt går etter planen helt til det kommer en oppgave fra administrasjonspanelet: «fjern Utvalgt-merket og kommaet etter det, men bare for produkter innenfor holder-kategorien.» Manuell behandling er ikke et alternativ, det er hundrevis av produkter. Vi trenger et skript som finner blokken med teksten «featured» på egen hånd, når forelderen, tar nabospennet og fjerner hele konstruksjonen.

Og det er her jQuery kommer inn med sine kjeder: .each() for iterasjon, .find() for søk, :contains() for filtrering etter tekst, .closest() for å klatre til forelderen, .next() for å flytte til naboen og .remove() for opprydding. Fem metoder, og oppgaven er løst på fire linjer. Nedenfor bryter jeg ned hvert steg: fra selektoren til den endelige oppryddingen, og forklarer logikken og fallgruvene.

💡 Rask oversikt:

  • Først finner vi målblokken med tekst gjennom contains-selektoren og klatrer til forelderen via closest
  • Så flytter vi til naboelementet via next og fjerner begge blokkene presist via remove
  • Til slutt feilsøker vi skriptet og analyserer typiske feil med konteksttap og grådig next

Oppgave: hva vi ser etter og hva vi fjerner

Den opprinnelige HTML-strukturen ser omtrent slik ut:

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>

Hovedmålet er å finne <span class="tg-item-term"> som inneholder teksten featured, klatre til forelderen <a class="product_visibility">, deretter flytte til neste <span> (med kommaet) og fjerne det. Etter det fjerner du <a class="product_visibility"> med selve merket. Andre etiketter (salg osv.) forblir urørt.

Ferdig skript

1jQuery(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});

Koden er bevisst delt i to kjeder i stedet for å slås sammen til én. Årsaken er enkel: etter .remove() av et element brytes kjeden, det er ingen steder å gå videre. Så først rydder vi opp i nabospennet med kommaet (første kjede), deretter fjerner vi selve blokken (andre).

Steg-for-steg gjennomgang

Steg 1: gå inn i hver holder

1$('span.tg-cats-holder').each(function() {

Metoden .each() går gjennom hvert element i samlingen, i vårt tilfelle gjennom alle <span class="tg-cats-holder"> på siden. Hvis det er flere holdere (ulike produktkategorier), vil skriptet fungere i hver enkelt uavhengig. Inne i callback-funksjonen peker this til den gjeldende holderen, all videre søking går fra den.

Steg 2: søk etter blokken med tekst gjennom:contains()

1.find('span.tg-item-term:contains("featured")')

Selektoren :contains("featured") finner et element der det (inkludert undernoder) finnes delstrengen «featured». Tre viktige nyanser:

  • Skiller mellom store og små bokstaver. Strengene «Featured», «FEATURED» og «featured» er forskjellige. Hvis merket er skrevet annerledes i administrasjonspanelet, legg til en sjekk via .filter() med .toLowerCase(), eksempel i FAQ-delen.

  • Søk gjennom alle etterkommere. :contains() sjekker tekstinnholdet i både selve elementet og alle dets barn. Hvis det er en annen <strong> inni <span class="tg-item-term">, teller teksten inni den også.

  • Dette er ikke en ytelses-selektor. :contains() akselereres ikke av native querySelectorAll, jQuery går gjennom alle kandidater og leser .textContent. For sider med hundrevis av elementer er det bedre å snevre inn utvalget med en ekstra klasse eller attributt.

Metoden .find() begrenser søket til etterkommere av den gjeldende holderen, ikke hele siden, dette gir både et hastighetsløft og beskyttelse mot falske positiver.

Steg 3: klatre til forelderen gjennom.closest()

1.closest('a.product_visibility')

.closest() går opp i treet fra det funnede elementet og returnerer den nærmeste stamfaren som matcher selektoren. I motsetning til .parent() er den ikke begrenset til ett nivå, den vil klatre helt til <html> til den finner en match eller treffer roten.

Hvis vi hadde brukt .parent() i stedet for .closest(), ville skriptet brutt sammen ved enhver nesting: <span class="tg-item-term"><strong><a class="product_visibility">, .parent() ville returnert <strong>, ikke den nødvendige lenken. .closest() sikrer mot slike overraskelser.

Steg 4: hopp til naboen gjennom.next()

1.next('span:contains(",")')

.next() tar det umiddelbart følgende søskenelementet med samme forelder. Filteret span:contains(",") garanterer at vi tar nøyaktig spennet med kommaet, ikke et hvilket som helst følgende element. Uten filteret ville .next() tatt den første tilgjengelige søskennoden, for eksempel en annen <a class="product_visibility"> med neste etikett.

Forskjellen mellom .next() og .nextAll(): den første tar nøyaktig ett element, den andre tar alle påfølgende søsken. Her trenger vi et presist treff, så .next().

Steg 5: fjern

1.remove();

.remove() kutter elementet fra DOM-en fullstendig, sammen med hendelsesbehandlere og jQuery-data. Hvis du bare trenger å skjule (med mulighet for å returnere), bruk .hide() eller .detach(). Men for oppgaven «fjern merket for alltid», kun .remove().

Rekkefølgen har betydning: først fjerner vi nabospennet (første kjede), først deretter selve blokken (andre). Hvis vi fjerner blokken først, vil nabospennet miste kontekst, .next() vil fungere fra et annet element eller returnere en tom samling.

Utvidet eksempel: søk uten hensyn til store/små bokstaver

I et reelt prosjekt kan etiketteksten komme med ulik casing: featured, Featured, FEATURED. Standard :contains() vil ikke håndtere dette. Løsningen er en egendefinert selektor basert på .filter():

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});

Her sjekker .filter() med en callback-funksjon den små bokstav-teksten til hver kandidat. Det er litt flere linjer, men skriptet avhenger ikke av nøyaktig hvordan teksten ble skrevet inn i administrasjonspanelet.

Alternativ i ren JavaScript

Hvis jQuery ikke brukes i prosjektet i det hele tatt, skrives samme logikk i vanilla JS:

1document.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});

Samme algoritme: iterering av holdere → søk etter tekst via .textContent.includes() → klatring til forelder via native .closest() → sjekking og fjerning av nabo → fjerning av blokk. Den native implementasjonen er lengre, men drar ikke inn en jQuery-avhengighet.

Kort video om emnet, gjennomgang av :contains() og navigasjonskjeder i jQuery:

⁉️🤔 Ofte stilte spørsmål

Hvorfor finner ikke :contains() tekst som jeg ser på siden?

Mest sannsynlig ligger problemet i store/små bokstaver eller mellomrom. :contains("Featured") vil ikke finne «featured», dette er en selektor som skiller mellom store og små bokstaver. I tillegg kan nettleseren normalisere mellomrom inne i HTML annerledes enn du forventer. Sjekk det nøyaktige innholdet via console.log($('selector').text()) og kopier strengen én-til-én inn i :contains().

Kan vi klare oss uten .closest() og bruke en fast kjede .parent().parent()?

Teknisk sett, ja. Praktisk sett, ikke anbefalt. En hardkodet kjede .parent().parent() vil bryte sammen ved enhver endring i nesting: la til en wrapper, flyttet til et annet tema, skriptet stoppet. .closest('a.product_visibility') er mer fleksibelt: det søker etter det nærmeste matchende elementet på ethvert nivå oppover. Skrevet én gang, fungerer uavhengig av struktur.

Skriptet fjerner feil span. Hvordan feilsøke?

Første steg, sett inn console.log() før hver .remove() og sjekk hva som nøyaktig havner i utvalget. Andre, forfin selektoren for .next(). Uten filter tar .next() ethvert følgende element på samme nivå, selv om det er en annen <a> eller <div>. Legg til span:contains(",") eller en mer spesifikk klasse, og bekreft at naboen faktisk er den rette.

Må jeg pakke skriptet inn i jQuery(document).ready()?

Ja, hvis skriptet ligger i <head> eller kobles til før DOM-rendring. Konstruksjonen jQuery(document).ready(function($){ ... }) garanterer at koden kjøres først etter fullstendig lasting av DOM-treet. I tillegg sendes $ eksplisitt inn i callbacken, dette sikrer mot konflikter med andre biblioteker som også kan kreve $. Hvis skriptet ligger i footeren etter alle elementer, er .ready() formelt sett ikke påkrevd, men disiplinen med «alltid å pakke inn» sparer for vanskelig fangbare feil under refaktorering.

Hva er raskest: jQuery eller vanilla JS for en slik oppgave?

Native JavaScript vinner på en kaldstart: ikke nødvendig å laste, parse og kompilere jQuery, og dette sparer titalls kilobyte med trafikk og flere millisekunder med parsing. På DOM-operasjoner er gapet mer beskjedent, vi snakker om brøkdeler av et millisekund per kall. For et typisk WordPress-nettsted der jQuery allerede er tilkoblet av temaet eller plugins, er forskjellen umerkbar, ditt firelinjers skript vil ikke bli en flaskehals. Hvis jQuery allerede er i prosjektet, skriv i jQuery, koden er mer kompakt og lesbar. Hvis ikke, ta vanilla JS, ikke dra inn et bibliotek for én handler.

Er det verdt å bruke jQuery for tekstsøk i 2026?

jQuery har ikke forsvunnet. Ifølge W3Techs-statistikk for juni 2026 er biblioteket installert på 87,3% av nettsteder med et kjent JavaScript-bibliotek (68,1% av alle nettsteder), hovedsakelig takket være WordPress, der jQuery er i kjernen og automatisk tilkobles av temaer. For en WordPress-utvikler er jQuery et native verktøy som allerede er lastet og ikke skaper ekstra forespørsler.

Direkte alternativer som Alpine.js eller HTMX løser andre oppgaver (reaktivitet, delvise oppdateringer) og er overdrevne for et engangs DOM-skript. Native querySelectorAll + closest() + remove() er et fungerende alternativ uten avhengigheter, men kallkjedene blir lengre. Valget koker ned til en enkel regel: jQuery er allerede i prosjektet, ta jQuery; prosjekt uten jQuery, ta vanilla JS.

Hovedsaken er at du nå kjenner den nøyaktige mekanikken til kombinasjonen :contains() + .closest() + .next() + .remove(), og hvilken dialekt du skal skrive det i, avgjøres av det spesifikke prosjektet.