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 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>.
-
JS string cannot handle newlines. You can JSON encode them if you need the crlfmplungjan– mplungjan2017年07月07日 14:34:25 +00:00Commented Jul 7, 2017 at 14:34
-
1Check the error console?James– James2017年07月07日 14:35:21 +00:00Commented Jul 7, 2017 at 14:35
-
String building JS from another language is a bad idea. Consider researching unobtrusive JS.zzzzBov– zzzzBov2017年07月07日 15:36:07 +00:00Commented Jul 7, 2017 at 15:36
1 Answer 1
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>
2 Comments
$str1 in htmlspecialchars() and displaying it in <textarea>. Is there any way to handle the field.value problem without code refactoring? @JordanRunningAAA\r\nBBBB... to AAA\nBBBB.... See this related question: stackoverflow.com/questions/14217101/… If you're still having trouble, post a new question.