2010-02-23 4 views
12

Ich habe Probleme, meinen Kopf einzuwickeln, was eine einfache Lösung sein sollte. Ich möchte Text innerhalb eines Label-Tags ersetzen, ohne die anderen "Geschwister" zu beeinflussen, falls sie existieren.jQuery Text ersetzen, Geschwister intakt lassen

Beispiel Markup:

<fieldset class="myFieldsetClass"> 
    <legend>Sample Fieldset</legend> 
    <ol> 
     <li> 
      <label> 
       <span class="marker">*</span> 
       Some Label 1 
      </label> 
     </li> 
     <li> 
      <label> 
       Some Label 2 
      </label> 
     </li> 
     <li> 
      <label> 
       Text that doesn't match... 
      </label> 
     </li> 
    </ol> 
</fieldset> 

Ziel:

  • Um Text Some Label X mit Some Label zu ersetzen (d entfernen X aus dem Label-Text).
  • span Tags innerhalb des Labels müssen intakt bleiben, wenn sie existieren, wie zum Beispiel <span class="marker"> oben.
  • Ich kenne nicht den Wert X, der 1 oder mehr Zeichen lang sein könnte.

Aktuelles Skript:

Mein jQuery Skript unten funktioniert, aber ich weiß, ist sehr ineffizient. Ich kann meinen Kopf nicht scheinen aus irgendeinem Grund um dieses zu wickeln ...

//for each label in the fieldset that contains text "Some Label " 
$(".myFieldsetClass label:contains('Some Label ')").each(function() { 

    if ($(this).has("span").length > 0) { 

     //if the label has the span tag within, remove it and prepend it back to the replaced text 
     $(this).find("span").remove().prependTo($(this).text(labelText)); 

    } 
    else { 

     //otherwise just replace the text 
     $(this).text('Some Label'); 

    } 

}); 

ich zuerst dachte ich einfach tun könnte:

$(".myFieldsetClass label:contains('Some Label ')").text("Some Label"); 

Aber dies löscht alle Inhalte des Etiketts und Entfernt daher die Spannweite, die ich nicht möchte. Ich kann keine Ersatzfunktionen verwenden, um Some Label X durch Some Label zu ersetzen, weil ich nicht weiß, was X sein wird.

Kann jemand einen eleganteren/effizienteren Zugang zu diesem Problem vorschlagen?

Danke.

EDIT

Nach mehreren Antworten versuchen, ich denke, das Problem, dass auch zu sein scheint, wenn ich die richtige Sammlung auswählen, sie sind Textknoten, die jquery ich nicht ändern zu wollen, scheint .. habe FireBug verwendet, um die Sammlung auszuwählen (viele Antworten unter allen wählen korrekt, aber auf etwas unterschiedliche Weise). In Firebug Konsole resultierenden Satz ist:

[<TextNode textContent="Some Label 1:">, 
<TextNode textContent="Some Label 2:">, 
<TextNode textContent="Some Label 3:">, 
<TextNode textContent="Some Label 4:">, 
<TextNode textContent="Some Label 5:">] 

Das Problem scheint, dass Aufruf .replaceWith() zu sein, .replace(), .text() usw. scheint nicht die jquery Sammlung zu beeinflussen. Wenn ich erlaube die obige Sammlung eine der Spannweiten zu enthalten, dann ruft .replaceWith(), .replace(), etc Funktionen korrekt gegen die Spanne, aber die Textknoten bleiben wie es ist ..

+1

Wird 'X' jemals in seinem eigenen Tag enthalten sein, oder wird es immer einfacher Text sein? –

+0

Immer reiner Text, niemals in einem anderen Tag. –

Antwort

10

Versuchen:

$(".myFieldsetClass label:contains('Some Label ')").contents().filter(':last-child').text("Some Label"); 

Dies sollte funktionieren, vorausgesetzt, der zu ersetzende Text wird immer am Ende sein. Die contents() Funktion wählt alle Knoten aus, einschließlich Textknoten.

http://api.jquery.com/contents/

EDIT: Ich sollte verwendet Filter haben() anstelle von find().Korrigiert.

EDIT: Funktioniert jetzt. Hier ist ein Weg.

// Store proper labels in a variable for quick and accurate reference 
var $labelCollection = $(".myFieldsetClass label:contains('Some Label ')"); 

// Call contents(), grab the last one and remove() it 
$labelCollection.each(function() { 
    $(this).contents().last().remove() 
}); 

// Then simply append() to the label whatever text you wanted. 
$labelCollection.append('some text') 
+0

Danke für den Vorschlag. Ich fand ein Problem darin, dass '.contents(). Filter (': last')' gibt nur das letzte Element in der gesamten Sammlung zurück, wobei die Inhaltssammlung viele Etiketttextknoten enthält. Darüber hinaus scheint .text(), das auf diese Knoten angewendet wird, nicht zu wirken ... –

+0

Aber wenn Sie es auf einem Label aufrufen, sollte 'contents()' nur den Inhalt dieses Labels zurückgeben. Soweit es 'text()' betrifft, sollten Sie in der Lage sein, einfach() 'diesen Textknoten zu entfernen und()' neuen Text anzuhängen(). – user113716

+0

Ich verstehe. Ich wette, 'Last-Child' wird benötigt. – user113716

7

als Patrick weist darauf hin, können Sie contents() verwenden Sie den Text allein zu wählen, und dann ein alles auf sie ersetzen tun. Anpassen des Beispiels dort gegeben, könnte man auch versuchen:

$(".myFieldsetClass label:contains('Some Label ')").contents().filter(function() { 
    return this.nodeType == 3 && $(this).is(":contains('Some Label ')"); 
}) 
.replaceWith("Some Label"); 

Wenn Sie jedoch wissen, dass „einige Etikett“ wird immer das letzte Element sein in der <label> dann Patrick Methode wird schneller, glaube ich.

+0

Ok komischste Sache. Es findet die Sammlung von Knoten, aber der '.replaceWith (" Einige Label ");" Aufruf löscht tatsächlich alle Werte des Textknotens (Beschriftentexte werden leer, Spannen bleiben intakt) ... –

+0

@KP; Ich habe es aktualisiert - mit 'is()' in der Filterbedingung können Sie mehrere Textknoten haben und ändern nur die, die "Einige Label" enthält ... lassen Sie mich wissen, wenn das Problem nicht behoben –

+0

@KP, verwendet dies in IE und es hat gut funktioniert (vor dem .is Filterwechsel). Alternativ können Sie immer zu POJ zurückkehren und ... nodeType == 3) .each (function() {$ (this) [0] .data = "Some Label";}); – Marc

2

Warum nicht einfach eine ganze ersetzen mit Regex?

$(".myFieldsetClass label:contains('Some Label ')") 
    .each(function() { 
      $(this).html($(this).html().replace(/Some Label ./, "Some Label")); 
     }); 
+0

Keine schlechte Idee. Die Ersetzung funktioniert nicht? '.replace ("/Some Label ./ "," Irgendein Label "))' stimmt nicht mit dem Text überein. Ich stellte sicher, dass der gesamte Selektor '$ (". MyFieldsetClass label: contains ('Some Label') ")' die gewünschten Elemente ergreift. –

+0

+1 für eine gute Idee, Regex zu verwenden. Muster stimmte nicht überein und Regex ist nicht meine Stärke, also wählte ich eine andere Antwort. –

0

Ein Einzeiler:

$('.myFieldsetClass label').contents().last().remove().end().first().after('New Label')