Архив за Май 2009

  • Подключение entity в XSL-шаблон

    Я очень люблю использовать XSL в качестве шаблонизатора — более гибкого механизма для вывода HTML/XML не придумаешь. А еще я использую Eclipse в качестве основной среды разработки: хоть он тяжелый и глючный, собака, но он единственный удовлетворяет большинство моих потребностей (никуда не перелезу, пока там не появится аналог PyDev и Mylyn).

    Шаблоны, которые я использую, построены на кастомных энтити. Так как XSL-переменные нельзя использовать в атрибуте match шаблона, это довольно удобный способ их эмулировать:

    <!ENTITY navigation "/document/system/navigation[@type = 'root']">
    ...
    <xsl:template match="&navigation;">
    	<ul id="nav">
    		...
    	</ul>
    </xsl:template>
    

    Все энтити хранятся в отдельном файле (entities.dtd), которые я подключаю вот так:

    
    <!DOCTYPE xsl:stylesheet SYSTEM "entities.dtd">
    
    <xsl:stylesheet version="1.0" xmlns="http://www.w3.org/1999/xhtml" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    	...
    </xsl:stylesheet>
    

    В «штатном» Eclipse XSL editor это приводит к тому, что перестает code complete по XSL-тэгам — это баг всего Web Tools Project, связанный с тем, что при одновременном использовании XML Schema и внешнего файла с энтити предпочтение по code complete отдается последнему. Поиск решения этой проблемы привел меня к довольно интересному открытию. Теперь энтити я подключаю вот так:

    <!DOCTYPE xsl:stylesheet [
    	<!ENTITY % core SYSTEM "entities.dtd">
    	%core;
    ]>
    

    Это не только восстанавливает работу code complete, но и добавляет следующее преимущество: можно создавать локальные энтити в каждом файле и матчить на них шаблоны:

    <!DOCTYPE xsl:stylesheet [
    	<!ENTITY % core SYSTEM "entities.dtd">
    	%core;
    	<!ENTITY my_entity "/path/to/element[@with = 'very complex expression']">
    ]>
    ...
    <xsl:template match="&my_entity;">
    	сделать что-нибудь
    </xsl:template>
    
    <xsl:template match="&my_entity;[@some_attr = 'true']">
    	сделать что-нибудь другое
    </xsl:template>
    
    Метки: , ,
  • Спрайты в вебе. Часть 1

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

    Что такое спрайты?

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


    Спрайт с сайта «Житлобуд»

    Такой подход дает сразу несколько преимуществ. Во-первых, объем одного файла как правило меньше, чем сумма объемов отдельных файлов. Это можно объяснить снижением издержек на сохранение одного изображения: всякие там заголовки, указывающие на формат изображения, или общая палитра цветов, если речь идет об индексированном PNG или GIF. Бородатые кодеры могут вспомнить рекомендации 90-х годов по разбивке одного большого файла на несколько мелких, чтобы создать иллюзию у пользователя, что сайт грузится быстрее :) Такой подход создавал именно иллюзию, так как суммарный объем нескольких файлов был больше, чем объем одного файла, а сама картинка грузилась дольше.

    Во-вторых — самое главное — сокращается количество HTTP-запросов к серверу. Некоторые ребята не обращают на это внимание, а зря: зачастую отдельный запрос обходится намного дороже, чем десяток «лишних» данных в одном изображении. Не буду подробно расписывать этот момент, так как это тема для отдельного разговора.

    Итак, мы уже знаем, что спрайты — это круто и модно. Ограничено ли применение спрайтов только группировкой разных изображений в одно?

    Назад в прошлое

    Будучи неопытным юнцом, я очень любил играть в игры. Больше всего меня интересовало то, как же эти игры делаются. Тогда еще не было повсеместного использования 3D-графики, все игры, в которые я играл, в основном были 2D-аркадами (Another World, Commander Keen, Moles, Prince of Persia, эх…), активно использующими спрайты. Вообще, слово «спрайт» получило широкое распространение именно благодаря видеоиграм, и именно видеоигры больше всего повлияли на меня как на веб-разработчика.

    Помимо обычной группировки изображений можно выделить еще несколько типов спрайтов.

    Раскадровка


    Слон с сайта «Паритет98»

    Раскадровка, по сути, представляет собой набор кадров для анимации, сохраненных в одном файле. Для такого спрайта пишется контроллер на JavaScript, который управляет скоростью и направлением смещения спрайта. По сравнению с обычной GIF-анимацией это дает нам следующие преимущества:

    1. Можно использовать JPEG или полупрозрачный PNG.
    2. Более широкие возможности по оптимизации изображения.
    3. Можно самостоятельно управлять скоростью и направлением анимации, имея один и тот же набор кадров (то есть используя всего одно изображение).

    При создании такого спрайта нужно помнить следующее. Для начала нужно выбрать размер кадра; такой, чтобы в нем без проблем уместилась любое изображение из раскадровки +10-20% свободного пространства по бокам для надежности. Это позволит в дальнейшем без особых хлопот модифицировать изображение.

    Затем нужно точно совместить изображения в кадрах, чтобы при анимации не были заметны рывки. Если все сделаете правильно, то на создание JS-контроллера уйдет минимум сил и времени.

    Циклический спрайт

    Этот тип спрайтов в основном применяется для создания механизмов наподобие прелоудера: некая повторяющаяся текстура на блоке неопределенной ширины.

    Тут, конечно, руки так и чешутся использовать GIF-анимацию, однако перфекционистов вроде меня может не устроить плавность движения. Сравните:

    В первом случае я сделал GIF-анимацию с задержкой 0 ms (то есть вообще без задержки) между кадрами. В предпросмотре фотошопа все работает довольно плавно, а в браузере отчетливо заметны задержки между кадрами. В JS-анимации, используя контроллер из предыдущего примера, задержек никаких нет.

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

    Слои

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

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

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

    Естественно, этот пример довольно простой и примитивный: уверен, что многие так и поступили бы с этой картинкой. Наибольший эффект от такого типа спрайтов достигается в том случае, когда сердцевина имеет не прямоугольную форму. Хороший пример: раздел «Отделение Imperia» сайта Imperia Private Banking:

    imperia-branch

    Огромный узор на двери был разделен на 2 слоя: сердцевину и окантовку, каждый слой был по-своему оптимизирован, что в итоге позволило мне сэкономить около 200 КБ. Как быстро разделить изображение на два таких слоя я писал в статье «Про PNG. Часть 2».

    Векторные маски

    К сожалению, не всегда подобные картинки можно эффективно разделить по слоям. Например, когда сердцевина не прямоугольной формы содержит фотографическое изображение. В этом случае на помощь приходят современные браузерные технологии, а именно SVG, Canvas и VML. С помощью них можно наложить векторные маски на прямоугольную JPEG-картинку, добившись необходимого внешнего вида. Для этих целей я написал специальную библиотеку под названием ictinus, которая занимается решением таких задач. Хороший пример использования использования спрайтовых масок (и моей библиотеки :)) — главная страница сайта «Аймобилко»:

    imobilco

    В середине страницы находится красивый тизер продукта, у которого изображение должно принимать «неправильную» форму (в данном случае — коробка компакт-диска с загнутым углом). Так как фон не однородный (и тоже, кстати, меняется), единственным очевидным способом решения этой задачи было создание отдельного PNG-изображения весом более 100 КБ для каждого такого продукта. Меня такой расклад не устраивал, поэтому я решил в качестве эксперимента применить ictinus (на тот момент был в состоянии очень сырой альфа-версии). На прямоугольное JPEG-изображение накладывается векторная маска (в зависимости от типа продукта), затем под эту картинку ставится PNG-тень. Результат оказался более чем убедительным. Помимо сильной экономии на траффике пользователя я сэкономил нервы заказчику: теперь ему достаточно любому продукту в админке поставить галочку «Показывать на главной», а не готовить в фотошопе новые картинки.

    ***

    С типами спрайтов, пожалуй, всё (ничего не забыл?), в следующей части рассмотрим способы хранения данных в спрайтах и некоторые рекомендации по использованию.

    Скачать JS-котроллер для спрайтовой анимации



    Метки: , , , ,
  • Техсуппорт по-русски

    Недавно один из клиентов переслал мне письмо, пришедшее на support@ от одного недовольного пользователя, который заявлял, что не может выполнить какие-то действия на сайте. Причина: появляется сообщение, что в его браузере чего-то сделать нельзя. Я был крайне удивлен этим, так как сам лично контролирую поддержку проекта и таких сообщений на сайте не должно быть в принципе.

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

    значит, объясняю, как решаются такие вопросы:

    [...]

    если все везде работает — пишете любому клиенту «ставь последнюю версию браузера и не парь нам мозги, все везде должно работать»

    если что-то где-то не работает — ставите на заглавник определитение браузера и пишете тем, кому не повезло, что им не повезло — сразу, чтобы они время не теряли

    [...]

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

    И дело тут совсем не в том, что на банальную просьбу выслать URL и название браузера я получил нравоучения о том, как жить дальше. А в том, что такой «консультант» с порога предлагает писать пользователям «ставь последнюю версию браузера и не парь нам мозги», даже не исследовав проблему.

    К моему великому сожалению такая модель поведения типична для российский веб-разработчиков. Если где-то что-то не работает, то клиент обязательно должен разбиться в лепешку: поставить все обновления системы, десять раз перезагрузится, отключить все файерволы и антивирусы, проапгрэйдить свой компьютер, купить шаманский бубен, наконец (видел такой в магазине «Экспедиция»). И все это для того, чтобы 5 минут посмотреть на очередной шедевр подпольного сайтостроения Васи Пупкина. У разработчика, видите ли, в инкубаторных условиях все работает, а если клиент, не дай бог, нажал кнопки не в той последовательности — то виноват, конечно же, сам клиент.

    Потому что разработчик провозгласил себя священной коровой, которой все обязаны. Не работает кнопка? А в моем SuperMegaBrowser 0.6 alpha все работает замечательно, поставьте его себе. На странице все разъехалось? Ничего не знаю, у меня сайт валидный, должно везде работать, а если не работает — значит, у вас говеный браузер. У вас IE6? Сначала обновитесь хотя бы до IE7, а потом заходите на сайт. И мне плевать, что в вашем банке другие браузеры использовать нельзя, и что вы хотите купить на сайте, который сделал Я, телефон за 1000$. Идите ко всяким лузерам, которые не думают о валидности и верстают таблицами.

    Почему разработчики до сих пор не могут понять, что клиентов абсолютно не волнует размер мозолей на руках от постоянной дрочки на валидатор? Что дизайнерам пофигу, как вы сверстаете макет: таблицами или дивами. Что на дворе сейчас XXI век и инетрнет заполнен не гиками, а обычными пользователями, которые понятия не имеют, что такое HTML или JavaScript. Зато эти пользователи очень здорово умеют нажимать на кнопку «Купить» и следовать пошаговой инструкции, как расстаться с деньгами.

  • Zen Coding v0.3

    Большое обновление Zen Coding.

    Общее

    • Парсер аббревиатур теперь учитывает тэги: <div>p>span разворачивается в <div><p><span></span></p>.
    • Внесены в настройки все сокращения, описанные в Wiki (спасибо Николаю за детальный багрепорт).
    • Добавлен полноценный плагин для TextMate.
    • Добавлен полноценный плагин для Coda.

    Aptana

    • Добавлены команды «Перейти к следующей/предыдущей точке редактирования» (Next/Previous Edit Point: Alt+[ и Alt+] соответственно). Пока что точками редактирования является позиция между "" и ><. Таким образом очень удобно перемещаться между пустыми атрибутами и тэгами.
    • Добавлена команда «Обрамить тэгом» (Wrap In Tag: Alt+W). Обрамляется либо выделение, если оно есть, либо вся строка. Не забудьте включить в аптане опцию Modify pair tag (Aptana → Editors → HTML → Typing).
    • Добавлена команда «Форматировать выделение с помощью Showdown» (Format Selection With Showdown: Alt+F). Преобразует обычный текст в HTML-разметку. Сам скрипт Showdown подвергся небольшим изменениям: абзацы разделяются не двумя переносами строк, а одним, менее жесткие правила для обрамления ссылкой электронных адресов, добавлены отступы для элементов списка. То есть формат входящего текста больше похож на то, что копируется и вставляется из ворда.
    • Добавлена поддержка редактора XSL из проекта Eclipse WTP (с XML редактором почему-то не хочет работать). В settings.js для него появились отдельные правила.
    • Добавлена возможность разворачивать аббревиатуры по клавише Tab. Для этого в файле Expand Abbreviation.js в самом первом комментарии значение ключа Key нужно заменить на Tab и переменной use_tab поставить значение true. Нужно помнить, что в этом случае все нажания клавиши Tab будут обрабатываться скриптом, поэтому некоторые вещи (типа перемещение между плэйсхолдерами) перестанут работать.

    TextMate

    Бандл для TextMate теперь больше похож на полноценный Zen Coding плагин. Работает в HTML, CSS, XML и XSL режимах. Пока в работе добавление собственных сниппетов через интерфейс Bundle Editor. Тоже есть возможность раскрывать аббревиатуры по клавише Tab (сейчас по ⌘+E), однако в этом случае перестанут работать сниипеты из других бандлов.

    Coda

    Наконец-то разработчики этого редактора мне ответили. В общем, заявленная «полная поддержка бандлов из TextMate» даже близко не похожа на правду. Мой коллега Дима «Хобот» Яковлев (за что ему огромное спасибо) написал прослойку между Coda и PyZenCoding на Objective-C. Аббревиатуры разворачиваются по ⌃+E, пока нельзя менять это сочетание. Большая просьба ко всем пользователям этого редактора хорошенько протестировать плагин и написать мне о всех выявленных багах.

    Вроде ничего не забыл :) Скачать плагины можно с сайта проекта на Google Code. Следите за обновлениями.

    UPD: Zen Coding теперь входит в состав сахара TEA для редактора Espresso (разворачивается по ⌃+. [точка]).