Почему 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 получает свои данные.
Ответы
Ответ 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/> code<br/> 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 могло видеть это как встроенный тег и забывать о видимом пробеле.