0

php:

$str1 = "AAA\r\nBBBB\\CCC";
echo"<textarea id='aa1' onfocus='erase(\"".$str1."\", \"aa1\");'></textarea>";
$str2 = "AAABBBB\\CCC";
echo"<textarea id='aa2' onfocus='erase(\"".$str2."\", \"aa2\");'></textarea>";
$str3 = "AAABBBB\CCC";
echo"<textarea id='aa3' onfocus='erase(\"".$str3."\", \"aa3\");'></textarea>";
$str4 = "AAABBBBCCC";
echo"<textarea id='aa4' onfocus='erase(\"".$str4."\", \"aa4\");'></textarea>";

javascript:

function erase(str, id)
{
 alert("good");
 var field = document.getElementById(id);
 if(field.value == str)
 {
 field.value = '';
 }
}

If I click on textarea id='aa1', nothing happens.

If I click on textarea id='aa2' or textarea id='aa3', 'good' is printed but nothing happens to field.value.

If I click on textarea id='aa4', 'good' is printed and field.value is ''.

I want a string like AAA\r\nBBBB\\CCC to work like textarea id='aa4.

How can I do that?

I read the post below but it does not seem to help my situation:

Javascript parameter

Javascript Line Break Textarea


update:

I've replaced $str1 with json_encode($str1), So alert(); works fine now. (Thanks to Jordan Running.)

But the field.value part still does not work.

code refactoring is too hard in my situation... Is there any way to handle the field.value problem without code refactoring?

If quotes corrupt my HTML, I can putting $str1 in htmlspecialchars() and displaying it in <textarea>.

asked Jul 7, 2017 at 14:31
3
  • JS string cannot handle newlines. You can JSON encode them if you need the crlf Commented Jul 7, 2017 at 14:34
  • 1
    Check the error console? Commented Jul 7, 2017 at 14:35
  • String building JS from another language is a bad idea. Consider researching unobtrusive JS. Commented Jul 7, 2017 at 15:36

1 Answer 1

0

Generally speaking it's a bad idea to use string concatenation to build JavaScript. Your PHP code produces the following HTML:

<textarea id='aa1' onfocus='erase("AAA
BBBB\CCC", "aa1");'></textarea>

That's valid HTML, but the code in your onfocus attribute is not valid JavaScript. In JavaScript, you can't have a line break in the middle of a string literal. You can have a line break in a template literal (i.e. `one of these`), but that's not the right solution here.

A quick but short-sighted fix

When you need to "inject" some data into a block of JavaScript, you should always use json_encode:

$str1 = "AAA\r\nBBBB\\CCC";
echo "<textarea id='aa1' onfocus='erase(" . json_encode($str1) . ", \"aa1\");'></textarea>";

Make careful note of the quotation marks above. Because json_encode wraps strings in quotation marks, you don't need additional quotes around . json_encode($str1) ..

This will produce the following HTML:

<textarea id='aa1' onfocus='erase("AAA\r\nBBBB\\CCC", "aa1");'></textarea>

...whose onfocus handler works correctly, as you can see in this snippet:

function erase(...args) { console.log('erase called with', args); }
<textarea id='aa1' onfocus='erase("AAA\r\nBBBB\\CCC", "aa1");'></textarea>

A better way

The above is still fragile. What if your data has a ' in it? That'll break your HTML. The correct solution is to move your data out of the HTML entirely. Consider if you refactored your code to look something like this:

<textarea id="aa1"></textarea>
<textarea id="aa2"></textarea>
<textarea id="aa3"></textarea>
<textarea id="aa4"></textarea>
<?php
 $erase_map = [
 'aa1' => "AAA\r\nBBBB\\CCC",
 'aa2' => "AAABBBB\\CCC",
 'aa3' => "AAABBBB\CCC",
 'aa4' => "AAABBBBCCC",
 ];
?>
<script>
 const ERASE_MAP = <?php echo json_encode($erase_map); ?>;
 function erase(event) {
 if (event.target.value == ERASE_MAP[event.target.id]) {
 event.target.value = '';
 }
 }
 document.querySelectorAll('textarea').forEach(textarea => textarea.addEventListener('focus', erase));
</script>

In the above code, all of the data is in one place—a single associative array—instead of scattered around your HTML. It generates HTML code with a <script> tag into which the data is injected as a JSON object and assigned to a JavaScript variable:

<textarea id="aa1"></textarea>
<textarea id="aa2"></textarea>
<textarea id="aa3"></textarea>
<textarea id="aa4"></textarea>
<script>
 const ERASE_MAP = {"aa1":"AAA\r\nBBBB\\CCC","aa2":"AAABBBB\\CCC","aa3":"AAABBBB\\CCC","aa4":"AAABBBBCCC"};
 
 function erase(event) {
 if (event.target.value == ERASE_MAP[event.target.id]) {
 event.target.value = '';
 }
 }
 document.querySelectorAll('textarea').forEach(textarea => textarea.addEventListener('focus', erase));
</script>

answered Jul 7, 2017 at 15:10
Sign up to request clarification or add additional context in comments.

2 Comments

If quotes corrupt my HTML, I can putting $str1 in htmlspecialchars() and displaying it in <textarea>. Is there any way to handle the field.value problem without code refactoring? @JordanRunning
@Saturn It's hard to help you solve a problem if you don't explain what it is. However, I have a feeling the issue is that you're comparing AAA\r\nBBBB... to AAA\nBBBB.... See this related question: stackoverflow.com/questions/14217101/… If you're still having trouble, post a new question.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.