Javascript-форум (https://javascript.ru/forum/)
-   Ваши сайты и скрипты (https://javascript.ru/forum/project/)
-   -   history рассширение для браузеров не поддерживающих pushState, replaceState (https://javascript.ru/forum/project/21077-history-rassshirenie-dlya-brauzerov-ne-podderzhivayushhikh-pushstate-replacestate.html)

devote 27.08.2011 20:57

HTML5 history API рассширение для браузеров не поддерживающих pushState, replaceState
 
для работы с данной библиотекой просто подключите ее и работайте с ней так, как будто вы работаете со встроенными возможностями браузера.

Библиотека которая не добавляет ненужные методы заставляя их изучать, а оперирует по спецификации w3c, по интерфейсу History.

Для примера могу привести короткий код как с ней работать.

По принципу мы работаем с HTML5 History API так как описано например тут http://htmlbook.ru/html5/history или по спецификации http://www.w3.org/TR/html5/history.h...tory-interface то-есть коротенький пример:

на чистом JS:
<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="history.js"></script>
        <script type="text/javascript">
            (function(eventInfo) {
                // вешаем события на все ссылки в нашем документе
                document[eventInfo[0]](eventInfo[1] + 'click', function(event) {
                    event = event || window.event;
                    var target = event.target || event.srcElement;
                    // ищем все ссылки с классом 'ajax'
                    if (target && target.nodeName === 'A' &&
                       (' ' + target.className + ' ').indexOf('ajax') >= 0)
                    {
                        // заносим ссылку в историю
                        history.pushState(null, null, target.href);


                        // тут можете вызвать подгрузку данных и т.п.


                        // не даем выполнить действие по умолчанию
                        if (event.preventDefault) {
                            event.preventDefault();
                        } else {
                            event.returnValue = false;
                        }
                    }
                }, false);

                // вешаем событие на popstate которое срабатывает при нажатии back/forward в браузере
                window[eventInfo[0]](eventInfo[1] + 'popstate', function(event) {
                    // получаем нормальный объект Location

                    /*
                    * заметьте, это единственная разница при работе с данной библиотекой,
                    * так как объект document.location нельзя переопределить, поэтому
                    * библиотека history возвращает сформированный "location" объект внутри
                    * объекта window.history, поэтому получаем его из "history.location".
                    * Для браузеров поддерживающих "history.pushState" получаем
                    * сформированный объект "location" с обычного "document.location".
                    */
                    var returnLocation = history.location || document.location;


                    // тут можете вызвать подгрузку данных и т.п.


                    // просто сообщение
                    alert("We returned to the page with a link: " + returnLocation.href);
                }, false);
            })(window.addEventListener ? ['addEventListener', ''] : ['attachEvent', 'on']);
        </script>
    </head>
    <body>
        <a class="ajax" href="/mylink.html">My Link</a>
        <a class="ajax" href="/otherlink.html">Other Link</a>
    </body>
</html>
за простой пример не судите, на коленках написал.

Вы можете использовать дополнительные параметры конфигурации библиотеки:

history-1.2.8.min.js?basepath=/pathtosite/ - базовый путь к сайту, по умолчанию имеет значение корня "/".
history-1.2.8.min.js?redirect=true - включить преобразование ссылок.
history-1.2.8.min.js?type=/ - подставлять подстроку после якоря, по умолчанию ничего не подставляет.

Также вы можете комбинировать опции:
history-1.2.8.min.js?type=/&redirect=true&basepath=/pathtosite/ - порядок опций не имеет значение.

Демо-сайт тут, пока еще в разработке но посмотреть что-то можно.

Преимущества от библиотеки Balupton History. Весит в три раза меньше, работать проще, никаких лишних дополнительных методов, поддерживает все браузеры которые в ходу.

1.2.1 - Обновил версию, добавил полную поддержку replaceState и параметра title - огромное спасибо trikadin за помощь в реализации replaceState.

1.2.2 - Исправил серьезную ошибку, которая не позволяла событию идти по цепи. Проблема была в том что если на событие popstate повесить два и более обработчика, то срабатывало только лишь одно первое. Остальные не получали событие.

1.2.3 - Исправлена работа с относительными ссылками и добавлен параметр type для возможности изменить тип отображения якоря в браузерах не поддерживающих history.pushState теперь можно настроить любой для вас удобный вид для ссылки. По умолчанию этот параметр пустой, и ссылки выглядят http://somesite.com/#path, вы можете добавить например слешь, и ваша ссылка будет выглядеть так: http://somesite.com/#/path.

1.2.4 - Исправлена назначение текущего параметра history.state при вызове pushState ( Спасибо "zebra" )

1.2.5 - Исправлена ошибка вызывающая exception при возврате значения state.

1.2.6 - Добавлена возможность вешать событие через window.onpopstate.

1.2.7 - Исправлена ошибка в работе с сайтами имеющими иной порт от стандартных.

1.2.7a - Добавлена поддержка ИЕ6.

1.2.8 - Исправлена замусоривание глобального пространства.

2.0 - Полностью переписана библиотека с нуля, исправлено некорректное сохранение state, убраны провисания, переделана система управления кнопками back/forward, и много другое. Ну и как всегда, стала более оптимизирована, весить стала меньше, работать быстрее.

2.0.1 - Исправлен отказ работы во фрейме и при использовании frameset'ов.

2.0.2 - Исправлена назначение document.title, при отсутствующем титле назначал null.

2.0.3 -
Добавлен объект Location в экземпляр History, теперь текущий URL можно получить из любого места в документе: alert( history.location || document.location );

Исправлена ошибка работы с URL адресами, имеющие другой регистр символов.

Переделано использование sessionStorage, теперь для библиотеки выделяется отдельная ячейка в хранилище.
2.0.4 - Исправлена работа библиотеки в FireFox ниже 4-ой версии.

3.0 beta - Полностью переработанная версия.
Что в ней нового.

Теперь библиотека не просто добавляет API в браузеры где ее нет, но и исправляет баги/недоделки в браузерах где они имеются.

Chrome, Safari - Убрана стартовое событие при загрузке документа.
Safari - добавлено свойство state в объект window.history
Opera - добавлено срабатывание события popstate при смене hash документа, по спецификации оно должно срабатывать при любой смене объекта state.

Добавлен объект Location в интерфейс History, теперь history.location работает во всех браузерах и ничем не отличаеться от объекта window.location. То-есть теперь вы можете применять на нем все теже действия что и на обычном window.location.

Библиотека была протестирована в браузерах:
IE 6+
FireFox 3.6+
Opera 11.6x+, Mobile
Chrome 18+
Safari 5+

Если у вас есть возможность протестировать в других браузерах то это будет очень здорово.
3.0.1 beta - Исправлена ошибка, не срабатывало событие popstate если до него было повешено событие hashchange.

3.1.0 beta - Были проблемы с формированием ссылок, так же разветвил версии сделал отдельную версию для IE8+ то есть вырезал все что связано с ИЕ7 и ниже

3.1.1 beta - Не менялся адрес в адресной строке если на странице присутствовал хоть один frame/iframe

3.1.2 beta - Переставал работать в ИЕ9 при переключении браузера в режим совместимости.

3.1.3 beta - Не правильно работал параметр redirect/basepath. при указании basepath=/path/ и при переходе по ссылке http://somesite.com/path получали ссылку http://somesite.com/path/path - подробнее

3.2.0 - Реализован метод history.redirect() и исправлена работа с обычными хешами в ссылках. Подробнее.

3.2.1 - Не корректно работала библиотека c относительными ссылками в IE 10. Подробнее.

3.2.2 - Firefox не вызывал события объекта window при подключении библиотеки. Подробнее.

4.0.0 - Новая версия, переписана с нуля. Исправлены ошибки в работе на мобильных браузерах и многие ошибки на десктопных браузерах.

4.0.5 - Мелкие правки.

4.1.6 - Поддержка AMD и многое другое.

Подробнее о библиотеке вы можете прочитать статью на хабре: http://habrahabr.ru/post/144071/
Проект на GitHub: https://github.com/devote/HTML5-History-API
Ссылка для скачивания: http://code.spb-piksel.ru/?history.latest.zip

Важно! Мне часто стали писать/сообщать о неработоспособности библиотеки в ИЕ9. Проблема связана с тем, что ИЕ9 капризный браузер и придирается ко всем мелочам. Как выяснилось, многие разработчики что используют скрипты взятые с GitHub сталкиваются с проблемами их неработоспособности, потому что ИЕ9 при подключении скриптов ожидает получить заголовок application/javascript, но GitHub возвращает заголовок text/plain. Поэтому подключать скрипты напрямую с GitHub не рекомендуется. Скачайте скрипт к себе на хост и используйте.

TAGS: History API, history, pushState, смена ссылки без перезагрузки, ajax навигация, управление историей

devote 27.08.2011 21:29

Цитата:

Сообщение от melky
ого, хорошая задумка!

Все для вас :) Мне не жалко, но пока версия в статусе alpha нужно тестить и т.д. ну и доку написать, есть несколько просто тонкостей, но мелочные... плюс еще storage не написан для параметра state и title. Но писал я его один день, так что прошу раньше времени не судить. Замечания и баги пишем тут...

Всем заранее спасибо за все!

dmitriymar 27.08.2011 22:54

devote,
а вариант в возвратом сервером заголовка 204 не рассматривал?

devote 27.08.2011 23:04

Цитата:

Сообщение от dmitriymar
а вариант в возвратом сервером заголовка 204 не рассматривал?

Вариант для чего? Для хранения storage? Просто не могу понять как может относиться отправка данных в одну сторону, к тому что я сделал

dmitriymar 27.08.2011 23:11

У меня руки не доходили проверить эту штуку. Точнее меняется ли адресная строка при Get отправке данных на сервер через форму и возврате сервером заголовка 204. Если меняется ,маловероятно очень конечно ,позволит делать интересные штуки для старых браузеров. Не пробовал по трём причинам-первая лень,вторая- если бы менялась то этим давно бы уже пользовались ,третья- по логике не должна работать эта фишка

devote 27.08.2011 23:17

Цитата:

Сообщение от dmitriymar
Не пробовал по двум причинам-первая лень,вторая- если бы менялась то этим давно бы уже пользовались .

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

dmitriymar 27.08.2011 23:28

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

devote 27.08.2011 23:33

мини демо могу привести сейчас, тоесть то на чем тестил:

создаем файл например index.html c содержимым:
<!DOCTYPE html>
<html>
	<head>
		<title>...</title>
		<script type="text/javascript" src="history-1.0.3.js"></script>
	</head>
	<body>
		<div id="popstatus"></div>
		<button type="button" onclick="history.pushState({page: 3}, 'title 3', '/site/bla.php?'+Math.random());">Change URL now!</button>

	<script type="text/javascript">
	if ( window.addEventListener ) {
		// for Other event
		window.addEventListener('popstate', function( e ) {
			var loc = e.location || document.location;
			document.getElementById('popstatus').innerHTML += 'popstate change to url: ' + loc + '<br />';
		}, false);
	} else if ( window.attachEvent ) {
		// for IE event or browser not supported addEventListener
		window.attachEvent('onpopstate', function( e ) {
			var loc = e.location || document.location;
			document.getElementById('popstatus').innerHTML += 'popstate change to url: ' + loc + '<br />';
		});
	}
	</script>
	</body>
</html>
тонкость это то что мы обращаемся к document.location в во время перехвата popstate немного иначе. Собственно вот и вся модель библы... в остальном все как обычно... в параметре гет есть еще пару настроек, это:
redirect - true/false перенаправлять на основную ссылку или нет
basepath - указываем директорию в которой находиться сайт. По умолчанию просто корень "/"

devote 15.12.2011 04:27

Дауж, так и не добрался до того что бы сделать тестовый пример ;)

Nekromancer 15.12.2011 14:14

dmitriymar,
Не сработает. Смена URL происходит при получении заголовков ответа с сервера. А статус вообще первая строка :)
devote,
Зачем вообще бланк и spacer.gif для старых ие? Вот никак не могу понять.

