jQuery: Preserve user-inputted line breaks in <textarea> - javascript

I've been scouring Google and SO for hours but can't seem to find an answer to this for the life of me!
All I want to do is preserve the line breaks entered into a <textarea> element by the user, to post the content via a jQuery $.ajax() call. If I simply submit the form to a page as usual, this works, but I've been told by my boss to use REST/AJAX.
Many, many posts on SO and across the net in general mention replacing \n's with <br />'s, or using white-space: pre-wrap; in the element's CSS. These solutions do not work for me as the line breaks simply don't show up in Chrome Developer Tools.
Code snippet:
<form id="addPostForm" role="form" method="post" action="/blog">
<div class="form-group">
<textarea rows="5" id="postBody" name="postBody"></textarea>
...more input controls
</div>
<button type="submit" class="btn btn-primary btn-block">Submit</button>
</form>
<script type="text/javascript">
$(document).on('submit', '#addPostForm', function() {
var postBody = $(this)[0].postBody.value;
...more code
});
</script>
When I enter e.g.:
"This is the first paragraph.
And here is another.
And yet another."
The postBody variable's value is:
"This is the first paragraph. And here is another. And yet another."
This is driving me crazy! Surely this shouldn't be as hard as it seems to be!
P.S. I don't think it should make a difference, but just in case anyone is wondering, I'm using Python/Pyramid, Jinja2 and Bootstrap 3 for this project.

Use this in JS
$("input[type=submit]").click(function(){
$.ajax({
type: "POST",
url: "yoururl",
data: $("#addPostForm").serialize()
(...)
});
});
In your server side code you can get POST value postBody with original spaces.

It would appear to me that this problem stems from the Chrome Dev Tools stripping the line breaks. Change the tool settings, or try something else like firebug.

Try splitting the lines by '\n' (yes I have tested this) and rejoin them with tags, check this out:
$('textarea').val().split('\n')
put this in your onclick function and set a breakpoint on it if you are using Chrome, it splits the lines into an array. if you join them with
.join('<br>')
you should be good to go.

Oops sorry for wasting your time, it was as simple as using $('#postBody').val() instead of $(this)[0].postBody.value. Thanks anyway to all commenters and answerers!

Related

Why does JQuery .val() method sometimes return undefined when code is valid? [duplicate]

This question already has answers here:
val() vs. text() for textarea
(2 answers)
Closed 4 years ago.
Not a duplicate question; so please consider the content closely before presumption.
I've been using JQuery for years and have never seen this type of behavior before. Consider the following:
<html>
<div class="order-form-group">
<label class="order-form-label" for="guestSpecialInstructions">Special Instructions:</label>
<textarea class="order-form-textarea" id="guestSpecialInstructions" type="text"></textarea>
</div>
<div class="order-form-group">
<label class="order-form-label" for="guestReason">Reason:</label>
<textarea class="order-form-textarea" id="guestReason" type="text"></textarea>
</div>
<div class="button-container">
<input class="order-form-submit" type="submit" value="Submit">
</div>
</html>
I've observed that the following script in some instances will return 'undefined' even when "all" the more obvious reasons have been eliminated. Such as
having the incorrect selector, having more than 1 id on the page and etc.
<script>
var specInstr = $("#guestSpecialInstructions").val();
var guestReason = $("#guestReason").val();
</script>
I spent literally hours attempting to determine what the disconnect was; stripping my code to the simplest basic level and couldn't find any reasonable explanation for the behavior.
The code is contained within a simple HTML page; nothing fancy and references the JQuery repository https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js
I have another project which runs in an aspx page, still the markup is identical and the .val() method works without issue.
After hours of hitting a wall I ran across the post at JQuery: .val() is not working for textarea and someone else attesting to the exact same issue using valid code and the suggestion was:
<script>
var specInstr = $("#guestSpecialInstructions")[0].value;
var guestReason = $("#guestReason")[0].value;
</script>
Then the issue is automagically resolved. Only problem I have with this is that there no one seems to have answered the question of why the JQuery .text() method sometimes return undefined when all aspects of the code is valid.
Resolutions are great but without understanding why the issue exists, really gains nothing intellectually.
If I need to change the wording of the title, let me know.
You can only use text() on a <textarea> if it is pre-populated and to return the original content
Any changes to the content by user or setting new value programatically will not alter what is returned by text() as it will always be the original pre-pre-populated content
Always use val() to get and set
var $txt = $('textarea')
console.log('text() Original content:', $txt.text())
console.log('val() Original content:', $txt.val())
$txt.val( 'Some new content')
console.log('text() after value change:', $txt.text())
console.log('val() after value change:', $txt.val())
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="one" type="text">
Original text
</textarea>

