Bir metin alanından metin alırken satır sonlarını nasıl koruyabilirim?


96

Kullanıcı gönder düğmesine bastığında değeri bir metin alanında alıyorum. Daha sonra bu değeri alıp sayfanın başka bir yerine yerleştiriyorum. Ancak, bunu yaptığımda, çıktıyı oldukça çirkinleştiren yeni satır karakterlerini kaybediyor.

İşte eriştiğim metin alanı:

<textarea id="post-text" class="form-control" rows="3" placeholder="What's up?" required></textarea>

İşte gönderiye erişen ve onu kopyalayan JavaScript kodu.

var post = document.createElement('p');
var postText = document.getElementById('post-text').value;
post.append(postText);
var card = document.createElement('div');
card.append(post);
var cardStack = document.getElementById('#card-stack');
cardStack.prepend(card);

Giriş şöyle bir şey olduğunda:

Grup Programı:

5. katta Salı antrenmanı (20:00 - 23:00)

5. katta Perşembe antrenmanı (20:00 - 23:00)

Pazar antrenmanı @ (21:00 - 12:00)

Çıktı:

Grup Programı: 5. katta Salı antrenmanı (20:00 - 23:00) Perşembe antrenmanı, 5. katta (20:00 - 23:00) Pazar antrenmanı @ (21:00 - 12:00)

Peki, satır sonlarını korumanın bir yolu var mı?


1
jQuery'yi kullanma izniniz varsa, bu size yardımcı olabilir: metin alanından-div'e-koruyan-satır
boşluklarına kopyala

1
Satır sonları gerçekte korunur, hedef öğe metni görüntülerken onları yok sayacak şekilde ayarlanır, ancak incelerseniz burada olduklarını göreceksiniz. Stefano'nun cevabı basitçe hedefi artık onları görmezden gelmemesini sağlıyor, muhtemelen en iyi yol bu.
spectras

2
Nitpick için üzgünüm, ancak 2'den getElementByIdson satıra kadar işlev nerede ? Ya başka bir yerde tanımladınız ya da unuttunuz document.
trysis

Yanıtlar:


175

En kolay çözüm, metni eklediğiniz öğenin aşağıdaki CSS özelliğiyle stilini belirlemektir:

white-space: pre-wrap;

Bu özellik , eşleşen elemanlar içindeki beyaz boşlukların ve satırsonlarının a içindekilerle aynı şekilde ele alınmasına neden olur <textarea>. Yani, ardışık beyaz boşluklar daraltılmaz ve satırlar açık yeni satırlarda kesilir (ancak öğenin genişliğini aşarlarsa otomatik olarak kaydırılırlar).

Şimdiye kadar burada yayınlanan cevapların birçoğunun HTML yerleştirmeye açık olduğu (örneğin, çıkış karaktersiz kullanıcı girdisi atadıkları için innerHTML) veya yanlış olduğu göz önüne alındığında, orijinal kodunuza dayanarak bunu güvenli ve doğru şekilde nasıl yapacağınıza dair bir örnek vereyim:


Orijinal kodunuz gibi yukarıdaki kod parçasının append()ve kullandığını unutmayın prepend(). Bu yazı itibariyle, bu işlevler hala deneysel olarak kabul edilmektedir ve tüm tarayıcılar tarafından tam olarak desteklenmemektedir. Güvende olmak ve eski tarayıcılarla uyumlu kalmak istiyorsanız, bunları aşağıdaki gibi kolayca değiştirebilirsiniz:

  • element.append(otherElement)ile değiştirilebilir element.appendChild(otherElement);
  • element.prepend(otherElement)ile değiştirilebilir element.insertBefore(otherElement, element.firstChild);
  • element.append(stringOfText)ile değiştirilebilir element.appendChild(document.createTextNode(stringOfText));
  • element.prepend(stringOfText)ile değiştirilebilir element.insertBefore(document.createTextNode(stringOfText), element.firstChild);
  • özel bir durum olarak, elementboşsa, her ikisi de element.append(stringOfText)ve element.prepend(stringOfText)basitçe ile değiştirilebilir element.textContent = stringOfText.