devote 15.12.2011 15:42

Цитата:

Сообщение от Nekromancer
devote,
Зачем вообще бланк и spacer.gif для старых ие? Вот никак не могу понять.

Да именно, для ИЕ < 8 нужна эта хрень. А вообще я уже в библе небольшие исправления сделал... Проблемы были в событиях. когда обработчик сажаешь через какую нить библу например jQuery, тоесть:
$( window ).bind( "popstate", function( e ){
    // ...
});
иногда бывало не срабатывало событие... Перезалил файл

Nekromancer 15.12.2011 15:53

http://javascript.ru/forum/ajax/2334...tml#post138521
spacer.gif и всё такое, как бы вообще не нужны

devote 15.12.2011 16:51

Цитата:

Сообщение от Nekromancer (Сообщение 143167)
http://javascript.ru/forum/ajax/2334...tml#post138521
spacer.gif и всё такое, как бы вообще не нужны

Да спасибо, отличнейший хак... странно что я его нигде не видел... Сенькс... Заменил файлы снова.

trikadin 15.12.2011 17:02

Цитата:

Сообщение от devote
отличнейший хак

Взаимоисключающие параграфы)

devote 15.12.2011 17:07

Цитата:

Сообщение от trikadin
Взаимоисключающие параграфы)

=)


