I am getting the value in a textarea when the user hits submit. I then take this value and place it elsewhere on the page. However, when I do this, it loses newline characters making the output pretty ugly.
Here is the textarea I am accessing:
<textarea id="post-text" class="form-control" rows="3" placeholder="What's up?" required></textarea>
Here is the JavaScript code accessing the post and transcribing it.
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);
When the input is something like:
Group Schedule:
Tuesday practice # 5th floor (8 pm - 11 pm)
Thursday practice # 5th floor (8 pm - 11 pm)
Sunday practice # (9 pm - 12 am)
The output is:
Group Schedule: Tuesday practice # 5th floor (8 pm - 11 pm) Thursday practice # 5th floor (8 pm - 11 pm) Sunday practice # (9 pm - 12 am)
So is there a way to preserve line breaks?
The easiest solution is to simply style the element you're inserting the text into with the following CSS property:
white-space: pre-wrap;
This property causes whitespace and newlines within the matching elements to be treated in the same way as inside a <textarea>. That is, consecutive whitespace is not collapsed, and lines are broken at explicit newlines (but are also wrapped automatically if they exceed the width of the element).
Given that several of the answers posted here so far have been vulnerable to HTML injection (e.g. because they assign unescaped user input to innerHTML) or otherwise buggy, let me give an example of how to do this safely and correctly, based on your original code:
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>
Note that, like your original code, the snippet above uses append() and prepend(). As of this writing, those functions are still considered experimental and not fully supported by all browsers. If you want to be safe and remain compatible with older browsers, you can substitute them pretty easily as follows:
element.append(otherElement) can be replaced with element.appendChild(otherElement);
element.prepend(otherElement) can be replaced with element.insertBefore(otherElement, element.firstChild);
element.append(stringOfText) can be replaced with element.appendChild(document.createTextNode(stringOfText));
element.prepend(stringOfText) can be replaced with element.insertBefore(document.createTextNode(stringOfText), element.firstChild);
as a special case, if element is empty, both element.append(stringOfText) and element.prepend(stringOfText) can simply be replaced with element.textContent = stringOfText.
Here's the same snippet as above, but without using append() or 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. If you really want to do this without using the CSS white-space property, an alternative solution would be to explicitly replace any newline characters in the text with <br> HTML tags. The tricky part is that, to avoid introducing subtle bugs and potential security holes, you have to first escape any HTML metacharacters (at a minimum, & and <) in the text before you do this replacement.
Probably the simplest and safest way to do that is to let the browser handle the HTML-escaping for you, like this:
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>
Note that, while this will fix the line breaks, it won't prevent consecutive whitespace from being collapsed by the HTML renderer. It's possible to (sort of) emulate that by replacing some of the whitespace in the text with non-breaking spaces, but honestly, that's getting rather complicated for something that can be trivially solved with a single line of CSS.
The target container should have the white-space:pre style.
Try it below.
<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>
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>
You can split textarea rows into array:
var arrayOfRows = postText.value.split("\n");
Then use it to generate, maybe, more p tags...
Here is an idea as you may have multiple newline in a textbox:
var text=document.getElementById('post-text').value.split('\n');
var html = text.join('<br />');
This HTML value will preserve newline. Hope this helps.
You could set width of div using Javascript and add white-space:pre-wrap to p tag, this break your textarea content at end of each line.
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>
I suppose you don't want your textarea-content to be parsed as HTML. In this case, you can just set it as plaintext so the browser doesn't treat it as HTML and doesn't remove newlines No CSS or preprocessing required.
<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>
Similar questions are here
detect line breaks in a text area input
detect line break in textarea
You can try this:
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; will get the text content of the
textarea and textContent.replace(/\n/g, '<br/>') will find all the newline character in the source code /\n/g in the content and replace it with the html line-break <br/>.
Another option is to use the html <pre> tag. See the demo below
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>
Related
This question already has answers here:
How to keep Quill from inserting blank paragraphs (`<p><br></p>`) before headings with a 10px top margin?
(3 answers)
Closed 1 year ago.
I have some HTML as a string
var str= "<p><br/></p>"
How do I strip the p tags from this string using JS.
here is what I have tried so far:
str.replace(/<p[^>]*>(?:\s| )*<\/p>/, "") // o/p: <p><br></p>'
str.replace("/<p[^>]*><\\/p[^>]*>/", "")// o/p: <p><br></p>'
str.replace(/<p><br><\/p>/g, "")// o/p: <p><br></p>'
all of them return me same str as above, expected o/p is:
str should be ""
what im doing wrong here?
Thanks
You probably should not be using RegExp to parse HTML - it's not particularly useful with (X)HTML-style markup as there are way too many edge cases.
Instead, parse the HTML as you would an element in the DOM, then compare the trim()med innerText value of each <p> with a blank string, and remove those that are equal:
var str = "<p><br/></p><p>This paragraph has text</p>"
var ele = document.createElement('body');
ele.innerHTML = str;
[...ele.querySelectorAll('p')].forEach(para => {
if (para.innerText.trim() === "") ele.removeChild(para);
});
console.log(ele.innerHTML);
You should be able to use the following expression: <p[^>]*>( |\s+|<br\s*\/?>)*<\/p>
The expression above looks at expressions enclosed in <p>...</p> and matches them against , whitespace (\s+) and <br> (and / variations).
I think you were mostly there with /<p[^>]*>(?:\s| )*<\/p>/, but you just needed to remove ?: (not sure what you were trying to do here), and adding an additional case for <br>.
const str = `
<p><br></p>
<p><br/></p>
<p><br /></p>
<p> <br/> </p>
<p> </p>
<p> </p>
<p><br/> </p>
<p>
<br>
</p><!-- multiline -->
<p><br/> don't replace me</p>
<p>don't replace me</p>
`;
const exp = /<p[^>]*>( |\s+|<br\s*\/?>)*<\/p>/g;
console.log(str.replace(exp, ''));
I'm working on a contenteditable innerHTML string in JavaScript and tried to remove pairs of
<div><br></div>
It appears when user presses Enter for a newline.
Example String : (will be dynamic)
<div><br></div><div><br></div><div><br></div>Example <br> String d<<div><br></div><div><br></div><div><br></div></div>
so I can get
Example <br> String d<
I tried my regex by searching Stack Overflow too:
let final_text = document.getElementById('chat_room_input_box').innerHTML.trim();
final_text = final_text.replace(/^\s*(?:<br\s*\/?\s*>)+|(?:<br\s*\/?\s*>)+\s*$/gi, '');
final_text = final_text.replace(/^(?: |\s)+|(?: |\s)+$/ig,'');
final_text = final_text.replace(/^\s*(?:<div\s*\/?\s*>)+|(?:<div\s*\/?\s*>)+\s*$/gi, '');
I can remove <br> or at start/ end but fails to remove <div><br></div>
Don't use regex to handle HTML. Regex is not powerful enough for this.
Use an HTML parser. Luckily the world's most capable HTML parser is right at your finger tips - a browser. All that is necessary to parse a piece of HTML is to set an element's .innerHTML property.
Then you can easily remove any elements you define, for example <div> that are empty - which includes those that only contain <br> and/or whitespace.
As a bonus, you even are guaranteed to get valid HTML back from the operation, so the invalid String d< will be returned as the valid String d<.
function sanitizeHtml(html) {
const container = document.createElement('DIV');
// Step 1: Parse the HMTL
container.innerHTML = html;
// Step 2: Modify the structure
for (let div of container.querySelectorAll('div')) {
if (div.textContent.trim() === '') div.parentNode.removeChild(div);
// ...over time, I'm sure you'll find more things you'd like to correct
}
// Step 3: return the modified HTML
return container.innerHTML;
}
function showResult() {
const result = sanitizeHtml(this.innerHTML);
document.getElementById('outputHtml').textContent = result;
document.getElementById('outputDisplay').innerHTML = result;
}
const input = document.getElementById('input');
input.contentEditable = true;
input.addEventListener('input', showResult);
showResult.call(input);
#input, #outputDisplay {
border: 1px solid red;
}
#outputHtml {
border: 1px solid blue;
}
<div id="input"><div><br></div><div><br></div><div><br></div>Example <br> String d<<div><br></div><div><br></div><div><br></div></div></div>
<pre id="outputHtml"></pre>
<div id="outputDisplay"></pre>
so, by what I see, it would make sense to do it in steps
first remove elements like br (self closing) elements
str="<div><br></div><div><br></div><div><br></div>Example String d<<div><br></div><div><br></div><div><br></div></div>"
############## REMOVING SELF CLOSING ELEMENTS
# here is a list of self closing elements, you can add more that you want to remove
str = str.replace(/<(br|img)>/g, "")
# another way of removing self closing elements, is to look for the closure when they are properly coded <br />
str = str.replace(/<br\s*\/?>/g, "")
# if wanted, you can use both
str = str.replace(/(<br\s*\/?>|<(br|img)>)/g, "")
########## REMOVE ELEMENTS THAT CLOSE EMPTY (divs)
str = str.replace(/<([^>]*)>\s*<\/\1>/g, "")
# this will return
# str = str.replace(/<([^>])>\s*<\/\1>/g, "")
If what you want it to look for specific elements, you can use
str = str.replace(/<\/?\s*(br|img|div)\s*\/?>/g, "")
## this returns
"Example String d<"
To learn more, I recomend
https://www.regular-expressions.info/tutorial.html
https://cheatography.com/davechild/cheat-sheets/regular-expressions/
I have to show pdf books in Hebrew, but the Hebrew alphabet has 2 styles of text (with dots and without dots).
When book has text style with dots - appear issues occur: when I select text - it randomly has spaces in one word and also problems with search.
So I want to change text rendering function and implement it.
HTML:
Enter input text here:<br/>
<textarea id="input" rows="10" cols="60"></textarea><br/><br/>
Enter output text here:<br/>
<textarea id="output" rows="10" cols="60"></textarea><br/><br/>
<button id="convert" onClick="doStrip()">
Strip Vowels
</button>
JS/JQuery
function stripVowels(rawString)
{
var newString = '';
for(j=0; j<rawString.length; j++) {
if(rawString.charCodeAt(j)<1425
|| rawString.charCodeAt(j)>1479)
{ newString = newString + rawString.charAt(j); }
}
return(newString);
}
/* #shimondoodkin suggested even a much shorter way to do this */
function stripVowels2(rawString) {
return rawString.replace(/[\u0591-\u05C7]/g,"")
}
function doStrip() {
var input = $('#input').val();
var output = stripVowels(input);
$('#output').val(output);
}
link to Fiddle editor
example text (copied from book, seems pdf js wrong render spaces): לּעַ , עִ גוּוֵּ ן, רִ בָּ רָ ה, מַ לְ בׁ: מְ צֻ לָ ע, צֶ לַ ע, קָ דְ קֹד, זָ וִ ית יְ שָ ג ִ י םׂמֻ ש
hope when I will change characters with dots into characters without dots
in rendering function - it will solve this issue
I also try to change SPACE_FACTOR, but still have issues
in file evaluator.js
in function buildTextContentItem
do what you needed with variable "glyphUnicode"
txt = '<a class="info" href="/some/link" original-title="hello world <br/> Monday <br/> 2 days <br/> Test"> 10 </a>';
var pattern = /\s\d+/;
var parsed_data = parseInt((txt.match(pattern)||['0'])[0]);
Got this regex pattern from some example. I am trying to parse the text i.e. value 10 from the anchor tag. But the value obtained is 2.
EDIT:
I am using datatables to populate the tables.
And problem is the string i.e. txt is a row element, extracted from table using loop and need to add these values e.g.
var parsed_data += parseInt((txt.match(pattern)||['0'])[0]);
It is a very bad idea to parse a html content with regex, in this case use jQuery to fix it
var txt = '<a class="info" href="/some/link" original-title="hello world <br/> Monday <br/> 2 days <br/> Test"> 10 </a>';
var parsed_data = parseInt($(txt).text(), 10);
console.log(parsed_data)
Demo: Fiddle
You could have something like that:
var txt = '<a class="info" href="/some/link" original-title="hello world <br/> Monday <br/> 2 days <br/> Test"> 10 </a>';
var pattern = /.*>\s*(\d+)/;
var matches = txt.match(pattern);
var parsed = matches ? +matches[1] : 0;
However, this regexp takes just the last digit inside a tag (>): if you want to have something more precise, you should parse the HTML using the DOM – that is more expensive. It's really depends by what is your data, if you always have such format, you don't need the DOM.
Let's say I have a text :
<p> hello world! </p>
and I am using a function that cut the text after 5 words and adds " ...show more"
I want the result to be like this :
hello ... show more
Because of the <p> tags what I get is this output :
hello ...show more
what I see when I inspect the element is this :
<p> hello </p> ...show more
I must mention that the text can be with <p> or without.
Is there a way to solve this problem ?
Is there a way to insert the added text inside the <p> tag ?
I need to mention that I need the <p> tags, I can't use strip tags function.
Thanks,
Yami
Do you mean this?
var text = "<p>hello world</p>";
var res = "<p>" + text.substring(3, 8) + " ...show more</p>";
It results in:
<p>hello ...show more</p>
The way I see it, you have two options:
.split() the string by spaces (assuming a space separates words) then slice the first (up to) 5 elements. If there are greater than 5 element, add "...read more"; if not, it's unnecessary.
You can use some regex replace and (with a negative lookahead) ignore the first 5 words, but replace all other text with your "...read more". (I personally find this one having more overhead, but you could probably use (?!(?:[^\b]+?[\b\s]+?){5})(.*)$ as a pattern)
Having said that, here's what i mean with a string split:
function readMore(el){
var ary = el.innerHTML.split(' ');
el.innerHTML = (ary.length > 5 ? ary.slice(0,5).join(' ') + '... read more' : ary.join(' '));
}
var p = document.getElementById('foo');
readMore(p);
Assuming of course, for the purposes of this demo, <p id="foo">Hello, world! How are you today?</p> (which would result in <p id="foo">Hello, world! How are you...read more</p>)
$('p').text($('p').text().replace('world!', '... show more'));