IE7为什么不复制

时间:2020-03-06 14:45:10  来源:igfitidea点击:
blocks to the clipboard correctly?

We've noticed that IE7 has an odd behavor with code blocks posted on Stack Overflow. For example, this little code block:

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?

Update: this specifically has to do with <pre> <code> blocks that are being modified at runtime via JavaScript. The native HTML does render and copy correctly; it's the JavaScript modified version of that HTML which doesn't behave as expected. Note that copying and pasting into WordPad or Word works because IE is putting different content in the rich text clipboard compared to the plain text clipboard that Notepad gets its data from.

解决方案

删除内部的" <code>"。 IE的复制/粘贴行为可能会将其视为内联标签,而忽略了可见的空白。

这是问题所在:

代码着色脚本将换行符替换为<br />标记。复制/粘贴时,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中的错误,PRE或者CODE中的BR标签未在纯文本复制缓冲区中转换为换行符。富文本复制缓冲区很好,因此对于像写字板之类的应用程序,该粘贴可以按预期工作。

为代码着色的prettify脚本会删除所有空白,并用HTML标记替换空格和换行符。生成的代码如下所示:

<pre><code>code<br/>  code<br/>  code<br/>code</code></pre>

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

为了修复它,我们有3个选择。 (我假设我们需要漂亮的HTML以及在客户端上启用和未启用javascript的情况下都能正常工作的功能):

  • 我们可以将代码放在普通的div中,并使用CSS使用{whitespace:pre}对其进行呈现。这是一个简单的解决方案,尽管可能不希望HTML标记纯文本作者。
  • 我们可能有两个代码副本,一个使用正确的PRE / CODE标签,另一个在常规div中。在CSS中,我们可以隐藏普通的div。使用javascript,我们可以修饰普通的div并隐藏pre / code版本。
  • 修改prettify脚本以识别其作用于PRE或者CODE元素,并且在该事件中不替换空格。

笔记:

  • 重要的不是源代码中的HTML,而是在运行美化脚本后生成的HTML。
  • 即使使用CSS将PRE的空白模式更改为正常模式,该错误仍然存​​在。

坏消息:提议的修复程序均无效。围绕行1000修改prettify.js

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

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

我想也许这只是IE7中的一个错误,与JavaScript重建一个<pre>元素有关–无论我在其中放置了多少\ n换行符,粘贴到记事本的行为都不会改变。

@杰夫·阿特伍德
这是正确的主意,但实施仍需要努力。我想我的空中代码只是没有削减:)

我怀疑我前面提到的修复方法无效,因为在调用〜1000行之后prettify正在对文本进行一些其他处理。

尝试从添加内容到页面时向后跟踪内容,我在第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似乎基本上是需要发生的事情。我会继续四处寻找美化,看看是否可以进一步缩小范围。

更新:IE7似乎从分配给innerHTML属性的字符串中去除了换行符(\ r或者\ n)。似乎需要在1227行附近重新添加它们。

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

看来这是IE6的已知错误,prettify.js有了解决方法。具体来说,它将BR标签替换为'\ 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中的原始变通办法,因此我猜测它的渲染中没有IE7中出现的'\ n'所引起的空间,否则修复会更简单。