142 votes

Comment préserver les sauts de ligne lorsque je récupère du texte dans une zone de texte ?

Je récupère la valeur dans une zone de texte lorsque l'utilisateur clique sur "soumettre". Je prends ensuite cette valeur et la place ailleurs dans la page. Cependant, lorsque je fais cela, je perds les caractères de nouvelle ligne, ce qui rend la sortie plutôt moche.

Voici la zone de texte à laquelle j'accède :

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

Voici le code JavaScript permettant d'accéder au message et de le transcrire.

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

Quand l'entrée est quelque chose comme :

Horaire du groupe :

Entraînement du mardi au 5e étage (20 h - 23 h)

Entraînement du jeudi au 5e étage (20 h - 23 h)

Entraînement du dimanche @ (21 h - 12 h)

La sortie est :

Horaire du groupe : Pratique du mardi au 5e étage (20 h - 23 h) Pratique du jeudi au 5e étage (20 h - 23 h) Pratique du dimanche (21 h - 12 h)

Existe-t-il un moyen de préserver les sauts de ligne ?

1 votes

si vous êtes autorisé à utiliser jQuery, cela pourrait vous aider : copier-de-textarea-to-div-preserving-linebreaks Sinon, ceci pourrait vous aider préserver les coupures de ligne dans les entrées de textures

1 votes

Les sauts de ligne sont en fait préservés, l'élément cible est simplement configuré pour les ignorer lors de l'affichage du texte, mais si vous l'inspectez, vous verrez qu'ils sont là. La réponse de Stefano permet simplement à l'élément cible de ne plus les ignorer, ce qui est probablement la meilleure solution.

2 votes

Désolé de pinailler, mais où est le getElementById de l'avant-dernière ligne ? Je suppose que soit vous l'avez définie ailleurs, soit vous avez oublié la fonction document .

272voto

Ilmari Karonen Points 20585

La solution la plus simple consiste à donner un style à l'élément dans lequel vous insérez le texte avec la propriété CSS suivante :

white-space: pre-wrap;

Cette propriété fait en sorte que les espaces et les retours à la ligne à l'intérieur des éléments correspondants soient traités de la même manière qu'à l'intérieur d'un fichier de type <textarea> . En d'autres termes, les espaces blancs consécutifs ne sont pas supprimés et les lignes sont coupées par des sauts de ligne explicites (mais elles sont également enveloppées automatiquement si elles dépassent la largeur de l'élément).

Etant donné que plusieurs des réponses postées ici jusqu'à présent ont été vulnérables à Injection HTML (par exemple, parce qu'ils attribuent les entrées utilisateur non encodées à l'option innerHTML ) ou bogué d'une autre manière, laissez-moi vous donner un exemple de la manière de le faire correctement et en toute sécurité, sur la base de votre code original :

document.getElementById('post-button').addEventListener('click', function () {
  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);
});

#card-stack p {
  background: #ddd;
  white-space: pre-wrap;  /* <-- THIS PRESERVES THE LINE BREAKS */
}
textarea {
  width: 100%;
}

<textarea id="post-text" class="form-control" rows="8" 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>
<input type="button" id="post-button" value="Post!">
<div id="card-stack"></div>

Notez que, comme votre code original, l'extrait ci-dessus utilise append() et prepend() . Au moment où nous écrivons ces lignes, ces fonctions sont encore considérées comme expérimentales et ne sont pas entièrement prises en charge par tous les navigateurs. Si vous voulez être sûr et rester compatible avec les anciens navigateurs, vous pouvez les remplacer assez facilement comme suit :

  • element.append(otherElement) peut être remplacé par element.appendChild(otherElement) ;
  • element.prepend(otherElement) peut être remplacé par element.insertBefore(otherElement, element.firstChild) ;
  • element.append(stringOfText) peut être remplacé par element.appendChild(document.createTextNode(stringOfText)) ;
  • element.prepend(stringOfText) peut être remplacé par element.insertBefore(document.createTextNode(stringOfText), element.firstChild) ;
  • comme un cas particulier, si element est vide, les deux element.append(stringOfText) et element.prepend(stringOfText) peut simplement être remplacé par element.textContent = stringOfText .

Voici le même extrait que ci-dessus, mais sans utiliser la fonction append() ou prepend() :

document.getElementById('post-button').addEventListener('click', function () {
  var post = document.createElement('p');
  var postText = document.getElementById('post-text').value;
  post.textContent = postText;
  var card = document.createElement('div');
  card.appendChild(post);
  var cardStack = document.getElementById('card-stack');
  cardStack.insertBefore(card, cardStack.firstChild);
});

