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

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

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

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

Chrome extension

Chrome拡張機能

Q&A

解決済

1回答

917閲覧

新規タブの要素に値を代入できない

jupeeze

総合スコア5

JavaScript

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

Chrome extension

Chrome拡張機能

0グッド

1クリップ

投稿2022/05/04 07:47

前提

JavaScriptの初学者です。
ChromiumであるBrave Browserの拡張機能を作ろうとしたのですが、
思い通りの結果にならず困っております。

実現したい処理というのが、
【拡張機能を起動した時にGoogle翻訳のウェブサイト翻訳機能で現在のURLを翻訳する】
というものです。

現状の問題は、新規タブの要素に値を代入できないことです。
3パターンを試してましたが、エラーの意味がわからず行き詰まっています。
私自身の説明につたないところもあると思いますが、アドバイス頂ければと思います。

実現したいこと

  • 拡張機能を起動した時の、現在のタブのURLを取得
  • 新しいタブでGoogle翻訳ウェブサイト翻訳機能のページを開く
  • フォームに取得したURLを入力し、矢印ボタンを押す
  • Google翻訳ウェブサイト翻訳機能のページを閉じる

3つ目の 新規タブの要素に値を代入する時に、色々なエラーが起きます。

試したソースコード

JavaScript

1//ソースA 2function ElClick(arg) { 3 console.log(arg); 4 let obj = window.open('https://translate.google.co.jp/?hl=ja&tab=cT&sl=en&tl=ja&op=websites '); 5 let timer = setInterval(function () { 6 if ($("#i44", obj.document) != undefined) { 7 document.getElementById('i44').value = arg; 8 obj.document.getElementsByClassName('VfPpkd-Bz112c-LgbsSe yHy1rc eT1oJ DiOXab zhBWDc Pk9dvb')[0].click(); 9 clearInterval(timer); 10 } 11 }, 500); 12} 13chrome.action.onClicked.addListener((tab) => { 14 const url = tab.url 15 chrome.scripting.executeScript({ 16 target: { tabId: tab.id }, 17 function: ElClick, 18 args: [url] 19 }) 20}) 21 22//ソースB 23function _OnLoad() { 24 console.log(url); 25 document.getElementById('i44').value = url; 26 obj.document.getElementsByClassName('VfPpkd-Bz112c-LgbsSe yHy1rc eT1oJ DiOXab zhBWDc Pk9dvb')[0].click(); 27} 28var readStateCheck = function () { 29 if (obj.document.readyState == "complete") { 30 _OnLoad(); 31 } 32 else { 33 setTimeout(readStateCheck, 100); 34 } 35} 36function _OnClick() { 37 obj = window.open('https://translate.google.co.jp/?hl=ja&tab=cT&sl=en&tl=ja&op=websites '); 38 setTimeout(readStateCheck, 100); 39} 40chrome.action.onClicked.addListener((tab) => { 41 url = tab.url 42 chrome.scripting.executeScript({ 43 target: { tabId: tab.id }, 44 function: _OnClick 45 }) 46}) 47 48//ソースC 49function ElClick(arg) { 50 let obj = window.open('https://translate.google.co.jp/?hl=ja&tab=cT&sl=en&tl=ja&op=websites'); 51 obj.addEventListener('load', function () { 52 console.log(arg); 53 obj.document.getElementById('i44').value = url; 54 obj.document.getElementsByClassName('VfPpkd-Bz112c-LgbsSe yHy1rc eT1oJ DiOXab zhBWDc Pk9dvb')[0].click(); 55 }, false); 56} 57chrome.action.onClicked.addListener((tab) => { 58 const url = tab.url 59 chrome.scripting.executeScript({ 60 target: { tabId: tab.id }, 61 function: ElClick, 62 args: [url] 63 }) 64}) 65

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

Error

1//ソースA 2Uncaught ReferenceError: $ is not defined 3 4//ソースB 5Uncaught ReferenceError: readStateCheck is not defined 6 7//ソースC 8エラーメッセージはないが、obj.addEventListener();が動かない

補足情報

manifestのバージョンは3で、background.service_workerを使っています。

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

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

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

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

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

itagagaki

2022/05/04 08:11 編集

Uncaught ReferenceError: $ is not defined これは $("#i44", obj.document) のことだと思われます。これはJavaScriptにそぐわないです。何かを参考にしましたか? たぶん obj.document.getElementById('i44') に置き換えれば良さそうな気はしますが。
jupeeze

2022/05/04 09:42

