Как изменить текст элемента без изменения его дочерних элементов?

Я хочу динамически обновлять текст элемента:

<div>
   **text to change**
   <someChild>
       text that should not change
   </someChild>
   <someChild>
       text that should not change
   </someChild>
</div>

Я новичок в jQuery, поэтому эта задача кажется для меня довольно сложной задачей. Может ли кто-нибудь указать мне на функцию/селектор, чтобы использовать?

Если это возможно, я бы хотел сделать это, не добавляя новый контейнер для текста, который мне нужно изменить.

Ответ 1

Знаки получили лучшее решение с использованием jQuery, но вы также можете сделать это и в обычном JavaScript.

В Javascript свойство childNodes предоставляет вам все дочерние узлы элемента, включая текстовые узлы.

Итак, если вы знали, что текст, который вы хотите изменить, всегда будет первым элементом в элементе, а затем дается, например, этот HTML:

<div id="your_div">
   **text to change**
   <p>
       text that should not change
   </p>
   <p>
       text that should not change
   </p>
</div>

Вы можете сделать это:

var your_div = document.getElementById('your_div');

var text_to_change = your_div.childNodes[0];

text_to_change.nodeValue = 'new text';

Конечно, вы все равно можете использовать jQuery для выбора <div> в первую очередь (т.е. var your_div = $('your_div').get(0);).

Ответ 2

Обновление 2018

Поскольку это довольно популярный ответ, я решил немного обновить и украсить его, добавив селектор textnode в jQuery в качестве плагина.

В приведенном ниже фрагменте вы можете видеть, что я определяю новую функцию jQuery, которая получает все (и только) textNodes. Вы можете также связать эту функцию с помощью функции first(). Я делаю обрезку текстового узла и проверяю, не пуст ли он после обрезки, потому что пробелы, табуляции, новые строки и т.д. Также распознаются как текстовые узлы. Если вам тоже нужны эти узлы, просто удалите это из оператора if в функции jQuery.

Я добавил пример, как заменить первый текстовый узел и как заменить все текстовые узлы.

Такой подход облегчает чтение кода и позволяет использовать его несколько раз и для разных целей.

Обновление 2017 года (adrach) также должно работать, если вы предпочитаете это.

jQuery.fn.textNodes = function() {
  return this.contents().filter(function() {
    return (this.nodeType === Node.TEXT_NODE && this.nodeValue.trim() !== "");
  });
}

