HTML文本框忽略第一个换行符,为什么?

13

你能解释一下为什么会出现这种情况吗:

<script type="text/javascript">
   document.write("<textarea cols='10' rows='10'>" + "\nhello\nbabe\n" + "</textarea>");
</script>

渲染一个文本域,底部有一个换行符,但顶部没有

enter image description here

在IE8、FF11、Safari 5.1和Chrome 24中测试过。

这不是JavaScript的问题,即使您在页面中编写HTML,也会得到相同的结果。

<textarea cols='10' rows='10'>
hello
babe
</textarea>

第一行还是没有换行!!!

我需要在顶部添加另一个换行才能显示一个:

document.write("<textarea cols='10' rows='10'>" + "\n\nhello\nbabe\n" + "</textarea>");

你尝试使用 <br> 标签了吗? - Ezhil V
2
"\n"不会被视为文本区域值,而是作为HTML换行符。 - imclickingmaniac
6个回答

5

在编写XHTML时,请使用适当的实体。

<textarea>&#13;hello</textarea>

如果一个文本节点以空格或者换行符开头,它将被HTML解析器忽略。把换行符编码成适当的HTML实体可以强制解析器识别它。

&#13; == carriage return

它在IE8上无法工作,但在Chrome 24、Safari和FF上可以正常工作。我认为这是IE8的bug。 - Marco Demaio
@Marco Demaio - IE8可能需要一个换行符(&#10), 因为Windows认为一个新的换行符“\n”是回车加换行( &#10)。 - Louis Ricci
你让我的一天变得美好了。Textarea 已经占用了一个小时的时间啦。 - shukshin.ivan
1
对我来说可以。在脚本中:s = s.replace (/^\n/," ") - Panu Logic

5
回答“为什么”的问题。这在HTML 5规范中的一章中指定,该章描述了如何从HTML文档中找到的标签创建DOM树。
在当前的HTML 5生存标准中,它是“12.2解析HTML文档”>“12.2.6树构造”>“12.2.6.4解析HTML内容中的令牌的规则”>"12.2.6.4.7"插入模式"。

(在HTML 5.2中,相同的部分编号为
8.2.5.4.7)。
向下滚动以查看“其标记名称为“textarea”的开始标记”的项目
引用块:

其标记名称为“textarea”的开始标记
运行以下步骤:
1.为令牌插入HTML元素。
2.如果下一个令牌是U+000A LINE FEED(LF)字符令牌,则忽略该令牌并继续进行下一个令牌。(在textarea元素开头的换行符被忽略为作者方便。)
3.将标记器切换到RCDATA状态。
......

该算法仅处理LF字符,因为CR字符已在先前处理
(从历史上看,研究已过时的HTML 4.01规范: 其第17.7章“TEXTAREA元素”有一个示例,显示textarea的文本内容从新行开始。 附录B.3.1换行符(信息)解释了这种行为起源于SGML。)

现在,在HTML 5中,</textarea>结束标记之前的换行符不再被忽略。

3
如果可能的话,请将您的代码更改为预定义为HTML的文本区域,然后像这样编写字符串:
HTML:
<textarea cols='10' rows='10' id='test'></textarea>

脚本:

document.getElementById('test').innerHTML = '\nhello\nbabe\n';

那样可以保留空格。你可以选择添加CSS规则:
textarea {
    white-space:pre;
    }

一个可以玩耍的小提琴:
http://jsfiddle.net/RFLwH/1/

更新:

楼主在IE8中测试了这个小提琴,但它并不起作用——这似乎是这个浏览器的限制/bug。如果你在顶部手动插入换行符,则IE8确实使用CR+LF,但当设置为编程时,这在浏览器中完全被忽略。

将此添加到HTML中进行测试:

<span onclick="this.innerHTML = escape(document.getElementById('test').innerHTML);">
    Get textarea content
</span>

你可以看到返回的字符串是:
 %0D%0Ahello%20babe%20

这意味着CR+LF存在(其他换行符被转换为空格 - 但在开头插入空格也没有帮助)。我猜测您无法解决此问题;浏览器已经过时(但不幸的是,仍然广泛使用,因此如果这很重要,则可能会对那些用户造成问题)。


它在IE8上无法工作,但在Chrome 24、Safari和FF上可以。我认为这是IE8的bug。 - Marco Demaio
是的,这并不奇怪。我为ie8进行了测试(本地测试,因为fiddle在ie8中也无法显示),手动在顶部插入了一个换行符,并将文本取出并转义以查看其包含的内容。它确实在/r/n处插入,但是当从javascript中设置时,它完全忽略它。猜想对此没有太多可以做的 :-/ - user1693593

1
在第一个“\n”前添加一个空格,像这样:
<script type="text/javascript">
   document.write("<textarea cols='10' rows='10'>" + " \nhello\nbabe\n" + "</textarea>");
</script>

或者

<textarea cols='10' rows='10'> <!-- whitespace here -->
hello
babe
</textarea>

否则它将无法正常工作。
更新: 在服务器端,您可以通过执行以下操作来删除第一个空格。
$str = ltrim ($str,' ');

或者

$str2 = substr($str, 4);

如果这是PHP。

脚本中的空格会在第一行渲染一个空格。这不好,文本区域中的数据可能会被发送到服务器,并且它们将被保存到数据库中,其中包含没有人需要的额外空格。 - Marco Demaio

1

在顶部应该有一个\n\r

document.write("<textarea cols='10' rows='10'>" + "\n\rhello\nbabe\n" + "</textarea>");

jsbin


多么奇怪,但是对我来说使用 '\n\r' 而不是 '\r\n' 起作用了! - Zack Macomber

0

最终我完成了这个服务器端的解决方案:

在将其输出到文本区域之前,将首个换行符的引导符号(仅限第一个!)加倍:

if(str_startswith("\r\n",$value))
{
    $value = "\r\n".$value;             
}elseif(str_startswith("\n",$value))
{
    $value = "\n".$value;
}elseif(str_startswith("\r",$value))
{
    $value = "\r".$value;
}

function str_startswith($start, $string)
{
  if(mb_strlen($start)>mb_strlen($string))
    return FALSE;
  return (mb_substr($string, 0,mb_strlen($start))==$start);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接