İşte yukarıdakiyle aynı kod parçacığı, append()veya kullanmadan prepend():


Ps. Bunu gerçekten yapmak istiyorsanız olmadan CSS kullanarak white-spaceözelliğini alternatif bir çözüm ile açıkça metinde herhangi satır karakterlerini değiştirmek şeklinde olur <br>HTML etiketleri. İşin zor kısmı, ince hatalar ve olası güvenlik açıklarından kaçınmak için, bu değişikliği yapmadan önce metindeki herhangi bir HTML meta karakterinden (en azından &ve <) kaçınmanız gerektiğidir.

Muhtemelen bunu yapmanın en basit ve en güvenli yolu, tarayıcının sizin için HTML çıkışını işlemesine izin vermektir, örneğin:

var post = document.createElement('p');
post.textContent = postText;
post.innerHTML = post.innerHTML.replace(/\n/g, '<br>\n');

Bu, satır sonlarını düzeltirken, ardışık beyaz boşlukların HTML oluşturucu tarafından daraltılmasını engellemeyeceğini unutmayın. Metindeki boşlukların bir kısmını bölünemez boşluklarla değiştirerek bunu (bir nevi) taklit etmek mümkündür, ancak dürüst olmak gerekirse, tek bir CSS satırı ile önemsiz bir şekilde çözülebilecek bir şey için bu oldukça karmaşık hale gelmektedir.


2
Bu, en kapsamlı cevap gibi görünüyor. Neden olumsuz oy verildi? Yanlış bilgi içeriyorsa lütfen paylaşın.
Ethan Vander Horn

4
beyaz boşluk: ön sarma ilk satırda girintiye sahip olduğu için ön satır benim için çalıştı.
dev4life

1
Tesekkurler dostum.
Günümü

Mesele şu ki, metin alanındaki beyaz boşlukları görebiliyorum, ancak bunları API ucunda aldığımda ve bir e-postaya gönderildiklerinde, boşlukları korumuyor.
Apurva Kunkulol

@ApurvaKunkulol: Bu, sunucu tarafı kodunuzda bir sorun gibi görünüyor. Bununla ilgili yeni bir soru sorabilirsiniz, ancak sorunu gösteren minimum tekrarlanabilir bir örnek sağlamanız gerekir .
Ilmari Karonen

23

Hedef kapsayıcı white-space:prestile sahip olmalıdır . Aşağıda deneyin.

<script>
function copycontent(){
 var content = document.getElementById('ta').value;
 document.getElementById('target').innerText = content;
}
</script>
<textarea id='ta' rows='3'>
  line 1
  line 2
  line 3
</textarea>
<button id='btn' onclick='copycontent();'>
Copy
</button>
<p id='target' style='white-space:pre'>

</p>


10
pre-wrapya pre-lineda daha iyi olurdu. presatır kaydırmayı engeller, bu nedenle çok uzun bir metin satırı yatay kaydırma çubuğunu zorlar.
Salman A

10
Bu kod HTML yerleştirmeye karşı savunmasızdır, çünkü çıkış karaktersiz kullanıcı girişi atıyorsunuz innerHTML. Bu durumda, sadece değiştirilmesi innerHTMLile textContentgiderirdi.
Ilmari Karonen

1
@IlmariKaronen Bir şeyleri bozacak. Sen ayarlamanız gerekir innerText ve textContent . Ayar yalnızca textContentIE'de (herhangi bir sürümde) innerTextçalışmaz ve ayar yalnızca gelecekte Chrome'da çalışmayabilir ve Firefox'ta çalışmayacaktır.
Ismael Miguel

3
@IsmaelMiguel: Bu garip - Bunu IE 11'den gönderiyorum ve burada gayet iyi çalışıyor. Görünüşe göre IE, textContentsürüm 9'dan beri destekliyor .
Ilmari Karonen

