読者です 読者をやめる 読者になる 読者になる

AutoPagerizeで継ぎ足された部分に自分のスクリプトを適用する方法あれこれ

AutoPagerize

以前からある手法から順番に見ていきます。

ページの高さの監視

setIntervalでページの高さを監視して、増えていたらAutoPagerizeが動いたとみなして処理を行う

var THRESHOLD = 300;
var _height = window.innerHeight;
setInterval(function(){
    if (window.innerHeight - _height > THRESHOLD) {
         // 処理
    }
    _height = window.innerHeight;
}, 300);
メリット

AutoPagerizeだけでなく、はてなダイアリー・ブックマーク、Twitterなどでのサイト側でのページの継ぎ足しにも対応できる

デメリット

THRESHOLDをいくつにするかなど、一概に決められない。タイマーをたくさん回すと重くなる。Floatしている要素を継ぎ足した場合など、ページの高さが変わらない場合がある。スマートな方法ではないので、最近は使われません。

DOMNodeInsertedで監視

DOMNodeInsertedイベントを監視して要素が足されたタイミングを捕捉する

document.body.addEventListener('DOMNodeInserted',function(evt){
    if (/hoge/i.test(evt.target.className)) {
         // 処理
    }
}, false);
メリット

AutoPagerizeだけでなく、はてなダイアリー・ブックマーク、Twitterなどでのサイト側でのページの継ぎ足しにも対応できる

デメリット

補足した要素がAutoPagerizeによるものか(処理の対象とするべきか否か)検証する必要がある。
要素の書き換えを頻繁に行うサイトで重くなる(特にlivedoor Readerなど)。

Tips

特定のサイト用のスクリプトならば、監視対象のノードを限定すると良い。例えばTwitterの場合、

document.getElementById('timeline').addEventListener('DOMNodeInserted',function(evt){
    if (/hentry/i.test(evt.target.className)) {
         // 処理
    }
}, false);

AutoPagerize APIのaddFilterを使う

AutoPagerize.addFilterは、登録された関数をページの継ぎ足し時に実行してくれる。

var boot = function(){
    AutoPagerize.addFilter(function(docs){
        docs.forEach(function(node){
            if (/hentry/i.test(node.className)) {
                // 処理
            }
        });
    });
};
if (window.AutoPagerize) {
    boot();
} else {
    window.addEventListener('GM_AutoPagerizeLoaded',boot,false);
}
メリット

引数で継ぎ足された要素を配列として受け取れるので、効率的に足された部分だけを処理できる。

デメリット

addFilterが使えるようになるタイミングに注意しなければいけないので、冗長なコードになる。

GM_AutoPagerizeLoaded以前

GM_AutoPagerizeLoadedが実装される前はsetTimeoutで監視する方法が使われていた。今でもこのタイプのスクリプトは多い。(Firefox限定ではsetTimeoutを1回挟めば確実にwindow.AutoPagerizeを取れるが、Google Chromeでは失敗することがあるので注意が必要。下記のように数回実行すると良い)

var init = function(count){
    if (!window.AutoPagerize) {
        if (count > 0) {
            setTimeout(init, 300, count - 1);
        }
        return;
    }
    AutoPagerize.addFilter(function(docs){
        docs.forEach(function(node){
            if (/hentry/i.test(node.className)) {
                // 処理
            }
        });
    });
};
init(4);

AutoPagerize Event APIAutoPagerize_DOMNodeInserted を使う

AutoPagerize_DOMNodeInserted イベントは、名前の通りAutoPagerize独自のDOMNodeInsertedイベントで、追加された要素をtargetとしたイベントが発火される。

document.body.addEventListener('AutoPagerize_DOMNodeInserted',function(evt){
    var node = evt.target;
    var requestURL = evt.newValue;
    var parentNode = evt.relatedNode;
    // 処理
}, false);
メリット

追加されたノードを効率的に処理できる。
実行順を気にする必要がないのでコードがシンプル

デメリット

最新バージョンのAutoPagerize(version 0.40 以降)、jAutoPagerize(Rev: 33889+ 以降)でないと対応していない

Tips

AutoPagerize_DOMNodeInsertedは元々oAutoPagerizeで実装したものなので、当然oAutoPagerizeでも使用できます。(oAutoPagerizeに実装する際には例によってnanto_vi先生にアドバイスを頂き、AutoPagerize、jAutoPagerizeの実装もnanto_vi先生のPatchによるものです。nanto_vi++ )
twitter.AutoPager for GreasemonkeyAutoPagerize_DOMNodeInsertedに対応させました。

まとめ

というわけで、今後は AutoPagerize_DOMNodeInserted を推奨したい次第です。


ちなみに、サイト側でAutoPagerizeするときも、これらのEventを投げてくれると嬉しいですね。