Pull to refresh

Интерактивная открытка в виде HTA

Reading time 6 min
Views 11K
HTA-приложения уже описывались на хабре. Теперь же рассмотрим конкретный пример использования технологии в мирных целях.

Для чего?

Иногда хочется сделать красивую открытку, но при этом не заморачиваться с FLASH, Silverlight и т.п. А ведь зная только HTML и немного JavaScript можно сделать превосходные открытки в виде приложения одним файлом! Тот кто пролистает статью не вчитавшись может отметить что это не совсем просто. Но сделав один раз каркас (который я предоставляю в конце статьи на суд и свободное использование), вы будете легко и быстро делать новые и новые открытки. И даже вполне можно автоматизировать процесс создания персональных интерактивных открыток.

Человеческие требования

1. Знание HTML и JavaScript.
2. Фантазия.
3. Навыки верстки.

Системные требования

Из ПО для создания подойдет хоть блокнот, по вкусу. А для просмотра потребуется mshta.exe идущий в поставке с любой версией windows с которой поставлялся IE выше версии 5.0 (проверено даже на Windows 7E поставляющейся без IE).

К железу требования минимальны, главное — чтобы машина смогла отобразить всю ту анимацию, что вы задумали. С *NIX операционными системами намного сложнее, в целом мы создадим приложение в одном файле, которое в общем то будет открываться любым браузером, но с ограниченными возможностями. Чтобы сделать открытку полностью кросс-платформенной необходимо достаточно сильно дополнять код. Дело в том, что мы будем создавать приложение с контейнером mhtml, понимает который только IE. Для других браузеров необходимо предусмотреть хранение ресурсов в конструкциях data URI, что увеличит размер приложения минимум в два раза. А так как мы делаем именно HTA-приложение с прицелом на OS Windows, то в рамках данной статьи ограничимся контейнером mhtml. Конечно если тема окажется интересной, в следующий раз я покажу, как сделать кросс-браузерный самодостаточный html-документ.

Приступим

Для начала создадим каркас приложения в файле postcard.hta:
<html>
  <head>
    <title>iPostcard</title>
      <hta:application
      applicationName="HTAPOSTCARD"
      innerBorder="no"
      selection="no"
      scroll="no"
      caption="no"
      maximizebutton="no"
      minimizebutton="no"
      contextmenu="no" />
    <style type="text/css">
    </style>
  </head>
  <body>
  </body>
</html>


Как видим внутри практически обычный HTML-код. Смутить могут только тег hta и его атрибуты. Хоть они уже красовались на хабре и подробно описаны в статье на википедии, но так как у нас конкретный пример, то распишу конкретное их применение:

applicationName — идентификатор приложения, можно писать что угодно, пусть будет «HTAPOSTCARD» для примера.
innerBorder — наличие внутренней рамки окна. Выключим для красоты, хотя тут возможно расхождение во вкусах. Значение или «yes» или «no».
selection — разрешение/запрещение выделения текста в окне HTA. Для открытки в этом нет необходимости, ставим «no» в значении параметра. Соответственно «yes» разрешит такое действие.
scroll — определяет наличие полосы прокрутки в окне. Запретим, так как размер контента будет фиксированным.
caption — определяет наличие заголовка окна. Нам оно не пригодится, так что поставим «no».
maximizebutton и minimizebutton — определяет наличие кнопок «свернуть» и «развернуть на весь экран» с заголовке и соответствующих пунктов системного меню приложения. Заголовок с кнопками мы уже и так отключили, так что воспользуемся этими пунктами, как раз для исключения возможности сворачивать-разворачивать окно через системное меню приложения.
contextmenu — наконец уберем контекстное меню (вызываемого правой кнопкой мыши), поставив в значение параметра «no» (хочу отметить, что выставив «yes» я так и не увидел этого меню).

Дизайн

Теперь создадим красивую приветственную страничку (она же будет шаблоном для остальных). Сразу же возвращаемся к вопросу о графике. Мы создаем самостоятельное приложение, которое должно распространятся в виде одного файла, иначе нет никакого смысла пытаться заменить flash и т.п. А ответ на вопрос относительно прост — воспользуемся контейнерами данных MHTML. Для этого необходимо все картинки закодировать в base64. Для данного примера я воспользовался удобным online-инструментом, который выдает не только голый код, но и некоторые готовые конструкции. Стоит отметить, что кодировщик принимает файлы размером не более 10 килобайт, но это на самом деле немало. Для больших изображений всегда можно найти другие кодировщики в сети, без подобных ограничений. На этот раз мне нужен чистый base64 код, я беру его и в самое начало файла вписываю контейнер:

