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

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

新規登録して質問してみよう
ただいま回答率
85.35%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

5623閲覧

window.open()で開いたタブのURLを書き換えられた場合の対応

sk_3122

総合スコア1126

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

1クリップ

投稿2021/08/03 09:43

編集2021/08/04 01:29

よろしくお願いします。

前提・実現したいこと

  • リンクをクリックしたら別タブでページを開きたい。
  • クリックするたびにタブが増えるのではなく、1 つのタブを使い回したい。

対応ブラウザ

  • 最終的には Edge, Chrome で動作するようにしたいです。
  • ひとまず Edge でテストしています。今回のエラーも Edge で起きています。

発生している問題・エラーメッセージ

  • リンククリック時に呼んでいる関数内で、window.open(uri, "HOGE") で別タブを開いています。
    素直にリンクをクリックしている分には希望通りの動きをします。

  • 開いた別タブのアドレスバーを手打ちで変更し、google.com など外部サイトに遷移すると
    後述「該当のソースコード」の ★★★ の行で JavaScript エラーが出ます。

    Uncaught DOMException: Blocked a frame with origin "http://localhost" from accessing a cross-origin frame.

該当のソースコード

html

1<a href="javascript:showPreview(111)">111</a> 2<a href="javascript:showPreview(222)">222</a>

js

1let _win = null; 2function showPreview(id) { 3 let uri = "../File/Preview?id=" + id; 4 5 // リンクをクリックした際、前回の画面を一旦クリアしたい 6 if (_win && _win.closed == false) { 7 _win.document.body.innerHTML = ""; //★★★ 8 } 9 10 _win = window.open(uri, "MyPreview"); 11}

なお innerHTML = "" している箇所の if 文を削除すると、
エラーは出ず、タブがアクティブになりますが、ページは変わりません(外部サイトのまま)

試したこと

location=no

  • window.open の際に「アドレスバーを表示しないオプション」を指定しましたが、これだと別タブではなく 別ウインドウで開いてしまいました。

js

1window.open(uri, "MyPreview", "location=no")

target="xxx"

  • JavaScript ではなく、href に URL を指定して target="MyPreview" で別タブを開く方法も試しましたが、開いた別タブの URL を外部サイトのものに書き換えると
    エラーは出ず、タブがアクティブになりますが、ページは変わりません(外部サイトのまま)

html

1<a href="../File/Preview?id=111" target="MyPreview">111</a>

追記:location.href をセット

  • 別タブの URL を外部サイトのものに書き換えた後 以下を実行すると、
    エラーは出ず、タブがアクティブになりますが、ページは変わりません(外部サイトのまま)

  • なおコメントアウトしている console.log() を生かすとエラーになります。
    値のセットはエラーにならず無視するけど 参照は許されない...?

js

1if (_win && _win.closed == false) { 2 _win.location.href = uri; 3 4 //console.log(_win.location.href); //★ここで Uncaught DOMException エラー 5}

以下のいずれかが出来ないものかと思っています

  1. window.open で開いたタブの URL を変更させない。
  2. window.open で開いたタブの URL が変更された後、再度こちらから location を変更する。
  3. window.open で開いたタブが同一ドメインでなくなっていたら閉じる。(その後 同名で開き直す)

妥協案

最悪どうしようもなければ、以下どちらかにしようと思っています。

  • location=no を指定して別ウインドウで開く
  • Uncaught DOMException が出る部分を try - catch で囲んで
    エラーになったら "MyPreview_2" など name を変えて開く...?

他に何か方法はないのかなと思い質問させて頂きました。
よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

自己解決

ちょっと思い付いたので書いてみました。
try - catch で囲んで、エラーが出たら一度 _win.close() してから開き直します。

このロジックだと以下の挙動になりました。

  • 素直にリンクをクリックしている間は 1 つのタブを使い回し。
  • 別タブの URL を外部サイトのものに書き換えた後に呼ぶと、そのタブは放置して 新しくタブが開く。以降はそちらのタブを使い回し。

一応 希望する挙動になったと思います。これで良いかな~...

 
もし他にも方法があれば聞いてみたいので、質問はもう少し開けておきたいと思います。
しばらくしたら Close します。よろしくお願いします。

js

1let _win = null; 2function showPreview(id) { 3 let uri = "../File/Preview?id=" + id; 4 5 // 別タブの URL が外部サイトのものに書き換えられた場合などは 6 // 一度タブを閉じて開き直す 7 let reopen = false; 8 try { 9 10 // リンクをクリックした際、前回の画面を一旦クリアしたい 11 if (_win && _win.closed == false) { 12 _win.document.body.innerHTML = ""; 13 } 14 15 _win = window.open(uri, "MyPreview"); 16 17 if (_win.document.domain != window.document.domain) { 18 reopen = true; 19 } 20 21 } catch (ex) { 22 //console.error(ex); 23 reopen = true; 24 } 25 26 // reopen フラグが立っていたら一度タブを閉じて開き直す 27 if (reopen) { 28 _win.close(); 29 _win = window.open(uri, "MyPreview"); 30 } 31}

投稿2021/08/04 01:52

編集2021/08/04 01:55
sk_3122

総合スコア1126

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

Same origin ポリシーがあって、子ウィンドウであっても別ドメインであればほとんどの権限はありません。読み書きができるとやりたい放題できてしまうので。

ブラウザによって許可されているものは違うのですが Firefox だと以下のプロパティは許可されるので以下のように書けます。
https://developer.mozilla.org/ja/docs/Web/Security/Same-origin_policy#window

if (!_win) { _win = window.open(uri, "MyPreview"); } else { _win.location.href = uri _win.focus() }

(安全なアカウント・ゲストなどで)特定のセキュリティを外したウィンドウを用意してそこでのみ動かすのも方法の一つかもしれません。(拡張機能や flags、起動オプションなどで)

投稿2021/08/03 14:05

anozon

総合スコア662

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

anozon

2021/08/03 14:08

Chrome (Chromium) の場合の仕様の調べ方がわからなくて探したんですが見つからなかったのであれば僕も知りたいです。
Lhankor_Mhy

2021/08/04 01:15

横からすみません。 ご提示のプロパティ一覧は、Firefoxのものではなくて、HTMLの仕様だと思います。 Firefox と Chrome がこの仕様に従っているという保証はないですが、そうでなかったとしたらバグレポートが上がっていると思いますので、そのように動作すると期待していいと思います。
sk_3122

2021/08/04 01:24

回答ありがとうございます。 > 読み書きができるとやりたい放題できてしまうので。 ですよねー... ちなみに質問を編集して「追記:location.href をセット」を追記しました。 Edge, Chrome は location.href をセットしてもページが変わりませんでした。 Firefox なら OK なんですね... 難しい...
sk_3122

2021/08/04 01:25

> HTMLの仕様 あ、なるほど そうなんですね... ありがとうございます
anozon

2021/08/04 01:25

ありがとうございます。 https://codepen.io/anozon/pen/oNWMdqW こちらで検証して Chrome と Firefox と Safari で別々の挙動をしたのでおかしいなと思いました。 Chrome の場合は質問にあるように ドメインが変わった場合 location.href の書き換えなどが動作してなさそうです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問