Pdf with java script

Javascript в PDF

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

Любое ПО содержит некоторый активно используемый функционал и значительную долю редко используемого функционала. Можно прикинуть, все ли возможности операционной системы (или Microsoft Word, или своей IDE) мы используем в повседневной работе или вообще использовали хоть раз в жизни. Как правило, далеко не все.

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

  • Для изменения содержимого документа в зависимости от некоторых событий. Например, скрыть часть документа при отправке на печать. Или при открытии документа автоматически заполнить часть полей формы.
  • Для ограничения действий читателя. Например, для валидации вводимых значений при заполнении форм.

Рассмотрим ряд практических примеров использования Javascript в PDF документах.

Hello World

Начнем рассмотрение темы с традиционного Hello World примера. В данном и последующих примерах используется язык C# и библиотека Docotic.Pdf для работы с PDF документами. Ссылка на исходники с кодом всех примеров приводится в конце статьи.

using BitMiracle.Docotic.Pdf; namespace JavascriptInPdf < public static class Demo < public static void Main(string[] args) < PdfDocument pdf = new PdfDocument(); pdf.OnOpenDocument = pdf.CreateJavaScriptAction("app.alert(\"Привет, Хабр!\", 3);"); pdf.Save("Hello world.pdf"); >> >

Если открыть созданный этим кодом документ в Adobe Reader, то увидим примерно следующее:

Читайте также:  Initialize nested class java

Что же происходит в примере? Суть заключена в строке

pdf.OnOpenDocument = pdf.CreateJavaScriptAction("app.alert(\"Привет, Хабр!\", 3);");

Формат PDF включает поддержку actions – это действия, происходящие по тому или иному событию. Например, когда в оглавлении в некотором PDF документе кликаем на ссылку с номером страницы – срабатывает определенный action для перехода на соответствующую страницу:

Для Javascript также есть соответствующий action. Мы создаем его с помощью метода PdfDocument.CreateJavaScriptAction, которому передаем в качестве параметра JS код. Созданный action мы привязываем к событию OnOpenDocument, происходящему при открытии документа просмотрщиком.

Непосредственно Javascript код выглядит так:

Статический класс app является частью Javascript API и предоставляет набор методов для взаимодействия с приложением-просмотрщиком. В частности, он содержит несколько перегрузок метода alert для показа модального диалога с сообщением. В данном примере используется перегрузка со вторым необязательным параметром – индексом иконки диалога, значение 3 соответствует Status Icon.

От простого – к сложному

Рассмотрим более реалистичный пример.

Многие PDF документы описывают некоторые формы для заполнения – это может быть договор открытия банковского вклада, анкета на получение визы или загран. паспорта, заявление на отпуск и т.п. Довольно удобно, поскольку такую форму можно заполнить прямо в просмотрщике и сохранить или распечатать. Авторы PDF документов, содержащих формы, могут облегчить пользователю их заполнение с помощью Javascript.

Реальные документы часто содержат поля для ввода даты заполнения. Например, это может выглядеть так:

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

Устанавливаем дату по умолчанию

C# код по созданию полей для даты, как на скриншоте, в данном случае не так интересен. Рассмотрим лишь часть, касающуюся Javascript. Необходимо при открытии документа устанавливать в полях текущую дату, делается это так:

function setDay(date) < var dayField = this.getField("day"); if (dayField.value.length == 0) < dayField.value = util.printd("dd", date); >> function setMonth(date) < var monthField = this.getField("month"); if (monthField.value.length == 0) < monthField.value = util.printd("date(ru)", date, true); > > function setYear(date) < var yearField = this.getField("year"); if (yearField.value.length == 0) < yearField.value = util.printd("yyyy", date); >> function setCurrentDate() < var now = new Date(); setDay(now); setMonth(now); setYear(now); >setCurrentDate();

По сравнению с предыдущим примером JS код увеличился в объемах, поэтому использовать его напрямую в C# строке стало неудобно из-за необходимости экранировать кавычки и вставлять переносы строк. Поэтому поместим данный код в ресурсы, тогда использоваться скрипт будет так:

