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

Saturn
  • 55
  • 10

1 Answers1

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>
Jordan Running
  • 102,619
  • 17
  • 182
  • 182
  • If quotes corrupt my HTML, I can putting `$str1` in `htmlspecialchars()` and displaying it in ` – Saturn Jul 07 '17 at 16:09
  • @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: https://stackoverflow.com/questions/14217101/what-character-represents-a-new-line-in-a-text-area If you're still having trouble, post a new question. – Jordan Running Jul 07 '17 at 16:22