$(document).ready(function(){
  $('#replaceAll').on('click', function() {
    $('#testSubject').textNodes().replaceWith('Replaced');
  });

  $('#replaceFirst').on('click', function() {
    $('#testSubject').textNodes().first().replaceWith('Replaced First');
  });
});
p {
  margin: 0px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="testSubject">
   **text to change**
   <p>text that should not change</p>
   <p>text that should not change</p>
   **also text to change**
   <p>text that should not change</p>
   <p>text that should not change</p>
   **last text to change**
</div>
<button id="replaceFirst">Replace First</button>
<button id="replaceAll">Replace All</button>

Ответ 3

См. В действии

Разметка:

$(function() {
  $('input[type=button]').one('click', function() {
    var cache = $('#parent').children();
    $('#parent').text('Altered Text').append(cache);
  });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">Some text
  <div>Child1</div>
  <div>Child2</div>
  <div>Child3</div>
  <div>Child4</div>
</div>
<input type="button" value="alter text" />

Ответ 4

<div id="divtochange">
    **text to change**
    <div>text that should not change</div>
    <div>text that should not change</div>
</div>
$(document).ready(function() {
    $("#divtochange").contents().filter(function() {
            return this.nodeType == 3;
        })
        .replaceWith("changed text");
});

Это изменяет только первый текстовый индекс

Ответ 5

Просто оберните текст, который вы хотите изменить, в диапазоне с выбранным классом.

Не обязательно отвечать на ваш вопрос, который я знаю, но, вероятно, лучше практика кодирования. Держите вещи чистыми и простыми

<div id="header">
   <span class="my-text">**text to change**</span>
   <div>
       text that should not change
   </div>
   <div>
       text that should not change
   </div>
</div>

Вуаля!

$('#header .mytext').text('New text here')

Ответ 6

В данном конкретном случае вы упомянули:

<div id="foo">
   **text to change**
   <someChild>
       text that should not change
   </someChild>
   <someChild>
       text that should not change
   </someChild>
</div>

... это очень просто:

var div = document.getElementById("foo");
div.firstChild.data = "New text";

Вы не указываете, как вы хотите обобщить это. Если, скажем, вы хотите изменить текст первого текста node в <div>, вы можете сделать что-то вроде этого:

var child = div.firstChild;
while (child) {
    if (child.nodeType == 3) {
        child.data = "New text";
        break;
    }
    child = child.nextSibling;
}

Ответ 7

$.fn.textPreserveChildren = function(text) {
  return this.each(function() {
    return $(this).contents().filter(function() {
      return this.nodeType == 3;
    }).first().replaceWith(text);
  })
}

setTimeout(function() {
  $('.target').textPreserveChildren('Modified');
}, 2000);
.blue {
  background: #77f;
}
.green {
  background: #7f7;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>

<div class="target blue">Outer text
  <div>Nested element</div>
</div>

<div class="target green">Another outer text
  <div>Another nested element</div>
</div>

Ответ 8

Вот еще один метод: http://jsfiddle.net/qYUBp/7/

HTML

<div id="header">
   **text to change**
   <div>
       text that should not change
   </div>
   <div>
       text that should not change
   </div>
</div>

JQuery

var tmp=$("#header>div").html();
$("#header").text("its thursday").append(tmp);

Ответ 9

Здесь много замечательных ответов, но они обрабатывают только один текстовый узел с детьми. В моем случае мне нужно было работать на всех текстовых узлах и игнорировать html файлы, НО СОХРАНЯТЬ ЗАКАЗ.

Поэтому, если у нас есть такой случай:

<div id="parent"> Some text
    <div>Child1</div>
    <div>Child2</div>
    and some other text
    <div>Child3</div>
    <div>Child4</div>
    and here we are again
</div>

Мы можем использовать следующий код для изменения только текста и СОХРАНЕНИЯ ЗАКАЗА

    $('#parent').contents().filter(function() {
        return this.nodeType == Node.TEXT_NODE && this.nodeValue.trim() != '';
    }).each(function() {
    		//You can ignore the span class info I added for my particular application.
        $(this).replaceWith(this.nodeValue.replace(/(\w+)/g,"<span class='IIIclassIII$1' onclick='_mc(this)' onmouseover='_mr(this);' onmouseout='_mt(this);'>$1X</span>"));
	});
<script src="https://code.jquery.com/jquery-3.0.0.min.js"></script>
<div id="parent"> Some text
    <div>Child1</div>
    <div>Child2</div>
    and some other text
    <div>Child3</div>
    <div>Child4</div>
    and here we are again
</div>

Ответ 10

Я думаю, что вы ищете .prependTo().

http://api.jquery.com/prependTo/

Мы также можем выбрать элемент на страницы и вставьте ее в другую:

$( 'h2') prependTo ($ ( 'контейнер.'));.

Если элемент, выбранный таким образом, вставлен в другое место, он будет перемещен в цель (не клонировано):

<div class="container">  
  <h2>Greetings</h2>
  <div class="inner">Hello</div>
  <div class="inner">Goodbye</div> 
</div>

Если существует более одной цели элемент, однако, клонированные копии вставленный элемент будет создан для каждая цель после первого.

Ответ 11

Простой ответ:

$("div").contents().filter(function(){ 
  return this.nodeType == 3; 
})[0].nodeValue = "The text you want to replace with"

Ответ 12

Проблема с ответом Марка заключается в том, что вы также получаете пустые текстовые поля. Решение как плагин jQuery:

$.fn.textnodes = function () {
    return this.contents().filter(function (i,n) {
        return n.nodeType == 3 && n.textContent.trim() !== "";
    });
};

$("div").textnodes()[0] = "changed text";

Ответ 13

Это старый вопрос, но вы можете сделать простую функцию, подобную этой, чтобы сделать вашу жизнь проще:

$.fn.toText = function(str) {
    var cache = this.children();
    this.text(str).append(cache);
}

Пример:

<div id="my-div">
   **text to change**
   <p>
       text that should not change
   </p>
   <p>
       text that should not change
   </p>
</div>

Использование:

$("#my-div").toText("helloworld");

Ответ 14

2019 vesrsion - Короткая и короткая версия Простой

document.querySelector('#your-div-id').childNodes[0].nodeValue = 'new text';

Объяснение

document.querySelector('#your-div-id') используется для выбора родителя (элемент, текст которого вы собираетесь изменить)

.childNodes[0] выбирает текстовый узел

.nodeValue = 'new text' устанавливает значение текстового узла в "новый текст"


Этот ответ, возможно, вдохновлен комментарием Дина Мартина. Не могу сказать наверняка, так как я использую это решение в течение многих лет. Просто подумал, что я должен опубликовать эту вероятность здесь, потому что некоторые люди заботятся об этом больше, чем тот факт, что это лучшее решение.