Alt öğelerini değiştirmeden bir öğenin metnini nasıl değiştirebilirim?


120

Öğenin metnini dinamik olarak güncellemek istiyorum:

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

JQuery'de yeniyim, bu nedenle bu görev benim için oldukça zor görünüyor. Biri beni kullanmam için bir işlev / seçiciye yönlendirebilir mi?

Mümkünse, değiştirmem gereken metin için yeni bir kap eklemeden yapmak istiyorum.


7
"Mümkünse, değiştirmem gereken metin için yeni bir kapsayıcı eklemeden yapmak isterim." - Gerçekten mi? Çünkü içeride bir konteyner olsaydı çok daha kolay olurdu.
Paul D. Waite

Beyler, orijinal soruya baktım ve OP'nin çocuk unsurları hakkında hiçbir şey söylediğini sanmıyorum ...
Šime Vidas

W3 standartlarına göre div metin düğümlerine bile sahip olamaz (eğer doğru hatırlıyorsam). <p>, <h1> vb. Gibi bir metin kapsayıcı eklenmelidir.
Mark Baijens

2
@Mark: muhtemelen (X) HTML Katı, ancak artık değil. (HTML5 şimdi burada.)
Paul D. Waite

@Matt Ball: Gerçek html'de someChild yerine span etiketleri vardır.
ika

Yanıtlar:


75

Mark , jQuery kullanarak daha iyi bir çözüme sahip , ancak bunu normal JavaScript'te de yapabilirsiniz.

Javascript'te, childNodesözellik size metin düğümleri dahil bir öğenin tüm alt düğümlerini verir.

Öyleyse, değiştirmek istediğiniz metnin her zaman öğedeki ilk şey olacağını biliyorsanız, örneğin şu HTML verilir:

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

Bunu yapabilirsin:

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

var text_to_change = your_div.childNodes[0];

text_to_change.nodeValue = 'new text';

Tabii ki, <div>ilk etapta (yani var your_div = $('your_div').get(0);) seçmek için jQuery'yi kullanabilirsiniz .


1
Metin düğümünü değiştirmeye gerek yok. Sadece mevcut olanı dataveya nodeValuemülkü değiştirin.
Tim Down

@Tim: ah, daha kolay bir yolu olmalı diye düşündüm. JQuery gelmeden önce hiç JavaScript yapmadım. Şerefe, cevabı buna göre düzenleyeceğim.
Paul D. Waite

11
Yani bu cevabın daha güncel bir uygulaması şu olacaktır$('#yourDivId')[0].childNodes[0].nodeValue = 'New Text';
Dean Martin


1
"Bunu normal javascript ile de yapabilirsiniz"
duhaime

65

2018 Güncellemesi

Bu oldukça popüler bir cevap olduğundan, textnode seçiciyi bir eklenti olarak jQuery'ye ekleyerek biraz güncellemeye ve güzelleştirmeye karar verdim.

Aşağıdaki kod parçacığında, tüm (ve yalnızca) textNode'ları alan yeni bir jQuery işlevi tanımladığımı görebilirsiniz. Bu işlevi, örneğin işlevle zincirleyebilirsiniz first(). Metin düğümünde bir kırpma yapıyorum ve kırpmadan sonra boş olup olmadığını kontrol ediyorum çünkü boşluklar, sekmeler, yeni satırlar vb. De metin düğümleri olarak tanınır. Bu düğümlere de ihtiyacınız varsa, jQuery işlevindeki if ifadesinden basitçe kaldırın.

İlk metin düğümünün nasıl değiştirileceğine ve tüm metin düğümlerinin nasıl değiştirileceğine bir örnek ekledim.

Bu yaklaşım, kodu okumayı ve birden çok kez ve farklı amaçlarla kullanmayı kolaylaştırır.

Bunu tercih ederseniz, 2017 Güncellemesi (adrach) yine de iyi çalışacaktır.

JQuery uzantısı olarak

Javascript (ES) eqivilant


2017 Güncellemesi (adrach):

Bu yayınlandıktan sonra birkaç şey değişmiş gibi görünüyor. İşte güncellenmiş bir versiyon

$("div").contents().filter(function(){ return this.nodeType == 3; }).first().replaceWith("change text");

Orijinal cevap (Mevcut sürümler için çalışmıyor)

$("div").contents().filter(function(){ return this.nodeType == 3; })
.filter(':first').text("change text");

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


Aha! Bir yerlerde akıllı bir jQuery işlevi olacağını biliyordum. Yazdığınız çözümle ilgili tek sorun, her metin düğümünün bir sonraki metni almasıdır (örneğin, alt öğelerin içindekiler dahil). Sanırım onu ​​sınırlamak çok zor olmaz mı?
Paul D. Waite

10
Kullanmakta biraz sorun yaşadım .filter(':first')ama .first()bunun yerine kullanmak benim için çalıştı. Teşekkürler!
hollaburoo

16
Bu benim için işe yaramıyor .text()( bu jsfiddle'a bakın ) ama .replaceWith()( jsfiddle burada ) ile işe yarıyor .
magicalex

2
Bu benim için işe yarıyor, çünkü textObject = $ (myNode) .contents (). Filter (function () {return this.nodeType == 3;}) [0] $ (textObject) .replaceWith ("metnim" );
Maragues

merak kimse nodeType=3bunun ortalama filtresi yalnızca düğümü "" metnini türünü olduğu w3schools.com/jsref/prop_node_nodetype.asp fazla bilgi için
ktutnik

53

Eylemde görün

İşaretleme:

$(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" />


6
Şimdiye kadar karşılaştığım en iyi çözüm. Zarif ve sade.
Yoav Kadosh

3
Ancak bu, düğümlerin sırasını korumaz. Örneğin, metin önce öğenin sonundaysa, şimdi başlangıçta olacaktı.
Matt

Sırayı korumaz, ancak çoğu durumda metni ilk veya son düğüm olarak istersiniz. Dolayısıyla, append () istenen sonucu almazsa, metnin önünde mevcut alt öğelerin olmasını istiyorsanız prepend () deneyin.
Sensei


11
<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");
});

