[解決済み】ブラウザの戻るボタンのイベントを検出する方法 - クロスブラウザ編
質問
ユーザーがブラウザの戻るボタンを押したかどうかを確定的に検出するにはどうすればよいですか?
単一ページのウェブアプリケーションで、ページ内戻るボタンを強制的に使用するには
#URL
の仕組みを教えてください。
ブラウザの戻るボタンは、なぜ独自のイベントを発生させないのですか!?
解決するには?
(注:Sharkyのフィードバックにより、バックスペースを検出するコードを含めました)
SOでは、このような質問をよく見かけますが、最近、私自身も戻るボタンの機能を制御する問題に直面しました。私のアプリケーション(ハッシュナビゲーションを持つシングルページ)に最適なソリューションを数日間探した結果、戻るボタンを検出するためのシンプルでクロスブラウザ、ライブラリ不要のシステムを思いつきました。
ほとんどの人が使用を推奨しています。
window.onhashchange = function() {
//blah blah blah
}
しかし、この関数は、ユーザーがページ内要素でロケーションハッシュを変更したときにも呼び出されます。ユーザーがクリックしたときにページが前後するのは、最良のユーザーエクスペリエンスとは言えません。
私のシステムの概要を説明すると、ユーザーがインターフェイス内を移動するたびに、以前のハッシュを配列に詰めています。それは次のようなものです。
function updateHistory(curr) {
window.location.lasthash.push(window.location.hash);
window.location.hash = curr;
}
かなりわかりやすい。クロスブラウザのサポートと古いブラウザのサポートを確実にするためにこうしているのです。新しいハッシュを関数に渡すだけで、関数がそれを保存し、ハッシュを変更します(ブラウザの履歴に入れられます)。
また、ページ内の戻るボタンを利用して、ユーザーをページ間で移動させるために
lasthash
の配列があります。以下のような感じです。
function goBack() {
window.location.hash = window.location.lasthash[window.location.lasthash.length-1];
//blah blah blah
window.location.lasthash.pop();
}
つまり、これはユーザーを最後のハッシュに戻し、その最後のハッシュを配列から削除します(今、私は進むボタンを持っていません)。
では、ユーザーがページ内の戻るボタンやブラウザのボタンを使用したかどうかを検出するにはどうすればよいのでしょうか?
最初、私は
window.onbeforeunload
これは、ユーザーがページを変更する場合にのみ呼び出されます。これは、ハッシュナビゲーションを使用した単一ページのアプリケーションでは起こりません。
そこで、さらに調べてみると、フラグ変数を設定することを推奨していることがわかりました。私の場合の問題は、設定しようとしても、すべてが非同期なので、ハッシュの変更のif文に間に合うように設定できるとは限らないということです。
.onMouseDown
は常にクリックで呼び出されるわけではなく、onclickに追加しても十分な速さで発動することはありませんでした。
という違いに注目し始めたのがきっかけです。
document
と
window
. 私の最終的な解決策は、フラグを設定するために
document.onmouseover
を使用し、無効化するには
document.onmouseleave
.
ユーザーのマウスがドキュメント領域(レンダリングされたページ、ただしブラウザーのフレームは除く)にあるとき、私のブーリアンは次のように設定されます。
true
. マウスがドキュメントエリアから離れるとすぐに、ブール値は
false
.
こうすることで、私の
window.onhashchange
に変更します。
window.onhashchange = function() {
if (window.innerDocClick) {
window.innerDocClick = false;
} else {
if (window.location.hash != '#undefined') {
goBack();
} else {
history.pushState("", document.title, window.location.pathname);
location.reload();
}
}
}
のチェックに注目です。
#undefined
. これは、もし私の配列の中に利用可能な履歴がなければ、それは
undefined
. 私はこれを使って、ユーザーに退出するかどうかを
window.onbeforeunload
イベントが発生します。
つまり、必ずしもページ内の戻るボタンや履歴を保存するための配列を使用していない人のために、このようになります。
document.onmouseover = function() {
//User's mouse is inside the page.
window.innerDocClick = true;
}
document.onmouseleave = function() {
//User's mouse has left the page.
window.innerDocClick = false;
}
window.onhashchange = function() {
if (window.innerDocClick) {
//Your own in-page mechanism triggered the hash change
} else {
//Browser back button was clicked
}
}
ハッシュ・ナビゲーションに関して、戻るボタンの使用とページ内要素を検出するためのシンプルな3つの方法です。
EDIT
ユーザーが backspace を使って back イベントをトリガーしないようにするには、次のように記述することもできます(Thanks to @thetoolman on この質問 ):
$(function(){
/*
* this swallows backspace keys on any non-input element.
* stops backspace -> back
*/
var rx = /INPUT|SELECT|TEXTAREA/i;
$(document).bind("keydown keypress", function(e){
if( e.which == 8 ){ // 8 == backspace
if(!rx.test(e.target.tagName) || e.target.disabled || e.target.readOnly ){
e.preventDefault();
}
}
});
});
関連
-
[解決済み] 要素外でのクリックを検出するにはどうすればよいですか?
-
[解決済み] どのラジオボタンが選択されているかをjQueryで知るにはどうしたらよいですか?
-
[解決済み] チェックボックスとそのラベルをクロスブラウザーで一貫して揃える方法
-
[解決済み] Safari、Chrome、IE、Firefox、Operaのブラウザを検出する方法は?
-
[解決済み] ブラウザのビューポート寸法を取得する方法を教えてください。
-
[解決済み] jQueryを使用してキーボードのEnterキーを押したことを検出する方法は?
-
[解決済み] chromedriverでSeleniumを使用していることをWebサイトで検出することは可能ですか?
-
[解決済み] HTMLバックリンクの作り方
-
[解決済み】戻るボタンをホームボタンのように動作するように上書きする
-
[解決済み] ブラウザがファイルのダウンロードを受信したことを検出する
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】 Uncaught TypeError: data.push is not a function
-
[解決済み】Uncaught ReferenceError: angular is not defined - AngularJSが動作しない。
-
[解決済み] jQueryで、ユーザーがそのフィールドを編集している間、テキストフィールドの最初の文字を大文字にするにはどうすればよいですか?
-
[解決済み】JavaScriptのgetElementByNameが機能しない
-
[解決済み】NodeJS "ESモジュールをロードするためにインポートを使用する必要があります。"
-
[解決済み】「Uncaught TypeError: Chromeで "Illegal invocation "が発生する。
-
[解決済み】未定義のプロパティ 'bind' を読み込めない。React.js【重複あり
-
[解決済み】SyntaxError: ChromeのJavascriptコンソールでUnexpected Identifierが発生する。
-
[解決済み】PhantomJS 2.1.1を使用してReactJSアプリケーションをレンダリングできない理由とは?
-
[解決済み】バックスペースキーで戻ることができないようにするには?