Html – Why doesn’t IE7 copy
 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;

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;

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.

Best Solution

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];
-               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.