先述の通り、 if ($("#i44", obj.document) != undefined) { を if (obj.document.getElementById('i44') != undefined) { に 置き換えてきましたが、うまくいきません。 Uncaught TypeError: Cannot read properties of undefined (reading 'getElementById') at <anonymous>:5:20 というErrorが新規タブではなく、最初のタブのConsoleで出力されます。 おそらく 新規タブから要素を探すことができていないと考えたのですが、 なにか対処法はありますか?
itagagaki

2022/05/04 09:48

新しく開かれたタブにスクリプトを挿入すれば、そのスクリプトからそのタブのDOMにアクセスすることが可能になると思います。 ちょうど最近似たような質問に回答したので、その回答が参考になるかもしれません。 https://teratail.com/questions/1h91g27u79z4hv
itagagaki

2022/05/04 09:57

あ、chrome.scripting.executeScript() は使ってるんですね。ただそこでスクリプトを挿入しているタブは、新しく開いたウィンドウのタブではないのでダメなんだと思います。そのタブからさらに新しいウィンドウをオープンしちゃっているわけですよね。
jupeeze

2022/05/04 11:46 編集

新しく開くウィンドウのタブにスクリプトを挿入するにはどうすればいいのでしょうか? 以下のようにしているのですが、targetが存在しないというエラーが起きます。 また、 let obj = () => window.open(); を let obj = window.open();にすると、 window is not definedというエラーが起きるのですが、なぜでしょうか? let obj = () => window.open('https://translate.google.co.jp/hl=ja&tab=cT&sl=en&tl=ja&op=websites'); chrome.scripting.executeScript({ target: { tabId: obj.id }, function: ElClick, args: [arg] })
itagagaki

2022/05/04 11:55

やり方はあると思いますが、それより、DOMアクセス部分についてはバックグラウンドスクリプト(サービスワーカー)ではなくコンテンツスクリプトで動かす方が簡単じゃないですかね。 "content_scripts": [ { "all_frames": true, "matches": ["https://translate.google.co.jp/*"], "run_at": "document_end", "js": ["./script.js"] } ], みたいな感じで。
jupeeze

2022/05/04 12:48

コンテンツスクリプトを使ってGoogle翻訳に翻訳したいタブのURLを入力する場合、 最初に開いている翻訳したいタブのURLはどのように取得すればいいのでしょうか?
guest

回答1

0

ベストアンサー

メッセージパッシングを使って実装するのが筋だとは思うのですが、自分でやってみても、どうもうまくいきませんでした。
しかし一晩寝て質問者の目的に沿いそうな代替案を見つけたので紹介します。

manifest.json

JSON

1{ 2 "manifest_version": 3, 3 4 "name": "jupeeze", 5 "version": "1.0.0", 6 "action": {}, 7 "background": { 8 "service_worker": "background.js" 9 }, 10 "content_scripts": [ 11 { 12 "all_frames": true, 13 "matches": ["https://translate.google.co.jp/*"], 14 "run_at": "document_end", 15 "js": ["content.js"] 16 } 17 ], 18 "host_permissions": ["*://*/*"] 19}

background.js

JavaScript

1chrome.action.onClicked.addListener(tab=>{ 2 chrome.tabs.create( 3 { url: 'https://translate.google.co.jp/?hl=ja&tab=cT&sl=en&tl=ja&op=websites&jupeezeURL=' + encodeURI(tab.url) } 4 ); 5});

content.js

JavaScript

1let arg = new Object; 2let pair = location.search.substring(1).split('&'); 3for (let i = 0; pair[i]; i++) { 4 let kv = pair[i].split('='); 5 arg[kv[0]] = kv[1]; 6} 7if (arg['jupeezeURL']) { 8 console.log(arg['jupeezeURL']); 9}

新しいタブで開くページのURLに勝手に jupeezeURL というパラメーターを追加しています。これでサーバーがエラーを返すようだとダメですが、幸い無視してくれているようでした。

そして開かれたページに自動的に挿入される content.js では自分のlocationは当然読めますので、そこからこのパラメーターを拾うことができるし、開いているページのDOMにそれをセットしたりすることもできるはずです。

"host_permissions": ["*://*/*"] は任意のタブのどんなURLでも取得するために必要でした。
もしこの拡張機能を配布するのでしたら、これはちょっと危険視されるかもしれませんね…。

(追記)

コメントを受けて

content.js

const start = ()=>{ let arg = new Object; let pair = location.search.substring(1).split('&'); for (let i = 0; pair[i]; i++) { let kv = pair[i].split('='); arg[kv[0]] = kv[1]; } if (arg['jupeezeURL']) { document.getElementById('i44').value = arg['jupeezeURL']; document.getElementsByClassName('VfPpkd-Bz112c-LgbsSe yHy1rc eT1oJ DiOXab zhBWDc Pk9dvb')[0].click(); window.close(); } }; window.onload = () => start();

こんな風にしたらどうですか?

投稿2022/05/05 02:57

編集2022/05/05 05:34
itagagaki

総合スコア8402

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

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

jupeeze

2022/05/05 04:55 編集

パラメーターというものを使うんですね! 少し調べて理解できた気がします! 最終的に、以下のようにプログラムを組めたのですが、 最後の三行でタブが閉じてくれないのですが、なにか対処法はあるのでしょうか? 質問に質問を重ねてしまい、申し訳ありませんが、教えてくれれば幸いです。 let arg = new Object; let pair = location.search.substring(1).split('&'); for (let i = 0; pair[i]; i++) { var kv = pair[i].split('='); arg[kv[0]] = kv[1]; } document.getElementById('i44').value = arg['jupeezeURL']; document.getElementsByClassName('VfPpkd-Bz112c-LgbsSe yHy1rc eT1oJ DiOXab zhBWDc Pk9dvb')[0].click(); getCurrentTab().then((tab) => { chrome.tabs.remove(tab.id); });
itagagaki

2022/05/05 05:08

単に window.close() で閉じるかもです
jupeeze

2022/05/05 05:24

ウィンドウの読み込み中に閉じてしまいます…
itagagaki

2022/05/05 05:34

回答に追記しました
jupeeze

2022/05/05 05:46

window.setTimeoutと組み合わせた結果、思い通りのものができました。 ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問