2010-02-23 9 views
12

Tengo problemas para entender lo que debería ser una solución simple. Quiero reemplazar el texto dentro de una etiqueta etiquetada, sin afectar a los otros "hermanos", si existen.jQuery reemplazar texto dejando intactos a los hermanos

de marcado de la muestra:

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

Objetivo:

  • para sustituir el texto Some Label X con Some Label (es decir, eliminar X desde el texto de la etiqueta).
  • Las etiquetas de span dentro de la etiqueta deben permanecer intactas si existen, como el <span class="marker"> anterior.
  • No sé el valor de X, que podría tener 1 o más caracteres de longitud.

guión actual:

Mi script jQuery a continuación las obras, pero sé que es muy ineficiente. Parece que no puedo envolver mi cabeza alrededor de éste por alguna razón ...

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

    } 

}); 

que pensé al principio yo podría simplemente hacer:

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

Pero esto borra todo el contenido de la etiqueta y por lo tanto, elimina el lapso, que no quiero. No puedo usar ninguna función de reemplazo para reemplazar Some Label X con Some Label porque no sé qué será X.

¿Alguien puede sugerir un enfoque más elegante/eficiente para este problema?

Gracias.

EDITAR

Después de probar varias respuestas, creo que el problema parece ser que incluso si selecciono el derecho de cobro, que son los nodos de texto, que jQuery no parece querer modificar .. I He usado FireBug para seleccionar la colección (muchas respuestas debajo de todas seleccionan correctamente pero de maneras ligeramente diferentes). En la consola de Firebug conjunto resultante es:

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

El problema parece ser que llamar .replaceWith(), .replace(), .text(), no parece etc. afectar la colección de jQuery. Si permito que la colección anterior para contener uno de los tramos, a continuación, llamar .replaceWith(), .replace(), etc funciones correctamente contra la luz, pero los nodos de texto quede tal cual ..

+1

Will 'x' nunca se va a envolver en su propia etiqueta, o va a ser siempre de texto sin formato? –

+0

Texto plano de Allways, nunca dentro de otra etiqueta. –

Respuesta

10

Probar:

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

Esto debería funcionar suponiendo que el texto que se va a reemplazar siempre estará al final. La función contents() selecciona todos los nodos, incluidos los nodos de texto.

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

Edit: Debo tener filtro utilizado() en lugar de find().Corregido

EDITAR: Funciona ahora. Aquí hay una manera.

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

Gracias por la sugerencia. Encontré un problema, en el que '.contents(). Filter (': last')' devuelve solo el último elemento de la colección completa, donde la colección de contenido contiene muchos nodos de texto de etiqueta. Además, .text() aplicado a estos nodos no parece tener efecto ... –

+0

Pero si lo está llamando en una etiqueta, 'contents()' solo debe devolver el contenido de esa etiqueta. En lo que concierne a 'text()', debería poder simplemente 'eliminar()' ese nodo de texto, y 'agregar()' texto nuevo. – user113716

+0

Ya veo. Apuesto que se necesita 'último hijo'. – user113716

7

como Patrick señala, puede utilizar contents() para seleccionar el texto por sí solo, y luego hacer un reemplazo de todo. Adaptar el ejemplo dado allí, también podría intentar:

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

Sin embargo, si usted sabe que "alguna etiqueta" será siempre el último elemento de la <label> entonces el método de Patrick será más rápido que yo creo.

+0

Lo más extraño. Encuentra la colección de nodos, pero la llamada '.replaceWith (" Some Label ") ;, en realidad borra todos los valores del nodo de texto (los textos de las etiquetas se vuelven vacíos, los intervalos permanecen intactos) ... –

+0

@KP; Lo he actualizado: usar 'is()' en la condición de filtro te permite tener múltiples nodos de texto y solo cambiar el que contiene "Some Label" ... avísame si esto no soluciona el problema –

+0

@KP, usé esto en IE y funcionó bien (antes del cambio de filtro .is). Alternativamente, siempre puede regresar a POJ y llamar ... nodeType == 3) .each (function() {$ (this) [0] .data = "Some Label";}); – Marc

2

¿Por qué no hacer simplemente un reemplazo completo utilizando expresiones regulares?

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

No es una mala idea. El reemplazo no está funcionando sin embargo? '.replace ("/Some Label ./ "," Some Label "))' no coincide con el texto. Me aseguré de que el selector global '$ (". Etiqueta myFieldsetClass: contains ('Some Label') ")' capte los elementos deseados. –

+0

+1 para una buena idea usar regex. El patrón no coincide y la expresión regular no es mi fuerza, así que elegí una respuesta diferente. –

0

Una sola línea:

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