こんにちは、さち です。
先日、Firefox のアドオン「Tampermonkey」で
とあるサイト用のユーザースクリプトを書いていました。
動作テストをすると
なぜか、ユーザースクリプトが2回実行される問題が発生。
今回は、この現象の解決方法について書いていきます。
ユーザースクリプトが2回実行される
- テスト用のユーザースクリプトを作りました。
ユーザースクリプトが実行されるとコンソールにログが表示されます。// ==UserScript== // @name Test Userscript // @namespace http://tampermonkey.net/ // @version 0.1 // @description test // @author uminosachi // @match http://example.com/ // @grant none // ==/UserScript== (function() { console.log('ユーザースクリプト 実行'); })();
- Firefox の「コンソール(Ctrl + Shift + K)」で確認してみると
ユーザースクリプトが2回も実行されています。
同じユーザースクリプトでも
Greasemonkey で動かすと1回しか実行されませんでした。
Tampermonkey とは挙動が異なるようです。
解決方法
原因は、「iframe」内でもユーザースクリプトが実行されるためでした。
スクリプトにおまじないを書いてフレームを無視するようにしましょう。
- 9行目のように「==UserScript==」内に「@noframes」を追記します。
// ==UserScript== // @name Test Userscript // @namespace http://tampermonkey.net/ // @version 0.1 // @description test // @author uminosachi // @match http://example.com/ // @grant none // @noframes // ==/UserScript== (function() { console.log('ユーザースクリプト 実行'); })();
- これで、ユーザースクリプトの実行は1回だけになります。
ちなみに、Tampermonkey の場合
問題が発生しているユーザースクリプトのエディター画面から「設定」タブを開き
「最上位フレーム(top)のみで実行する」を「はい」にしても同じ効果が得られます。
当然、「最上位フレーム(top)のみで実行する」は
自分のブラウザでのみ有効な設定です。
配布する予定があるものは、スクリプト内に「@noframes」を記述しましょう。
多くのユーザースクリプトはフレーム内での実行を想定していないと思うので
Tampermonkey のテンプレートに追記しておいても良いかもしれません。
余談 - 自力実装してみる
前述のような用意されているものを使わないで
JavaScript だけで自力実装する場合はこうなります。
// ==UserScript== // @name Test Userscript // @namespace http://tampermonkey.net/ // @version 0.1 // @description test // @author uminosachi // @match http://example.com/ // @grant none // ==/UserScript== (function() { if(top !== self) return false; console.log('ユーザースクリプト 実行'); })();
「top」は window.top の省略記述で、トップフレームの URL
「self」は window.self の省略記述で、現在のフレームの URL です。
両者が一致しない時は、フレーム内での実行なのでスクリプトを終了します。
これで、スクリプトの実行は(トップフレームでの)1回だけになります。
原理的には
自分のサイトがフレームで他サイトに読み込まれるのを防ぐ方法と同じですね。
コメント