Pull to refresh

Использование URI-Fragment адресации в RIA приложениях на основе ExtJS и Mootools

Reading time7 min
Views1.7K
URI-fragments (они же fragment identifiers, hash, закладки, якоря) в последнее время стали активно использоваться в интерактивных веб-приложениях как удобное средство для указания прямых ссылок на различные элементы интерфейса и состояния приложения. Наиболее ярким примером использования fragment-адресации является GMail. Как Вы могли заметить, папки Входящие, Отправленные, Черновики имеют ссылки, оканчиващиеся на #inbox, #sent, #drafts. Переход между ними не приводит к перезагрузке всей страницы (обновляется только список писем), но в то же время при открытии каждой из них в отдельном окне/вкладке мы сразу же попадаем на искомую страницу.

Реализации такого удобного механизма навигации средствами 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 и соответсвующим образом реагировали (слайдшоу показывало нужную фотографию, а карусель выполняла прокрутку к ней и выделяло ее рамкой). Так же, сразу же после создания, каждый из этих компонентов проверял текущий фрагмент и осуществлял переход к фотографии.

image

Данный принцип организации приложения очень удобен. Его компонентам не надо «цепляться» обработчиками событий друг за друга для отслеживания изменений состояния. Достаточно всем сразу следить за изменениями URI-фрагмента и выполнять нужные действия. Вместо системы с множеством связей «многие к многим» мы получаем систему с централизированным упралением, которую намного легче разрабатывать и отлаживать.

В ExtJS


Фреймворк ExtJS предоставляет удобный синглтон Ext.History для работы с fragment-адресацией. Перед началом его использования необходимо
  • создать воспомагательную форму со скрытым полем и iframe. Стандартные возможности JavaScript позволяют только считать текущий фрагмент (window.location.hash) и нету события, которое возникало бы при его изменении. Для его отслеживания Ext.History сохраняет текущий фрагмент в скрытом поле (в IE иcпользуеться iframe) и при помощи работающей по таймеру функции периодически проверяет, не изменился ли он.
  • инициализировать синглтон, вызвав его метод init();


Ниже приведен пример кода:
  1.       Ext.getBody().createChild({
  2.           tag:  'form',
  3.           action: '#',
  4.           cls:  'x-hidden',
  5.           id:   'history-form',
  6.           children: [{
  7.              tag: 'div',
  8.              children: [{
  9.                tag: 'input',
  10.                id:  Ext.History.fieldId,
  11.                type: 'hidden'
  12.              },
  13.              {
  14.                tag: 'iframe',
  15.                id:  Ext.History.iframeId
  16.              }]
  17.           }]
  18.       });
  19.       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).


Пример использования:

  1. <script type=”text/javascript>
  2.  
  3. Ext.onReady(function () {
  4.  
  5. <инициализация ExtHistory (см код выше)>
  6.  
  7.       var showToken = function(token) {
  8.          if (Ext.isString(token) && token != '') Ext.Msg.alert('Token changed', String.format('New token: {0}', token));
  9.       },
  10.       t = Ext.History.getToken();            
  11.       Ext.History.on('change', showToken);
  12.       Ext.get('settoken4').on('click', Ext.History.add.createDelegate(Ext.History, ['token4'], false));
  13.       showToken(t);
  14.     });
  15. </script>
  16.  
  17.   <a href="#token1">token 1</a> | <a href="#token2">token 2</a> | <a href="#token3">token 3</a>
  18.   <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.

Пример использования:
  1.   <script type="text/javascript">
  2.     window.addEvent('domready', function () {      
  3.       var showToken = function(token) {
  4.          if ($type(token) == 'string' && token != '') alert('New token: {t}'.substitute({t:token}));
  5.       },
  6.       t = HistoryManager.getToken();            
  7.       HistoryManager.addEvent('change', showToken);
  8.       $('settoken4').addEvent('click', HistoryManager.add.bind(HistoryManager, ['token4']));
  9.       showToken(t);
  10.     });
  11. </script>
  12. </head>
  13. <body>
  14.   <a href="#token1">token 1</a> | <a href="#token2">token 2</a> | <a href="#token3">token 3</a>
  15.   <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
Tags:
Hubs:
+16
Comments11

Articles

Change theme settings