2
@IlmariKaronen Bu tuhaf ... Bunun farkında değildim. Ancak innerTextIE8'e ihtiyacınız varsa eklemek iyi bir fikirdir .
Ismael Miguel

7

function get() {
  var arrayOfRows = document.getElementById("ta").value.split("\n");
  var docfrag = document.createDocumentFragment();
  
  var p = document.getElementById("result");
  while (p.firstChild) {
    p.removeChild(p.firstChild);
  }
  
  arrayOfRows.forEach(function(row, index, array) {
    var span = document.createElement("span");
    span.textContent = row;
    docfrag.appendChild(span);
    if(index < array.length - 1) {
      docfrag.appendChild(document.createElement("br"));
    }
  });

  p.appendChild(docfrag);
}
<textarea id="ta" rows=3></textarea><br>
<button onclick="get()">get</button>
<p id="result"></p>

Metin alanı satırlarını diziye bölebilirsiniz:

var arrayOfRows = postText.value.split("\n");

Daha sonra, belki daha fazla p etiketi oluşturmak için kullanın ...


3
@IlmariKaronen ne dedi: textarea.valueHTML ( innerHTML) bekleyen bir özelliğe düz metin ( ) atadığınız için bu kod yanlış . Bu, bozuk metinden güvenlik açıklarına kadar değişen sorunlara neden olan bir tür hatasıdır. Bunun yerine kullanmanın innerHTML, yapabileceğin appendChildile document.createTextNode(text)ve document.createElement('br').
Kos

1
Bunu daha verimli hale getirmenin iyi bir yolu document.createDocumentFragment.
Kos

1
@IlmariKaronen, Kos, bu ne güvenlik ne de verimlilik meselesi değildi. Yine de optimize ettim.
kolodi

3
@misher: OP, satır sonlarını korumanın ve HTML yerleştirmeye izin vermenin bir yolunu değil, satır sonlarını korumanın bir yolunu istedi . Bir UI hatasını düzeltmek için yardım istediğinizde ücretsiz bir güvenlik açığı almak, bir hamburger istediğinizde köftede ücretsiz bir raptiye almak gibidir. Her neyse, "optimize edilmiş" kodunuz artık savunmasız görünmediğinden, olumsuz oyumu kaldırdım.
Ilmari Karonen

3

Bir metin kutusunda birden fazla yeni satırınız olabileceği için işte bir fikir:

 var text=document.getElementById('post-text').value.split('\n');
 var html = text.join('<br />');

Bu HTML değeri yeni satırı koruyacaktır. Bu yardımcı olur umarım.


1
Bu ayrıca, ortaya çıkan htmldizge gerçekten HTML olarak işlenirse, bir HTML yerleştirme güvenlik açığı yaratacak olan, çıkış karaktersiz kullanıcı girdisi ve HTML etiketlerinin bir karışımını üretecektir .
Ilmari Karonen

@IlmariKaronen - Yani endişen, birinin kendine saldırabileceği mi? OP, herhangi bir veri tabanı türünden bahsetmez. Bir kullanıcının girişi başka bir kullanıcıyı herhangi bir şekilde nasıl etkiler? Belki de bu sadece OP'lerin gözleri için olan ve sanitasyona 0 ihtiyacı olan bir şeydir (buna herhangi bir ihtiyacı olsa bile).
Jesse

1
@Jesse: Genel olarak, kullanıcı girdisinin güvenilir bir kaynaktan geldiğinden emin olmak zor. Bir saldırganın metin alanına doğrudan metin enjekte etmenin bir yolu olmasa bile, sosyal mühendislik yoluyla saf kullanıcıları savunmasız bir giriş alanına bir şeyi kopyalayıp yapıştırmaya ikna ederek yayılan çok sayıda sosyal medya virüsü vardır. Ayrıca, girdi gerçekten% 100 güvenilir olsa bile, bu kod yine de &veya gibi HTML meta karakterleri içeren herhangi bir metni karıştırır <. Güvenlik bir sorun olmasa bile, bu hala bir hata.
Ilmari Karonen