pdf.OnOpenDocument = pdf.CreateJavaScriptAction(Resources.SetCurrentDate);

В результате при открытии документа увидим примерно следующую картину:

Читайте также:  Function returns string php

Обратите внимание на код для установки месяца – мы используем специфическую перегрузку метода util.printd для вывода локализованного месяца.

monthField.value = util.printd("date(ru)", date, true); 

Это дает отличные результаты в Adobe Reader, но, к сожалению, не гарантируется, что другие просмотрщики будут корректно поддерживать столь специфические конструкции. При проектировании документа это нужно учитывать. Возможно, стоит заменить этот код на более многословный (самостоятельное получение названия месяца в нужном падеже), но зато поддерживаемый большим количеством просмотрщиков.

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

Валидация вводимых значений

Если при заполнении формы все-таки необходимо поменять дату, то имеет смысл разрешать ввод только цифр в поля для дня и года. Используем для этого следующий Javascript код:

function validateNumeric(event) < var validCharacters = "0123456789"; for (var i = 0; i < event.change.length; i++) < if (validCharacters.indexOf(event.change.charAt(i)) == -1) < app.beep(0); event.rc = false; break; >> > validateNumeric(event);

В C# коде используем событие OnKeyPress у контролов для проверки вводимого символа:

PdfJavaScriptAction validateNumericAction = m_document.CreateJavaScriptAction(Resources.ValidateNumeric); dayTextBox.OnKeyPress = validateNumericAction; yearTextBox.OnKeyPress = validateNumericAction;

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

Синхронизация значений полей

Часто бывает, что одну и ту же информацию в документе нужно указывать несколько раз. И в случае PDF документов с помощью Javascript можно избавить пользователя от повторения одних и тех же действий.

Предположим, имеется документ следующего вида:

Модифицируем его так, чтобы при изменении одного из полей с ФИО обновлялось и другое.

Читайте также:  Javascript интерактивная web страница

Используем простую Javascript функцию:

function synchronizeFields(sourceFieldName, destinationFieldName) < var source = this.getField(sourceFieldName); var destination = this.getField(destinationFieldName); if (source != null && destination != null) < destination.value = source.value; >>
PdfDocument pdf = new PdfDocument(“Names.pdf”); pdf.SharedScripts.Add( pdf.CreateJavaScriptAction(Resources.SynchronizeFields) ); pdf.GetControl("name0").OnLostFocus = pdf.CreateJavaScriptAction("synchronizeFields(\"name0\", \"name1\");"); pdf.GetControl("name1").OnLostFocus = pdf.CreateJavaScriptAction("synchronizeFields(\"name1\", \"name0\");"); pdf.Save("NamesModified.pdf");

Теперь при потере фокуса любым из текстбоксов будет обновлено значение другого. Обратите внимание на прием, не встречавшийся ранее, — общий Javascript код помещается в коллекцию PdfDocument.SharedScripts, и далее мы получаем возможность из конкретных action’ов вызывать функцию, определенную в общем коде.

Подытожим

Использовать Javascript можно не только в web-разработке, но и в такой области, как оформление PDF документов. Немного дополнительных усилий, и создаваемые PDF документы порадуют читателя не меньше, чем программа с удобным и продуманным интерфейсом – искушенного пользователя.

  • Сложнее писать Javascript код, чем в случае обычной web-разработки. Нужно создать и открыть документ, чтобы проверить корректность написанного кода.
  • Javascript полноценно поддерживается лишь просмотрщиками от Adobe. В альтернативных просмотрщиках поддержка существенно ограничена либо отсутствует вообще.
  • Javascript может быть отключен в просмотрщике PDF.
  • Теоретически исполнение Javascript скриптов в документе небезопасно, и периодически обнаруживаются различные уязвимости.

Скачать код примеров из статьи можно здесь.

Источник

Оцените статью