使用例
関数や変数の上書き
ユーザー JavaScript はページ内のスクリプトによって定義された変数や関数を上書きできます。上書きに用いるメソッドは defineMagicVaribale と defineMagicFunction です。たとえばサイトが Opera を正しく認識しない場合、Opera に他のブラウザ用のコードを実行させることができます。
var ie = document.all;
たとえば以下のようなユーザー JavaScript を適用することで、このような誤ったブラウザ判定を上書きし、サイトを Opera でも正しく動作させることができるかもしれません。
window.opera.defineMagicVariable( 'ie', function () { return 0; }, null );ページが変数の値へアクセスしようとすると、この関数が代わりに実行され、変数の値として上書きされた値が用いられるようになります。
スクリプトの読み込み
window.opera.addEventListener メソッドを用いて、スクリプトの読み込みや中断、実行イベントの発生したタイミングを検出できます。
ユーザー JavaScript では、ページ内のスクリプトの実行が JavaScript エンジンによって中断されたことを「BeforeScript」イベントにて検出できます。必要に応じてスクリプト自体を書き換えて中断を防ぐこともできます。
たとえば if( node.getAttribute('myattribute') != null ) { のように値の存在しない属性を null によって比較するスクリプトが存在します。getAttribute は空白の文字列を返すべきであるため、この条件式が真になることはありません。しかし、ブラウザによっては誤って null を返すものもあります。正しく空白の文字列を返しているにもかかわらず、結果として Opera はそのようなスクリプトの実行に失敗します。この問題を防ぐため、ユーザー JavaScript にてスクリプトの中断を検出し、この比較文を取り除くことができます。
if( location.hostname.indexOf('example.com') != -1 ) {
window.opera.addEventListener(
'BeforeScript',
function (e) {
e.element.text = e.element.text.replace(/!=\s*null/,'');
},
false
);
}特定の外部スクリプトを読み込むことが問題の原因となっている場合、「BeforeExternalScript」にてスクリプトの読み込みを検出し、そのスクリプトを読み込まないようにできます。
if( location.hostname.indexOf('example.com') != -1 ) {
window.opera.addEventListener(
'BeforeExternalScript',
function (e) {
if( e.element.getAttribute('src').match(/problem\/script\.js$/) ) {
e.preventDefault();
}
},
false
);
}イベントハンドラの上書き
ユーザー JavaScript では、スクリプトイベントの発生を「BeforeEvent.type」イベントにて検出できます。スクリプトを含まないページについても同様にイベントを監視します。利用の際には「BeforeEvent.click」のように監視するイベントを指定します。
全てのイベントを監視するために「BeforeEvent」自身を使うこともできます。Opera 8 では、特定の「BeforeEvent.type」を監視している場合、BeforeEvent からそのイベントは監視されません。たとえば「BeforeEvent.click」を監視している場合、click イベントが発生しても「BeforeEvent」イベントは発生しなくなります。「BeforeEvent」は多くのイベントを監視できますが、使用することでパフォーマンスが低下する可能性がありますのでご注意ください。
onload イベントを検出してページ内のスクリプトが実行される場合、「BeforeEvent.load」を使用してその読み込みをキャンセルできます。onload イベントは画像などページ内の他の要素においても発生するため、スクリプトでは onload イベントがドキュメントそのものに対するものであるか確認する必要があります。
if( location.hostname.indexOf('example.com') != -1 ) {
window.opera.addEventListener('BeforeEvent.load',function (e) {
//check that it is the page loading, not just an image
if( e.event.target instanceof Document ) {
e.preventDefault();
}
},false);
}ページ内のスクリプトが監視しているイベントについてのみ発生する「BeforeEventListener」イベントは、多くの場合においてより便利に使うことができます。これらはイベントオブジェクトへのアクセスとイベントハンドラ関数双方へのアクセスを可能にします。また、「preventDefault」を使うことで、そのイベントはキャンセルされます。
「BeforeEvent」の代わりに「BeforeEvent.type」を用いるのと同様に、これらのイベントも「BeforeEventListener.type」を用いて特定のイベントのみを監視できます。たとえば以下のように、スクリプトによるマウスの移動の監視を抑止できます。
if( location.hostname.indexOf('example.com') != -1 ) {
window.opera.addEventListener(
'BeforeEventListener.mousemove',
function (e) {
e.preventDefault();
},
false
);
}関数を削除する必要がある場合には、細心の注意を払ってください。この例においてユーザー JavaScript は、イベントハンドラがページ内で作成された「myMouseTrail」関数であるか確認した後、マウスがページ最上部に位置しているかのようにイベントオブジェクトを書き換えます。
if( location.hostname.indexOf('example.com') != -1 ) {
window.opera.addEventListener(
'BeforeEventListener.mousemove',
function (e) {
if( e.listener == moveMouseTrail ) {
e.event.clientY = 0;
e.event.pageY = 0;
}
},
false
);
}「AfterEvent」を用いて、ユーザー JavaScript からページ内のスクリプトによってアクションがキャンセルされたことを確認できます。ユーザー JavaScript は、アクションが中断された場合にそのキャンセル処理を上書きし、別のアクションを実行させることができます。
たとえばフォームを送信する場合、標準のアクションではフォームを submit した後、新しいページをサーバから受信します。しかしページ内のスクリプトによって submit イベントを中断し、フォームの内容を検証、それを通過したときにだけフォームを送信する場合があります。検証スクリプトが間違っているためにフォーム内容が正しく入力されていないと判断されてしまう場合、結果としてフォームは送信されないこととなります。ユーザー JavaScript にてこの動作を検出し、フォームの送信が行えるように変更できます。
if( location.hostname.indexOf('example.com') != -1 ) {
window.opera.addEventListener(
'AfterEvent.submit',
function (e) {
if( e.eventCancelled ) {
//スクリプトがフォームの送信を止めようとした
if( confirm( 'Submission was prevented. Submit anyway?' ) ) {
//フォーム送信を抑制しているスクリプトが実行されるのを防ぐ
e.preventDefault();
}
}
},
false
);
}JavaScript URL
スクリプトを開始するために、ページ内で JavaScript URL を使用できます。たとえばリンクの HREF 属性やフォームの TARGET 属性へ直接 JavaScript を記述するのがこれにあたります。ユーザー JavaScript は JavaScript URL による実行を検出し、その動作の抑制や実行されるスクリプトの上書きができます。この機能は javascript: プロトコルを用いたブックマークレットにも影響を与えますのでご注意ください。
たとえばページ内で新しいウィンドウを開くために JavaScript URL が用いられている場合、「BeforeJavascriptURL」イベントにて新しいウィンドウが開く前に確認ダイアログを表示させることができます。
if( location.hostname.indexOf('example.com') != -1 ) {
window.opera.addEventListener(
'BeforeJavascriptURL',
function (e) {
if( e.source.indexOf('window.open') != -1 ) {
//ウィンドウを開く前に確認ダイアログを開くようにスクリプトを書き換え
e.source = e.source.replace(
/window\.open/g,
'if( confirm(\'Allow window to open?\') ) window.open'
);
}
},
false
);
}JavaScript URL は値を返すこともあります。ページ内を新しいコンテンツによって上書きするため、意図的にこの値が使用される場合もあります。しかし、ページによっては誤った値を返してしまい、誤ったコンテンツによって上書きしてしまう場合もあります。ユーザー JavaScript にて「AfterJavascriptURL」イベントを使用し、この返値を遮断して新しいコンテンツへ書き換える前に確認ダイアログを表示させることができます。この場合、必要であれば新しいコンテンツに書き換えさせることもできます。
if( location.hostname.indexOf('example.com') != -1 ) {
window.opera.addEventListener(
'AfterJavascriptURL',
function (e) {
if( typeof( e.returnValue ) == 'string' ) {
if( confirm('Overwrite page?') ) {
e.returnValue += 'Changed by User JavaScript';
} else {
e.preventDefault();
}
}
},
false
);
}通常のスクリプトとイベント
ユーザー JavaScript は、これまでに紹介した特殊なイベントに依存しているわけではありません。通常のスクリプトを動作させることもできます。たとえば Opera で使用しているレンダリングモード (WuirksMode もしくは CSS1Compat)を全てのページに表示させるために、以下のようなソースを使用できます。
document.addEventListener(
'load',
function (e) {
if( !document.body ) { return; }
var mydiv = document.createElement('div');
mydiv.style.position = 'fixed';
mydiv.style.top = '0px';
mydiv.style.right = '0px';
mydiv.style.border = '1px solid #000';
mydiv.style.backgroundColor = '#fff';
mydiv.style.color = '#000';
mydiv.appendChild(document.createTextNode(document.compatMode))
document.body.appendChild(mydiv);
},
false
);Greasemonkey スクリプト
Opera は多くの Greasemonkey スクリプトを実行できます。これらの JavaScript はMozilla 系ブラウザのアドオン、 Greasemonkey で動作するように設計されています。スクリプトが Greasemonkey 記法を使用していることを Opera へ認識させるには、スクリプトのファイル名の末尾を .user.js とする必要があります (その他全ての .js ファイルは通常のユーザー JavaScript とみなされます)。Greasemonkey 記法を使用したスクリプトは、既存のスクリプトとの互換性を保つため、若干異なる方法で処理されます。
- window.opera.addEventListener や関連するメソッド、magic 関数及び変数を使用できません。
- スクリプトは、ページの読み込みが完了し、ページ用の DOM が構築された後、onload ハンドラによって定義された関数が実行される前に実行されます。
Greasemonkey スクリプトでは、このような処理の違いから、問題が発生する前にそれを修正できない場合があります。つまり、そのようなスクリプトは一般的にページの拡張に最適であり、スクリプトの問題修正には不適です。
通常のスクリプトと同様にページアドレスを検出することもできますが、一般的に Greasemonkey スクリプトでは ==UserScript== コメントブロックを用いてスクリプトの実行されるページアドレスを制限します。一般的に、それぞれを拡張する JavaScript のコードはそれぞれのファイルへ記述されます。とはいえこれは必ずしも必要ではありません。
スクリプトはいかなる onload イベントハンドラよりも前に実行されるため、インラインに記述することができます。しかし、グローバル変数の生成を回避するため、実行直後に匿名関数を定義し、それを用いるのが最良の方法です。たとえば target="_blank" が指定されていようとリンク先を新しいページで開かないようにするために、以下のようなソースを使用できます。
(function () {
for( var i = 0; document.links[i]; i++ ) {
if( document.links[i].target == '_blank' ) {
document.links[i].target = '_self';
}
}
})();Greasemonkey 記法の利用は、イベントとイベントハンドラの上書きの項へ記載の通り、通常のユーザー JavaScript にて「BeforeEvent.load」イベントリスナを生成することと等価です。
ヒント: 多くの Greasemonkey スクリプトは window._content を用いて window オブジェクトを参照します。Opera ではこのような参照の必要はありません。しかし、それを使用した全てのスクリプトを編集する手間を省くため、通常のユーザー JavaScript ファイルに以下のような記述を追加し、対処することができます。
window._content = window;
ナビゲーションモードの操作
ユーザー JavaScript は 履歴間移動に関する Opera の動作モードを上書きできます。これによって常に高速に動作させることや、互換性を重視した動作をさせることができます。この動作モードに関する詳細はナレッジベースの記事をご参照ください。この動作モードは setOverrideHistoryNavigationMode メソッドを使うことで設定できます。
opera.setOverrideHistoryNavigationMode('fast')