Onhashchange только с кнопками браузера
У меня есть эта проблема (я использую jQuery, но не ограничиваюсь этим):
Я использую комбинацию навигации по якорям (#id) и запросов Ajax. Чтобы переместить страницы на место (с помощью навигации по якорям) или извлечь информацию (с помощью Ajax), я использую событие onhashchange.
EDIT: у меня была небольшая опечатка. Я забыл проверить, был ли флаг mouseDown истинным, и событие hashchange было вызвано, поэтому я добавил оператор if.
С jQuery это выглядит так: (of конечно, этот код завернут в функцию и инициализируется при загрузке DOM, но это не имеет значения для вопроса)
$(window).bind('hashchange', function(e) { }
Чтобы гарантировать, что только браузеры, поддерживающие onhashchange, читают код, я инкапсулирую его следующим образом:
if ('onhashchange' in window) {
$(window).bind('hashchange', function(e) { }
}
Мое веб-приложение сделано таким образом, что я хочу, чтобы событие onhashchange запускалось только при нажатии кнопок Назад/Вперед в браузере. Для этого я делаю вот что:
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) { }
}
Теперь, если я нажму в окне просмотра, я вызову событие mousedown. Если событие mousedown запускается я знаю, что не нажимал кнопки браузера назад / вперед, и я могу остановить событие onhashchange, используя такой флаг:
var mouseDown = false;
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) {
if (e.type === 'mousedown') {
mouseDown = true;
}
if (mouseDown && e.type === 'hashchange') {
// if the mousedown event was triggered and when the haschange event triggers,
// we need to stop the hashchange event and restore the mouseDown flag
mouseDown = false;
e.stopPropagation();
}
if (!mouseDown && e.type === 'hashchange') {
// Do the onhashchange stuff here
}
}
}
Это вызывает проблему для IE , так как он швы вы не можете привязать события мыши к объекту окна (?). IE никогда не" увидит " событие mousedown.
Для решения этой проблемы IE я могу взять свойство "clientY". Это свойство передается во всех вызовах событий в IE и сообщает вам координаты мыши. Если e. clientY меньше 0, мышь находится вне окна просмотра, и я буду знать, что я запустил onhashchange, нажав кнопки браузера назад/вперед. Теперь это выглядит так:
var mouseDown = false;
if ('onhashchange' in window) {
$(window).bind('mousedown hashchange', function(e) {
// IE: Use e.clientY to check if the mouse position was within the viewport (i.e. not a nagative value for Y)
// !IE: Use e.type
if (e.type === 'mousedown' || e.clientY > 0 ) {
mouseDown = true;
}
if (mouseDown && e.type === 'hashchange') {
// if the mousedown event was triggered and when the haschange event triggers,
// we need to stop the hashchange event and restore the mouseDown flag
mouseDown = false;
e.stopPropagation();
}
if (!mouseDown && e.type === 'hashchange') {
// Do the onhashchange stuff here
}
}
}
Это решение работало как заклинание, пока мне не пришлось добавить поддержку навигации с помощью стрелок на клавиатуре. Теперь не имеет значения, где на экране находится мышь. Пока окно IE "активно", событие keydown, прослушивающее ввод с клавиатуры, срабатывает при нажатии кнопки клавиатура. Это означает, что проверка клиента больше не работает так, как планировалось.
Задача:
Насколько мне известно, onhashchange должен быть привязан к объекту window. Все события должны обрабатываться в рамках одной и той же функции обратного вызова, если я хочу иметь возможность контролировать одно событие, прослушивая другое.Как я могу заставить это работать?
2 ответа:
Итак, проще говоря -
"как я отличаю нажатие кнопки Назад / Вперед от навигации, исходящей от взаимодействия с DOM".
Вы можете иметь такой флаг, что при изменении хэш-части URL из кода Вы устанавливаете этот флаг, игнорируете событие hashchange, а затем снимаете флаг. В этом случае событие будет проигнорировано (своего рода обратное решение относительно того, что вы пытаетесь сделать). Вы, очевидно, захотите обернуть это в функцию.
В целом однако приложения, использующие событие hashchange для навигации, часто используют событие hashchange как средство изменения состояния приложения. Таким образом, существует только одна точка входа, и вам не нужно различать, генерируется ли событие навигацией браузера или взаимодействием dom. Я бы, наверное, посоветовал изменить ваш подход.
Я бы также указал вам на тот факт, что история может поддерживаться во всех браузерах (даже IE6 и IE7 с помощью iframe hack). Взгляните на плагин jQuery history
Справочная библиотека для достижения этой цели: http://benalman.com/projects/jquery-bbq-plugin/
Я использовал его, и он отлично работает
Подумайте о том, чтобы положить "!"после" # " в url, так что google может обнаружить страницы ajax http://code.google.com/web/ajaxcrawling/docs/getting-started.html