Archive for the ‘Greasemonkey’ Category

Scriptish v0.1.3の更新内容とGreasemonkeyの互換性について

Scriptishが0.1 -> 0.1.3へとアップデートされたのでそれの更新内容を調べてみる。

- Version 0.1.1 issues
- Version 0.1.2 issues
- Version 0.1.3 issues

に全部載っている事です。
バグとかは面倒なので省いています。結構いろいろあるので気になる人は上のを見ておくといい。

オプション画面の変更

image

Scriptish自体のオプション画面も大きく変更されています。

imageimage

一枚目は主要プロトコルでの動作の設定以外は以前とそこまで変わらないので、問題ないと思います。
二枚目はグローバルのExclude(スクリプトに書かれてるexcludeとは違ってグローバルで動かないURL)の設定がタブに分かれて書きやすくなっています。

image

三枚目が結構重要な変更が入っていて、特にGreasemonkeyスクリプトを書く人はここの設定に注意する必要があります。

☑ユーザスクリプトをキャッシュする

という設定にチェックが入っていると、スクリプトを書き換えてページをリロードしても、すぐには反映しない(キャッシュが使われる)ため、スクリプトを書く人はチェックを外した方がいいと思います。

後は、UIを常に英語にしたり、今までabout:configから直接決めないといけなかったものもGUIから設定できるようになっているみたいです。(全てではないですが)

これ以外にも、パフォーマンスとか内部のバグなど結構改善されてると思います。

Greasemonkeyとの互換性の話

新しいAPIはGreasemonkeyが実装してくれないと互換性はない(fail safeを書くか、分岐するなどで対処)ですが、元々あったGM_openInTabなどは拡張して実装されてるので基本的にGreasemonkeyと互換性があると思います。

ただ、GM_registerMenuCommandはGreasemonkeyでは第一引数にeventオブジェクトが渡されるようになって、

function sayHello(evt) { console.log(evt) }
GM_registerMenuCommand("Hello, world (simple)", sayHello);

のようなコードがScriptishではundefinedで、Greasemonkeyで動かすとなぜかイベントオブジェクトが入るようになり互換性がちょっとないです。(これはGreasemonkeyが勝手に壊した感じです)

function sayHello(evt) { console.log(evt) }
GM_registerMenuCommand("Hello, world (simple)", function(){
sayHello();
});

そのため、Scriptish、Greasemonkeyどちらでも安全に動くようにするには、明示的に無名関数などを使った方が良いでしょう。

後、外部コンテンツを読み込む系のGreasemonkeyやブラウザ拡張を作る際の注意事項などの対策(Full Feedのものが行ってるタイプ)として、GM_xhrで取得したコンテンツを自前でフィルターするのをベタに書くと速度的な問題が発生したりするので、そういう時はScriptishにあるGM_safeHTMLParser APIを使用するのが良いでしょう。
自前で書いても工夫すれば実用的な速度にはなるが、用意されているものを使うのが楽という意味で。

また、まだ入っていませんが、Scriptish 2.0でGM_xpath – GitHubというXPathのAPIが入るようなので楽しみ。

Greasemonkeyにとどまる意義はあまり見つける事ができませんが、Scriptitshに移行する意義は見つける事ができるような感じの状態です。
Scriptish作者のErik VoldさんはGreasemonkeyに対してさよならと言ってるので、これから少しずつ差が出てくるような気がします。

これからGreasemonkeyスクリプト実行環境がどうなるのかはまだ何ともいえませんが、とりあえず私はScriptishを中心に使っていきます。

gistページにraw masterへのリンクを追加するGreasemonkey

gistに置いたファイルの最新版を常に参照するraw masterなURLが最近変更されたり、昔使えた方法が使えなくなっています。

