Greasemonkeyでprototype.jsやscript.aculo.usを使う方法

Greasemonkeyprototype.jsscript.aculo.usが使えたら便利だろうな、と考えたことのある開発者は少なくないのではないでしょうか。ちょっとそんなアイデアを試してみたことのある方ならわかると思うのですが、Greasemonkeyでそういった外部JavaScriptライブラリは簡単には使えません。案外ハードルが高いです。

Googleで調べていたら、面白い解決方法が見つかったので紹介します。

Loading External JavaScript Libraries in Greasemonkey

このブログで解説されているアプローチを用いれば、Greasemonkeyで外部JavaScriptライブラリが使えるようになります。

ポイントは、

  • 外部ライブラリがロードされるまで待ち続ける制御構造
  • unsafeWindowを経由して外部ライブラリにアクセス

といったところでしょうか。

このブログの解説を参考にして、簡単なサンプルを作ってみました。このGreasemonkeyをインストールすると、各サイトの一番下に"hello"と表示されます。その"hello"の文字をクリックすると、Effect.Fade()によって"hello"の文字がフェードアウトします。自作のlibs.jsを通して、prototype.jsscript.aculo.usに含まれるeffects.jsをロードし、それらのライブラリに含まれる機能の一部をGreasemonkeyで利用しています。

// ==UserScript==
// @name           GM Hack
// @namespace      http://vaio.redirectme.net/lib/greasemonkey/
// @description    Loads external javascript libraries on the fly
// @include        *
// ==/UserScript==
(function() {
	// See: Loading External JavaScript Libraries in Greasemonkey -
	// http://manalang.com/archives/2006/01/04/loading-external-javascript-libraries-in-greasemonkey/
	
	var l = unsafeWindow;
	
	function waitForLoadLibs() {
	        if (typeof l.Prototype != 'undefined' && typeof l.Effect != 'undefined') {
			// The libraries have been loaded.
			// Now you can use the libraries via the 'l' variable.
			
			// Create a greeting div section and append it to the body element.
			var greeting = document.createElement("div");
			greeting.id = "hello";
			greeting.innerHTML = "<h1>hello</h1>";
			document.body.appendChild(greeting);
			
			// $() is provided by prototype.js.
			// Effect.Fade() is provided by effects.js(script.aculo.us).
			hello = l.$('hello');
			hello.addEventListener('click',
				function() { new l.Effect.Fade(hello); }, false);
	        } else {
	                // Try again...
	                window.setTimeout(waitForLoadLibs, 100);                
	        }
	}

	function loadLibs() {
		// Note: 'libs.js' loads prototype.js and effects.js(script.aculo.us).
	        var libs_js     = document.createElement("script");
	        libs_js.type    = "text/javascript";
	        libs_js.src     = "http://your.machine/js/libs.js";

	        var head = document.getElementsByTagName("head")[0];
	        head.appendChild(libs_js);
	        
	        waitForLoadLibs();
	}

	window.addEventListener('load', loadLibs(), false);
})();

ちなみに、libs.jsでは以下のようにしてライブラリをロードしています。

// prototype.js
var prototype_js = document.createElement("script");
prototype_js.type = "text/javascript";
prototype_js.src = "http://your.machine/js/prototype.js";

// effects.js
var effects_js = document.createElement("script");
effects_js.type = "text/javascript";
effects_js.src = "http://your.machine/js/effects.js";

// load scripts
var head = document.getElementsByTagName("head")[0];
head.appendChild(prototype_js);
head.appendChild(effects_js);

unsafeWindowを経由してライブラリにアクセスするため、いちいち"l."が必要になるのがちょっと気になりますね。

l.$(...);
l.Effect.Fade(...);