Почему IE7 неправильно копирует <pre><code> блоки в буфер обмена? - PullRequest
37 голосов
/ 26 сентября 2008

Мы заметили, что IE7 имеет странное поведение с блоками кода, размещенными в переполнении стека. Например, этот маленький блок кода:

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

Так что же мы делаем не так? Почему IE7 не может рационально копировать и вставлять этот HTML-код?

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

Ответы [ 7 ]

35 голосов
/ 02 октября 2008

Похоже, что это известная ошибка для 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, в противном случае исправление проще .

13 голосов
/ 26 сентября 2008

Вот проблема:

Ваш скрипт раскрашивания кода заменяет разрывы строк тегами
. При копировании / вставке IE7, по-видимому, не переводит тег
в разрыв строки, как для экрана.

Другими словами, ваш код становится таким:

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 ... Я не уверен, каким (если есть) браузерам нужны теги
.

Обновление: Больше информации в моем втором ответе:
Почему IE7 неправильно копирует

 блоков в буфер обмена? 

2 голосов
/ 26 сентября 2008

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

Сценарий prettify, который окрашивает код, удаляет все пробелы и заменяет его HTML-тегами для пробелов и новых строк. Сгенерированный код выглядит примерно так:

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

Теги PRE и CODE отображаются по умолчанию со стилем CSS {пробел: pre} . В этом случае IE не удается превратить теги BR в символы новой строки. Он будет работать с вашим исходным HTML, потому что IE успешно превратит фактические новые строки в новые.

Чтобы исправить это, у вас есть 3 варианта. (Я предполагаю, что вы хотите хороший HTML и возможность хорошо работать с и без включенного JavaScript на клиенте):

  1. Вы можете поместить код в обычный div и использовать CSS для его рендеринга, используя {пробел: pre} . Это простое решение, хотя может не понравиться пурист HTML-разметки.

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

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


Примечания:

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

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

1 голос
/ 05 ноября 2011

Этот сайт решил проблему: http://www.developerfusion.com/tools/convert/csharp-to-vb/

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

0 голосов
/ 01 октября 2008

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

Я подозреваю, что упомянутое ранее исправление не работает, потому что 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.

0 голосов
/ 01 октября 2008

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

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

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

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

0 голосов
/ 26 сентября 2008

Снимите внутреннюю <code>. IE в режиме копирования / вставки может видеть это как встроенный тег и забывать о видимых пробелах.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...