Печатное родительское окно страниц iframed вызывает нечетное масштабирование - PullRequest
6 голосов
/ 11 июля 2011

Мне было поручено объединить несколько документов HTML в одну страницу для печати.Моя первая попытка потерпела неудачу - я попытался изолировать содержимое страницы, каждое из которых было изменено в соответствии с собственным тегом <div> и правилами таблицы стилей.Моя вторая попытка с использованием iframes для изоляции каждого документа выглядит значительно лучше, но страницы увеличиваются при печати из родительского фрейма стека iframe по сравнению с печатью документов по отдельности в их собственных окнах.

Вот примердокументы, с которыми я работаю: http://dl.dropbox.com/u/291229/print-test/index.html

Вы можете сделать предварительный просмотр в Firefox, чтобы понять, что я имею в виду.Если вы откроете первый фрейм в его собственной вкладке / окне и начнете предварительный просмотр, выделенные поля хорошо уместятся на странице.То же самое в родительском окне стека iframe показывает ячейки, выходящие за границы страницы.

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

Ответы [ 2 ]

9 голосов
/ 18 июля 2011

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

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

Однако, если вам действительно нужно динамически изменять их размер, вы можете запустить следующий код после загрузки документа (протестировано в Chrome):

var iframes = document.getElementsByTagName("iframe");
for(var i = 0; i < iframes.length; ++i) {
    var curFrame = iframes[i];
    var curBody = curFrame.contentDocument.body;
    curBody.innerHTML = '<div id="iframe-print-content" style="display:inline-block; overflow:hidden; white-space: nowrap;">'
                      +  curBody.innerHTML + '</div>';
    var printContent = curFrame.contentDocument.getElementById("iframe-print-content");
    var curWidth = printContent.offsetWidth + printContent.offsetLeft;
    iframes[i].style.width=(curWidth + "px");
}

После запуска вы можете печатать как обычно, звонить window.print() или делать все, что захотите.


Примечание : Этот метод не совсем работает на ie6 или ie7, так как они не поддерживают inline-block. (Есть также несколько других старых браузеров, которые тоже этого не делают). Можно, конечно, попробовать

display:-moz-inline-stack; display:inline-block; zoom:1; *display:inline; overflow:hidden; white-space: nowrap;

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

Удачи, извините, что вы застряли с кодом на этих страницах.




Редактировать: Вышеупомянутое решение немного неудачно в Firefox.

Решение для Firefox (протестировано и работает в Firefox 5):

var iframes = document.getElementsByTagName("iframe");
for(var i = 0; i < iframes.length; ++i) {
    var curFrame = iframes[i];
    var curBody = curFrame.contentDocument.body;
    var oldHTML = curBody.innerHTML;
    curBody.innerHTML = '<div id="iframe-print-content" style="display:inline-block; overflow:hidden;">' +  oldHTML + '</div>';
    var printContent = curFrame.contentDocument.getElementById("iframe-print-content");
    var curWidth = printContent.offsetWidth + printContent.offsetLeft + 25;
    var curHeight = printContent.offsetHeight + printContent.offsetTop + 25;
    curBody.innerHTML = oldHTML;
    iframes[i].style.width=(curWidth + "px");
    iframes[i].style.height=(curHeight + "px");
}

Для полного объяснения того, почему этот общий подход работает, см. Мой ответ выше.

Чем отличается решение выше и чем?

Во-первых, особенности Firefox:
Есть несколько ключевых отличий. Во-первых, обратите внимание, что Firefox обрабатывает display: inline-block и white-space: nowrap иначе, чем Chromium / WebKit для элементов фиксированной ширины (именно поэтому один документ выглядел по-настоящему шатким с предыдущим кодом). Далее следует отметить, что Firefox любит вносить небольшой запас в свои фреймы. Я не очень знаком с кодом Firefox, который делает это (провожу свои дни, взламывая Chromium), но мое обычное решение (кроме того, чтобы избегать фреймов) - просто добавить дополнительные 25px на полях. Такая небольшая сумма, кажется, популярна, чтобы решить эту проблему.

Теперь части кода, которые на самом деле лучше:
Во-первых, теперь в нем хранится старое тело, он поднимает тело на div для измерения, а затем восстанавливает старое тело. Это должно избежать проблем с негибким CSS и должно гарантировать более предсказуемое поведение. Во-вторых, это теперь делает то же самое для высоты и ширины (мое предыдущее предположение, что жестко запрограммированные ширины просто сработали бы, было бесполезно, и в любом случае это более гибкое решение).

Почему это все еще плохо?

Удаление white-space: nowrap приведет к переносу текста при печати в Chromium / WebKit. Он по-прежнему печатается нормально, но это не совсем правильно, поскольку какой-то дополнительный текст будет перенесен. Чтобы сделать это действительно работоспособным решением, вам все равно придется выполнять код, определяющий браузер.

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

1 голос
/ 19 июля 2011

Я полагаю, что вы (опять же) можете "обмануть" браузер, добавив статическую ширину к одному из iFrames в середине ... Это заставит версию для печати изменить размер, перенеся всю вашу информацию обратно на страницу ...Я изменил только этот iFrame и вернул размер (обратите внимание на ширину: 150%):

<iframe src="order/form.html" style="height: 1707px;width:150%">
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...