IE неправильно отображает динамический контент, пока не будет изменена таблица стилей - PullRequest
5 голосов
/ 09 октября 2009

У меня есть таблица данных, которая генерируется динамически с помощью Javascript. Каждые несколько минут страница обновляет данные, запуская Ajax-запрос, возвращая данные с сервера и заменяя данные в таблице. Это довольно стандартно, и таблица в итоге выглядит так:

image

Это прекрасно работает, если я сгенерирую данные, опустошив таблицу и постепенно добавляя строки обратно. Однако эта таблица может содержать тысячи строк, и генерация таблицы, которую дает браузер, может занять очень много времени. пользователь «Этот сценарий занимает слишком много времени, чтобы выполнить» ошибки. Поэтому я исправил это, разбив генерацию таблицы на куски и выполнив немного по очереди, используя setInterval.

Это сработало нормально, но, поскольку для полной генерации таблицы может потребоваться некоторое время, я попытался быть умным и выполнить некоторую псевдо-двойную буферизацию. У меня есть вторая таблица, для которой display имеет значение none, чтобы скрыть ее, и когда я заново генерирую таблицу, я добавляю строки в скрытую таблицу по очереди. Таким образом, существующие данные будут видны пользователю до тех пор, пока не будет завершена повторная генерация таблицы, после чего мы просто заменим их новым контентом сразу.

Я делаю замену следующей строкой кода

$("#loading_area tbody").children().appendTo( $("#unplanned tbody").empty() );

Это прекрасно работает в Firefox, Safari и Google Chrome. Но в IE я получаю следующее:

image

Эти строки на самом деле не пустые - содержимое есть, если я прокручиваю достаточно горизонтально:

image

Кажется, что первый столбец имеет ширину более 55 000 пикселей! И вот действительно странная часть: контент снова отображается правильно, как только я изменю НИЧЕГО в отношении стиля таблицы. Поэтому, если я поменяю цвет шрифта на зеленый, IE немедленно выполнит корректную визуализацию таблицы.

Но я не могу внести изменения напрямую. Так что, если я скажу

$("#unplanned").css("color", "green");

тогда он не рендерится должным образом; цвет меняется, но ширина первого столбца составляет 55 000 пикселей. Но если я внесу изменения непосредственно в таблицу стилей

document.styleSheets[1].rules[3].style.color = "green";

тогда он корректно отображает таблицу.

Итак, я решил исправить это, сделав случайное изменение стиля, переключая поле кнопки «Развернуть / Свернуть» между 1px и 0px, каждый раз, когда я заканчивал раскладывать таблицу, и это работало.

Моя проблема заключается в том, что при попытке распечатать страницу строки выглядят пустыми, поскольку содержимое страницы неправильно отображается на принтере.

Так что я попробую больше обмана, возможно, просто переключая отображаемую таблицу и меняя их id или что-то еще, чтобы это работало. У меня вопрос, что здесь происходит? Это похоже на ошибку в IE; Я использую IE8, но то же самое происходит в IE6 и IE7. Я бы хотел избежать попадания в эту яму в будущем, но я не уверен, что является причиной этого, поэтому я не совсем уверен, чего мне следует избегать. Любой свет, который кто-либо может пролить на это, будет очень признателен.

РЕДАКТИРОВАТЬ: замена отображаемой таблицы устраняет проблему рендеринга в браузере, не требуя взлома таблицы стилей, но проблема с печатью все еще существует. На самом деле, проблема печати существует даже тогда, когда таблица генерируется напрямую, без каких-либо хитростей в отображении / скрытии или перемещении элементов. Так что я определенно запутался и не уверен, что я могу сделать, чтобы эта проблема исчезла. Возможно, мне придется сделать отдельную статическую страницу только для печати, если я не могу понять это.

Ответы [ 3 ]

3 голосов
/ 09 октября 2009

Не могу сказать точно без теста, но в целом:

  • Убедитесь, что вы используете table-layout: fixed. IE плохо угадывает auto ширину столбцов, особенно когда задействованы colspans. Это также медленно угадывает ширину, когда есть много строк. Возьмите это из рук IE, установив явные размеры для каждого столбца с фиксированной разметкой таблицы.

  • Избегайте добавления строк в большие таблицы. Когда вы говорите children().appendTo(), jQuery по-прежнему выполняет каждое добавление по одному, что вскоре становится очень медленным. Лучшее, что вы можете сделать, чтобы ускорить манипуляции с таблицами, - это установить весь лот за один раз, используя innerHTML для родительского элемента таблицы. Конечно, подготовка HTML-строки может раздражать, если вы хотите вставить данные (значения атрибутов и контент), поскольку она должна быть экранирована HTML. Обходной путь - записать все строки сразу со значениями-заполнителями, а затем на втором проходе заполнить реальные данные, задав .data в узлах Text и так далее. Вам нужно будет повторно присоединить все обработчики событий, которые вы добавляете к этим кнопкам на этом шаге, если вы не используете live.

  • Я думаю, что, написав строки с помощью innerHTML, вы сможете ускорить его настолько, чтобы избавиться от частичных обновлений, основанных на тайм-ауте (которые, как представляется, могут иметь неприятные потенциальные условия гонки). Конечно, альтернативой на основе DOM будет обновление только тех строк, которые были изменены. Когда вы используете фиксированный макет, поскольку ширина не зависит от содержимого, вы можете разбить вашу таблицу на несколько таблиц друг за другом. Они будут выглядеть как одна таблица, но вы можете работать с каждой таблицей отдельно, либо записывая ее innerHTML за один раз, либо добавляя его строки без потери производительности DOM, которую вы получите, имея тысячи строк в одной таблице.

1 голос
/ 09 октября 2009

У вас есть ширина на столе? Мне приходит в голову, что если вы генерируете таблицу, пока она скрыта, она может не воспринимать такие вещи, как текущая ширина окна браузера, которую она обычно использует для установки ширины таблицы, поэтому она возвращается к максимуму.

1 голос
/ 09 октября 2009

Вы можете просто иметь два tbody элемента в вашей основной таблице. Один будет использоваться для отображения, а другой для буферизации. Таким образом, вы можете пропустить добавление другого tbody и просто удалить display.none из буфера, чтобы отобразить его. Я думаю, что это может быть немного быстрее и, возможно, решить проблему в IE.

Еще один метод (уловка?) Для отображения или сокрытия элементов в таблице, которую я выучил, - установить position в absolute в строке или tbody, чтобы скрыть ее, вместо использования display. Это все еще скрывает это, но не изменяя (портя) расположение стола. Вы можете попробовать использовать его, чтобы скрыть буфер.

Как правило, таблицы являются одним из самых причудливых элементов, даже в современных браузерах. Выполнение с ними чего-либо сложного обычно приводит к этим небольшим головным болям, так что удачи.

...