Pull to refresh

JSNAV

Reading time3 min
Views2.8K

Навигация по странице


Всё чаще и чаще в web появляются сайты, использующие навигацию, написанную на JavaScript. Типичный случай использования javascript для навигации: страница с меню и блоком контента, куда через AJAX подгружается содержимое:



Пользователь кликает по пункту, JavaScript грузит из сети содержимое, вставляет в блок контента, пользователь доволен: страница без перезагрузки показывает требуемое и траффика потребовалось меньше за счёт того, что не потребовалось грузить все эти HEAD, BODY, STYLE и прочие элементы.

Но вот проблема: URL страницы. Если на old scool сайтах на каждый пункт меню показывается новая HTML страница, и у пользователя есть вменяемый URI, который он может скопировать из адресной строки бразуера, послать другу или положить в закладки, то в случае AJAX интерфейсов в URI странице зачастую нет никаких ссылок на текущий контент документа.

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

Не с секрет, что для решения этой проблемы многие программисты кодируют ссылку на текущее просматриваемое содержимое в якорь (anchor) URI документа. К примеру, на сайте jqapi.com (скриншот которого приведён вначале топика) при выборе того или иного пункта меню якорь страницы меняется на #p={contentId}.

К примеру:
jqapi.com/#p=jQuery.ajax
jqapi.com/#p=height
jqapi.com/#p=addClass

В этом случае после загрузки страницы по якорю в ссылке можно просто восстановить и показать запрашиваемое содержимое.

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

Чтобы как-то решить эти проблемы к нам в голову с хабраюзером gbezyuk пришла идея создания библиотеки JSNAV, которая помогает решить указанные выше проблемы.

Как это работает?

JSNAV кодирует вызовы JavaScript обработчиков в URI документа. Для кодирования используется RFC1630 совместимые URI следующего вида:
user:pass@host:port/path/resource?query#anchor;navEventName;param1;param2;...

Cинтаксис якоря страницы:
  • до служебного символа # URI страницы ничем не отличается, от указанного в стандарте, изменения касаются лишь синтаксиса якоря
  • сразу же после # и до символа; идёт обычный HTML якорь со стандартным действием (прокручивание страницы до элемента якоря)
  • после якоря идёт служебный символ; и указывается имя события
  • далее через символ; идёт список параметров, с которыми будут вызваны обработчики событий; параметры закодированы в URL encoding в байтовой кодировке UTF-8

Библиотека после загрузки страницы начинает следить за изменениями URI по переменной window.location.href и, в случае его изменения, вызывает зарегистрированные обработчики.

JSNAV так же поддерживает работу с и обычными якорями: в случае перехода по ссылке с якорем производится scrollTo к элементу якоря. При этом в URI сохраняется описание последнего зарегистрированного события.

Обработчики представляют из себя обычные function объекты, на вход которым передаются декодированные из якоря параметры события.

var addClassHandler = function(className, textId) {
  var elm = textId? document.getElementById(textId) : this;
  if (elm.className && elm.className.indexOf(className) < 0) {
    elm.className += " " + className;
  }
}
JSNAV.bind("addClass", addClassHandler);


Обработчик addClassHandler из примера будет вызываться на URI вида:
  • test.html#;addClass — вызов addClassHandler() в контексте window.document.body
  • test.html#;addClass;className — вызов addClassHandler('className') в контексте window.document.body
  • test.html#;addClass;className;elementId — вызов addClassHandler('className', 'elementId') в контексте window.document.body
  • test.html#anchor;addClass;className — вызов addClassHandler('className') в контексте элемента якоря (элемента с id=='anchor' или name=='anchor') и прокрутка до элемента якоря

JSNAV

Библиотека написана на pure JS и, по идее, не должна конфликтовать ни с одним из известных фреймворков.

Зарепортить ошибку, предложить патч или скачать код можно на сайте проекта. Исходники доступны под Apache2 License.

Посмотреть, как всё это работает можно в примере на этой странице.

P.S.

Буду рад услышать комментарии, пожелания, получить баг-репорты. Кроме того приглашаю всех желающих присоединиться к разработке кода и документации.
Tags:
Hubs:
Total votes 72: ↑63 and ↓9+54
Comments97

Articles