Pull to refresh

Comments 97

Я слоупок, но за jqapi.com спасибо. А то я для быстрой справки до сих пользуюсь visualjquery.com :(
Поддержу своим Спасибо — вообще пользовался оф. сайтом Jquery
Решение конечно достойное, но неудачное:
1. Что такое анкер-навигация и какие цели она преследует? Это возможность сохранить ссылку, для того чтобы в последстии вставить в адресную строку, и перейти на указанный урл. А не вызов определенных методов у dom-объектов.
2. Этот урл должен быть красивым и легкочитаемым… Роутинги в др. языках это показывают. Т.е. вместо host/path/resource#anchor;params;... лучше делать uri похожие на host/path/resource#method/params/.... Это более красиво. К тому же, для гугля и для noscript можно использовать: host/path/resource/method/params/..., т.е. просто заменив # на / мы не потеряем функциональности проекта.

А так решение красивое. +1
Интересное соображение.

Заменить; на / можно легко. Я выбирал символ разделителя исходя из стандарта URL encoding — он не должен заменяться на то-то типа %xx. Символ / вполне для этого подходит. В следующей версии я изменю символ разделителя.
Эмм… Решение удачное, но ему есть куда расти, с вашего позволения.
Идея отличная, но реализовать конечно нужно как посоветовал aavezel выше.
«Нет единого стандарта кодирования якорей.», ибо есть HTML5 History API.
и как это помогает переслать ссылку другому пользователю?
в смысле прямо сегодня?
HTML5 History API предоставляет нам возможность изменить сам url, а не хэшик. В итоге вы получаете полноценную ссылку, по которой можно пройти и получить желаемое без всяких там последующих преобразований на стороне клиента, то бишь сформировать все на сервере. В случае же с хэшиком такого сделать не получится, ибо он на сервер не передается. Собственно — html5demos.com/history (увы, серверная часть в демке не реализована, но ничто не мешает сделать ее самому :) ).
Ну как бы это не совсем правда: якорь передаётся на сервер в случае прямого GET запроса.

Плюс опять же вопрос «как это поможет мне прямо сегодня?». JSNAV работает даже в линксе, а вот History пока что полноценно фурычит лишь в хроме и фф.
Я и не спорю, что History работает только в передовых браузерах, но вот про передачу хешика на сервер я слышу впервые.
однако, передаётся :) можете просто проверить это
разве jsnav будет работать в Линксе? там ведь только плейн-хтмл. я вот ссылка после html5 history будет работать даже в Линксе. Давно ждал эту возможность. Надеюсь, через год можно будет полноценно использовать
какой? когда я в последний раз смотрел свой lynx он про существование JS даже не догадывался
Для справочника Ample SDK я сделал так:
если Javascript включен то внутренняя навигация осуществляется с использованием javascript/hash: www.amplesdk.com/reference/#/ample/runtime/ample.xml
если не включен то с использованием привычной query string www.amplesdk.com/reference/?/ample/runtime/ample.xml

если Javascript включен но пришли по ссылке www.amplesdk.com/reference/?/ample/runtime/ample.xml (например с Google), то она будет перенаправлена на www.amplesdk.com/reference/#/ample/runtime/ample.xml

P.S. Кстати в самом Ample SDK (Javascript GUI Framework) есть поддержка hashchange event согласно будущего стандарта HTML5
спасибо, посмотрю
отмигрируйте на github.com — как никак, лучшая платформа для коллективного творчества
Мастер ноду GIT может держать и sourceforge. Чем github лучше?
легкими форками, pull-реквестами, активным сообществом.
что насчёт trac?
Есть встроенный issue tracker. А также система на подобии patie.org (Gist) с историей изменений. Есть публичные и приватные репозитории.
Хочется иметь wiki систему, чтобы не делать сайт проекта. Собственно, по жтому меня и устраивает trac. Впрочем, мастер-ноду GIT можно перенести на github, а trac оставить на sourceforge. Как вам такой вариант?
И кстати, помимо собственно wiki, можно захостить сайт прям на github и хранить его исходники там же. Пример: neteye.github.com/
спасибо. правда не создаёт он репу =( ну я надеюсь починят…
И да, вики тоже есть.
Интересная вещь. Мы такое сами на коленке писали.
млин нифига это не удобно.

По мне мой велосипед лучше чем ваш.

Берем создаем $.Router() у которого будут два паблик метода:
1) set — Изменить hash
2) bind (regExp, callback) — callback принимает строчку запроса. Уже объект принявший заботится дальше о корректности