@IlmariKaronen - Bir saldırı konusunda hiç endişelenmiyorum ama bu bilgi için teşekkür ederim!
Ethan Vander Horn

3

Sen ayarlayabilirsiniz widthdiv kullanarak Javascript ve eklemek white-space:pre-wrapiçin p tagher satırın sonunda bu mola, sizin textarea içeriği.

document.querySelector("button").onclick = function gt(){
var card = document.createElement('div');
card.style.width = "160px";
card.style.background = "#eee";
var post = document.createElement('p');
var postText = document.getElementById('post-text').value;
post.style.whiteSpace = "pre-wrap";
card.append(post);
post.append(postText);
document.body.append(card);
}
<textarea id="post-text" class="form-control" rows="3" placeholder="What's up?" required>
Group Schedule:

Tuesday practice @ 5th floor (8pm - 11 pm)

Thursday practice @ 5th floor (8pm - 11 pm)

Sunday practice @ (9pm - 12 am)</textarea>
<br><br>
<button>Copy!!</button>


3

Metin alanı içeriğinizin HTML olarak ayrıştırılmasını istemediğinizi varsayalım. Bu durumda, tarayıcının onu HTML olarak ele almaması ve yeni satırları kaldırmaması için düz metin olarak ayarlayabilirsiniz. CSS veya ön işleme gerekmez.

<script>
function copycontent(){
 var content = document.getElementById('ta').value;
 document.getElementById('target').innerText = content;
}
</script>
<textarea id='ta' rows='3'>
  line 1
  line 2
  line 3
</textarea>
<button id='btn' onclick='copycontent();'>
Copy
</button>
<p id='target'></p>


2

Benzer sorular burada

bir metin alanı girişindeki satır sonlarını algılama

metin alanında satır sonunu algıla

Bunu deneyebilirsiniz:

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

submit.addEventListener('click', function(){
var textContent = document.querySelector('textarea').value;
  
document.getElementById('output').innerHTML = textContent.replace(/\n/g, '<br/>');
  

});
<textarea cols=30 rows=10 >This is some text
this is another text

Another text again and again</textarea>
<input type='submit' id='submit'>


<p id='output'></p>

document.querySelector('textarea').value;metin alanının metin içeriğini alacak ve içerikteki textContent.replace(/\n/g, '<br/>')kaynak kodda tüm satırsonu karakterini bulacak /\n/gve onu html satır sonu ile değiştirecektir <br/>.


Diğer bir seçenek de html <pre> etiketini kullanmaktır . Aşağıdaki demoya bakın

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

submit.addEventListener('click', function(){

  var content = '<pre>';
  
  var textContent = document.querySelector('textarea').value;
  
  content += textContent;
  
  content += '</pre>';

  document.getElementById('output').innerHTML = content;

});
<textarea cols=30 rows=10>This is some text
this is another text

Another text again and again </textarea>
<input type='submit' id='submit'>

<div id='output'> </div>


2
Lütfen soruyu tekrar okuyun. Poster, başka bir metin alanının içine değil, bir sayfaya bir metin alanından metin yerleştirirken satır sonlarının nasıl korunacağını soruyor.
Jesse

1
İlk örneğiniz buggy ve işe yaramıyor. (Hiçbir zaman sonucunu textContent.replace()hiçbir şeye atamazsınız.) İkinci örneğiniz, diğer birkaç cevapta olduğu gibi aynı HTML yerleştirme hatasına karşı savunmasızdır, çünkü çıkış karaktersiz kullanıcı girdisini atıyorsunuz innerHTML(ve denerseniz ilk örnek eşit derecede savunmasız olursunuz) aslında replace()çağrının çıktısıyla yararlı bir şey yapmak için )
Ilmari Karonen

Teşekkür ederim! Outlook 2013 aslında <pre> nedir biliyor
user1566694
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.