А вообще моя библа хороша тем, что ее достаточно подключить к сайту где уже организованно history.pushState для новых браузеров. То есть если писать под новые браузеры не задумываясь о старых, то потом можно просто подрубить этот скрипт до вызова других, и все сразу заработает в старых. Хотя конечно есть нюансы с ссылками. но это мелочи.

trikadin 15.12.2011 17:10

Цитата:

Сообщение от devote
А вообще моя библа хороша тем, что ее достаточно подключить к сайту где уже организованно history.pushState для новых браузеров. То есть если писать под новые браузеры не задумываясь о старых, то потом можно просто подрубить этот скрипт до вызова других, и все сразу заработает в старых. Хотя конечно есть нюансы с ссылками. но это мелочи.

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

devote 15.12.2011 17:15

Цитата:

Сообщение от trikadin
Мне тоже всегда нравился такой подход - не писать оболочку, а дописать функционал для старых браузеров.

Ну дык этож проще, темболее когда есть возможность перезагрузить функции, тоесть когда объекты не readonly.

Nekromancer 15.12.2011 17:30

devote,
Не видели потому, что я сам написал :)
Цитата:

Сообщение от trikadin
Мне тоже всегда нравился такой подход - не писать оболочку, а дописать функционал для старых браузеров.

Да я тоже как бы за него. Особенно в последнее время. Например с WebSockets и XHR )

