質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.98%

JSで特定のページに(一瞬たりとも)戻れなくする方法

解決済

回答 6

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,935

cnx

score 17

JS(JavaScript)であるページへの「戻る」動作を抑制したいのですが、シンプルで簡潔に実装する方法はあるでしょうか。
対象ブラウザはAndroidのWebViewです(AndroidアプリにWebViewが埋め込まれておりJSをユーザーがOFFにしたり、Blank指定で新しいページを表示することは出来ません)。
また、WebViewのイベント経由で遷移URLをログとして収集しているため、innerHTMLなどをAjaxで取得した内容で置き換えるといったWebViewのloadedイベントなど発生しない方法は検討の対象外となります。

独自に調査したところではHTML5のhistory.stateなどを使ったものがあるようですが「あるページにおいて、おしなべてどのページにも戻れなくする方法」にしかならないようです。
また、現在は仕方なくwebstorageにフラグを立てて戻ってきたらフラグ判定して条件に合う場合にのみ強制的にhistory.forwardなどを掛けているのですが、一瞬戻っていることに変わりは無いため前出のWebViewイベントが反応してしまいログに複数の履歴が残り困っています(ログを残したくない)。

やりたいこと
ページAにおいて、
ページA → ページB(直前のページがB) は戻れても良いが
ページA → ページZ(長髯のページがZ。Zは特別戻らせたくないページ)のようにZにだけは戻れないようにする。

という動作です。
WebStorageなどでフラグを立てて判定する他ないのでしょうか。
それとも、完結に特定のページに対する戻り動作だけを寸前で抑止する方法はありますでしょうか。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 6

+6

要件は、「ページZ→ページAと遷移した状態で、ページZに戻れないようにする方法」ということで間違いないでしょうか(それ以外のパターンがあるなら補足をお願いします)。

このような場合、ページZの側で、ページAへのリンクを押した時に、

  • ブラウザによる遷移をキャンセル
  • ページAの内容をAjaxで取得して差し替え
  • history.replaceStateで履歴をページAに差し替え

