jquery/javascript maintain linebreak when copying text - javascript

Suppose I have
<input type="hidden" id="in1">
...
<p id="editable_p"></p>
<script>
$('#some_button').click( function() {
$('#in1').val($('#editable_p').text());
});
</script>
Clearly, my intention is to set the value of the hidden field to be the content of the <p> tag. This works, however it does not maintain line breaks, which is important for me. Is there a basic library function that will copy the value of the editable paragraph that maintains the linebreaks, or is there some kind of extended hack that must be performed to get this to work as I intend?
Thanks much in advance.

You may find there are a number of text nodes in your #editable_p.p and calling text() as per a lot of XML type environments, will just concatenate the strings from the text nodes found in the descendant tree, potentially losing structure. This operation can do weird stuff to line breaks and other whitespace.
To avoid this, iterate over the actual text nodes, and concatenate the strings yourself, adding \n end of lines as necessary. Assuming you have succeeded in this and have the string with line breaks, I think talereader could be correct that a textarea or similar may be needed to represent the resulting string, and submit it faithfully to a server.
Selecting text nodes with JQuery is already outlined in
How do I select text nodes with jQuery?

Related

How to append newline to text value in javascript array?

I have a narrow button that contains an image and label text. The state of the button changes to one of several values which are stored as text in an array and then changed out with textContent.
One of the values forces a line break in the label text. I would like to reserve the "blank line" below my label so that layout isn't affected every time the label breaks to two lines of text. To accomplish this, I'm trying to append a newline to every single-line value. For layout reasons, I can't simply pad the container — I need it to match the height of a line of formatted text.
Is there any way to put a newline into a text array value? I've tried adding a CR to my text both within the array and prior to the array as a variable using:
Labelname + \n
Labelname\n
Labelname<br /> (HTML, I know)
var label = 'Labelname' + String.fromCharCode(13)
Nothing seems to make the newline "stick," and the console reveals the value "Labelname" without the newline.
HTML generally ignores whitespace (including newline characters). To have it rendered, you need to use an element that doesn't ignore whitespace (like <pre>), or opt in to <pre>-style whitespace handling via CSS with white-space: pre-wrap.
I ended up using innerHTML to put formatted text into the element. I was resistant to using it for various reasons, but it provided a straightforward solution to this problem.

How to replace html tags with our own tags

In my MVC web application, I have a text area inside View, in that user will put HTML text so in that text, I want to replace html tags with my own custom tags.
For Example:
HTML tag:
<input type='text' name='MyList.First_Name' data-val='true' data-val-required='Please enter first name' />
Replace with:
[~TextFieldTag|MyList.First_Name|||0|data-val=>true|data-val-required=>Please enter first name|~]
Can anyone suggest what is the best approach to do this?
I was going to recommend a simple string replacement at first, but given the seemingly complicated nature of your replacements, that might not be the best approach.
Probably the best approach would be to take the HTML, convert it to DOM elements, which can be done simply by throwing it into an elements innerHTML:
document.querySelector('button').addEventListener('click', () => {
document.querySelector('#renderSpace').innerHTML = document.querySelector('textarea').value;
});
Add some HTML:
<textarea></textarea>
<button>Press Me</button>
<div id="renderSpace"></div>
You can position the area you render it inside of off-screen so users don't actually see it.
From there, I would walk the DOM tree (basically, start at the root, then look at all of its children, then their children, etc., recursively), reading off any properties that you deem appropriate and then writing your string replacement as you go along.
That does require that they have entered valid HTML (which is generally a requirement, but can be difficult to rely on users to enter), so you'll want to have some good, user-friendly, error handling in there.

Is there a way to modify content being pasted in textAngular?