trikadin 15.12.2011 17:32

Цитата:

Сообщение от Nekromancer
Не видели потому, что я сам написал

Понт детектед :D

devote 15.12.2011 17:41

Цитата:

Сообщение от trikadin (Сообщение 143195)
Понт детектед :D

Не знаю как насчет понта, но я сам пробовал миллионы способов что бы не юзать этот идиотский blank.gif но увы так и не нашел.

Nekromancer 15.12.2011 17:43

trikadin,
Ну вот и чё сразу понт?) Человек поинтересовался, я и рассказал. Может конечно кто то и делал такое ещё, но это не меняет сути )

trikadin 15.12.2011 17:43

Цитата:

Сообщение от devote
Не знаю как насчет понта, но я сам пробовал миллионы способов что бы не юзать этот идиотский blank.gif но увы так и не нашел.

Это шутка была) Способ-то хороший)

devote 23.12.2011 18:58

Выложил в первый топик самую последнюю версию библиотеки.

FINoM 23.12.2011 20:42

Тю блин, открыв тему я возрадовался, но когда увидел хеш, немножечко скривился. Думал на флеше и по-кошерному, а тут фиг.

FINoM 23.12.2011 20:52

А что происходит, если человек перезагрузил страницу?

devote 23.12.2011 20:53

