Подтвердить что ты не робот

JQuery заменить текст, оставляя братьев и сестер неповрежденными

У меня возникли проблемы, обертывая голову вокруг того, что должно быть простым решением. Я хочу заменить текст в теге метки, не затрагивая других "братьев и сестер", если они существуют.

Разметка образца:

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

Цель:

  • Чтобы заменить текст Some Label X на Some Label (I.e. remove X из текста метки). Теги
  • span внутри метки должны оставаться неповрежденными, если они существуют, например, <span class="marker"> выше.
  • Я не знаю значения X, длина которого может быть 1 или более символов.

Текущий Script:

Мой jQuery script ниже работает, но я знаю, что он очень неэффективен. Кажется, я не могу обернуть голову вокруг этого по какой-то причине...

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

    }

});  

Сначала я подумал:

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

Но это очищает все содержимое метки и, следовательно, удаляет диапазон, который я не хочу. Я не могу использовать любые функции замены, чтобы заменить Some Label X на Some Label, потому что я не знаю, что будет X.

Может ли кто-нибудь предложить более элегантный/эффективный подход к этой проблеме?

Спасибо.

ИЗМЕНИТЬ

После нескольких ответов я думаю, что проблема в том, что даже если я выбираю нужную коллекцию, это текстовые узлы, которые jquery, похоже, не хотят изменять. Я использовал FireBug для выбора коллекции (многие ответы ниже всех выбираются правильно, но несколько по-разному). В комплекте с консолью firebug:

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

Проблема заключается в том, что вызов .replaceWith(),.replace(),.text() и т.д., похоже, не влияет на коллекцию jquery. Если я разрешаю вышеуказанной коллекции содержать один из пролетов, то вызов функции .replaceWith(),.replace() и т.д. Корректно действует против диапазона, но текстовые узлы остаются такими же, как и..

4b9b3361

Ответ 1

Try:

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

Это должно работать, предполагая, что текст, который будет заменен, всегда будет в конце. Функция contents() выбирает все узлы, включая текстовые узлы.

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

EDIT: я должен использовать filter() вместо find(). Исправлено.

EDIT: работает сейчас. Здесь один путь.

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

Ответ 2

Как указывает Патрик, вы можете использовать contents(), чтобы выбрать текст самостоятельно, а затем выполнить замену на нем. Адаптируя приведенный здесь пример, вы также можете попробовать:

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

Однако, если вы знаете, что "Some Label" всегда будет последним элементом в <label>, тогда метод patrick будет быстрее, я верю.

Ответ 3

Почему бы просто не просто выполнить замену с помощью регулярного выражения?

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

Ответ 4

Однострочный:

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