
🔍 JQuery: hur man hittar ett element med specifik text
En utvecklare skapar en produktkortslayout i WooCommerce. Allt går enligt plan tills en uppgift kommer från adminpanelen: "ta bort märket Utvald och kommatecknet efter det, men bara för produkter inom hållarkategorin." Manuell hantering är inget alternativ, det finns hundratals produkter. Vi behöver ett skript som själv hittar blocket med texten "featured", når föräldern, hämtar det intilliggande span-elementet och tar bort hela konstruktionen.
Och det är här jQuery kommer in i bilden med sina kedjor: .each() för iteration, .find() för sökning, :contains() för filtrering efter text, .closest() för att klättra till föräldern, .next() för att flytta till grannen och .remove() för städning. Fem metoder, och uppgiften löses på fyra rader. Nedan bryter jag ner varje steg: från selektorn till den slutliga städningen, och förklarar logiken och fallgroparna.
💡 Snabb översikt:
- Först hittar vi målblocket med text via contains-selektorn och klättrar till dess förälder via closest
- Sedan flyttar vi till det intilliggande elementet via next och tar bort båda blocken exakt via remove
- Till sist felsöker vi skriptet och analyserar typiska fel med kontextförlust och girig next
Uppgift: vad vi letar efter och vad vi tar bort
Den ursprungliga HTML-strukturen ser ut ungefär så här:
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>
Huvudmålet är att hitta <span class="tg-item-term"> som innehåller texten featured, klättra till föräldern <a class="product_visibility">, sedan flytta till nästa <span> (med kommatecknet) och ta bort det. Därefter tar vi bort <a class="product_visibility"> med själva märket. Andra etiketter (rea, etc.) förblir orörda.
Färdigt skript
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 });
Koden är medvetet uppdelad i två kedjor istället för att slås ihop till en. Anledningen är enkel: efter .remove() av ett element bryts kedjan, det finns ingenstans att gå vidare. Så först rensar vi det intilliggande span-elementet med kommatecknet (första kedjan), sedan tar vi bort själva blocket (andra).
Steg-för-steg-genomgång
Steg 1: gå in i varje hållare
1 $('span.tg-cats-holder').each(function() {
Metoden .each() går igenom varje element i samlingen, i vårt fall alla <span class="tg-cats-holder"> på sidan. Om det finns flera hållare (olika produktkategorier) kommer skriptet att arbeta i var och en oberoende. Inuti callback-funktionen pekar this på den aktuella hållaren, all vidare sökning utgår från den.
Steg 2: sök efter blocket med text via:contains()
1 .find('span.tg-item-term:contains("featured")')
Selektorn :contains("featured") hittar ett element inuti vilket (inklusive barnnoder) det finns delsträngen "featured". Tre viktiga nyanser:
Skiftlägeskänslighet. Strängarna "Featured", "FEATURED" och "featured" är olika. Om märket är skrivet annorlunda i adminpanelen, lägg till en kontroll via
.filter()med.toLowerCase(), exempel i FAQ-avsnittet.Sökning genom alla avkomlingar.
:contains()kontrollerar textinnehållet i både själva elementet och alla dess barn. Om det finns ett annat<strong>inuti<span class="tg-item-term">, räknas texten inuti det också.**Detta är inte en prestandaselektor.
:contains()accelereras inte av inbyggdquerySelectorAll, jQuery går igenom alla kandidater och läser.textContent. För sidor med hundratals element är det bättre att begränsa urvalet med en extra klass eller attribut.
Metoden .find() begränsar sökningen till avkomlingar till den aktuella hållaren, inte hela sidan, detta ger både en hastighetsökning och skydd mot falska träffar.
Steg 3: klättra till föräldern via.closest()
1 .closest('a.product_visibility')
.closest() går uppåt i trädet från det hittade elementet och returnerar den närmaste förfadern som matchar selektorn. Till skillnad från .parent() är den inte begränsad till en nivå, den klättrar ända upp till <html> tills den hittar en matchning eller når roten.
Om vi hade tagit .parent() istället för .closest() skulle skriptet brytas vid minsta nästling: <span class="tg-item-term"> → <strong> → <a class="product_visibility">, .parent() skulle returnera <strong>, inte den nödvändiga länken. .closest() försäkrar mot sådana överraskningar.
Steg 4: hoppa till grannen via.next()
1 .next('span:contains(",")')
.next() tar det omedelbart följande syskonelementet med samma förälder. Filtret span:contains(",") garanterar att vi tar exakt span-elementet med kommatecknet, inte vilket efterföljande element som helst. Utan filtret skulle .next() ta den första tillgängliga syskonnoden, till exempel ett annat <a class="product_visibility"> med nästa etikett.
Skillnaden mellan .next() och .nextAll(): den första tar exakt ett element, den andra tar alla efterföljande syskon. Här behöver vi en precis träff, så .next().
Steg 5: ta bort
1 .remove();
.remove() klipper ut elementet ur DOM helt, tillsammans med händelsehanterare och jQuery-data. Om du bara behöver dölja (med möjlighet att återställa), använd .hide() eller .detach(). Men för uppgiften "ta bort märket för alltid" är det bara .remove() som gäller.
Ordningen spelar roll: först tar vi bort det intilliggande span-elementet (första kedjan), först därefter själva blocket (andra). Om vi tar bort blocket först förlorar det intilliggande span-elementet sin kontext, .next() kommer att arbeta från ett annat element eller returnera en tom samling.
Utökat exempel: skiftlägesokänslig sökning
I ett verkligt projekt kan etiketttexten förekomma med olika skiftläge: featured, Featured, FEATURED. Standard :contains() hanterar inte detta. Lösningen är en anpassad selektor baserad 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 });
Här kontrollerar .filter() med en callback-funktion den gemena texten för varje kandidat. Det blir något fler rader, men skriptet är inte beroende av exakt hur texten matades in i adminpanelen.
Alternativ i ren JavaScript
Om jQuery inte används alls i projektet skrivs samma logik i vanilla JS:
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 });
Samma algoritm: iterera hållare → söka efter text via .textContent.includes() → klättra till förälder via inbyggd .closest() → kontrollera och ta bort granne → ta bort block. Den inbyggda implementationen är längre men drar inte in ett jQuery-beroende.
Kort video om ämnet, genomgång av :contains() och navigeringskedjor i jQuery:
⁉️🤔 Vanliga frågor
Varför hittar inte :contains() text som jag ser på sidan?
Troligtvis ligger problemet i skiftläge eller mellanslag.
:contains("Featured")hittar inte "featured", detta är en skiftlägeskänslig selektor. Dessutom kan webbläsaren normalisera mellanslag inuti HTML på ett sätt du inte förväntar dig. Kontrollera det exakta innehållet viaconsole.log($('selector').text())och kopiera strängen exakt till:contains().
Kan vi klara oss utan .closest() och använda en fast kedja .parent().parent()?
Tekniskt sett, ja. Praktiskt sett, rekommenderas det inte. En hård kedja
.parent().parent()bryts vid minsta förändring i nästling: lade till en wrapper, bytte till ett annat tema, skriptet slutade fungera..closest('a.product_visibility')är mer flexibel: den söker efter det närmaste matchande elementet på valfri nivå uppåt. Skrivs en gång, fungerar oavsett struktur.
Skriptet tar bort fel span. Hur felsöker man?
Första steget, lägg in
console.log()före varje.remove()och kontrollera vad som exakt hamnar i urvalet. Andra, förfina selektorn för.next(). Utan filter tar.next()vilket efterföljande element som helst på samma nivå, även om det är ett annat<a>eller<div>. Lägg tillspan:contains(",")eller en mer specifik klass, och verifiera att grannen faktiskt är den rätta.
Behöver jag wrappa skriptet i jQuery(document).ready()?
Ja, om skriptet ligger i
<head>eller ansluts före DOM-rendering. KonstruktionenjQuery(document).ready(function($){ ... })garanterar att koden körs först efter fullständig inläsning av DOM-trädet. Dessutom skickas$explicit in i callbacken, detta försäkrar mot konflikter med andra bibliotek som också kan göra anspråk på$. Om skriptet ligger i sidfoten efter alla element är.ready()formellt sett inte nödvändigt, men disciplinen att "alltid wrappa" räddar dig från svårfångade buggar vid refaktorisering.
Vad är snabbast: jQuery eller vanilla JS för en sådan här uppgift?
Inbyggd JavaScript vinner vid en kallstart: inget behov av att ladda, tolka och kompilera jQuery, och detta sparar tiotals kilobyte trafik och flera millisekunder parsning. Vid DOM-operationer är gapet mer blygsamt, vi pratar om bråkdelar av en millisekund per anrop. För en typisk WordPress-sajt där jQuery redan är anslutet av temat eller plugins är skillnaden omärkbar, ditt fyrradiga skript kommer inte att bli en flaskhals. Om jQuery redan finns i projektet, skriv i jQuery, koden är mer kompakt och läsbar. Om inte, ta vanilla JS, dra inte in ett bibliotek för en enda hanterare.
Är det värt att använda jQuery för textsökning 2026?
jQuery har inte försvunnit någonstans. Enligt W3Techs statistik för juni 2026 är biblioteket installerat på 87,3% av sajter med ett känt JavaScript-bibliotek (68,1% av alla sajter), främst tack vare WordPress, där jQuery finns i kärnan och automatiskt ansluts av teman. För en WordPress-utvecklare är jQuery ett inhemskt verktyg som redan är laddat och inte skapar extra anrop.
Direkta alternativ som Alpine.js eller HTMX löser andra uppgifter (reaktivitet, partiella uppdateringar) och är överdrivna för ett engångs-DOM-skript. Inbyggd querySelectorAll + closest() + remove() är ett fungerande alternativ utan beroenden, men anropskedjorna blir längre. Valet kokar ner till en enkel regel: jQuery finns redan i projektet, ta jQuery; projekt utan jQuery, ta vanilla JS.
Huvudsaken är att du nu kan den exakta mekaniken i kombinationen :contains() + .closest() + .next() + .remove(), och vilken dialekt du ska skriva den i avgörs av det specifika projektet.



