Onhashchange только с кнопками браузера - PullRequest
6 голосов
/ 03 января 2011

У меня есть эта проблема (я использую jQuery, но я не ограничен этим):

Я использую комбинацию навигации Anchor (#id) и запросов Ajax.Чтобы заставить страницы перемещаться на место (используя навигацию привязки) или получать информацию (используя Ajax), я использую событие onhashchange.

РЕДАКТИРОВАТЬ: У меня была небольшая опечатка.Я забыл проверить, был ли флаг mouseDown истинным, и было ли инициировано событие hashchange, поэтому я добавил, что оператор if.

с jQuery выглядит так: (конечно, этот код обернут в функцию и инициализирован в 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 является «активным», событие нажатия клавиши при прослушивании ввода с клавиатуры срабатывает при нажатии на клавиатуру.Это означает, что проверка clientY больше не работает должным образом.

Проблема:

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

Как я могу заставить это работать?

Ответы [ 2 ]

3 голосов
/ 03 января 2011

Итак, проще говоря -

«как отличить нажатие кнопки« назад / вперед »от навигации, возникающей при взаимодействии с DOM».

Возможно, вы захотите иметь такой флаг, чтобы при изменении хеш-части URL-адреса из кода вы устанавливали этот флаг, игнорировали событие hashchange и затем сбрасывали флаг. В этом случае событие будет проигнорировано (своего рода обратное решение относительно того, что вы пытаетесь сделать). Вы, очевидно, захотите обернуть это в функцию.

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

Я бы также указал на тот факт, что история может поддерживаться во всех браузерах (даже в IE6 и IE7 с использованием хака iFrame). Взгляните на плагин jQuery history

1 голос
/ 04 января 2011

Справочная библиотека для достижения этой цели: http://benalman.com/projects/jquery-bbq-plugin/

Я использовал его, и он прекрасно работает

Подумайте о том, чтобы поставить "!" после "#" в URL, так что Google может обнаружить страницы AJAX http://code.google.com/web/ajaxcrawling/docs/getting-started.html

...