When someone pastes content copied from a website or even a word document, textAngular adds additional break <br> tags before and after the content.
I'm using textAngular like this:
<text-angular name="summary" ng-model="summary" ta-paste="trimTags($html)" required>
</text-angular>
What I'd like to do is somehow trim the leading and trailing <br> tags.
The first approach I tried was writing a regex that will trim 2 leading and trailing <br> tags.
/(\<br\s*\/\>)(\<\/?body\>)(\<br\s*\/\>)/g
This works, but the changes are NOT reflected in the text presented. Is there a way to pass this $html being pasted and reflect the changes after modifying it?
Alternatively, I tried the ng-change approach, with no luck since it pastes the actual code, sometimes mixing <br> and <p> tags it adds.
Another problem is that, you could paste something in the middle of the text, which makes detecting changes difficult and time consuming.
A silly overlook, if anyone has trouble with this, use the ta-paste and the regex from the question, and after modifying the content simply return it.
$scope.trimTags = function(content){
//process the content
return content;
};

Place tags around certain text within contenteditable without moving cursor

I am working on a simple (I thought) word processor. It uses contenteditable. I have a list of words that I want to always appear highlighted.
<article contenteditable="true" class="content">
<p>Once upon a time, there were a couple of paragraphs. Some things were <b>bold</b>, and other things were <i>italic.</i></p>
<p>Then down here there was the word highlight. It should have a different color background.</p>
</article>
So basically what I need is a way to wrap a word in <span> tags. This has proven more difficult than I expected.
Here was what I tried first:
var text = document.querySelector('article.content').innerHTML
start = text.indexOf("highlight"),
end = start + "highlight".length;
text = text.splice(end, 0, "</span>");
text = text.splice(start, 0, "<span>");
document.querySelector('article.content').innerHTML = text;
It uses the splice method found here.
And it does exactly what I need it to do, with one big issue: the cursor gets moved. Because all the text is replaced, the cursor loses its place, which isn't a good thing for a text editor.
I've also tried a couple times using document.createRange, but the issue is that while given the start and end points of a range only includes visible characters, text.indexOf("highlight") gives the index including the tags and such.
A few ideas which I'm not sure how to execute:
Figure out where the cursor begins and place it there again after using the code above
Find the difference in indexes between createRange and indexOf
Maybe there's already a library with this kind of functionality that I just can't find
Thank you for your help!
Firstly, I would recommend against doing this by manipulating innerHTML. It's inefficient and error-prone (think of the case where the content contains an element with a class of "highlight", for example). Here's an example of doing this using DOM methods to manipulate the text nodes directly:
https://stackoverflow.com/a/10618517/96100
Maintaining the caret position can be achieved a number of ways. You could use a character offset-based approach, which has some disadvantages due to not considering line breaks implied by <br> and block elements but is relatively simple. Alternatively, you could use the selection save and restore module of my Rangy library, which may be overkill for your needs, but the same approach could be used.
Here is an example using the first approach:
http://jsbin.com/suwogaha/1

Preserving Newlines When Using ".text" or ".textContent". Possible? Alternatives? Workarounds?

If I grab some html from one element, then attempt to assign it as the text content of another element, newlines are not preserved (at least not in the latest Firefox and Chromium).
So, for example, the follow code (with sensible html) produces output where the newlines are replaced by spaces. Well, except the alert, which works as expected.
$("#info").data("html", $("#info").html());
$("#jquery").text($("#info").data("html"));
document.getElementById("javascript").textContent = $("#info").data("html");
$("#alert").click(function() { alert($("#info").data("html")) });
Here's a running example: http://jsfiddle.net/76S7z/2/
There should be some method of setting the html of one element as the text of another while preserving newlines properly.
Is this possible with "text" or "textContent"? Is there an alternative way to do this? Is there a simple workaround? A less than simple workaround?
As you've already determined, Web browsers don't normally render newline characters \n as line breaks. If you're resistent to adding the line break element <br />, you can use the white-space CSS property with the value pre-line, which will:
Sequences of whitespace are collapsed. Lines are broken at newline characters, at <br>, and as necessary to fill line boxes.
Be sure to check the property's compatibility tables before using.
<div style="white-space: pre-line;">
Look
at
these line breaks!
</div>
Here's a JSFiddle example.

Categories