Логин:   Пароль:






Новости
Рассылки
Форум
Поиск


Java
- Апплеты
- Вопрос-ответ
- Классы
- Примеры
- Руководства
- Статьи
- IDE
- Словарь терминов
- Скачать

Мобильная Java
- Игры
- Примеры
- Статьи
- WAP, WML и пр.

JavaScript
- Вопрос-ответ
- Примеры
- Статьи

Веб-мастеринг
- HTML
- CSS
- SSI

Разминка для ума
Проекты
Книги
Ссылки
Программы
Юмор :)




Rambler's Top100
Rambler's Top100

Веб-мастерингSSI в примерах

SSI в примерах

Для начала о причинах, побудивших написать меня эту статью: в обсуждениях членов Всероссийского Клуба Вебмастеров не раз возникали споры о том, что лучше применять в случае повторяющейся разметки (информации) на большом количестве страниц - фреймы, JavaScript или SSI (Server Side Includes, http://www.webclub.ru/materials/ssi/index.phtmll). Моим глубоким убеждением является то, что фреймы следует использовать только там, где без этого действительно никак не обойтись, JavaScript (да и любые другие клиентские скрипты) слишком капризен и зависит от настроек браузера, поэтому его можно использовать только для дополнительных возможностей, но никак для простроения, допустим, системы навигации. Я не буду с пеной у рта доказывать, что технология SSI круче всех гор и яиц, а просто приведу решения часто встречающихся на практике задач с применением этой технологии.

(Сразу предвижу возмущение со стороны приверженцев технологий ASP и PHP, с использованием которых также возможны решения подобных задач, поэтому специально для них: технология SSI значительно проще, в ней всего десяток операций, поэтому для не программиста это более удачный выбор хотя бы потому, что ее можно быстрее освоить).

Дата последней модификации документа

Простая директива:


<!--#echo var="LAST_MODIFIED"-->

Сегодняшнее число в нужном формате
Если нам нужно вывести дату не в стандартном для данной конфигурации программных средств виде, а в том, какой нам нужен (например, "вторник, 30 мая, 2000"), то можно воспользоваться следующей конструкцией:
Получение дня недели.


<!--#config timefmt="%u" -->
<!--#set var="NUM_DAY" value="$DATE_LOCAL"-->
<!--#if expr="$NUM_DAY=1" -->
<!--#set var="DAY" value="понедельник" -->
<!--#elif expr="$NUM_DAY=2" -->
<!--#set var="DAY" value="вторник" -->
<!--#elif expr="$NUM_DAY=3" -->
<!--#set var="DAY" value="среда" -->
<!--#elif expr="$NUM_DAY=4" -->
<!--#set var="DAY" value="четверг" -->
<!--#elif expr="$NUM_DAY=5" -->
<!--#set var="DAY" value="пятница" -->
<!--#elif expr="$NUM_DAY=6" -->
<!--#set var="DAY" value="суббота" -->
<!--#else -->
<!--#set var="DAY" value="воскресенье" -->
<!--#endif -->
Получение числа

<!--#config timefmt="%e" -->
<!--#set var="DATE" value="$DATE_LOCAL"-->
Получение названия месяца

<!--#config timefmt="%m" -->
<!--#set var="NUM_MONTH" value="$DATE_LOCAL"-->
<!--#if expr="$NUM_MONTH=01"  -->
<!--#set var="MONTH" value="января" -->
<!--#elif expr="$NUM_MONTH=02" -->
<!--#set var="MONTH" value="февраля" -->
<!--#elif expr="$NUM_MONTH=03" -->
<!--#set var="MONTH" value="марта" -->
<!--#elif expr="$NUM_MONTH=04" -->
<!--#set var="MONTH" value="апреля" -->
<!--#elif expr="$NUM_MONTH=05" -->
<!--#set var="MONTH" value="мая" -->
<!--#elif expr="$NUM_MONTH=06" -->
<!--#set var="MONTH" value="июня" -->
<!--#elif expr="$NUM_MONTH=07" -->
<!--#set var="MONTH" value="июля" -->
<!--#elif expr="$NUM_MONTH=08" -->
<!--#set var="MONTH" value="августа" -->
<!--#elif expr="$NUM_MONTH=09" -->
<!--#set var="MONTH" value="сентября" -->
<!--#elif expr="$NUM_MONTH=10" -->
<!--#set var="MONTH" value="октября" -->
<!--#elif expr="$NUM_MONTH=11" -->
<!--#set var="MONTH" value="ноября" -->
<!--#else -->
<!--#set var="MONTH" value="декабря" -->
<!--#endif -->

Получение года

<!--#config timefmt="%G" -->
<!--#set var="YEAR" value="$DATE_LOCAL"-->
Собственно вывод получившейся строки

<!--#echo var="DAY" -->, 
<!--#echo var="DATE" --> 
<!--#echo var="MONTH" -->, 
<!--#echo var="YEAR"-->

Форматы параметров для config timefmt надо смотреть для каждой конфигурации веб-сервера отдельно. Приведенный пример - FreeBSD, Apache. Более подробно см. man timefmt

Подобная конструкция используется на веб-узле интернет-магазина Levingston.Ru (http://www.levingston.ru/)

Дата модификации внешнего файла

Часто на компьютерных сайтах выкладывают прайс-лист в формате MS Excel или Word и каждый раз руками прописывают дату его изготовления. С помощью SSI это делается примерно следующим образом:


<a href=pricelst.doc>Прайс-лист</a>
<!--#config timefmt="%d.%m.%y" -->
(MS Word 6.0/95, <!--#flastmod virtual="pricelst.doc" -->)

Такая конструкция используется на веб-узле компании Дункан Сервис (http://www.duncan.ru/)

Борьба с <noframes>

Как правило, в этом контейнере пишут "извините, но вам следует обновить браузер", по идее же там должны быть альтернатива для пользователей старых версий браузеров. Поскольку на нормальном сервере информация часто меняется, а вебмастеру же лениво каждый раз вносить правки в двух местах. С помощью SSI проблема решается раз и навсегда: в контейнер <noframes></noframes> вносится директива, вставляющая тот самый файл, в котором делаются правки или попросту линейку навигации.

Борьба с прямыми ссылками на документы на веб-узле с фреймами

Одним из аргументов против использования фреймовых структур при создании веб-узлов является неудобство прямых ссылок на содержательные файлы. Например, при ссылке из поисковых машин или на конкретный (не корневой) документ с другого веб-узла пользователь попадает на страницу, лишенную оформления или элементов навигации, которые обычно помещаются в отдельный навигационный фрейм. С помощью нехитрой конструкции SSI эту проблему можно решить. Для этого необходимо проанализировать, откуда пришел пользователь (переменная HTTP_REFERER) Если он пришел не с нашего сервера, а извне - построить фреймовую структуру и в качестве содержательного фрейма подставить документ, запрошенный пользователем.

В примере ниже файл content.phtmll - это тот документ, на который стоит прямая ссылка (допустим, из поисковой машины), frame.phtmll - файл в котором строится фреймовая структура. В QUERY_STRING подставляется значение done для того, чтобы избежать бесконечной вложенности фреймовых структур.

Файл content.phtmll


<phtmll>
<head>
...
<!--#include virtual="frame.phtmll" -->
</head>
<body>
...
</body>
</phtmll>
Файл frame.phtmll

<!--#if expr="$QUERY_STRING!=done && $HTTP_REFERER!=/your_domain\.ru/" -->
<frameset rows="150,*">
<frame name="NAVIGATION" src="/navigation.phtmll">
<frame name="CONTENT" src="<!--#echo var="DOCUMENT_URI" -->?done">
</frameset>
<!--#endif -->

Подобная конструкция использовалась на веб-узле интернет-магазина Болеро (http://www.bolero.ru/) в фреймовом варианте дизайна

Версия страницы для печати

Часто возникает прикладная задача - красивый многоколоночный дизайн с верхней и нижней шапками, туча баннеров, но при печати все это не нужно - лишняя бумага, ненужная информация... Поэтому хочется сделать простой альтернативный вид страницы специально для печати. Чтобы это проделать, достаточно подготовить два варианта верхней и нижней шапок, один --для экранного отображения, другой - для печати. В качестве переключения между этими вариантами используем переменную QUERY_STRING. Ниже приведены принципиальные структуры для самой страницы (file.phtmll) и для верхней и нижней шапок (top.phtmll и bottom.phtmll).

Структура самой страницы (file.phtmll):

<!--#include virtual="top.phtmll?$QUERY_STRING" -->
здесь тело документа 
<!--#include virtual="bottom.phtmll?$QUERY_STRING" -->
Структура top.phtmll и bottom.phtmll

<!--#if expr="$QUERY_STRING == /for_printing/" -->
шапка для печати

<!--#else -->
шапка для просмотра

<!--#endif -->
Ссылка на каждой странице должна быть вида

<a href=<!--echo var="$DOCUMENT_URI" -->?for_printing>версия для печати</a> 

Подобная конструкция используется на веб-узле Всероссийского Клуба Вебмастеров (http://www.webclub.ru/)

Борьба с пунктами меню

Предположим, у нас есть несколько разделов веб-узла, документы, относящиеся к разделам, лежат в разных директориях. Задача - сделать так, чтобы в меню навигации по этим разделам пропадала (или не подсвечивалась, выделялась другим цветом и т.д.) ссылка на тот раздел, в котором находится пользователь в данный момент. Для этого можно использовать переменную DOCUMENT_URI.


<!--#if expr="$DOCUMENT_URI!=/^\/index.phtmll/" -->
<a href="/">Первая страница</a><br>
<!--#endif -->
<!--#if expr="$DOCUMENT_URI!=/\/about\/index.phtmll/" -->
<a href="/about/">О нас</a><br>
<!--#endif -->><!--#if expr="$DOCUMENT_URI!=/\/done\/index.phtmll/" -->
<a href="/done/">Наши работы</a><br>
<!--#endif -->
<!--#if expr="$DOCUMENT_URI!=/\/partner\/index.phtmll/" -->
<a href="/partner/">Наши партнеры</a><br>
<!--#endif -->
<!--#if expr="$DOCUMENT_URI!=/\/client\/index.phtmll/" -->
<a href="/client/">Наши клиенты</a><br>
<!--#endif -->
<!--#if expr="$DOCUMENT_URI!=/\/price\/index.phtmll/" -->
<a href="/price/">Наши цены</a><br>
<!--#endif -->
<!--#if expr="$DOCUMENT_URI!=/\/contacts\/index.phtmll/" -->
<a href="/contacts/">Наши координаты</a><br>
<!--#endif -->
<!--#if expr="$DOCUMENT_URI!=/\/history\/index.phtmll/" -->
<a href="/history/">Наша история</a><br>
<!--#endif -->
<!--#if expr="$DOCUMENT_URI!=/\/search.phtmll/" -->
<a href="/search.phtmll">Поиск</a><br>
<!--#endif -->

Подобная конструкция используется веб-узле компании Веб 2000 (http://www.web2000.ru/)

Контекстный вывод текста в зависимости от условий

Предположим, у нас стоит задача менять внешний вид первой страницы узла в зависимости от того, откуда пришел пользователь. Например, компания Веб 2000 ставит на поддерживаемых ею проектах надпись-ссылку Supported by Web 2000, а при клике по ней пользователь попадает на первую страницу веб-узла компании и видит всплывющую подсказку с подробностями о разработке именно того проекта, с которого он пришел (попробуйте нажать на ссылку с веб-узла фирмы “Округ” (http://www.okrug.ru/) - "Поддержка Веб 2000" - мелким шрифтом внизу - увидите:-). Для реализации этой задачи используется следующая конструкция:


<!--#if expr="$HTTP_REFERER=/om.ru/" -->
Здесь пояснительный текст про веб-узел журнала ОМ

<!--#endif -->
т.е. сравнивается переменная HTTP_REFERER

Борьба с разными версиями дизайна для разных браузеров

Всем известно, что браузеры различных производителей и версий по-разному отображают одну и ту же phtmlL-разметку документа, начиная от специальных тагов и атрибутов и заканчивая поддержкой различных версий JavaScript. Для того, чтобы веб-узел выглядел нормально и для одной версии браузера и для другой или чтобы не сыпались ошибки JavaScript средствами SSI можно сделать проверку версий или браузеров и выдавать различные варианты phtmlL-разметки. Для этого анализируется переменная HTTP_USER_AGENT, в которой содержится информация о типе и производителе браузера:


<!--#if expr="$HTTP_USER_AGENT=/Mozilla\/4/ || $HTTP_USER_AGENT=/Mozilla\/5/" -->
Если версия браузера не ни же 4 или 5, то вывести вариант дизайна, использующий, например, DphtmlL

<!--#else -->
Здесь вывести простой дизайн

<!--#endif --> 

Подобная конструкция используется для построения фреймовой структуры и выводе внутреннего меню (для Netscape - на DphtmlL, для MSIE - на ActiveX) на веб-узле журнала "ОМ" (http://www.om.ru/)

Борьба с оформлением результатов работы скриптов

Самая большая проблема со скриптами заключается в том, что если есть большое количество наработанного ПО - при смене дизайна требуется их перенастройка. Хорошо, если ПО сделано правильно и изменение шаблонов отображения не касается самой математики, однако и в таких случаях существуют проблемы. Например, на странице поиска было бы неплохо крутить баннеры и рекламных сетей, но директивы SSI не отрабатываются в файлах .cgi. Решить подобные проблемы можно использованием SSI следующим образом: не скриптом обрабатывать шаблоны отображения, а вызывать скрипт из phtmlL-документа через SSI (к сожалению, таким образом можно работать только с теми скриптами, которые используют метод GET - переменная CONTENT_LENGTH не доступна в SSI) Итак, как это делается Есть phtmlL-документ, который размечен в общем стиле дизайна. В него вставляется директива:


<!--#include virtual="/cgi-bin/script.cgi?$QUERY_STRING" -->

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


...
# определение адреса, куда направлять данные
$query = $ENV{QUERY_STRING};
# определение места, из которого был вызван скрипт
$uri = $ENV{DOCUMENT_URI};
...
# отправка данных в тот же phtmlL-документ, из которого был вызван скрипт
print "<form action=$uri method=get>\n";
...

Подобная конструкция использована в разделе "Голосования" для интернет-супермаркета Levingston.Ru

Что можно сделать, используя Cookie и SSI

Часто встречается конструкция на JavaScript, которая выводит "Здравствуйте, Иван Иваныч!" при заходе на страницу веб-узла. То же самое можно проделать с помощью SSI директивой:


<!--#echo var="HTTP_COOKIE" -->

Баннеры, кэширование и SSI

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

  1. Можно генерировать всю страницу скриптом, от первого до последнего символа
  2. Можно сделать как советуют страницы помощи баннерных систем - включить by SSI скрипт, генерящий случайный баннер
  3. Динамически записать часть документа с кодом банера JavaScrip-ом 
А можно еще так:

<!--#config timefmt="%s"-->
<!--#set var="RND" value="$DATE_LOCAL"-->

<!-- Russian LinkExchange code START -->
<iframe src=http://www.linkexchange.ru/cgi-bin/erle.cgi?some_id?
<!--#echo var="RND"-->
frameborder=0 vspace=0 hspace=0 width=468 height=60 marginwidth=0 marginheight=0 scrolling=no>
<a href=http://www.linkexchange.ru/users/some_id/goto.map target=_top>
<img src=http://www.linkexchange.ru/cgi-bin/rle.cgi??<!--#echo var="RND"-->
alt="RLE Banner Network" border=0 height=60 width=468></a>
</iframe>
<!-- Russian LinkExchange code END -->

То есть как случайная величина выступит количество секунд от 1970 года. Не тратится время и память на запуск скрипта-генератора, Java-Script (как среди некоторых пользователей сейчас это модно) может быть выключен. На мой взгляд вполне радужно :-)
Все это проверено и применяется нашим администратором на http://www.j2.ru/

Один шаблон отображения - разное содержание

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


<!--#include virtual="$QUERY_STRING.phtmll"-->
ссылки, соответственно, будут иметь вид:
href="www.your_domain.ru/index.phtmll?page1"
href="www.your_domain.ru/index.phtmll?page2"
...
Проблема возникает, если пользователь набирает адрес непосредственно http://www.your_domain.ru, т.е. QUERY_STRING="" Решение:

<!--#if expr="$QUERY_STRING" -->
<!--#include virtual="$QUERY_STRING.phtmll"-->
<!--#else -->
<!--#include virtual="default.phtmll"-->
<!--#endif -->
где default.phtmll - страница корневого индекса (оглавления) и просто заглушка.



Пожалуй на этом пока все. Если у вас есть красивые примеры использования технологии SSI - буду рад опубликовать их здесь. Пишите письма.



Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/books/show2b.php on line 11

Warning: mysql_db_query() [function.mysql-db-query]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/books/show2b.php on line 19

Warning: mysql_db_query() [function.mysql-db-query]: A link to the server could not be established in /pub/home/javaport/javaportal/books/show2b.php on line 19

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /pub/home/javaport/javaportal/books/show2b.php on line 30
Узнай о чем ты на самом деле сейчас думаешь тут.


Опрос
Считаете ли вы целесообразным сделать аналог упражнений по Hibernate на базе вопросов www.sql-ex.ru?
Да, полный аналог упражнений
Да, но с реализацией основных конструкций объектной модели
Нет, Hibernate не актуален, использую др. технологии
Нет



Warning: mysql_connect() [function.mysql-connect]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/news/worldnews.php on line 91

Warning: mysql_db_query() [function.mysql-db-query]: Can't connect to local MySQL server through socket '/tmp/mysql.sock' (2) in /pub/home/javaport/javaportal/news/worldnews.php on line 93

Warning: mysql_db_query() [function.mysql-db-query]: A link to the server could not be established in /pub/home/javaport/javaportal/news/worldnews.php on line 93

Warning: mysql_fetch_array(): supplied argument is not a valid MySQL result resource in /pub/home/javaport/javaportal/news/worldnews.php on line 95