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

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-кода, приправим скриптами и получим наш долгожданный пример в котором на одной странице текст, на другой — картинка из ресурсов. Код приложения абсолютно открыт. Перед запуском его можно открыть в текстовом редакторе и проинспектировать код.
  • +12
  • 6,6k
  • 9
Поделиться публикацией
Похожие публикации
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 9
  • 0
    Все бы хорошо, но со времен autorun вирусов у пользователей одной очень популярной операционной системы, имеется стойкое неприятие к файлам HTA.
    • +3
      Есть финт, чтобы не ругалась безопасность — в начале документа вставить
      <!-- saved from url=(0014)about:internet -->
      • +6
        Я не к тому что безопасность будет панически кричать. У меня первый рефлекс при виде HTA файла — это проверить его антивирусом, а уже потом подумать открывать ли его. А если не дай боже он еще и называется «Открытка» или «С любовью», или еще что то в этом духе, то скорее всего я его удалю не открывая или вообще не буду скачивать.

        Хотя возможно это личной мной приобретенная админская паранойя. :-)
        • 0
          С названием открытка, мне кажется, такая паранойя сработает у каждого второго :)
          Особенно если файл придет по почте.

          Тут есть финт, что выполнение hta четко регламентируется безопасностью, и раньше это был чуть ли не самый продвинутый способ трояна. Если ставить инсталлятором в папку для программ, то тогда адекватно ведет себя защита, часто автолоадеры на дисках делают по такой технологии. Вот без строчки saved from url=(0014)about:internet, например, из рабочего стола Hta не стартанет, те вылетит месседж о разрешении запуска файла, а если вставить строку то не вылетит… мини хук, сам вычитал в какой-то умной книжке уже не помню, было лет 5 назад, когда писал приложение свое, тогда еще и jQuery не было в природе. Кстати есть очень хороший учебник от микрософта по использованию JScript, качается с официального сайта, мне в свое время помог шибко.
          • +1
            Согласен, я даже ожидал такой реакции, и поэтому отметил что любой желающий может проинспектировать код перед запуском. При сильных приступах недоверия или паранойи можно еще заменить код фреймворка на заведомо проверенный.

            Но стоит отметить что ровно такую же реакцию, у меня лично, вызывают FLASH открытки, а ведь у них код перед запуском уже не проверишь.

            А по поводу доверия источнику — тот же журнал «хакер» распространяет свое печатное издание с диском использующим HTA в качестве автозапуска. И не смотря на тематику издания, люди пользуются :) Так что рекомендации для получателя «открыток с любовью» в виде HTA остаются ровно такими же как и для всего остального контента из сети — проверять отправителя, запускать только будучи в полной уверенности в своей безопасности.
      • 0
        Да с помощью HTA можно делать очень даже полезные приложения, вот в свое время делал управление заказами для интернет-магазина, посмотреть можно тут.
        • 0
          Я когда-то давно делал простенький ICQ-клиент, к сожалению, вторая версия не сохранилась: webicq.chat.ru/
        • 0
          работает только под windows?
          • 0
            Да, в сети пишут что под wine не запускаются HTA-приложения. По крайней мере без танцев с бубном. Соответственно, можно говорить что технология работает только под windows.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.