<!--
/*
Content-Type: multipart/related; boundary="_SEPARATOR_"

--_SEPARATOR_
Content-Location:imagebg
Content-Transfer-Encoding:base64

/9j/4AAQSkZJRgAB ... 5Jxk570UUUAf//Z
--_SEPARATOR_--
*/
-->
<html>...</html>


Контейнер поместим в комментарий ради привычки на будущее — другие браузеры просто пропустят этот код как комментарий, а IE увидит как родной контейнер. Поясню что и зачем в этом куске кода:
Content-Type: multipart/related; — указываем тип содержимого.
boundary="_SEPARATOR_" — фраза в кавычках может быть любой, это разделитель контейнеров. Конечно стоит учитывать, что комбинация букв в этой фразе никоим образом не должна встретиться в base64 коде.
--_SEPARATOR_ — начало очередного ресурса, начинается с "--" и включает указанный выше разделитель.
Content-Location — метка очередного ресурса, именно по этой метке мы будем получать необходимую картинку. Как и всегда лучше давать внятные имена. В этом примере это image — картинка, bg — background — фон.
Content-Transfer-Encoding — метод шифрования ресурса.
После этого идет наша кодированная картинка, которую я привел в усеченном виде.

По спецификации RFC 2387 каждый контейнер должен быть обрамлен связкой --[фраза-разделитель], а последний ресурс должен быть закрыт связкой --[фраза-разделитель]--. Должен сказать, что работает даже вообще без закрывающего разделителя, но не будем отступать от стандартов.

Теперь у нас есть встроенное изображение, которое мы собираемся сделать фоном приложения. Нет ничего проще:
  <style>
    body{
      background-image: url(mhtml:file://C:\Путь_до_файла\postcard.hta!imagebg);
  </style>

Но внимательный читатель уже увидел проблему. Что еще за ПУТЬ_ДО_ФАЙЛА? А тут открывается проблема созданная mhtml, который требует полного пути до файла с контейнером ресурсов. Если честно, когда я узнал об этом (и попробовал обойтись различными вариациями относительных путей), у меня практически опустились руки. Но интернет — это бездонная кладезь знаний, и решение было найдено! На одном ресурсе я подсмотрел идею о замене стилей во время выполнения приложения. Основная мысль в том чтобы подменять путь до ресурса на полный URL документа. Я не стал брать решение приведенное автором, потому что не хотел разношерстных скриптов в приложении. Пусть будет JavaScript и только. Однако я конечно же потерял функциональность. Тот скрипт сразу меняет пути во всех стилях. Что же, и тут есть у меня что ответить — я буду менять пути не только в стилях. Об этом ниже. А сейчас…

… начнем программировать

Чтобы подменять полный путь до ресурса динамически, дождемся пока в документе появится тег тела документа и сразу же встроим скрипт:
  <body>
    <script language=javascript>
      $("body").css("background-image","url(mhtml:"+document.URL+"!imagebg)");
    </script>
    ...
  </body>


В вновь внимательный хабрапользователь уже бьет тревогу: — Что за $(«body»)? Это же jQuery! И правильно его негодование, для удобства я использую популярный фреймворк. Я думаю у вас не возникнет вопроса как он оказался в самодостаточном приложении, но все же раскрою этот «секрет». Просто берем jQuery и вставляем исходный код фреймворка между тегами:
<html>
  <head>
    ...
    <script language=javascript>
      ...
      /*текст фреймворка по вкусу*/
      ...
    </script>
  </head>
  ...
</html>

Сохранение копирайта создателей jQuery, оставлю на вашей совести. Но сам считаю, что чужой труд надо уважать.

Имея такой превосходный функционал, встраивание картинок не представляет проблем:
<img src="" id="imgdata1"/></div>
<script language=javascript>
  $("#imgdata1").attr("src","mhtml:"+document.URL+"!imgdata1");
</script>

Итог

Что мы получили в итоге? Полноценное самодостаточное приложение, с хранилищем ресурсов (копнув RFC глубже, вы увидите, что ресурсы могут быть абсолютно любые) и мощным стартовым функционалом (имею в виду фреймворк). Кроме того интерфейс размечается обычным HTML! Что может быть прекраснее и удобнее? У сообразительного хабраюзера уже рождаются различные идеи применения этой незатейливой песочницы. От обычных открыток и полно-экранных презентаций, до полноценных ВЭБ-клиентов и настольных приложений (благодаря VBScript можно работать и с файлами и с реестром).

Немного добавим стилей, HTML-кода, приправим скриптами и получим наш долгожданный пример в котором на одной странице текст, на другой — картинка из ресурсов. Код приложения абсолютно открыт. Перед запуском его можно открыть в текстовом редакторе и проинспектировать код.
Tags:
Hubs:
+12
Comments 9
Comments Comments 9

Articles