При этом нужно еще одно это каждые 50-100мс проверять изменился ли адрес и если изменился то вызывающая соответствующие колбеки.

И того у мя вышло 80 строк. с красивым форматированием кода.

Следовательно дальше в системе описываем свои классы и объекты, в которых есть функция обработчик адрес, принимающая адрес.
Все никаких зависимостей и чистота кода.

А в вашем случае быдлокод напрашивается прям=)

>При этом нужно еще одно это каждые 50-100мс проверять изменился ли адрес
в том же jQuery есть $(window) .hashchange()
не в jQuery, а в каком-то плагине к нему
Нее это не стандартные не подходящие мне скриптики.

Проверка изменения hash-a делается по сути так (ну в сокращении без оберток)

var prev ="";

function changed() {}

recheck = function() {
if(prev != document.location.hash){
prev = doucment.location.hash;
changed();
}
}

setInterval(recheck, 100)

А не те 100500 строк не нужного кода в библиотке .hashchange() + еще поиск скрипта делающего то что мне нужно занимает больше чем написание нужного кода.

Плюс суть моего скрипта от того каким образом происходит hashchange никак не меняется=)

Мы используем регекспы, для определения нужно ли вызвать так сказать событие у определенного объекта hash чейнжед=)

ну допустим делаем так

Main = {
hashChanged: function(){

},
init: function() {
$.Router.bind("\/#Main(.)*", Main.hashChanged);
}
}

И так далее=) красота

В результате имеем свой, велосипедный синтаксис: где-то хэшкод будет #p=abyrvalg, где-то #a/br/valg и т.д.

Ну и внимательно следим за document.anchors, чтоб имена хэшей не пересеклись, так?
а не проще повесить обработчик на все ссылки, чем проверять интервально изменился ли якорь?
ИМХО легче все ссылки с правильными ссылками давать, а через onclick делать своё нечистое дело…
Все зависит от задачи.

Если задача такая, что у нас сайт и на нем куча ссылок по которым переход происходит, и одно поле $("#content") где мы заполняем результат от перехода, то да, проще сделать $(«a»).click(function(){some_code});

Ну а если у нас есть дофига разнообразных объектов, которые зависят от текущего адреса, и каждый из этих элементов может адрес менять, то с вашим методом, возникнет очень много лишних строк, ошибок, зависимостей и код станет трудно редактируемым и нечитабельным, поэтому нужен именно маршрутизатор, который должен выполнять колбеки нужных функций для нового адреса.=)
Наверно я виноват, не дописал мысль до конца.

Пишем в href обычные ссылки, какие и должны быть, хоть с анчорами, хоть с посылами на mailto, а при загрузке документа обрабатываем все $(«context a») и добавляем обработчик события по клику, стандартную функцию для всех, отдавая назад this.href, а при её выполнении производим всё тот же парсинг.

Те же мухи, тока без постоянно опроса.
Нет не виноваты=-) я вас прекрасно понял.

Ну вы путаете немного…

Во-первых прослушка не юзает никаких ресурсов, ее можно даже в 200мс сделать (при современных мощностях, 1 проверка одной булевой переменной в 200мс фигня), при этом она используется ТОЛЬКО тогда когда пользователь САМ забивает адрес в адресбар.

Пы.Сы. Вот и возникает проблема, пользователь ввел адрес в строчку, как обработать этот адрес? код какой ссылки нужно обработать? =)

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

Но если у вас есть >10 взаимо-свзяаных объектов не ссылок, каждый из которых меняет состояния другого.

Ваш подход, заставляет каждому из >10 элементов знать про другие >9 и вызывать методы из других 9ти и каждый из этих элементов должен как то устанавливать другие >9… Будет просто каша которую не разрести, будут странные и не отлавливаемые ошибки и тп и тд… И вся система будет держатся на соплях.

