<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="/xml.xsl" type="text/xsl"?><feed xmlns="http://www.w3.org/2005/Atom">
  <title>nulog, NULL::something : out of the headphone &gt; 2006 &gt; August &gt; 12 &gt; GreaseMonkey で MochiKit 使ってみる。すなわち外部ライブラリの読み込み。あるいははてなのグラフが綺麗じゃない</title>
  <link href="http://lowreal.net/logs/2006/08/12/1"/>
  <icon>http://lowreal.net/img/banner.png</icon>
  <link rel="self" type="application/atom+xml" href="http://lowreal.net/logs/2006/08/12/1.atom"/>
  <link rel="alternate" type="application/xhtml+xml" href="http://lowreal.net/logs/2006/08/12/1.xhtml"/>
  <updated>2006-08-12T23:54:14+09:00</updated>
  <author>
    <name>cho45(砂糖)</name>
  </author>
  <id>http://lowreal.net/2006/08/12/1</id>
  <entry>
    <title>GreaseMonkey で MochiKit 使ってみる。すなわち外部ライブラリの読み込み。あるいははてなのグラフが綺麗じゃない</title>
    <link rel="alternate" type="text/html" href="http://lowreal.net/logs/2006/08/12/1.html"/>
    <link rel="alternate" type="application/xml+xhtml" href="http://lowreal.net/logs/2006/08/12/1.xhtml"/>
    <updated>2006-08-12T23:54:14+09:00</updated>
    <published>2006-08-12T23:54:14+09:00</published>
    <id>http://lowreal.net/2006/08/12/1</id>
    <category term="web"/>
    <category term="js"/>
    <category term="gm"/>
    <content type="xhtml" xml:base="http://lowreal.net/">
      <div xmlns="http://www.w3.org/1999/xhtml">
        <p>GreaseMonkey で外部ライブラリが使いたいな。みたいな。似たようなのでは <a href="http://d.hatena.ne.jp/ysano2005/20060127/1138382734">CMS researcher - Greasemonkeyでprototype.jsやscript.aculo.usを使う方法</a> があるのですが、どうもうまくいかなかったので自力実装。</p>
        <pre class="ECMAScript">
function dll(loadLibs, afterLoadedFunction) {
    if (afterLoadedFunction._retry)
        afterLoadedFunction._retry = 0;
    else
        afterLoadedFunction._retry++;
    if (afterLoadedFunction._retry &gt; 10) throw("Library is not loaded because of some reason.");
    
    loadLibs.forEach(function (lib) {
        GM_xmlhttpRequest({
            method : "GET",
            url : lib[0],
            onload : function (req) {
                try {
                    (function (r) { eval(r.responseText) }).call(window, req);
                } catch (e) {
                    //  nigiri tubushi
                }
            },

            onerror : function (req) {
                alert(req.responseText);
            }
        });
    });

    var loaded = true;
    loadLibs.forEach(function (lib) {
        try {
            loaded = loaded &amp;&amp; typeof eval(lib[1]) != "undefined";
        } catch(e) {
            loaded = false;
        }
    });
    if (loaded) {
        try {
            afterLoadedFunction();
        } catch (e) {
            unsafeWindow.console ? unsafeWindow.console.log(e)
                                 : window.dump(e);
        }
    } else {
        var f = arguments.callee;
        setTimeout(function () { f.apply(this, [loadLibs, afterLoadedFunction])}, 500);
    }
}</pre>
        <p>で、以下のように使う。</p>
        <pre class="ECMAScript">
// 第一要素にロードする js への URL
// 第二要素にロード確認用のオブジェクトの名前
// を入れた配列の配列
dll([["http://example.com/mochi/Base.js", "MochiKit"]], function () {
 // ロードされたら実行される
})</pre>
        <p>ポイントは eval を使うところ？　eval を使うので unsafeWindow を極力使わなくてすむ。あとは DOM 系の処理でおかしいこと (ここには append できないぜ系エラー) になりにくい気がする。</p>
        <p>ロードするスクリプトの依存関係上、何度かリクエストが発射されることがある。めんどいのでブラウザのキャッシュ機能にまかせてこっちではキャッシュしていないけど、ホントはちゃんとキャッシュしたほうがいいはず。</p>
        <hr/>
        <p>でもって、はてなアンケートの円グラフを PlotKit で描画しなおす GreaseMonkey スクリプトを書いてみた。<a href="/2006/hatena-q-make-graphs-with-plotkit.user.js">hatena-q-make-graphs-with-plotkit.user.js</a></p>
        <ins datetime="2006-08-13T00:57:24+09:00">
          <p>結果をソートするようにした。あと Global じゃなくて window 使うようにした。</p>
        </ins>
        <ins datetime="2006-08-17T21:18:16+09:00">
          <p>id:secondlife さんからの指摘により、エラーを握りつぶす処理を追加し、最大ロード試行数を加えました。</p>
        </ins>
      </div>
    </content>
  </entry>
</feed>
