Why doesn't IE7 copy
 blocks to the    
                                                      
                                                              
                                                                      
                                
                                                                                                                                    





                            

2020-05-22 09:31发布

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;
}

Copy and pasted from IE7, ends up like this:

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

Not exactly what we had in mind.. the underlying HTML source actually looks fine; if you View Source, you'll see this:

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

So what are we doing wrong? Why can't IE7 copy and paste this HTML in a rational way?

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.

7条回答
We Are One
2楼-- · 2020-05-22 09:43

It seems that this is a known bug for IE6 and prettify.js has a workaround for it. Specifically it replaces the BR tags with '\r\n'.

By modifying the check to allow for IE6 or 7 then the cut-and-paste will work correctly from IE7, but it will render with a newline followed by a space. By checking for IE7 and providing just a '\r' instead of a '\r\n' it will continue to cut-and-paste and render correctly.

Add this code to prettify.js:

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

and then modify the prettyPrint function as follows:

   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);
          }

You can see a working example here.

Note: I haven't tested the original workaround in IE6, so I'm guessing it renders without the space caused by the '\n' that is seen in IE7, otherwise the fix is simpler.

查看更多
女痞
3楼-- · 2020-05-22 09:48

@Jeff Atwood It's the right idea, but the implementation still needs work. I guess my air code just didn't cut it :)

I suspect that the fix I mentioned earlier doesn't work because prettify is doing some additional processing on the text after line ~1000 is called.

Trying to track the content backwards from when it's added to the page, I came across this comment around line 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.

When I took the isIE6 condition off of the code, it mostly worked in IE7 (there was an extra line break at the top and bottom), and Firefox 3... But I'd assume that it causes issues with older versions of FFX.

At the very least, it appears that IE7 will require \r\n, instead of just \n. Figuring out exactly what will work with which browsers will take a more extensive test setup than I have handy at the moment.

Anyway, inserting the \r\n for IE7 appears to be basically what needs to happen. I'll keep poking around prettify to see if I can narrow it down further.

UPDATE: IE7 appears to strip newline characters (\r or \n) from strings that are assigned to an innerHTML property. It looks like they need to be added back in, around line 1227.

A correct solution would probably mean inserting a placeholder tag around line 1000, and then replacing it around line 1227.

查看更多
Explosion°爆炸
4楼-- · 2020-05-22 09:48

Remove the inner <code>. IE's copy/paste behavior could see that as an inline tag and forget about the visible whitespace.

查看更多
叼着烟拽天下
5楼-- · 2020-05-22 09:49

This site has addressed the issue: http://www.developerfusion.com/tools/convert/csharp-to-vb/

I suggest a "Copy to Clipboard" button as part of the code display box. This button would copy version of the displayed information as plain text. The plain text could be stored as an internal page property.

查看更多
戒情不戒烟
6楼-- · 2020-05-22 09:56

bad news : none of the proposed fixes work. Modifying prettify.js around line 1000

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

This causes double-spacing in other browsers, and still doesn't solve the IE7 copy to notepad problem! So even if I selectively detected IE7, this "fix" doesn't fix anything.

I guess maybe it is simply a bug in IE7 having to do with JavaScript rebuilding a <pre> element -- no matter how many \n newlines I put in there, nothing changes w/r/t to the paste to notepad behavior.

查看更多
一夜七次
7楼-- · 2020-05-22 10:04

Here's the issue:

Your code colorization script replaces line breaks with <br /> tags. When copying/pasting, IE7 apparently doesn't translate the <br /> tag into a linebreak like it does for the screen.

In other words, your code becomes this:

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

But you want it to become this:


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

In the latest version of prettify.js on Google Code, the line responsible is line 1001 (part of recombineTagsAndDecorations):


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

Edited, based on the comments:
For IE7, this is what the line should probably be changed to:


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

(Assuming newlineRe is a placeholder).

This fix also holds up in Chrome, and FFX3... I'm not sure which (if any) browsers need the <br /> tags.

Update: More information in my second response:
Why doesn't IE7 copy <pre><code> blocks to the clipboard correctly?

查看更多
登录 后发表回答