#card-stack p {
  background: #ddd;
  white-space: pre-wrap;  /* <-- THIS PRESERVES THE LINE BREAKS */
}
textarea {
  width: 100%;
}

<textarea id="post-text" class="form-control" rows="8" 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>
<input type="button" id="post-button" value="Post!">
<div id="card-stack"></div>

Ps. Si vous voulez vraiment le faire sans en utilisant le CSS white-space une solution alternative serait de remplacer explicitement tout caractère de nouvelle ligne dans le texte par <br> Balises HTML. La partie délicate est que, pour éviter d'introduire des bogues subtils et des failles de sécurité potentielles, vous devez d'abord échapper à tous les métacaractères HTML (au minimum, & et < ) dans le texte avant vous effectuez ce remplacement.

La façon la plus simple et la plus sûre de procéder est probablement de laisser le navigateur se charger de l'encodage HTML pour vous, comme ceci :

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

document.getElementById('post-button').addEventListener('click', function () {
  var post = document.createElement('p');
  var postText = document.getElementById('post-text').value;
  post.textContent = postText;
  post.innerHTML = post.innerHTML.replace(/\n/g, '<br>\n');  // <-- THIS FIXES THE LINE BREAKS
  var card = document.createElement('div');
  card.appendChild(post);
  var cardStack = document.getElementById('card-stack');
  cardStack.insertBefore(card, cardStack.firstChild);
});

#card-stack p {
  background: #ddd;
}
textarea {
  width: 100%;
}

<textarea id="post-text" class="form-control" rows="8" 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>
<input type="button" id="post-button" value="Post!">
<div id="card-stack"></div>

Notez que, bien que cela corrige les sauts de ligne, cela n'empêchera pas les espaces blancs consécutifs d'être écrasés par le moteur de rendu HTML. Il est possible d'émuler (en quelque sorte) ce phénomène en remplaçant certains espaces blancs dans le texte par des espaces insécables, mais honnêtement, cela devient plutôt compliqué pour quelque chose qui peut être résolu trivialement avec une seule ligne de CSS.

2 votes

Cette réponse semble être la plus complète. Pourquoi le produit est-il rejeté ? Si elle contient des informations incorrectes, veuillez la partager.

7 votes

white-space : pre-line a fonctionné pour moi, car pre-wrap avait une indentation sur la première ligne.

1 votes

Merci, mec. Tu as fait ma journée

28voto

Stefano Altieri Points 2522

Le conteneur cible doit avoir l'attribut white-space:pre style. Essayez-le ci-dessous.

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

0 votes

Oui, c'est mieux pour une balise p unique.

11 votes

pre-wrap ou pre-line serait mieux. pre empêche le retour à la ligne, de sorte qu'une très longue ligne de texte forcera la barre de défilement horizontale.

10 votes

Ce code est vulnérable à l'injection HTML, car vous attribuez une entrée utilisateur non encodée à innerHTML . Dans ce cas, il suffit de remplacer innerHTML avec textContent le réparerait.

9voto

misher Points 357
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>

Vous pouvez diviser les lignes du textarea en tableau :

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

Puis l'utiliser pour générer, peut-être, plus de p tags...

3 votes

Ce que @IlmariKaronen a dit : ce code est incorrect car vous assignez du texte en clair ( textarea.value ) à une propriété qui attend du HTML ( innerHTML ). Il s'agit d'une erreur typographique qui entraîne des problèmes allant de la rupture du texte à des failles de sécurité. Au lieu d'utiliser innerHTML vous pouvez faire appendChild avec document.createTextNode(text) et document.createElement('br') .

2 votes

Un bon moyen de rendre cela plus efficace est document.createDocumentFragment .

1 votes

@IlmariKaronen, Kos, ce n'était pas une question de sécurité ou d'efficacité. Je l'ai optimisée, cependant.

3voto

frnt Points 6896

Vous pouvez définir width de div en utilisant Javascript et en ajoutant white-space:pre-wrap à p tag cela casse le contenu de votre textarea à la fin de chaque ligne.

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>

3voto

tkausl Points 7822

Je suppose que vous ne voulez pas que le contenu de votre textarea soit analysé comme du HTML. Dans ce cas, vous pouvez simplement le définir comme texte en clair afin que le navigateur ne le traite pas comme du HTML et ne supprime pas les nouvelles lignes. Aucune CSS ou prétraitement n'est nécessaire.

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X