Bu yalnızca ilk metin düğümünü değiştirir


9

Değiştirmek istediğiniz metni, seçeceğiniz bir sınıfla kaydırmanız yeterlidir.

Sorunuza mutlaka cevap vermiyor bildiğim ama muhtemelen daha iyi bir kodlama uygulaması. Her şeyi temiz ve basit tutun

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

Voila

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

Bu en iyi çözüm!
Şık Geek

5

Bahsettiğiniz özel durum için:

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

... bu çok kolaydır:

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

Bunu nasıl genellemek istediğinizi belirtmiyorsunuz. Diyelim ki, içindeki ilk metin düğümünün metnini değiştirmek istiyorsanız, şöyle bir <div>şey yapabilirsiniz:

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

2

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


1

İşte yine bir başka yöntemi: 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);

1

Burada pek çok harika yanıt var, ancak çocuklarla yalnızca bir metin düğümünü ele alıyorlar. Benim durumumda, tüm metin düğümlerinde çalışmam ve html çocuklarını görmezden gelmem gerekiyordu ANCAK SİPARİŞİ KORUYUN.

Öyleyse böyle bir vakamız varsa:

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

Aşağıdaki kodu sadece metni değiştirmek ve SİPARİŞİ KORUMAK için kullanabiliriz

    $('#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>

İşte jsfiddle çalışma bunun


0

.PrependTo () aradığınızı düşünüyorum.

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

Ayrıca sayfadaki bir öğeyi seçip başka birine ekleyebiliriz:

$ ( 'H-2') prependTo ($ ( 'konteyner.').);

Bu şekilde seçilen bir öğe başka bir yere yerleştirilirse, hedefe taşınacaktır (klonlanmamıştır):

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

Ancak birden fazla hedef öğe varsa, eklenen öğenin klonlanmış kopyaları, ilkinden sonra her hedef için oluşturulur.


2
Bence değil. Görünüşe göre OP, metni değiştirmenin bir yolunu arıyor, yeni metin eklemek değil.
Matt Ball

0

Basit cevap:

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

0

Mark'ın cevabıyla ilgili sorun, boş metin düğümleri de almanızdır. JQuery eklentisi olarak çözüm:

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

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

0

Bu eski bir sorudur, ancak hayatınızı kolaylaştırmak için bunun gibi basit bir işlevi yapabilirsiniz:

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

Misal:

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

Kullanımı:

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

0

2019 vesrsion - Kısa ve Basit

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

açıklama

document.querySelector('#your-div-id') ebeveyni seçmek için kullanılır (değiştirmek üzere olduğunuz metnin öğesi)

.childNodes[0] metin düğümünü seçer

.nodeValue = 'new text' metin düğümü değerini "yeni metin" olarak ayarlar


Bu cevap muhtemelen Dean Martin'in yorumundan ilham almıştır. Bu çözümü yıllardır kullandığım için kesin olarak söyleyemem. Sadece bu olasılığı buraya koymam gerektiğini düşündüm çünkü bazı insanlar bunu en iyi çözüm olduğu gerçeğinden daha çok önemsiyor.


2
Dean Martin'in 2014'teki yorumunu kopyaladınız ve bunun 2019 çözümünüz olduğunu iddia ettiniz. Ayrıca, bence iyi okunabilirlik için kötü bir uygulama olan gereksiz bir jQuery ve düz Javascript kombinasyonu kullanın. Son olarak, çözümünüzün nasıl çalıştığı hakkında herhangi bir ayrıntı vermediniz. Bu en karmaşık olanı değil, ama bu sorun da değil, bu yüzden muhtemelen bunu okuyan oldukça yeni programcılar, örneğin dizi dizinine erişerek jQuery nesnesinden yerel DOM düğümünü aldığınız gibi fazladan bir açıklama kullanabilirler.
Mark Baijens

@MarkBaijens Sanırım haklısınız, Dean Martin'in yorumu bu pasajı yıllar önce aldığım yer olabilir. Her neyse, o zamandan beri kullanıyorum ve Ocak ayında kişisel kod depomdan (faydalı komut dosyalarını listelediğim yer) kopyaladım. Daha ayrıntılı bir açıklama eklendi ve gereksiz jQuery kaldırıldı.
Silver Ringvee

Bu, aslında işe yarayan en basit çözümdür ve insanlar onu kullanmalıdır, ancak Dean Martin'e kredi vermeden kendi başınıza patlatmak için herhangi bir övgü almasanız da. Bu durumda saf Vanilla JS uygulamasının jQuery ve Vanilla JS'yi karıştırmaktan daha iyi olduğu konusunda Mark Baijens'e de katılıyorum. Sadece daha iyi okunabilirlik için değil, aynı zamanda jQuery işleri yavaşlattığı için daha iyi performans için.
Miqi180

@ Miqi180 - yukarıda da söylediğim gibi, bu mümkün, bu çözümü ilk nereden aldığımı hatırlamıyorum. Yıllardır işimde kullanıyorum. Cevaba bir not eklendi. Umarım, sizin gibi
SO'da
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.