URI-fragments (они же fragment identifiers, hash, закладки, якоря) в последнее время стали активно использоваться в интерактивных веб-приложениях как удобное средство для указания прямых ссылок на различные элементы интерфейса и состояния приложения. Наиболее ярким примером использования fragment-адресации является GMail. Как Вы могли заметить, папки Входящие, Отправленные, Черновики имеют ссылки, оканчиващиеся на #inbox, #sent, #drafts. Переход между ними не приводит к перезагрузке всей страницы (обновляется только список писем), но в то же время при открытии каждой из них в отдельном окне/вкладке мы сразу же попадаем на искомую страницу.
Реализации такого удобного механизма навигации средствами JavaScript посвящена данная статья
В классическом HTML URI-фрагменты использовались для создания простейшей навигации внутри большого документа. В нужных местах документа можно было вставить тэги вида (т.н. анкоры) и ссылаться на них при помощи ссылок вида Go Here. При клике на такую ссылку браузер прокручивал документ к нужному месту, не перезагружая страницы. Так же можно было открыть в новом окне ссылку site.com/path/to/doc.html#go-here, и браузер после загрузки документа автоматически отображал его с позиции анкора. Естественно, работали анкоры только в тех браузерах, которые поддерживали данную возможность, т.к. обработка фрагментов целиком и полностью перекладывалась на клиентскую сторону. URI-фрагменты даже не передавались (и не передаются сейчас) на веб сервер.
Как видим, у фрагментов есть два важных преимущества:
Сегодня, в эпоху победного шествия технологий DHTML и AJAX, фрагменты обрели новую жизнь благодаря этим двум замечательным свойствам. URI-Fragment адресация позволяет строить RIA приложения, работающие полностью на AJAX, без перезагрузки страницы, и в то же время с сохранением некоторых привычных нам возможностей обычных веб приложений. А именно, сохранение определенного состояния (открытое письмо/фотография/документ) в ссылке, передача этой ссылки другому пользователю, который, открыв ее, увидит то же самое, что и Вы.
Один из моих клиентов заказал для своего сайта фотогалерею в виде Javascript-слайд-шоу. Переход между фотографиями не должен вызывать перезагрузку страницы, но в то же время он попросил, чтобы присутствовала возможность скопировать и отправить кому-то ссылку на определенную фотографию. Такая задача была довольно легко решена мною при помощи fragment-адресации.
Ссылки на фотографии имели вид site.com/gallery/name-of-gallery/#photo_id, где photo_id – код изображения. Кнопки Вперед-Назад а так же миниатюры в карусели были обычными ссылками на фрагменты с кодами соответствующих фотографий. Компонент слайдшоу и карусель с миниатюрамы перехватывали событие изменения фрагмента URI и соответсвующим образом реагировали (слайдшоу показывало нужную фотографию, а карусель выполняла прокрутку к ней и выделяло ее рамкой). Так же, сразу же после создания, каждый из этих компонентов проверял текущий фрагмент и осуществлял переход к фотографии.
Данный принцип организации приложения очень удобен. Его компонентам не надо «цепляться» обработчиками событий друг за друга для отслеживания изменений состояния. Достаточно всем сразу следить за изменениями URI-фрагмента и выполнять нужные действия. Вместо системы с множеством связей «многие к многим» мы получаем систему с централизированным упралением, которую намного легче разрабатывать и отлаживать.
Фреймворк ExtJS предоставляет удобный синглтон Ext.History для работы с fragment-адресацией. Перед началом его использования необходимо
Ниже приведен пример кода:
Подробную документацию по синглтону можно прочитать по ссылке http://www.extjs.com/deploy/dev/docs/?class=Ext.History. Я же приведу описание наиболее часто используемых возможностей. В терминологии Ext.History фрагменты именуются токенами (token):
Пример использования:
Официальное демо можно посмотреть по ссылке
http://www.extjs.com/deploy/dev/examples/history/history.html
а пример работы приведенного здесь кода — здесь. Так же можно скачать исходный код примера (альтернативная ссылка без дистрибутива ExtJS).
В стандартной поставке MooTools класса для работы с fragment-адресацией не было, плагинов я не нашел и решил использовать синглтон Ext.History. На его адаптацию под MooTools времени ушло совсем немного. Так же я немного дообработал синглтон – встроил создание воспомагательной формы в метод init() и инициализирую синглетон автоматически при подключении js-файла
Mootolls-синглтон я назвал HistoryManager. Методы и события полностью идентичны методам и событиям Ext.History.
Пример использования:
Пример работы приведенного здесь кода можно посмотреть здесь, демо фотогалереи — здесь. Так же можно скачать исходный код примера (альтернативная ссылка без дистрибутива ExtJS) и фотогалереи.
P.S. Если необходимо перевести Ext.History на Prototype или jQuery — обращайтесь, помогу.
UPD: Спасибо за карму, перенесено в JavaScript
Реализации такого удобного механизма навигации средствами JavaScript посвящена данная статья
Как было…
В классическом HTML URI-фрагменты использовались для создания простейшей навигации внутри большого документа. В нужных местах документа можно было вставить тэги вида (т.н. анкоры) и ссылаться на них при помощи ссылок вида Go Here. При клике на такую ссылку браузер прокручивал документ к нужному месту, не перезагружая страницы. Так же можно было открыть в новом окне ссылку site.com/path/to/doc.html#go-here, и браузер после загрузки документа автоматически отображал его с позиции анкора. Естественно, работали анкоры только в тех браузерах, которые поддерживали данную возможность, т.к. обработка фрагментов целиком и полностью перекладывалась на клиентскую сторону. URI-фрагменты даже не передавались (и не передаются сейчас) на веб сервер.
…и как сейчас
Как видим, у фрагментов есть два важных преимущества:
- Переход между фрагментами не вызывает перезагрузки страницы
- Они, как и стандартные query-strings, могут использоваться в качестве прямых ссылок, пользователь визуально видит что произошел переход (адресная строка изменилась), их удобно скопировать и отправить кому-то
Сегодня, в эпоху победного шествия технологий DHTML и AJAX, фрагменты обрели новую жизнь благодаря этим двум замечательным свойствам. URI-Fragment адресация позволяет строить RIA приложения, работающие полностью на AJAX, без перезагрузки страницы, и в то же время с сохранением некоторых привычных нам возможностей обычных веб приложений. А именно, сохранение определенного состояния (открытое письмо/фотография/документ) в ссылке, передача этой ссылки другому пользователю, который, открыв ее, увидит то же самое, что и Вы.
Практический пример.
Один из моих клиентов заказал для своего сайта фотогалерею в виде Javascript-слайд-шоу. Переход между фотографиями не должен вызывать перезагрузку страницы, но в то же время он попросил, чтобы присутствовала возможность скопировать и отправить кому-то ссылку на определенную фотографию. Такая задача была довольно легко решена мною при помощи fragment-адресации.
Ссылки на фотографии имели вид site.com/gallery/name-of-gallery/#photo_id, где photo_id – код изображения. Кнопки Вперед-Назад а так же миниатюры в карусели были обычными ссылками на фрагменты с кодами соответствующих фотографий. Компонент слайдшоу и карусель с миниатюрамы перехватывали событие изменения фрагмента URI и соответсвующим образом реагировали (слайдшоу показывало нужную фотографию, а карусель выполняла прокрутку к ней и выделяло ее рамкой). Так же, сразу же после создания, каждый из этих компонентов проверял текущий фрагмент и осуществлял переход к фотографии.
Данный принцип организации приложения очень удобен. Его компонентам не надо «цепляться» обработчиками событий друг за друга для отслеживания изменений состояния. Достаточно всем сразу следить за изменениями URI-фрагмента и выполнять нужные действия. Вместо системы с множеством связей «многие к многим» мы получаем систему с централизированным упралением, которую намного легче разрабатывать и отлаживать.
В ExtJS
Фреймворк ExtJS предоставляет удобный синглтон Ext.History для работы с fragment-адресацией. Перед началом его использования необходимо
- создать воспомагательную форму со скрытым полем и iframe. Стандартные возможности JavaScript позволяют только считать текущий фрагмент (window.location.hash) и нету события, которое возникало бы при его изменении. Для его отслеживания Ext.History сохраняет текущий фрагмент в скрытом поле (в IE иcпользуеться iframe) и при помощи работающей по таймеру функции периодически проверяет, не изменился ли он.
- инициализировать синглтон, вызвав его метод init();
Ниже приведен пример кода:
- Ext.getBody().createChild({
- tag: 'form',
- action: '#',
- cls: 'x-hidden',
- id: 'history-form',
- children: [{
- tag: 'div',
- children: [{
- tag: 'input',
- id: Ext.History.fieldId,
- type: 'hidden'
- },
- {
- tag: 'iframe',
- id: Ext.History.iframeId
- }]
- }]
- });
- Ext.History.init();
* This source code was highlighted with Source Code Highlighter.
Подробную документацию по синглтону можно прочитать по ссылке http://www.extjs.com/deploy/dev/docs/?class=Ext.History. Я же приведу описание наиболее часто используемых возможностей. В терминологии Ext.History фрагменты именуются токенами (token):
- Ext.History.add(token) – изменить текущий токен на указанный. При этом изменится ссылка в адресной строке, как быдто мы кликали по гипертекстовой ссылке на этот фрагмент.
- Ext.History.getToken() – получает текущий токен
- Ext.History.back(),Ext.History.forward() – эквиваленты нажатиям кнопок Back и Forward браузера
- Событие change (String token) – вознкает при изменении токена (как при переходе по ссылке так и при вызове метода add).
Пример использования:
- <script type=”text/javascript”>
-
- Ext.onReady(function () {
-
- <инициализация ExtHistory (см код выше)>
-
- var showToken = function(token) {
- if (Ext.isString(token) && token != '') Ext.Msg.alert('Token changed', String.format('New token: {0}', token));
- },
- t = Ext.History.getToken();
- Ext.History.on('change', showToken);
- Ext.get('settoken4').on('click', Ext.History.add.createDelegate(Ext.History, ['token4'], false));
- showToken(t);
- });
- </script>
-
- <a href="#token1">token 1</a> | <a href="#token2">token 2</a> | <a href="#token3">token 3</a>
- <input type="button" value="Set Token 4" id="settoken4" />
* This source code was highlighted with Source Code Highlighter.
Официальное демо можно посмотреть по ссылке
http://www.extjs.com/deploy/dev/examples/history/history.html
а пример работы приведенного здесь кода — здесь. Так же можно скачать исходный код примера (альтернативная ссылка без дистрибутива ExtJS).
В MooTools
В стандартной поставке MooTools класса для работы с fragment-адресацией не было, плагинов я не нашел и решил использовать синглтон Ext.History. На его адаптацию под MooTools времени ушло совсем немного. Так же я немного дообработал синглтон – встроил создание воспомагательной формы в метод init() и инициализирую синглетон автоматически при подключении js-файла
Mootolls-синглтон я назвал HistoryManager. Методы и события полностью идентичны методам и событиям Ext.History.
Пример использования:
- <script type="text/javascript">
- window.addEvent('domready', function () {
- var showToken = function(token) {
- if ($type(token) == 'string' && token != '') alert('New token: {t}'.substitute({t:token}));
- },
- t = HistoryManager.getToken();
- HistoryManager.addEvent('change', showToken);
- $('settoken4').addEvent('click', HistoryManager.add.bind(HistoryManager, ['token4']));
- showToken(t);
- });
- </script>
- </head>
- <body>
- <a href="#token1">token 1</a> | <a href="#token2">token 2</a> | <a href="#token3">token 3</a>
- <input type="button" value="Set Token 4" id="settoken4" />
* This source code was highlighted with Source Code Highlighter.
Пример работы приведенного здесь кода можно посмотреть здесь, демо фотогалереи — здесь. Так же можно скачать исходный код примера (альтернативная ссылка без дистрибутива ExtJS) и фотогалереи.
P.S. Если необходимо перевести Ext.History на Prototype или jQuery — обращайтесь, помогу.
UPD: Спасибо за карму, перенесено в JavaScript