とすれば、ページZは履歴にも残りませんので、戻ることもできなくなります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/27 00:21

    ZからAに遷移する際に遷移をキャンセルしてしまうと、ページAへの遷移が出来なくなってしまう印象ですが如何でしょうか。
    ajaxについては、クライアント(WebView)に履歴が残らない気がします。
    前提に書かず申し訳ないのですが、クライアントで遷移ログを収集しているのでページAに遷移した履歴をイベント取得したい事情がございます。
    history.replacestateについて、もう少し勉強してみます!

    キャンセル

  • 2017/01/31 19:56

    Aへ遷移したような状態を「JavaScriptで作ってしまう」手法で、「pjax」と呼ばれます。

    ページの履歴を制御する目的ではありませんが、InstantClick(http://instantclick.io/)のように「高速化のためにページ遷移をJavaScriptでシミュレーションする」ということは、時折行われます(GitHubのページもそのような動きをします)。

    キャンセル

+2

なんともいえませんがブランクで開いけば戻れないですよね?
<a href="hoge.htm" target="_blank">hoge</a>
ただしこれは新しいタブで開くので元ページをうまく閉じないといけません。
セキュリティが許せばwindow.close()などで閉じられるかも

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/26 16:06

    早速のアイデアありがとうございます。
    WebViewではタブブラウザのように複数ページが開くことがなく、target="_blank"とするとページ自体が表示されないようです。
    うまく動けば元ページを閉じる必要も無く解決策になりそうだったのですが、target="_blank"で現在開いているウィンドウにコンテンツを表示するには、Androidアプリ側の実装が必要になってしまうようです。
    既に配布済みのアプリ(=WebView実装)でも動作する必要があるため本案は難しそうです。

    キャンセル

+2

質問文を読み違えてしまい、的外れな回答をしてしまいました。
失礼しました。


とりあえず、1つの方法としてこんなものも良いのではないかと思います。
A.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>A</title>
</head>
<body>
<a href="B.html" class="migr">Bへ移動</a>
<a href="C.html" class="migr">Cへ移動</a>
<script>
    for (let i = 0; i < document.getElementsByClassName("migr").length; i++) {
        document.getElementsByClassName("migr")[i].addEventListener('click', function (e) {
            if (document.getElementsByClassName("migr")[i].getAttribute("href") === "C.html") {
                return true;
            } else {
                alert("C.html以外へのアクセスは禁止しています。");
                e.preventDefault();
            }
        }, false);
    }
</script>
</body>
</html>


B.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>B</title>
</head>
<body>
B
</body>
</html>


C.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>C</title>
</head>
<body>
C
</body>
</html>

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/26 22:28

    アイデアありがとうございます。
    リンク経由での判定が必要な場合もあるかと思いますので参考になります。

    キャンセル

+2

ブラウザのポリシーとして、ユーザの意思で戻りたいページに戻る事をさせない、ということは出来ないのではないでしょうか。
JSでどう制御しようとしても、JSをブラウザで切られていたら意味ありませんし。

ページAにおいて、 
ページA → ページB は戻れても良いが 
ページA → ページZ(Zは特別戻らせたくないページ)のようにZにだけは戻れないようにする。

ページ経路がB→Aなのか、Z→Aなのか、私の理解が悪いのか、よくイメージが掴めないので的はずれであればすみません。

前述したとおりJS制御には限界があります。
phpとかサーバ側で、ページZをユニークなURLにするのがいいのではないでしょうか。
正しい経路でページZを閲覧する場合のみトークンを発行し、そのトークンをサーバ側で受け取れた場合のみページを表示させるという仕組みを作るイメージです。
ページAからはトークンを発行させなければ当然見ることは出来ませんし、戻るボタンを使われてもそのURL自体がユニークであれば表示しません。

追記:php側でキャッシュを無効にする必要もあります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/26 16:17

    これ面白いですね。

    キャンセル

  • 2017/01/26 22:27

    アイデアありがとうございます。
    ページAには、ページBからも、ページZからも遷移するリンクがある状況で、ページZから遷移してきた場合には戻るボタンなどの遷移を抑止したいという要件です。
    残念ながら静的なhtmlに対応できる方法が必要となります。

    キャンセル

  • 2017/01/27 10:10

    ページ自体は静的HTMLで作ればよろしいかと思います。閲覧許可をどうするかという部分をphpで処理するだけの問題なので。
    作成ポリシーとしてサーバスクリプト禁止という場合がたまにありますので、その場合は仕方ないですね。

    キャンセル

  • 2017/01/27 20:03

    コンテンツはクライアント製造者とは異なるユーザーサイドが作るので、phpの場合もあれば静的なファイルそのものの場合もありまちまちです。
    残念ながらphpなどプラットフォームを強要することができない環境です。
    jsはWebViewはめ込み型のアプリなので切られる心配はありません。

    キャンセル

check解決した方法

0

Androidアプリに貼り付けられた(全面に)WebViewという所を糸口にして解決出来ました。
この場合、通常のブラウザと違ってホームボタンや戻るボタン(◁)がOSから提供(表示)されていますが、進むボタンが存在しないため、Z→Aとページ遷移する際にZにてAへのリンクをタップするのですが、location.href="AのURL"とするのではなくて、history.go(-1)やhistory.go(-2)とすることで過去のZに戻すことにより、戻るボタンを押してもZに戻れないようになりました。
A→Z→Aのように、ページAからZを経由してページAに至った場合にZへ戻れないようにしたい。という事情があったため、この詳細な前提条件の説明をしていれば、他の方から同様の発想を指摘されていたかも知れません。

因みに、history.push(null,null,null)を使った方法は試験的に実装してみたのですが、複数回戻るボタンをタップされるといつか戻れてしまうため、100回pushするなど非現実的(時間も掛かるし完璧な方法ではない)と思われました。

皆さま、アイデア頂きありがとうございました。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

WebStorageでフラグを立てて判定しておられるとのことですが、
・ページZからAに遷移する時にフラグを立てる
・ページAで、フラグ有の時のみ、History.jsを使って履歴を書き換えて戻れなくする
というのはいかがでしょうか。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/01/31 22:15

    そうですね。Aから他ページに遷移する直前にフラグをクリアし、ZからAに遷移するときだけフラグを立てるなどすれば出来ると思うのですが、スマートな方法があればと思い投稿させて頂いた次第です。
    ネット検索でも他の方の回答でも既に確立されている方法はないようですので、この方法しかないという気がしてきました……。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.98%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる