Подтвердить что ты не робот

Почему IE7 не копирует <pre class="prettyprint-override"><code> blocks to the clipboard correctly?

Мы заметили, что 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-код рациональным образом?

Обновление: это специально связано с блоками <pre> <code>, которые изменяются во время выполнения через JavaScript. Собственный HTML делает рендеринг и копирование правильно; это модифицированная версия JavaScript этого HTML, которая не ведет себя так, как ожидалось. Обратите внимание, что копирование и вставка в WordPad или Word работает, потому что IE помещает различный контент в богатый текстовый буфер обмена по сравнению с обычным текстовым буфером обмена, из которого Notepad получает свои данные.

4b9b3361

Ответ 1

Кажется, что это известная ошибка для 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, поэтому я предполагаю, что он отображает без пространства, вызванного "\n", которое видно в IE7, в противном случае исправление проще.

Ответ 2

Здесь проблема:

Ваша окраска кода script заменяет разрывы строк на < 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 />

В последней версии prettify.js в Google Code строкой отвечает строка 1001 (часть recombineTagsAndDecorations):


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

Отредактировано на основе комментариев:
Для IE7 это то, что строка, вероятно, должна быть изменена на:


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

(Предполагая, что newlineRe является заполнителем).

Это исправление также сохраняется в Chrome и FFX3... Я не уверен, какие (если есть) браузеры нуждаются в < br/ > теги.

Update: Дополнительная информация в моем втором ответе:
Почему IE7 не копирует <pre> <code> блоков в буфер обмена правильно?

Ответ 3

Это выглядит как ошибка в IE, теги BR внутри PRE или CODE не преобразуются в символы новой строки в буфере текстовой копии. Буфер для полнотекстового копирования отлично, поэтому паста работает так, как ожидалось, для таких приложений, как wordpad.

Префикс script, который окрашивает код, удаляет все пробелы и заменяет его тегами 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 на клиенте):

  • Вы можете поместить код внутри нормального div и использовать CSS для его рендеринга с помощью {whitespace: pre}. Это простое решение, хотя, возможно, это не понравится пуриту разметки HTML.

  • У вас может быть две копии кода: одна с использованием правильных тегов PRE/CODE, а другая - в обычном div. В вашем CSS вы спрячете нормальный div. Используя javascript, вы отключаете нормальный div и скрываете версию pre/code.

  • Измените prettify script, чтобы узнать, что он действует на элемент PRE или CODE и не заменяет пробелы в этом событии.


Примечания:

  • Важно не HTML в вашем источнике, а HTML, который создается после того, как префикс script запущен на нем.

  • Эта ошибка все еще присутствует, даже если режим белого пространства PRE изменен на обычный с помощью CSS.

Ответ 4

На этом сайте рассмотрена проблема: http://www.developerfusion.com/tools/convert/csharp-to-vb/

Я предлагаю кнопку "Копировать в буфер обмена" как часть окна отображения кода. Эта кнопка копирует версию отображаемой информации в виде обычного текста. Обычный текст может быть сохранен как свойство внутренней страницы.

Ответ 5

Плохая новость: ни одна из предлагаемых исправлений не работает. Изменение prettify.js вокруг строки 1000

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

Это приводит к двойному интервалу в других браузерах и до сих пор не решает проблему с IE7 в проблему с записью! Поэтому, даже если я выборочно обнаружил IE7, это "исправление" ничего не фиксирует.

Возможно, это просто ошибка в IE7, связанная с JavaScript, перестраивающим элемент <pre> - независимо от того, сколько \n новых строк я вставляю туда, ничего не изменяет w/r/t на вставку в блокнот поведение.

Ответ 6

@Jeff Atwood Это правильная идея, но реализация все еще нуждается в работе. Думаю, мой воздушный код просто не сократил его:)

Я подозреваю, что исправление, о котором я упоминал ранее, не работает, потому что prettify выполняет некоторую дополнительную обработку текста после вызова строки ~ 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. Выясните, что именно будет работать с тем, какие браузеры проведут более обширную тестовую настройку, чем сейчас.

В любом случае, вставка \r\n для IE7 представляется в основном тем, что должно произойти. Я буду держать себя в курсе, чтобы увидеть, могу ли я сузить его дальше.

ОБНОВЛЕНИЕ: IE7 появляется, чтобы удалить символы новой строки (\ r или \n) из строк, которые назначены свойству innerHTML. Похоже, что их нужно добавить обратно, по линии 1227.

Правильное решение, вероятно, означало бы вставку тега-заполнителя вокруг строки 1000, а затем его замену на строку 1227.

Ответ 7

Удалите внутренний <code>. Поведение IE copy/paste могло видеть это как встроенный тег и забывать о видимом пробеле.