Мой же метод позволяет каждому элементу знать, только о себе, и иметь одну функцию, которая принимает адрес, причем который заведомо относится к данному элементу, обрабатывая адрес устанавливать себя как нужно. Дальше если этот объект вызывает изменение адреса, все остальные которых будет касаться этот адрес себя установят как надо.

> Пы.Сы. Вот и возникает проблема, пользователь ввел адрес в строчку, как обработать этот адрес? код какой ссылки нужно обработать? =)

Вот именно, какой?
Я в текущий момент ещё ввожу ссылку, а эти 200мс уже отработали и проверили — адреса не сходятся! и пробует грузить новый, а там — шиш на постном масле ))
Причём пока я буду набирать — это ситуация будет повторяться неоднократно.
И не надо аргументов, что «как только встретится существующий идентификатор», потому что могут быть ситуации с идентификаторами «xxx» и «xxxbbb»

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

когда ты нажимаешь кнопки вперёд/назад адрес меняется

Столкнулся со странным поведением на странице с примером.
При повторном нажатии на одну и туже ссылку, например на ссылку «two» в списке «add highlight», то ничего не происходит. Не происходит повторного перехода по якорю, как в случае с «Simple bookmarks».
угу. баг. исправлю.
Одна из основных проблем в такой навигации является проблема индексации сайтов.

Думаю будет не лишним добавить ссылку, на предложение от Google по поводу решения этой проблемы (там и про способ формирования URL немного есть).
Гугл умеет выполнять javascript и индексировать AJAX страницы. Одна проблема — это происходит медленнее.

А вот если говорит про рунет — то у яндекса с этим проблемы, да.
кстати, а что мешает поисковику делать запрос вида example.com/page?query#state а серверу отдавать соответствующее содержимое?
по идее, ничего не мешает кроме особеностей реализации пауков
я предпочитаю использовать facebook-style урлы.
все ссылки работают без яваскрипта, если что.
а если яваскрипт есть, то работает аякс, в строку после «#!» добавляется адрес кликнутой ссылки.
Если перейти на эту страницу с хэшем (типа «#!/new_page.html»), скрипт находит ссылку на new_page.html на странице и кликает в нее.
Делается все это очень просто и без плагинов.
Можно конечно усовершенствовать и сделать все совсем красиво и элегантно «под капотом», но мне пока лениво
тут есть 2 проблемы:
организация вперед/назад навигации и скролл в начало страницы после смены хеша, как вы это решаете?
вперед назад работает.
хэши записываются в историю, ловим hacheChange и счастье.
а скролл в начало — не происходит.
хэш записывается яваскриптом: window.location.hache
в этом случае браузер не подбрасывает страницу
не забывайте, что IE не записывает в историю переходы при которых изменяется хеш. поэтому при нажатии назад на вашем примере попадаем на первую страницу сайта
это да. и события изменения хэша там нет.
но вроде бы есть какие-то хаки, надо уточнить.
я обычно позволяю себе делать деградацию для этого у**ища
ой, извините пожалуйста. я из вашего комментария подумал, что вы автор топика
Так наоборот надо чтобы подбрасывало вверх, а то внизу по ссылке нажмешь и на новой подгруженной странице там же остаешься.
это нужно далеко не всегда.
и скорее реже нужно, чем не нужно.
при необходимости, страница поднимается яваскриптом очень просто
Ричаппликухи типа фейсбучных ещё писать уметь надо. REST API и всё такое.

Большинство же разработчиков (особенно на западе) не поднимаются выше вопросов типа «как прикрутить компоненту к джумле».
ну я, конечно, такие аппликухи не пишу ))) но стараюсь делать чтоб было хорошо, удовлетворяя собственные желания и амбиции)
пользователь доволен: страница без перезагрузки показывает требуемое и траффика потребовалось меньше за счёт того, что не потребовалось грузить все эти HEAD, BODY, STYLE и прочие элементы.

Одному мне кажется лицемерным говорить об экономии пары десятков байт в эпоху широкого распространения p2p сетей?
Но вот проблема: URL страницы.

