为什么IE7不能正确地将<pre> <code>块复制到剪贴板?

我们已经注意到,IE7有一个奇怪的行为,在Stack Overflow上发布代码块。 例如,这个小代码块:

public PageSizer(string href, int index) { HRef = href; PageIndex = index; } 

从IE7复制粘贴,结果如下:

公共PageSizer(stringhref,诠释指数){HRef = href的;  PageIndex = index;  }

不完全是我们想到的..底层的HTML源实际上看起来不错, 如果你查看源代码,你会看到这个:

 <pre><code>public PageSizer(string href, int index) { HRef = href; PageIndex = index; } </code></pre> 

那么我们做错了什么? 为什么不能IE7以合理的方式复制和粘贴这个HTML?

更新: 这个特别是与在运行时通过JavaScript修改的<pre> <code>块有关。 原生HTML确实呈现并正确复制; 这是该HTML的JavaScript修改版本,其行为不像预期的那样。 请注意,复制和粘贴到写字板或Word的作品,因为IE浏览器将富文本剪贴板中的不同的内容相比,记事本获取其数据的纯文本剪贴板。

看来这是IE6的一个已知的bug,prettify.js有一个解决方法。 具体来说,它将BR标签replace为“\ r \ n”。

通过修改检查以允许IE6或7,然后剪切和粘贴将从IE7正常工作,但它将呈现一个换行符后面一个空格 。 通过检查IE7并提供一个'\ r'而不是'\ r \ n'它将继续剪切并粘贴并正确渲染。

将此代码添加到prettify.js中:

 function _pr_isIE7() { var isIE7 = navigator && navigator.userAgent && /\bMSIE 7\./.test(navigator.userAgent); _pr_isIE7 = function () { return isIE7; }; return isIE7; } 

然后修改prettyPrint函数,如下所示:

  function prettyPrint(opt_whenDone) { var isIE6 = _pr_isIE6(); + var isIE7 = _pr_isIE7(); 

 - if (isIE6 && cs.tagName === 'PRE') { + if ((isIE6 || isIE7) && cs.tagName === 'PRE') { var lineBreaks = cs.getElementsByTagName('br'); + var newline; + if (isIE6) { + newline = '\r\n'; + } else { + newline = '\r'; + } for (var j = lineBreaks.length; --j >= 0;) { var lineBreak = lineBreaks[j]; lineBreak.parentNode.replaceChild( - document.createTextNode('\r\n'), lineBreak); + document.createTextNode(newline), lineBreak); } 

你可以在这里看到一个工作的例子 。

注:我没有在IE6中testing原来的解决方法,所以我猜测它没有IE7中看到的'\ n'造成的空间,否则修复更简单。

这是问题:

您的代码着色脚本用<br />标签replace换行符。 当复制/粘贴时,IE7显然不会将<br />标记转换为像屏幕一样的换行符。

换句话说,你的代码变成这样:

 public PageSizer(string href, int index)<br />{<br /> HRef = href;<br /> PageIndex = index;<br /> } 

但是你想让它变成这样:

 public PageSizer(string href, int index)<br /> {<br /> HRef = href;<br /> PageIndex = index;<br /> }<br /> 

在Google Code的最新版本prettify.js中,负责的行是1001行(recombineTagsAndDecorations的一部分):

 html.push(htmlChunk.replace(newlineRe, '<br />')); 

根据评论编辑:
对于IE7,这可能是该行应该改为:

 html.push(htmlChunk.replace(newlineRe, '\n')); 

(假设newlineRe是一个占位符)。

这个修补程序也支持Chrome和FFX3 …我不确定哪个(如果有的话)浏览器需要<br />标签。

更新:我的第二个回复中的更多信息:
为什么IE7不正确地将<pre> <code>块复制到剪贴板?

这看起来像IE中的错误, PRECODE内的BR标签不会被转换成明文复制缓冲区中的换行符。 富文本复制缓冲区是好的,所以粘贴工作正如预期的应用程序,如写字板

美化脚本为代码添加颜色,删除所有空白,并用空格和换行符的HTML标记replace。 生成的代码如下所示:

 <预> <代码>代码<BR/>&NBSP;&NBSP;代码<BR/>&NBSP;&NBSP;代码<BR/>代码</代码> </ PRE>

PRECODE标签默认以{whitespace:pre}的CSS样式呈现。 在这种情况下,IE无法将BR标签变成换行符。 它会在你原来的HTML上工作,因为IE会成功地将实际的换行符变成换行符。

为了解决它,你有3个选项。 (我假设你想要漂亮的HTML 并且能够在客户端上启用和不启用JavaScript):

  1. 你可以把代码放在一个普通的div中,并使用CSS来使用{whitespace:pre}来渲染它。 这是一个简单的解决scheme,虽然可能不会请一个HTML标记纯化。

  2. 你可以有两个代码副本,一个使用正确的PRE / CODE标签,另一个使用正常的div。 在你的CSS你隐藏正常的div。 使用JavaScript你美化正常的div和隐藏的前/代码版本。

  3. 修改美化脚本以识别它正在处理PRECODE元素,而不是replace该事件中的空白。


笔记:

  • 重要的不是源代码中的HTML,而是在美化脚本之后生成的HTML。

  • 即使使用CSS将PRE的空白模式更改为正常,该错误仍然存​​在。

这个网站已经解决了这个问题: http : //www.developerfusion.com/tools/convert/csharp-to-vb/

我build议“复制到剪贴板”button作为代码显示框的一部分。 该button将以纯文本forms复制显示信息的版本。 纯文本可以存储为内部页面属性。

坏消息:没有提出的修复工作。 修改1000行左右的prettify.js

 html.push(htmlChunk.replace(newlineRe, '\n')); 

这导致在其他浏览器的双间距, 仍然不解决IE7复制到记事本问题! 所以,即使我select性地检测到IE7,这个“修复”并不能解决任何问题。

我想也许这只是IE7中的一个bug,与JavaScript重build一个<pre>元素有关 – 无论我在那里放置多less个新行,都不会改变粘贴到记事本行为的w / r / t。

@Jeff Atwood这是正确的想法,但实施仍然需要工作。 我想我的空气代码只是没有削减它:)

我怀疑我之前提到的修补程序是行不通的,因为美化线正在对行1000之后的文本做一些额外的处理。

试图追踪从添加到页面的内容开始,我在1227行的第1227行看到这个评论:

 // Replace <br>s with line-feeds so that copying and pasting works // on IE 6. // Doing this on other browsers breaks lots of stuff since \r\n is // treated as two newlines on Firefox, and doing this also slows // down rendering. 

当我从代码中取得isIE6条件时,它主要在IE7中工作(在顶部和底部有一个额外的换行符)和Firefox 3 …但是我认为它会导致老版本的FFX 。

IE7似乎至less需要\ r \ n,而不是\ n。 搞清楚哪些浏览器将采取更广泛的testing设置什么将比我现在得心应手。

无论如何,插入IE7的\ r \ n似乎基本上是需要发生的事情。 我会继续围绕美化,看看我能否进一步缩小范围。

更新: IE7似乎从分配给innerHTML属性的string去掉换行符(\ r或\ n)。 看起来他们需要在1227行附近重新join。

一个正确的解决scheme可能意味着在行1000附近插入一个占位符标签,然后在1227行左右进行replace。

删除内部的<code> 。 IE的复制/粘贴行为可以看到,作为一个内联标签,忘记可见的空白。