IE7为何不复制<pre><code> blocks to the clipboard correctly?</code></pre>

时间:2008-09-25 21:58:05

标签: html internet-explorer

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

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

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

public PageSizer(string href, int index){    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与富文本剪贴板中的不同内容相比,而不是记事本从中获取数据的纯文本剪贴板。

7 个答案:

答案 0 :(得分:35)

似乎这是IE6的已知错误,而prettify.js有一个解决方法。具体来说,它用'\ r \ n'替换BR标签。

通过修改检查以允许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);
          }

您可以看到working example here

注意:我还没有在IE6中测试过原来的解决方法,所以我猜它没有IE7中出现的'\ n'引起的空间渲染,否则修复是简单。

答案 1 :(得分:13)

问题在于:

您的代码着色脚本使用&lt; br /&gt;替换换行符标签。复制/粘贴时,IE7显然不会翻译&lt; br /&gt;标记为与屏幕一样的换行符。

换句话说,您的代码变为:

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行(重组标记和修饰的一部分):


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

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


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

(假设newlineRe是占位符)。

此修复程序在Chrome和FFX3中也有用...我不确定哪些(如果有的话)浏览器需要&lt; br /&gt;标签

<强>更新 我的第二个回复中的更多信息:
Why doesn't IE7 copy <pre><code> blocks to the clipboard correctly?

答案 2 :(得分:2)

这看起来像IE中的一个错误, PRE CODE 中的 BR 标签未在纯文本副本中转换为换行符缓冲。富文本复制缓冲区很好,因此粘贴的工作方式与 wordpad 等应用程序一样。

用于为代码着色的美化脚本删除所有空白,并将其替换为空格和新行的HTML标记。生成的代码如下所示:

<pre><code>code<br/>&nbsp;&nbsp;code<br/>&nbsp;&nbsp;code<br/>code</code></pre>

PRE CODE 标签默认呈现,CSS样式为 {whitespace:pre} 。在这种情况下,IE无法将 BR 标记转换为换行符。它可以在原始HTML上运行,因为IE会成功地将实际换行符转换为换行符。

为了解决这个问题,你有3个选择。 (我假设你想要很好的HTML 能够在客户端上启用和不启用javascript的情况下运行良好):

  1. 您可以将代码置于普通div中,并使用CSS使用 {whitespace:pre} 进行渲染。这是一个简单的解决方案,虽然可能不会取悦HTML标记纯粹主义者。

  2. 您可以拥有两个代码副本,一个使用正确的 PRE / CODE 标记,另一个使用普通div。在你的CSS中隐藏正常的div。使用javascript你可以美化正常的div并隐藏pre / code版本。

  3. 修改美化脚本,以识别它是在 PRE CODE 元素上运行,而不是替换该事件中的空白。


  4. 备注:

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

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

答案 3 :(得分:1)

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

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

答案 4 :(得分:0)

坏消息:提议的修复工作都没有。在第1000行修改prettify.js

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

这会导致其他浏览器出现双倍间距,仍然无法解决IE7复制到记事本问题!因此,即使我有选择地检测到IE7,这个“修复”也无法解决任何问题。

我想也许这只是IE7中与JavaScript重建<pre>元素有关的一个错误 - 无论我放入多少\ n新行,没有任何改变w / r / t到粘贴记事本的行为。

答案 5 :(得分:0)

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

我怀疑我之前提到的修复不起作用,因为在调用第〜1000行之后,美化是对文本进行一些额外的处理。

尝试从添加到页面时向后追踪内容,我在第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似乎需要\ r \ n,而不仅仅是\ n。确切地说明哪些浏览器将采用比我现在更方便的更广泛的测试设置。

无论如何,为IE7插入\ r \ n n似乎基本上是需要发生的事情。我会一直在讨价还价,看看我是否可以进一步缩小范围。

更新: IE7似乎从分配给innerHTML属性的字符串中删除换行符(\ r或\ n)。看起来他们需要在第1227行附近重新加入。

正确的解决方案可能意味着在第1000行周围插入占位符标记,然后在第1227行附近替换它。

答案 6 :(得分:-1)

删除内部<code>。 IE的复制/粘贴行为可以将其视为内联标记并忘记可见空白。