А, то есть проблема индексации страницы поисковиками никого уже не волнует?
но ведь это еще и красиво :) в эпоху web 2.0 :)
хотя мне кажется такие вещи удобны в основном для админок, сам пользуюсь плагинами от ExtJS :)
Это очень удобно для пользователя в плане отзывчивости интерфейса: кликнул в меню и сразу получил результат. Я считаю, это настолько прекрасно, что нельзя стыдиться говорить (и писать) об этом.
По-моему идея плохая. Не нравится этот ворох колбеков с параметрами, передаваемый особым образом в URL. Я считаю, что нужно использовать что-то типа рoутера. Т.е. у нас на входе URL вида /section/subsection/#anchor/section1/section2/?query=param1&param2. Первая часть после # это родной якорь. Дальше URL, парсим в объект на JS.

Объект будет вида:
{ anchor: '...', section: '...', subsection: '...', params: { query: '...', .... } };


Дальше в JS файлах, где нужно что-то сделать в зависимости от якорного URL регистрируем обработчики по регуляркам, которые могут совпадать с частью URL и в колбек-функцию передаем наш объект:
$.History.bind('/section1/section2/', function(urlData) {
  alert(urlData.params.query);
});


Реализация же может быть на чем угодно, хоть на onhashchange, хоть на постоянной проверке по таймеру, хоть на HTML 5 History (но потребует некоторого допила, т.к. onpopstate вызывается только при переходе по истории).
Мысль с сабсешинами здравая, но вот ?query=param1&param2 — пережиток CGI.
URI получается громоздким
Нет, ранее не видел.
К сожалению, у меня в опере как-то не очень работает.
Интересный подход у них — лого на Флеше…
UFO just landed and posted this here
Насколько я понял, ничто не мешает добавлять #! в конец якоря.

Кроме того, встречаются ситуации, когда контент не подгружается, а изначально присутствует на странице со стилем display:none и показываться по нажатию на служебные элементы.

Такие ситуации как обрабатывать?
UFO just landed and posted this here
По-моему, такая навигация есть признак дурного тона. А приведённое решение — это громоздкий и неудобный костыль, частично решающий проблему, частично её усугубляющий.