parse <script> tag with js/jQuery

I have a HTML page where a user is able to edit a HTML resource (using ACE Editor). Within this HTML source, there is a <script>-tag, which does some pretty basic stuff.
Is there any elegant solution to parse the script tag in order to (e.g.) evaluate the variables used within the script tag? For "normal" tags I use parseHTML() to have the html as a jQuery object.
From this example, I would like to retrieve the value of $myVal (which is "f00") and write it to #myLabel:
<textarea id="myScript" rows="5" readonly>
<script>
$myVal = "f00";
</script>
</textarea>
<label id="myLabel">Hello</label>
$(function(){
$scriptVar = $('#myScript').text;
// parse the $scriptVar
// retrieve the value of, $myVal, write it to #myLabel
//$myParsedValue = ???
//$('#myLabel').text('bar!');
});
And here is the fiddle: https://jsfiddle.net/stepdown/jqcut0sn/
Is this possible at all? I don't really care about vanilla js, jQuery, regex or maybe even an external library for that purpose.
Thanks to #JeremyThille, who pointed me to the right direction. I found out, what I want to achieve is possible through jQuerys $.globalEval() - see the official documentation.
Basically what globalEval() does: it runs the script which is written in the <textarea> and makes the variables / functions globally accessible.
IMPORTANT: this implies, that syntax errors (etc) by the user will break the evaluation, and sequential functionality could be flawed. Also, the new variables are GLOBAL, so basically a user could rewrite scripts on the hosting page. (In my case both problems are of minor importance, since this is an internal application for trained users - they also have syntax highlighting through the amazing ACE editor. But I wanted to make sure to point it out. Also, there are several articles regarding the risks/ouch-moments when using eval()...)
I updated the fiddle to achieve what I wanted: https://jsfiddle.net/stepdown/Lxz7q6uv/
HTML:
<textarea id="myScript" rows="5" readonly>
$myVal = "f00";
</textarea>
<hr />
<label id="myLabel">Hello</label>
Script:
$(function(){
var myScriptContent = $('#myScript').text();
$.globalEval(myScriptContent);
console.log($myVal);
$('#myLabel').text($myVal);
});

knockout.js best way to bind html string in textarea with line breaks