Цитата:

Сообщение от FINoM
Тю блин, открыв тему я возрадовался, но когда увидел хеш, немножечко скривился. Думал на флеше и по-кошерному, а тут фиг.

Хм... что-то я тебя не понял, причем тут флешь? и почему по твоему флешь кошернее?

FINoM 23.12.2011 20:57

Цитата:

Сообщение от devote
Хм... что-то я тебя не понял, причем тут флешь? и почему по твоему флешь кошернее?

Флеш — наверно он, а не она.
Я думал что это обертка над флеш роликом, меняющим строку адреса, не используя хеш. Хотя, скорее всего, флеш такого не может.

devote 23.12.2011 20:57

Цитата:

Сообщение от FINoM
А что происходит, если человек перезагрузил страницу?

вызывается popstate для возврата в предыдущее состояние... все продумано поверь. Можешь посмотреть например тут: http://history.spb-piksel.ru/ по обновлять страницу.. там ничего пока нет, но что-то увидеть можно.

devote 23.12.2011 20:58

Цитата:

Сообщение от FINoM
Хотя, скорее всего, флеш такого не может.

вот именно что не может =)

FINoM 23.12.2011 21:00

Цитата:

Сообщение от devote
вызываеться popstate для возврата в предыдущее состояние

Я просто не работал с History еще. Получается, если перезагружаешь страницу, грузится не то, что по адресу, а текущее состояние?

devote 23.12.2011 21:03

Цитата:

Сообщение от FINoM
а текущее состояние?

по сути да. тоесть для не поддерживаемых браузеров все происходит прозрачно. Конечно же грузиться главная страница, но когда библиотека видит что хеш имеет иное значение, тут же вызывает событие popstate тем самым инициализируя загрузку нужного контента. То есть для юзера этого даже не заметно. При этом юзер видит то что положено.

FINoM 23.12.2011 21:14

devote, вы автор или участник?

devote 23.12.2011 21:16

Цитата:

Сообщение от FINoM
devote, вы автор или участник?

Да я сам писал ее

Nekromancer 23.12.2011 22:19

А я вот это делал, года 2 назад, когда ещё не было History API
http://www.linkexchanger.su/shared/widget.htm

devote 23.12.2011 22:22

Цитата:

Сообщение от Nekromancer
А я вот это делал, года 2 назад, когда ещё не было History API

Ну принцип тот же..

Nekromancer 23.12.2011 22:26

devote,
Ну конечно :)

devote 23.12.2011 22:34

Цитата:

Сообщение от Nekromancer (Сообщение 145603)
devote,
Ну конечно :)

А разве нет? Отслеживаешь изменение хеша, и делаешь запросы при его изменении. У меня тот же принцип, в старых браузерах ( ИЕ7 ) отслеживаю таймером изменение хеша, на более свежих ( ИЕ8, ИЕ9 и т.д.) слушаю событие hashchange, и запускаю событие popstate при изменении хеша.

Nekromancer 23.12.2011 22:40

devote,
"Ну конечно", это - да, так и есть. "Ну" - слово паразит.

devote 23.12.2011 22:44

Цитата:

Сообщение от Nekromancer
"Ну" - слово паразит.

дауж =)

devote 27.12.2011 07:46

обновил версию


Часовой пояс GMT +3, время: 10:19.