textareaからテキストを取得するときに改行を保持するにはどうすればよいですか?


98

ユーザーが送信を押すと、テキストエリアに値が表示されます。次に、この値を取得して、ページの他の場所に配置します。ただし、これを行うと、改行文字が失われ、出力がかなり見苦しくなります。

これが私がアクセスしているテキストエリアです:

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

これは、投稿にアクセスしてそれを転記するJavaScriptコードです。

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

入力が次のような場合:

グループスケジュール:

火曜日の練習@ 5階(午後8時から午後11時)

木曜日の練習@ 5階(午後8時から午後11時)

日曜日の練習@(午後9時から午前12時)

出力は次のとおりです。

グループスケジュール:火曜日の練習@ 5階(午後8時から午後11時)木曜日の練習@ 5階(午後8時から午後11時)日曜日の練習@(午後9時から午前12時)

では、改行を保持する方法はありますか?


1
jQueryの使用が許可されている場合、これは次の場合に役立ちます。copy-from-textarea-to-div-preserving-linebreaksまたは、これは、preserve-line-breaks-in-
textarea

1
改行は実際には保持され、ターゲット要素はテキストの表示中に改行を無視するように設定されていますが、それを調べると、改行がここにあることがわかります。ステファノの答えは、ターゲットを無視しないように設定するだけで、おそらく最善の方法です。
スペクトル2016年

2
ちなみに申し訳ありませんが、getElementById最後から2番目の行の関数はどこにありますか?他の場所で定義したか、を忘れたと思いますdocument
trysis 2016年

回答:


185

最も簡単な解決策は、次のCSSプロパティを使用して、テキストを挿入する要素のスタイルを設定することです。

white-space: pre-wrap;

このプロパティにより、一致する要素内の空白と改行が。内と同じように扱われ<textarea>ます。つまり、連続する空白は折りたたまれず、行は明示的な改行で分割されます(ただし、要素の幅を超えると自動的に折り返されます)。

これまでにここに投稿された回答のいくつかは、HTMLインジェクションに対して脆弱である(たとえば、エスケープinnerHTMLされていないユーザー入力をに割り当てるため)か、バグがあるため、元のコードに基づいて、これを安全かつ正しく行う方法の例を示します。


、あなたの元のコードのように、なお用途上記のスニペットappend()prepend()。この記事の執筆時点では、これらの機能はまだ実験的なものと見なされており、すべてのブラウザで完全にサポートされているわけではありません。安全で古いブラウザとの互換性を維持したい場合は、次のように簡単に置き換えることができます。

  • element.append(otherElement)で置き換えることができますelement.appendChild(otherElement);
  • element.prepend(otherElement)で置き換えることができますelement.insertBefore(otherElement, element.firstChild);
  • element.append(stringOfText)で置き換えることができますelement.appendChild(document.createTextNode(stringOfText));
  • element.prepend(stringOfText)で置き換えることができますelement.insertBefore(document.createTextNode(stringOfText), element.firstChild);
  • 特別な場合として、elementが空の場合、両方element.append(stringOfText)element.prepend(stringOfText)単純にelement.textContent = stringOfText。に置き換えることができます。

上記と同じスニペットですが、append()またはを使用していませんprepend()


追伸 CSSプロパティ使用せずにこれを本当に実行したい場合white-space、別の解決策は、テキスト内の改行文字を<br>HTMLタグで明示的に置き換えることです。トリッキーな部分は、微妙なバグや潜在的なセキュリティホールの導入を回避するために、この置換を行うに、テキスト内のHTMLメタ文字(少なくとも、&および<)を最初にエスケープする必要があることです。

おそらく、これを行う最も簡単で安全な方法は、次のように、ブラウザにHTMLエスケープを処理させることです。

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

これにより改行は修正されますが、連続する空白がHTMLレンダラーによって折りたたまれるのを防ぐことはできません。テキスト内の空白の一部を改行しないスペースに置き換えることで(一種の)エミュレートすることは可能ですが、正直なところ、CSSの1行で簡単に解決できるものではかなり複雑になっています。


2
これが最も包括的な答えのようです。なぜ反対票が投じられたのですか?間違った情報が含まれている場合は共有してください。
イーサンヴァンダーホーン

4
空白:プレラップの最初の行にインデントがあったため、プレラインが機能しました。
dev4life 2017

1
ありがとう、相棒。あなたは私の日を作りました
2017年

つまり、テキスト領域に空白を表示することはできますが、API側で空白を受信して​​電子メールで送信すると、空白が保持されません。
Apurva Kunkulol 2018

@ApurvaKunkulol:サーバー側のコードに問題があるようです。それについて新しい質問をすることもできますが、問題を示す最小限の再現可能な例を提供する必要があります。
Ilmari Karonen 2018

23

ターゲットコンテナにはwhite-space:preスタイルが必要です。以下でお試しください。

<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-wrapまたはpre-lineより良いでしょう。pre行の折り返しを防ぐため、テキストの行が非常に長いと、水平スクロールバーが強制されます。
サルマンA

