Mike Melnikov (cherry-design@mail.ru)
Web-studio "Cherry-Design"
Немного специфическая статья и посвящена она решению проблем, возникающих при использовании на сайте фреймов. И, в частности, проблеме индексации таких сайтов поисковыми роботами и формированию фреймовой структуры при обращении к одной из внутренних страничек.
В общем случае от применения фреймов лучше всего воздержаться. Описание возникающих при этом проблем можно найти вот в этой статье. Если же применения фреймов избежать не удается, то приходится как-то решать эти проблемы. Вот этим мы сейчас и займемся.
Подготовка сайта к индексации
Начнем с более простого - подготовки сайта, использующего фреймы, к индексации поисковыми роботами.
В чем суть проблемы? Поисковые роботы представляют собой специальные программы, которые умеют путешествовать по ссылкам, начиная от некоторой корневой страницы. Когда Вы пытаетесь занести свою страничку в базу данных поисковой системы, Вас обычно просят ввести адрес главной страницы сайта. И вот с этого момента робот ставит Ваш запрос в очередь. Через некоторое время он пойдет по указанной ссылке и тщательно проанализирует всю страничку, вытащив из нее ключевые слова, краткое описание и другую полезную информацию. Все это он заботливо сохранит в своей базе данных. После того, как главная страничка будет проиндексирована, робот пойдет по ссылкам, которые на ней указаны, и будет заносить в базу все встречающиеся по пути странички. Глубина индексации обычно ограничивается 3 уровнями иерархии в пределах домена, на котором расположен сайт. Что, в принципе, правильно, иначе индексация сайта никогда бы не подошла к своему логическому завершению.
Таким образом индексируются обычные сайты, и так как на первой страничке обычно есть ссылки на все основные разделы сайта, то индексация проходит успешно. В случае с фреймами все не так. Т.е. робот пытается честно проиндексировать сайт по своим правилам, но у него, к сожалению, ничего не получается. Если Вы создавали странички с использованием фреймов, то знаете, что фреймы описываются в специальной страничке-контейнере. И, как правило, описываются лишь фреймы и формирующие их файлы. Никаких ссылок во внешний мир на этой страничке попросту нет(!). И что же происходит? Робот находит такую страничку, сохраняет ее в своей базе и... дальше ему некуда идти - он считает, что работа закончена и переходит к индексации следующего сайта. А мы получаем абсолютно непроиндексированный сайт! А значит, нашу страничку не смогут найти при помощи поисковых систем!
Ради справедливости следует заметить, что наиболее "продвинутые" поисковые системы уже пытаются индексировать сайты с фреймами и усложняют свои программы-роботы.
Ну а как же все-таки подготовить сайт с фреймами к правильной индексации? Как уже было сказано выше, проблема заключается в отсутствии на страничке-контейнере ссылок на основные разделы сайта. Значит, нам нужно просто добавить эти ссылки самим. И, поместим мы их в секции <noframes></noframes>, которая, кстати, специально была придумана для таких случаев. Заметьте также, что этот способ позволяет нам сделать сайт доступным для броузеров, которые не поддерживают фреймы.
А вот и пример корректного кода, осуществляющего все сказанное выше:
<html>
<head>
<title>Пример документа с фреймами</title>
В данном фрагменте я опустил описание META-тегов для упрощения изложения, но Вам будет необходимо их добавить перед началом регистрации сайта в поисковых системах. Подробности о том, как это сделать, Вы можете найти вот на этой страничке.
Решение проблемы с формированием структуры фреймов
Ну, а теперь займемся самой сложной проблемой - формированием фреймовой структуры при обращении к одной из внутренних страниц сайта. Проблема, в общем-то, заключается не в формировании структуры фреймов, а в отображении в одном из окон той самой запрошенной пользователем странички.
Но давайте сначала рассмотрим истоки проблемы. Как ни странно, они связаны в основном с поисковыми системами - теперь уже не в контексте регистрации, а непосредственно при анализе результатов поиска. Если сайт верно проиндексирован, то это значит, что в базе есть "паспорт" на любую страничку данного сайта, и, следовательно, в результате запроса мы можем получить ссылку на одну из внутренних страниц. Щелчок на ссылке, как Вы догадываетесь, откроет нам только внутреннюю страничку сайта без всяких фреймов. И, значит, весь кропотливо сделанный дизайн никто не увидит. Ладно дизайн, но ведь и добраться до других страничек сайта возможно будет лишь единственным способом - редактированием содержимого адресной строки.
Как же этого избежать? Вот сейчас и разберемся. Для начала рассмотрим простые способы, которые позволят обойтись нам без применения JavaScript. В общем-то, способ всего один, и заключается он в том, что внизу каждой странички необходимо сделать ссылку на главную страницу сайта (которая, как Вы помните, одновременно является и контейнером). Этот нехитрый прием позволит посетителям попасть в начало Вашего сайта, не прибегая к ухищрениям типа редактирования адресной строки. И, вполне возможно, что он найдет на сайте и другие полезные материалы.
Использование же JavaScript дает нам в руки гораздо более мощные средства и позволяет полностью сформировать всю фреймовую структуру и отобразить страничку в одном из фреймов.
Я не буду пока полностью приводить весь код скрипта, а для начала рассмотрю несколько приемов, каждый из которых делает нужное нам дело. Начнем с автоматического перехода на другую страничку. Это делается при помощи следующей конструкции:
<script language="JavaScript">
<!--
location.href="anotherpage.htm";
//-->
</script>
Свойство href объекта location содержит адрес текущей страницы, который, кстати, можно в любой момент прочитать. И если мы при помощи скрипта поместим в эту переменную адрес какой-либо другой странички, то броузер немедленно осуществит переход.
Второй прием - это передача скрипту параметров при помощи адресной строки (так называемый метод GET). Осуществляется это добавлением к адресу странички знака '?' (вопрос) и перечислением после него всех необходимых переменных и их значений. Если переменных несколько, то они отделяются друг от друга при помощи знака '&' (амперсанд). Вот несколько примеров передачи параметров посредством метода GET:
http://www.domain.com/page.htm?name=John&id=1986321
search.php?keyword=design&area=title&type=full
guestbook.asp?page=2
Вы наверняка видели подобные конструкции на сайтах интернет-магазинов и при запросах поисковых систем.
Для нашего случая этот прием обозначает следующее - мы можем передать главной страничке, которая формирует фреймы - адрес странички, на которую попал пользователь. А уж на страничке-контейнере обработать этот адрес и создать нужные фреймы.
Код, который приведен ниже, должен быть размещен в начале каждой внутренней страницы, которая выводится во фрейме:
<script language="JavaScript">
<!--
location.href="index.htm?"+location.pathname;
//-->
</script>
Заметьте, что конструкция несколько сложнее, чем я описал выше. В качестве параметра адреса я использовал свойство pathname объекта location, которое содержит полный путь текущей странички от корня сайта (для любопытных - location.href - содержит абсолютный адрес странички, включая название протокола и имя домена).
Если мы немного подумаем, то поймем, что перед автоматическим редиректом на новую страничку необходимо проверить - а не открыта ли страничка во фрейме? Иначе мы получим эффект бесконечного редиректа, когда странички будут все время открываться, пока компьютер не зависнет ввиду недостатка ресурсов. Окончательный код должен выглядеть вот так:
<script language="JavaScript">
<!--
if (window.parent.frames.length == 0) {
location.href="index.htm?"+location.pathname;
}
//-->
</script>
Т.е. мы читаем количество фреймов на родительской страничке и если это значение равно нулю (т.е. родителя нет), то мы осуществляем переход. В противном случае страничка загружена во фрейме и необходимости в редиректе нет.
Хорошо, мы передали главной страничке-контейнеру адрес странички, на которую попал пользователь, теперь необходимо создать нужную фреймовую структуру. Так как мы заранее не знаем, какая страничка будет во внутреннем фрейме, то мы не можем написать код для организации фреймов непосредственно. Это придется делать при помощи команд JavaScript:
<script language="JavaScript">
<!--
document.write('<frameset cols=\"180,*\">');
document.write('<frame src=\"menu.htm\" name=\"menu\">');
document.write('<frame src=\"content.htm\" name=\"content\">');
document.write('</frameset>');
//-->
</script>
Сейчас мы слегка модифицируем этот скрипт, чтобы в основной фрейм грузилась не страничка по умолчанию (content.htm), а наша внутренняя страничка. Но сначала придется из адресной строки узнать, какую же страничку грузить.
Для обработки переменных, передаваемых в адресной строке, JavaScript нам предоставляет свойство search объекта location (право, очень удобный объект - без его помощи мы не смогли бы сделать то, что делаем :). Данное свойство хранит в себе адрес строки запроса, которая располагается сразу после знака '?'. Т.е. оно содержит адрес нашей внутренней странички (!). Но использовать это значение пока рано, т.к. строка запроса содержит и начальный знак вопроса. Поэтому для начала нам необходимо его отрезать:
var string = location.search;
var current_page=string.substring (1, string.length);
А теперь я приведу полный, модифицированный вариант скрипта:
<script language="JavaScript">
<!--
var string = location.search;
var current_page=string.substring (1, string.length);
document.write('<frameset cols=\"180,*\">');
document.write('<frame src=\"menu.htm\" name=\"menu\">');
if (location.search == "") {
document.write('<frame src=\"content.htm\" name=\"content\">');
} else {
document.write('<frame src=\"' + current_page + '\" name=\"content\">');
}
document.write('</frameset>');
//-->
</script>
Кроме формирования фрейма, в который будет грузиться наша страничка, что обеспечивается следующим фрагментом:
document.write('<frame src=\"' + current_page + '\" name=\"content\">');
мы также отслеживаем случай загрузки индексного файла, когда ему не передан адрес внутренней странички (например, пользователь сразу набрал главный адрес сайта), и в этом случае грузим обычную страничку по умолчанию (content.htm).
Вот, в общем-то, и все - мы справились с проблемой внутренних страниц. Осталось только сделать несколько замечаний и пояснений.
Применение метода GET для передачи адреса внутренней странички затрудняет использование других переменных, которые мы также хотим передать методом GET. Для реализации такого эффекта скрипт еще более усложнится, т.к. придется отслеживать все переменные, которые мы передаем, и, соответственно, формировать более сложную строчку для редиректа. Кроме того, если эти переменные предназначаются внутренней страничке, то подобный механизм передачи значений переменных придется реализовать и в индексном файле при формировании фреймов.
Внимательный читатель может заметить, что я использую не классическую форму передачи параметров (т.е. value=param), а сокращенную - сразу передавая нужное значение. Это возможно в простых скриптах и несколько облегчает их написание. Тем не менее, такой способ не позволяет нам передавать более одной переменной.
Основной индексный файл мы формируем при помощи конструкций JavaScript. А что будет, если на сайт зайдет человек с броузером, который не поддерживает JavaScript? В этом случае мы вообще ничего не увидим, ведь сформировать фреймы будет некому. Так что для разрешения этой проблемы мы воспользуемся тегами <noscript></noscript>, внутри которых разместим обычное описание фреймов.
Позволь, дорогой читатель, я еще раз полностью приведу код индексной странички, в которой учтены все эти необходимые мелочи и особенности:
<html>
<head>
<title>Пример документа с фреймами</title>
</head>
<script language="JavaScript">
<!--
var string = location.search;
var current_page=string.substring (1, string.length);
document.write('<frameset cols=\"180,*\">');
document.write('<frame src=\"menu.htm\" name=\"menu\">');
if (location.search == "") {
document.write('<frame src=\"content.htm\" name=\"content\">');
} else {
document.write('<frame src=\"' + current_page + '\" name=\"content\">');
}
document.write('</frameset>');
//-->
</script>
<noscript>
<frameset cols="180,*">
<frame src="menu.htm" name="menu">
<frame src="content.htm" name="content">
</frameset>
<noframes>
<a href="content.htm">Содержание сайта</a>
<a href="page_1.htm">Страница #1</a>
<a href="page_2.htm">Страница #2</a>
<a href="page_3.htm">Страница #3</a>
</noframes>
</noscript>
</html>
Как поставить ссылку на внутреннюю страничку?
Осталось только одна проблема. Та самая, что указана в заголовке. Механизм формирования фреймовой структуры при ссылке на внутреннюю страничку мы уже разобрали, так что проблем со ссылкой на внутреннюю страницу не будет. А вот как пользователю сделать закладку на нужной страничке?
Самый простой, но достаточно эффективный способ - размещать в начале или в конце странички ссылку на страничку без фреймов. Разумеется, это можно делать не на всех страничках, а лишь на тех, что представляют самостоятельный интерес - например, статьи. Кстати, можно совместить ссылку с версией странички для печати - будет очень удачно.
А второй способ - опять же использование JavaScript, но он, к сожалению, ограничен только версиями Internet Explorer выше 5.0. По крайней мере, пока. Данный способ добавления странички в избранное я описывал раньше, поэтому не буду здесь повторяться. Те, кого это заинтересовало, могут прочитать об этом вот здесь.
Как видите, преодоление недостатков фреймов процесс достаточно хлопотный и неинтуитивный. Так что решайте сами - использовать Вам фреймы или поискать другие, более удобные способы, которые решат Ваши проблемы.
Архив с примерами скриптов, рассмотренных в данной статье, можно взять отсюда.