I've got the html string that I'd like bind with knockout.js and display it in textarea, and of course allow submitting it after some editing. What is the proper way to achieve that?
When I use HTML binding, I can bind one <br/> two string and it displays the same in textarea, but after submitting, I get the encoded string one<br/>two, which isn't too bad as I can handle it later, but there's still the line breaks issue.
Basically I'd like to preserve:
original line breaks
original html text
Now, when I pass:
<html>
<body>
using both value and html binding, in knockout I get script exception, as new lines are not handled. Special characters are encoded as well:
Content: ko.observable("<html>
<body>
Any ideas?
You might want to use btoa to encode the actual value so that no munging goes on in submission. Then you would use atob to decode on the server. Here's a little demo that lets you see how various treatments of html come out.
ko.applyBindings({stuff: ko.observable('<h1>Foo</h1>hi\nthere')});
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<textarea data-bind="value:stuff"></textarea>
<pre data-bind="text:stuff"></pre>
<hr />
<pre data-bind="html:stuff"></pre>
<hr />
<pre data-bind="text: btoa(stuff())"></pre>

Load HTML within AJAX call

I'm having some difficulty with a Javascript function I am writing. The basic function of the script is that when a specific AJAX function is called and returns successful, it loads some HTML from a file and inserts that HTML into a on the main page and then (once loaded), fades in the parent div.
jQuery.ajax({
type: "POST",
url: "fns/authenticate.php",
data: dataString,
success: function (data) {
if (data=='1') {
jQuery("#authlogin").fadeOut(500, function(){
$(this).remove();
jQuery("#result").load("fns/logic.html", function() {
jQuery('#authtrue').fadeIn(1000);
});
});
} else {
jQuery('#details-error').fadeIn(200);
}
}
});
return false;
Now the AJAX seems to function properly, in that it will execute under the correct conditions and fade out and in the correct divs, the problem seems to be that the content isn't being loaded from logic.html or it is not being bound to the #result div correctly.
The main page's html looks like:
<div id="authlogin">
<!-- HTML form -->
</div>
<div id="authtrue" style="display: none;">
<div id="result"></div>
</div>
Any help would be much appreciated.
This is one of those things that you must troubleshoot yourself, because we do not have access to your fns/logic.html and therefore cannot test fully.
However, some thoughts:
(1) The basic logic of your .load() success function seems correct. Here is a jsFiddle that approximates the AJAX success function's logic. I substituted .html() for .load() because jsFiddle cannot do ajax. Anyway, assuming that .load() is doing what it should, that part should be working.
(2) You may already know this, but note that .load() is shorthand for $.ajax() -- as are .post() and .get(). You might find $.ajax() easier to troubleshoot as the code block is more structured. As a general rule, troubleshooting the shorthand constructions is slightly more abstract/difficult than troubleshooting $.ajax()
(3) Use developer tools in Chrome (press F12 key) to verify that the contents of logic.html have been inserted into the #result div. You might find, as I did in playing with my jsFiddle, that the contents were injected but the #authtrue div remained hidden. At least you will know that the logic.html document has been found and contents inserted. Knowing exactly where the problem is, finding/fixing the rest might now be trivial.
(4) Does your logic.html file include unnecessary header information? If so, you can strip it out by only inserting the BODY of the document, or a top-level containing div. See this section of the jQuery docs:
jQuery("#result").load("fns/logic.html #container", function() {//CALLBACK IN HERE});
(5) It would be a smart idea to create a test document that just and only loads the logic.html document, using various methods:
Method A: Using PHP (or whatever server-side language you use)
<div id="authlogin">
<!-- HTML form -->
<input type="button" id="mybutt" value="Click Me to Start" />
</div>
<div id="authtrue" style="display:none;">
<div id="result"><?php include 'logic.html'; ?></div>
</div>
Method B: Using load()
HTML:
<div id="authlogin">
<!-- HTML form -->
<input type="button" id="mybutt" value="Click Me to Start" />
</div>
<div id="authtrue" style="display:none;">
<div id="result"></div>
</div>
jQuery:
jQuery('#authtrue').show();
jQuery("#result").load("fns/logic.html");
(6) Ensure you do not have a typo in the destination element jquery selector: If no element is matched by the selector — in this case, if the document does not contain an element with id="result" — the Ajax request will not be sent. (from the docs)
I managed to fix this myself, thanks to the help of everyone here. It ended up being a browser caching problem. As soon as I cleared the cache everything magically worked.

Mixing razor syntax with Javascript in views

What's the proper way to go about it. I need it to work like in the example below.
<input type="button" value="Resume" onclick="window.location = '/Test?testid=#(ViewBag.TestID)'" />
I absolutely support Zabavsky's comment that you should use an ActionLink for this specific example in order to have semantically correct markup.
But since you asked:
Mixing razor syntax with Javascript in views
Never do that.
In your view you should have only markup:
<input type="button" value="Resume" id="myButton" data-url="#Url.Action("Test", new { testid = ViewBag.TestID })" />
and javascript (IN A SEPARATE FILE) where you could work with this markup and unobtrusively enhance it:
$(function() {
$('#myButton').click(function() {
window.location.href = $(this).data('url');
});
});
Of course if the user has javascript disabled your web application is completely busted. That's why you should always write semantically correct markup. In this case that would be to use an anchor because in HTML buttons are used to submit forms, anchors are used to redirect to some other location (which is exactly what you are trying to achieve in this specific case).
I would, as Zabavsky said, use an ActionLink for this:
Something like this:
#Html.ActionLink("Resume", "Test", new { testid = ViewBag.TestID })
There are quite a few overrides for actionlink, so you need to pick the one which fits your needs.
The one above output an a href with the text 'Resume' going to action 'Test' on the current controller, passing a routevalue of testid = ViewBag.TestID
You can do it like:
<html><head><script>function newDoc() { window.location.assign("http://www.abc.com") }</script></head><body><input type="button" value="Load new document" onclick="newDoc()"></body></html>
Hope it will help. Thanks.
Well, what you wrote is valid.
You may have VS underline your code in red cause it think you have a js error due to the '' string not ended... but if you run it, it works.
To avoid red underline, you could do :
#{string js = "window.location = '/Test?testid="+ViewBag.TestID+" '";}
<input type="button" value="Resume" onclick="#js" />

Categories