2010-02-23 3 views
12

Ho problemi a capire cosa dovrebbe essere una soluzione semplice. Voglio sostituire il testo all'interno di un tag etichetta, senza intaccare gli altri "fratelli", se esistono.jQuery sostituisce il testo lasciando intatti i fratelli

markup Esempio:

<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> 

Calcio:

  • Per sostituire testo Some Label X con Some Label (cioè rimuovere X dal testo etichetta).
  • I tag di estensione all'interno dell'etichetta devono rimanere intatti se esistono, come ad esempio lo <span class="marker"> precedente.
  • Non conosco il valore di X, che può contenere 1 o più caratteri.

Script corrente:

Il mio script jQuery sotto lavori, ma so che è molto inefficiente. Non riesco ad avvolgere la mia testa intorno a questo uno per qualche motivo ...

//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'); 

    } 

}); 

ho pensato in un primo momento si potrebbe semplicemente fare:

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

Ma questo cancella tutto il contenuto dell'etichetta e quindi rimuove lo span, che non voglio. Non posso utilizzare alcuna funzione di sostituzione per sostituire Some Label X con Some Label perché non so cosa sarà X.

Qualcuno può suggerire un approccio più elegante/efficiente a questo problema?

Grazie.

EDIT

Dopo aver provato risposte multiple, penso che il problema sembra essere che, anche se seleziono la raccolta destra, sono i nodi di testo, che jquery non sembra voler modificare .. Ho Ho usato FireBug per selezionare la raccolta (molte risposte sotto tutte selezionate correttamente ma in modi leggermente diversi). In Firebug console risultante set è:

[<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:">] 

Il problema sembra essere che chiama .replaceWith(), .Rimontare(), .text(), ecc non sembra influenzare la raccolta di jQuery. Se permetto la raccolta di cui sopra per contenere una delle campate, quindi chiamando .replaceWith(), .Rimontare(), ecc funzioni correttamente contro l'arco, ma i nodi di testo rimanere così com'è ..

+1

Will 'X' mai essere avvolto nel proprio tag, o intende sempre testo normale? –

+0

Allways plain text, mai all'interno di un altro tag. –

risposta

10

Prova:

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

Questo dovrebbe funzionare supponendo che il testo da sostituire sarà sempre alla fine. La funzione contents() seleziona tutti i nodi, inclusi i nodi di testo.

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

EDIT: avrei dovuto filtro utilizzato() al posto di find().Corretto.

MODIFICA: Funziona ora. Ecco un modo.

// 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

Grazie per il suggerimento. Ho trovato un problema, in quanto '.contents(). Filter (': last')' restituisce solo l'ultimo elemento dell'intera collezione, dove la raccolta dei contenuti contiene molti nodi di testo dell'etichetta. Inoltre, .text() applicato a questi nodi non sembra avere effetto ... –

+0

Ma se lo si chiama su un'etichetta, 'contents()' dovrebbe restituire solo il contenuto di tale etichetta. Per quanto riguarda 'text()', dovresti essere in grado di 'rimuovere()' quel nodo di testo, e 'append()' nuovo testo. – user113716

+0

Vedo. Scommetto che è necessario l'ultimo figlio. – user113716

7

come Patrick fa notare, è possibile utilizzare contents() per selezionare il testo da solo, e poi fare un Sostituisci tutto. Adattamento dell'esempio dato lì, si potrebbe anche provare:

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

Tuttavia, se si sa che "Alcuni Label" sarà sempre l'ultimo elemento della <label> allora il metodo di Patrick sarà più veloce credo.

+0

Ok, la cosa più strana. Trova la collezione di nodi, ma la chiamata '.replaceWith (" Some Label ");" chiama in realtà cancella tutti i valori del nodo di testo (i testi delle etichette diventano vuoti, gli spazi rimangono intatti) ... –

+0

@KP; L'ho aggiornato - usando 'is()' nella condizione di filtro consente di avere più nodi di testo e modificare solo quello che contiene "Some Label" ... fammi sapere se questo non risolve il problema –

+0

@KP, usato questo in IE e ha funzionato bene (pre il cambio del filtro .is). In alternativa, puoi sempre tornare al POJ e chiamare ... nodeType == 3) .each (function() {$ (this) [0] .data = "Some Label";}); – Marc

2

Perché non eseguire semplicemente un'intera sostituzione utilizzando regex?

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

Non è una cattiva idea. La sostituzione non funziona però? '.replace ("/Some Label ./ "," Some Label "))' non corrisponde al testo. Ho assicurato il selettore generale '$ (". Label myFieldsetClass: contains ('Some Label') ")' sta acquisendo gli elementi desiderati. –

+0

+1 per una buona idea di usare regex. Pattern non corrispondente e regex non è la mia forza, quindi ho scelto una risposta diversa .. –

0

una battuta:

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