詳細は以下を参考に

  • Gist の raw ファイルの URL が変わった: 「わ」の日記もどき
  • 以前はURLに.txtとつければよかったので、特に何もしなくても不便はしなかったのですが、2011年6月15日現在はraw masterなURLへのURLにするにはちょっと書き換える量が多いのでGreasemonkeyを書きました。

    gistのページのファイル名の横にraw master URLへのリンクを追加するGreasemonkeyです。
    Scriptishの場合は、リンクをクリックするだけでクリップボードにURLをコピーします。

    2011-06-14-ss1

  • gist: raw master URL for Greasemonkey
  • この仕様変更により、Greasemonkeyで.txtでrequireしてたりするスクリプトは新しくインストールすると死んでいると思うので確認が必要になるかもしれません。

    JavaScriptでAmazonからASINを取得する方法など

    一つの方法はinput要素から取得する方法

    document.getElementById("ASIN").value

    Amazonはページ中のhiddenなinput要素にASINを持たせてるのでこういう手が取れる。

    <input id="ASIN" type="hidden" value="4253196519" name="ASIN">

    ページの構造が変わったらダメだけど、結構昔からこの部分は変わってないので意外と安定しているかもしれない。
    amazon.comだと構造が違うものがあって、Amazon.com: Buried Prey eBook: John Sandford: Kindle StoreのようにKindle Storeだとページ構造が違ってID=ASINがない代わりに次のようなものがある。

    <input type="hidden" value="B004LRPGPC" name="ASIN.0">
    なので、inputを取得する場合は次のような形になる。
    var ASIN = document.getElementById("ASIN") || document.getElementsByName("ASIN.0")[0];

    もう一つの方法はwindowオブジェクトのプロパティから取得する方法

    (2011年6月5日現在だと)

    window.sitbAsin;
    にASINの数値が入っている。(ちょっとできるタイミングが特殊な気がするから扱いにくいかも)
    これはAmazon側のJavaScriptが生やしているので、ページのちょっとした構造の変化では変わらないと思うけど使うライブラリを変えたりJavaScriptが大きく変わると変更されることがある。
    以前はwindow.productTagsに入っていた。

    最後はURLからASIN部分を切り出す方法

    URLにはASINが入ってるはずなので、ページに構造の変化には強いけど、少しパースが面倒なところがある。
    どのようなURLがあるかを把握する必要があるので、条件分けなども必要になる。
    まあASINのフォーマットは\w{10}と決まっているので、ある程度安定するのかもしれない。

    ついでに、replaceStateを使ってリロードなしでAmazonのURLを/dp/ASINだけの短いURLにするGreasemonkey書いた。

    Gihubのcanonicalを除去するGreasemonkey

    最近、Gihubのレポジトリでlink rel="canonical"が、treeのその時一番新しいものを示すようになっていて、そのためブックマークが分散したり、気持ち悪いURLを知らない間に登録していたりします。

    なので、link rel="canonical"のタグを削除するGreasemonkeyを書いてみました。

    何でこんな仕様なのか意味不明なので、いずれは元に戻って欲しいです。(このGreasemonkeyは一応、仕様が変わったかどうかかもチェックしてます)

    Githubはhisotyオブジェクトを使って動的にURLを書き換えてるのは知ってる人多いと思いますが、link rel="canonicalもそれにあわせて動的に書き換えています。
    $.attrで書き換えてるだけなので、link要素を削除してもエラーは特にでないようになっています。

    link rel="canonicalはあった方がうれしいと思ってたけど、あると困るケースに遭遇したのは初めて。

    ニコニコ動画の検索履歴を保存するGreasemonkey

    今のニコニコだと好きな動画を探すときに、特定の検索をして探すって感じの場合が多くなってきた気がするので、検索履歴を保存して表示できるGreasemonkeyを書いてみました。

    検索画面の右上の方にボタンが出るようになるので、それをクリックすると検索した履歴が表示されます。
    検索履歴は検索キーだけではなくてsort方法によっても別々に保存されます。

    imageimage

    また、検索キーの横にある☆マークをクリックすることで、その検索キーを常に上の方に表示して、自動的に削除されないようにします。(お気に入り機能)
    お気に入りではない検索キーは100個ぐらいで自動的に削除されます。

    コード内容

    これを書き始めたときSandbox Patternを試してみたくて書いてたので、あんまり見ない書き方をしてると思う。
    それぞれ必要な部品をモジュールhistory,templeteとして定義して、必要な時に
    Sandbox(“history”, function(box) { … }) という感じで使うというような書き方になってる。

    トラッキングパラメーターなど邪魔なものをURLが削除するGreasemonkey

    ParamCleanerというURLからutm_*など不要なパラメーターを除去するGreasemonkeyを書きました。
    すでに同じ目的のGreasemonkeyやアドオンなどがありますが、

    history.replaceStateを使う事で他のものに比べて簡潔な処理でURLからトラッキングパラメーターなどを消せます。
    またhistory.replaceStateを使ってるのでFirefox4以上向けで(一応Firefox3でも動くようにしてある)、Scriptish向けに最適化してあるので、できればScriptishで使った方がいいです(Greasemonkeyでも動きます)

    history.replaceState(data, title [, url])の使い方

    historyオブジェクトについてはgithubなどで話題になったので知ってる人も多いと思いますが、pushStateはブラウザの履歴に新規エントリを追加するAPIで、replaceStateは現在のエントリを入れ替えるAPIです。
    引数はpushState()と同じで、

    history.replaceState(stateプロパティに入る値, 状態識別用のタイトル, [現在の状態に対応するURL]);

    という引数をとります。
    第三引数を指定してSame OriginならURLバーの表示を書き換える事ができるので、以下のように実際に移動しなくても表示が書き換わります。

    // http://example.com/ で実行
    history.replaceState(null, "", "/hey");
    // => http://example.com/hey とURLバーの表示が変わる

    これを使って、今回はトラッキングパラメーターが存在するURL(アイテム – データベース: UrlCleaner – wedataで管理)にアクセスしたとき、トラッキングパラメーターを除去したURLへhistory.replaceStateを使って書き換えているので他のGreasemonkeyのようなリロードがなかったり、アドオンのように通信を監視する手間が省けます。(以前同じ名前でアドオンを作ってたけど重すぎた)

    UrlCleanerと同じWedataで管理されたものを勝手に使ってるので、処理自体は互換性があるようにしています(一部拡張してるけど) 気になったものがあったらSITEINFOを書いて、UrlCleaner – wedataに登録するとよいです。

    ParamCleaner for Greasemonkeyi
    http://userscripts.org/scripts/show/100611

    GreasemonkeyからScriptishへ環境設定を移行する

    GreasemonkeyからScriptishへの環境移行メモです。
    ScriptishについてはScriptish wiki!Scriptish (Greasemonkey フォーク版) キタ━━━ヽ(゚∀゚)ノ━ – hogehoge @teramakoを見るとよいです。
    簡単にまとめると、使えるAPIが増えた(開発者的にうれしい)、管理画面の設定項目がGreasemonkeyより豊富(Greasemonkey0.9で削られたinclude,excludeの設定もGUIからできます)、UIが日本語化されてる(ちょっと分かりづらい訳だけど…)
    Greasemonkeyからフォークしてるので、Greasemonkey向けに書かれたスクリプト自体の互換性は問題ないです。
    逆にScriptishの新APIを使ったものはGreasemonkeyでは動かない事があるぐらいだと思います。

    環境の移行方法

    How To: Manually transfer user scripts from Greasemonkey to Scriptish – GitHub
    に手動での環境移行手順が書かれています。
    簡単に書き出してみると

    1. スクリプトフォルダ名はgm_scriptsからscriptish_scriptsになった
      (フォルダの中のconfig.xmlや配置自体は同じなのでフォルダ名だけ変更すればOK)
    2. prefs.jsへスクリプトの設定の保存書式が変更された
      これが移行時にネックになってる大きな変更で、GM_setValueなどGreasemonkeyスクリプトから値を保存するとpref.jsに書き込まれますが、そのときの書式が変わっているためGreasemonkey時に保存した値が引き継がれません。
      一応手動での書き換え手順も書かれています。
      greasemonkey.scriptvals から extensions.scriptish.scriptvals へ置換する
      スクリプト名とネームスペースの間の/を@に置き換える

    GreasemonkeyとScriptishのpref.jsの書式の違いを見てみると

    user_pref("greasemonkey.scriptvals.http://efcl.info//Post Now browsing to Twitter.GM_config", "{"defaultTag":"見てる:","isSelection":true,"removeUtm":true,"avoidLinktoMeta":true,"PostWithCtrl":true,"ShortCutKey":"C-Delete","ShortURL":"bit.ly","bitlyUserName":"remiko","bitlyAPIKey":"R_fa2240c646c07b2091c6bc6d109089ef","googlAPIKey":"AIzaSyDYer57o2GyHX_xylyaa4iGIyyjd81kGxc"}");
    // =>
    user_pref("extensions.scriptish.scriptvals.PostNowbrowsingtoTwitter@httpefcl.info.GM_config",  "{"defaultTag":"Now  browsing:","isSelection":true,"removeUtm":true,"avoidLinktoMeta":true,"PostWithCtrl":true,"ShortCutKey":"C-Delete","ShortURL":"bit.ly","bitlyUserName":"remiko","bitlyAPIKey":"R_fa2240c646c07b2091c6bc6d109089ef","googlAPIKey":""}");

    という風にpref.jsに保存される書式が変化しています。
    ネームスペースとスクリプト名の位置も逆転してまたスペースなど除去されてたりします。
    手動でやっても結構手間がかかるので、大事なものだけやって、後は普通に設定し直した方が楽だと思います。
    一応、自動的にできるようにNILScriptでGreasemonkeyToScriptish.ngというものを作ってみました。

        pref.jsに保存された値をGreasemonkeyからScriptishの書式へ変更する
        pref.jsと同じディレクトリにこのngスクリプトを置いて実行するとnew_pref.jsが生成される。

    実行する前にpref.jsのバックアップをとっておいてから、pref.jsと同じディレクトリにおいて実行すると、それぞれの値を書き換えたnew_pref.jsというのができるので、後はpref.jsのコピーし直すかpref.jsにリネームして使うなどしてください。
    不完全かもしれないので、保証はできません。

    Dropboxフォルダでスクリプト管理

    これを期にGreasemonkeyスクリプトのファイル自体をDropboxで共有しようと思ったので、移行手順の1の時にDropboxにgm_scriptsフォルダを移して、プロファイルフォルダにscriptish_scriptsへのシンボリックリンクを作りました。
    Windowsだとmklinkとかコマンドラインがややこしいので、Link Shell Extensionを使ってシンボリックリンクを張りました。

    このソフトを使えば普通のショートカットみたいにシンボリックリンクが貼れるので簡単。
    (シンボリックリンクのフォルダ名をちゃんとscriptish_scriptsにするのを忘れない)

    追記:起動時に変更がたくさんある(Dropbox共有してると起きやすい)とnotificationが大量に通知されて使い物にならないので、
    Manual: Preferences – GitHubを参考にabout:configのextensions.scriptish.enableScriptRefreshing を false にして変更の監視をオフにしました。副作用として、スクリプトのメタブロックを書き換えても反映されなくなると思います。
    (Greasemonkey0.8あたりと同じ動作になると思う)

    これでGreasemonkeyからScriptishへの移行手順は終わりです。
    Firefox4への移行と同時にGreasemonkeyもScriptishへ移行を行えば、無駄なスクリプトを削除できたり汚れたpref.jsも掃除できるので同時期にやると良いかと思います。(使ってないGreasemonkeyスクリプトを削除するngスクリプトも以前書きました)
    まだどっちのアドオンが優れてるのかはよく分かってないので、使ってるうちに何らかの違いが分かるんではないかと。
    (Scriptish向けのスクリプトってなんて呼べば良いんだろ?)

    Firefox4でcan’t wrap XML objectsというエラーが出る件について

    Firefox4にしてから主にGreasemonkeyのGM_addStyleメソッドで

    TypeError: can’t wrap XML objects

    というエラーが出たりすることがあります。
    これはBug 609143 – E4X XML objects cannot be passed to sandboxのsandbox内でのE4X(XML)の挙動が変わった(意図的に)のが原因らしいです。(あまり詳しくないので…)

    GM_addStyle(<><![CDATA[ 
    /* 適当なCSSのコード*/
        .clearfix:after {
            content: ".";  /* 新しい要素を作る */
            display: block;  /* ブロックレベル要素に */
            clear: both;
            height: 0;
            visibility: hidden;/*表示はしない*/
        }
     ]]></>)

    のような感じでE4X(XML)を直接GM_addStyleに渡しているときなどに起きています。
    これを回避するためには、E4X(XML)を明示的に文字列化して渡せばよい見たいです。

    GM_addStyle(String(<><![CDATA[
    /* CSSコード */
    ]]></>));

    のようにString(E4X)するか、E4X全体をtoString()、”"+E4X のような感じで文字列化すればいい。
    もしくはGreasemonkeyにはメタ情報に// @resource CSS example.css という感じで、CSSファイルをロードできるので、そのファイルをGM_addStyle(GM_getResourceText(‘CSS’));して使うなどでもいいと思います。

    もしくは下のようにGM_addStyleを書き換えてしまう事でも回避できそうです。(あんまり推奨しないけど)

    function GM_addStyle(css) {
        if (!GM_addStyle.style) {
            var head = document.getElementsByTagName("head")[0] ||
                    document.documentElement;
            if (!head) {
                return;
            }
            GM_addStyle.style = document.createElement('style');
            GM_addStyle.style.type = 'text/css';
            head.insertBefore(GM_addStyle.style, head.firstChild);
        }
        GM_addStyle.style.appendChild(document.createTextNode(css) + '\n');
    }

    書き換えの参考

    Constellation’s gist: 803115 — GistのようにTomblooパッチでGM_addStyleの挙動を変えてしまおうと思ったけどよく分からなくなってあきらめました。

    参考

    Google検索でのuserContent.cssの設定やGreasemonkeyなど

    Google検索は最も使うサービスの一つだと思うので、できる限り快適にしたいです。いろいろいじってたのがやっと落ち着いたので設定のメモです。

    まずはGreasemonkeyから

    と、このぐらいで思ったより、Greasemonkeyは入れてない感じします。
    Google検索自体が結構高機能なので、そこまで機能を付け加える必要が無いのかもしれないです。(期間指定をもっと簡単にやりたいけど)
    後はアドオンでGoogle Date :: Add-ons for Firefoxを入れているぐらいです。
    入れている理由は最終更新日を知るためなのでちょっと関係ないかもしれないです。

    次にuserContent.cssの設定。
    Stylishは入れてないので直接userContent.cssに書いています。(デバッグにはuserMenu.uc.jsのCSSリロードが便利)

    /* Google検索ページ
    +結果欄の幅拡張
    +検索バーを固定
    +サイトの背景色を奇数で色分
    +広告は犠牲になった
    */
    @-moz-document url-prefix("http://www.google.co.jp/search"),
                     url-prefix("http://www.google.com/search"){
        /* 「もっと見る」を押さなくても、最初から全部表示 */
        .nojsb {
            display: block !important;
        }
        #tads{
            display: none !important;
        }
        #showmodes {
            display: none !important;
        }
        #mbEnd{
            display:none !important;
        }
        /* fixedSearchbar */
        #nr_container {
            margin-top: 115px;
        }
        #sfcnt {
            -moz-box-shadow:0 1px 5px #000000;
            box-shadow:0 1px 5px #000000;
            left:0;
            padding:18px 0;
            top:25px;
            width:100%;
            z-index:10;
        }
        #gog {
            left:0;
            top: 0;
            width:100%;
            z-index:11;
        }
        #gog, #sfcnt, #subform_ctrl{
            background:none repeat scroll 0 0 rgba(255, 255, 255, 0.9)!important;
            position:fixed;
        }
        #sfcnt {
            height:70px !important;
            padding-top:0 !important;
        }
        #subform_ctrl {
          text-align:right;
          z-index: 10;
          right: 0;
          top: 88px;
          min-height: 0;
          background:none repeat scroll 0 0 transparent!important;
        }
        #guser, #gbar{
              padding: 1px 0;
        }
        #gbar nobr, #guser nobr {
            line-height: 22px;
        }
        /* oddには色をつける */
        li.g:nth-child(odd){
            background:#F7F7F7;
        }
        /* 説明文を横に延長 */
        .g{
            min-width:800px;
            padding:5px!important;
            -moz-border-radius : 5px;
            border-radius : 5px;
        }
        .s {
            min-width: 800px !important;
        }
    
        /* RealTimeの場合横幅に必要 */
        #center_col{
            min-width:820px!important;
        }
        /*右側のbox*/
        #rtro{
            width: 800px!important;
        }
        /* 普段は隠しておいて、マウスオーバーで表示させる */
        #rhs{
            -moz-box-shadow:-3px 3px 3px #000000;
            white-space: nowrap;
            background:#fff!important;
            right: 0!important;
            top: 0!important;
            width: 15px!important;
            overflow:hidden;
        }
        #rhs:hover{
            background:#fff!important;
            right: 0!important;
            top: 0!important;
            width: 800px!important;
        }
    }

    Googleの設定 — Gist

    今はこんな感じで、結果欄の横幅拡張、検索バーを固定、サイトの背景色を奇数で色分けなどを行っています。
    スクリーンショットで見ると以下のような感じになります。

    また、先ほどGoogleのTwitter検索である”Google Realtime Search”のSITEINFOをwedataに書いておいたのでかなり快適になりました。
    (各種AutopagerizeでSITEINFOの更新を行えば適応されると思います)

    思ったより地味ですが、こんな感じで使っています。
    Google++ for Greasemonkeyを結構参考にしました。

    ATNDをもっと便利にするGreasemonkey「Better ATND」

    ATNDのイベントページに最寄り駅情報の表示やGoogleカレンダーの登録ボタンを追加などをするGreasemonkeyスクリプトを書いてみました。 元ネタはATND++というものがあったのですが、メンテされてなかったので自分で修正(ATND++を適当に修正したもの — Gist)して使っていたのですが、そのままだとメンテしにくかったので最初から書き直してみました。

    機能としては以下のような機能が付いています。(2011-03-06)

    • 最寄り駅情報の表示
    • 最寄り駅をまとめた地図画像の表示
    • Google Calendarへの登録ボタンの追加

    Googleカレンダーへの登録時には、イベントページから場所や概要などの情報も自動で入力します(説明文は長すぎるとエラーになるので300文字ぐらいで切っています)


    画像でみる機能

    最寄り駅情報

    Google Calendarの登録ボタン

    Google Calendarの登録ページ

    作った(使ってた)理由としては場所を言われてもピンとこない場合が多いのと、電車が主な移動手段であることが多いので、会場がどの駅に近いのかがわかると便利です。また参加してなくてもUstや後で資料を出してくれるイベントも多いので、忘れないように気になったイベントはGoogle Calendarに登録していました。最初はブックマークレット(ATNDのイベント画面にGoogleカレンダーへ予定を登録するボタンを追加するブックマークレット – 電脳戦士ハラキリ -SE道とは死ぬ事と見つけたり-)を使ってたのですが、少し面倒になったのでGreasemonkeyにその機能を入れました。
    ATNDのリニューアルでicsリンクがでて、Google Calendarで読み込む事ができるのですが、icsを読み込むと”他のカレンダー”が増えるのであんまり好みじゃないので今まで通り登録ボタンにしました。

    APIは以下の2つを使っています

    両方ともjsonなどいろいろな形式ではいたりしてくれるので、手軽に使えて便利です。

    Better ATND for Greasemonkey
    http://userscripts.org/scripts/show/98456
    better_atnd at master from azu/Greasemonkey – GitHub
    https://github.com/azu/Greasemonkey/tree/master/better_atnd
    プロフィール: azu(アズ)
    Firefoxの事やソフトウェアの紹介や使い道、Greasemonkeyの作成
    • OS:Windows Vista, 7
    • ブラウザ:Firefox
    • Twitterのアカウントはこちら
    • azu_re
    • メールアドレス(Twitterの方が確実)
    • info@ドメイン名
    リンク

    WebMoney ぷちカンパ