10
エスケープされていないユーザー入力をに割り当てているため、このコードはHTMLインジェクションに対して脆弱ですinnerHTML。この場合、単純に置き換えるinnerHTMLtextContentそれを修正するでしょう。
Ilmari Karonen 2016年

1
@IlmariKaronenそれは物事を壊します。とを設定する必要がinnerText あり textContentます。設定のみ textContentはIE(すべてのバージョン)innerTextでは機能せず、設定のみは将来Chromeで機能しなくなり、Firefoxでは機能しなくなります。
Ismael Miguel

3
@IsmaelMiguel:それは奇妙です-私はこれをIE 11から投稿していますが、ここでは問題なく動作します。どうやらIEがサポートしているtextContentバージョン9以降
イルマリKaronen

2
@IlmariKaronenそれは奇妙です...私はそれを知りませんでした。ただし、innerTextIE8が必要な場合は含めることをお勧めします。
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>

textareaの行を配列に分割できます。

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

次に、それを使用して、おそらく、より多くのpタグを生成します...


3
@IlmariKaronenが言ったこと:textarea.valueHTML(innerHTML)を期待するプロパティにプレーンテキスト()を割り当てているため、このコードは正しくありません。これはタイプエラーであり、テキストの破損からセキュリティホールまでさまざまな問題を引き起こします。代わりに使用するのではinnerHTML、あなたが行うことができますappendChilddocument.createTextNode(text)して document.createElement('br')
コス2016年

1
それをより効率的にする良い方法はdocument.createDocumentFragmentです。
コス2016年

1
@ IlmariKaronen、コス、これはセキュリティや効率性についての質問ではありませんでした。しかし、私はそれを最適化しました。
kolodi 2016年

3
@misher:OPは、改行を保持してHTMLインジェクション許可する方法ではなく、改行を保持する方法を要求しました。UIのバグを修正するために助けを求めるときに無料のセキュリティホールを取得することは、ハンバーガーを要求するときにパティに無料の画鋲を取得するようなものです。とにかく、あなたの「最適化された」コードはもはや脆弱ではないように思われるので、私は反対票を削除しました。
Ilmari Karonen 2016年

4

テキストボックスに複数の改行がある場合があるため、次のアイデアがあります。

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

このHTML値は改行を保持します。お役に立てれば。


1
これにより、エスケープされていないユーザー入力とHTMLタグが混在するようになり、結果のhtml文字列が実際にHTMLとしてレンダリングされると、HTMLインジェクションの脆弱性が発生します。
Ilmari Karonen 2016年

@ IlmariKaronen-それで、あなたが持っている懸念は、誰かが自分自身を攻撃するかもしれないということですか?OPは、どのタイプのデータベースについても言及していません。あるユーザーの入力が別のユーザーにどのような影響を与えるでしょうか?たぶん、これはOPの目だけのためのものであり、衛生設備の必要性はまったくありません(それがまったく必要な場合でも)。
ジェシー

1
@Jesse:一般に、ユーザー入力が信頼できるソースからのものであることを確認するのは困難です。攻撃者がテキスト領域に直接テキストを挿入する方法がない場合でも、ソーシャルエンジニアリングを介してナイーブユーザーに脆弱な入力フィールドに何かをコピーアンドペーストするように説得することによって拡散したソーシャルメディアウイルスがたくさんあります。さらに、入力が実際に100%信頼できる場合でも、このコードは、&またはのようなHTMLメタ文字を含むテキストをマングルします<。セキュリティが問題ではない場合でも、それはまだバグです。
Ilmari Karonen 2016年

@ IlmariKaronen-私は攻撃についてはまったく心配していませんが、この情報をありがとうございます!
イーサンヴァンダーホーン

3

widthJavascriptを使用してdivを設定し、に追加white-space:pre-wrapすることができp tagます。これにより、各行の終わりでtextareaコンテンツが分割されます。

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

textarea-contentをHTMLとして解析したくないと思います。この場合、ブラウザがHTMLとして処理せず、改行を削除しないように、プレーンテキストとして設定するだけで済みます。CSSや前処理は必要ありません。

<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

同様の質問はここにあります

テキスト領域入力の改行を検出する

textareaの改行を検出する

あなたはこれを試すことができます:

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;textareaのテキストコンテンツを取得し、コンテンツtextContent.replace(/\n/g, '<br/>')内のソースコード/\n/g内のすべての改行文字を検索し、それをhtml改行に置き換え<br/>ます。


別のオプションは、html <pre>タグを使用することです。以下のデモをご覧ください

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
もう一度質問を読み直してください。ポスターは、別のテキスト領域内ではなく、ページ上のテキスト領域からテキストを配置するときに改行を保持する方法を尋ねています。
ジェシー

1
最初の例はバグが多く、機能しません。(結果textContent.replace()を何かに割り当てることさえありません。)2番目の例は、エスケープされていないユーザー入力をに割り当てているため、他のいくつかの回答と同じHTMLインジェクションのバグに対して脆弱ですinnerHTML(最初の例は、試した場合、同様に脆弱になります)replace()呼び出しの出力で実際に役立つことを行うため)。
Ilmari Karonen 2016年

ありがとうございました!Outlook 2013は実際に<pre>が何であるかを知っています
user15666 9419
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.