На мой взгляд, исключение, когда «анкорная» навигация уместна, составляют галереи картинок, как например тут: www.artgorbunov.ru/projects/thebat/gallery/#2
То есть когда анкоры соотвествуют:
а) строго последнему уровню вложенности
б) каким-то простым, однородным данным — единичной картинке или чему-то подобному
Оно самое. Только вот опять проблемы с обычными якорями.
ну ничто же не мешает добавить одним из параметров идентификатор фрагмента и прогручивать к нему. причём лучше делать это средствами браузера: создаётся фрейм, который растягивается на всё окно, и внутрь фрейма помещается содержимое текущей страницы. а в качестве хеша для фрейма задавать значение параметра fragment
фреймы — зло. их не обрабатывает линкс :)
Я не понимаю зачем городить огород?
Во-первых, возникают естественные опасения, что такие страницы будут некорректно индексироваться поисковиками.
Во-вторых — удобочитаемость ссылок. Плюс к тому, нужно что-то делать со ссылками в контенте, если они ведут в другой раздел этого же сайта.
Когда-то и передо мной стояла такая задача. Мне кажется, такое решение выглядит несколько элегантнее:
$('#navNewsButton')
    .attr('title', 'Новости')
    .attr('style', 'cursor:hand;cursor:pointer;')
    .bind('click', function(){
      $('#content').html('<div class="loading"><img src="/wp-content/themes/chel/images/loading.gif" alt="loading"><br/>Страница загружается</div>');
      $('#pageLayout').css('background-image', 'url(/wp-content/themes/chel/images/cbg_news.jpg)');
      $('#contentWrapper').load('/news/ #content', function(resp, stat, xhr){
        var response = String(resp).replace(/\r\n/g, '');
        var contents = response.match(/<script type=\"text\/javascript\">\nvar(.|\s)*?\/script>/gi);
        for(i = 0; i < contents.length; i++){
          var scriptBody = contents[i].replace(/<script type=\"text\/javascript\">/).replace(/<\/script>/);
          jQuery.globalEval(scriptBody);
        }
      });
      return false;
    });


* Кусок взят из рабочего проекта и работает для одной копки

При необходимости можно назначить всем ссылкам навигации в контексте сайта класс 'navi', спокойненько пройтись по ним при помощи each(), выдернуть ссылки на реальные страницы из аттрибута src и забиндить подгрузку страницы в блок контента по клику мыши. Не забываем вернуть false. Сюда же можно павернуть ещё кучу всего для любых ситуаций и на все случаи жизни.
Имеем следующие преимущества:
1. Естественная индексация роботами. Роботы не делают кликов, а грузят страницы.
2. У пользователя отключен яваскрипт? Не беда! Он всё равно увидит контент, если перейдет по ссылке.
3. В контенте есть скрипты (embed-видео например)? Скрипты будут выполнены.
4. ???
5. PROFIT!!!

P.S. Если есь какие-то косяки — с радостью выслушаю замечания по коду и по идее. Это буквально мои первые шаги в jQuery.
«павернуть» = "навернуть"
извините
Ну, в данном случае решается исключительно вопрос подгрузки страницы. Попробуйте открыть пример, который я привёл в топике — в этом случае я просто хочу сохранять подсветку определённого абзаца в URL страницы. На содержимое страницы такая подсветка не влияет.

Сделать такое сохранение можно тысячью способов, я предложил ещё один — стандартный.
Да, согласен. Немного разные задачи и совершенно разные решения.
У вас не решается задача, которая стоит у автора поста. А именно, работающая история браузера при смене состояния и возможность восстановить состояние интерфейса по URL. У вас просто реализована возможность что-то сделать по загрузке какого-то контента аджаксом. При этом реализована криво. Почитайте про кастомные события, многократно улучшите код и облегчите жизнь себе и последователям, которым придется работать с вашим доллар-супом.
Спасибо за замечания. Я ведь не волшебник, я только учусь =)
Бурное обсуждение у вас тут, вставлю свои 5 копеек.

Недавно вот закончил работу над проектом для заказчика, так какраз полная AJAX навигация, с красивыми якорями и прозрачным преобразованием URL из example.com/module/method/arg1/arg2.html в example.com/#module/method/arg1/arg2.html, которую юзеры даже не замечают. Если бы ещё можно было бы что бы браузеры умели при копировании URL преобразовывать такие урлы обратно в example.com/module/... вообще было бы супер.

Кстати при этом, полностью поддерживаются поисковые роботы. Вобщем-то если вырубить JS перед заходом (или потом отрубить JS и не забыть удалить куку js_enabled (или как-то так, с головы не помню), то по сайту (по его публичной части) можно будет вполне ползать (единственное что вёрстка не совсем хорошая, из-за этого ползёт частично, но поисковому роботу то пофигу :D).

Поглядеть можно тут: http://fizzer.ph/blogs.html. Регаться даже не пробуйте, оно чисто на филиппины и регистрация по мобильникам.
А самое главное, что когда видишь как это сделано, оказываеться настолько легко, что удивляешься чужим потугам и тому огороду, который они городят.
а нахрен там вам подгрузка контента аяксом? типа чтобы шапку и футер каждый раз не грузить? ну так их и грузите аяксом и закешируйте намертво
AJAX'ом грузятся и другие части сайта, просто в публичной части доступен только основной контент. Ну и переходы делаются гораздо быстрее + lazy load по возможности.

Скажем так, это ещё было моя первая проба пера, сделующий проект будет лучше, продуманее и круче :D Опыт штука бесценная.
с чего бы переходам тут делаться гораздо быстрее? сделайте нормальное кэширование и у вас будет всё летать и лениво загружаться.

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

полновесная страница состоит из статического содержимого + 2кб хтмл. вынести статику в отдельный файл и закешировать — не проблема совершенно. разница будет байтов 100
В авторизованной части есть панель с чатами, оповещения — всё это работает без перезагрузки в live режиме. Отчасти поетому тоже сайт на AJAX сделан. Так же на филлипинах весьма хреновые каналы, для них разница в подгрузить 2КБ HTML или полновесную страницу очень большая, даже с учётом кешей браузеров (которые не идиальны) первая версия была весьма тосклива. Так что причин несколько.
ребята молодцы
может скоро не придется изобретать велосипеды :)
возможно оно и так, но изобретение велосипедов позволяет развивать (или поддерживать) смелкалку, ум и всё такое )
Sign up to leave a comment.

Articles

Change theme settings