2012年3月1日木曜日

NAVERまとめのブックマークレットが何をしているのか見てみる #NAVERまとめ

特に意味はないですけど、勉強がてらに見てみます。
『コードリーディングとか出来ないぜ!頭皮から汁が出てくるぜ!』
と思ってしまうのですが、
ブックマークレットくらいからやるのが、俺くらいの技量の人間には丁度良いでしょう。

取りあえず綺麗にしてみる。

javascript:(function(){
    var d=document 
        ,w=window
        ,e=w.getSelection
        ,k=d.getSelection
        ,x=d.selection;
    try{
        s=(e?e():(k)?k():(x?x.createRange().text:''))
    }catch(e){
        s=''
    }
    var l=d.location
        ,e=encodeURIComponent
        ,d=decodeURIComponent
        ,g=function(s){
            try{
                d(s);return s
            }catch(e){
                return g(s.substr(0,s.length-1))
            }
        }
        ,f='http://matome.naver.jp/bml'
        ,p='?u='+e(l.href)+'&s='+e(s)
        ,u=g((f+p).substr(0,2500))
        ,a=function(){
            if(!w.open(u,'njMTMBookmarklet','links=0,scrollbars=0,toolbar=0,status=1,width=520,height=653'))l.href=u
        };
    (/Firefox/.test(navigator.userAgent))?setTimeout(a,0):a();
    void(0)
})();

というわけで、綺麗になったところで、見ていきます。
前半

    var d=document 
        ,w=window
        ,e=w.getSelection
        ,k=d.getSelection
        ,x=d.selection;
    try{
        s=(e?e():(k)?k():(x?x.createRange().text:''))
    }catch(e){
        s=''
    }


getSelection は、文字列が選択されているかを見るやつなので、
変数 s に e k x つまり、なんかかんか選択された要素があればそれを入れて、
それがなければ s を空の文字列にするよとしています。

後半

    var l=d.location
        ,e=encodeURIComponent
        ,d=decodeURIComponent
        ,g=function(s){
            try{
                d(s);return s
            }catch(e){
                return g(s.substr(0,s.length-1))
            }
        }
        ,f='http://matome.naver.jp/bml'
        ,p='?u='+e(l.href)+'&s='+e(s)
        ,u=g((f+p).substr(0,2500))
        ,a=function(){
            if(!w.open(u,'njMTMBookmarklet','links=0,scrollbars=0,toolbar=0,status=1,width=520,height=653'))l.href=u
        };


ブックマークレットを起動したら、ウィンドウが開く(またはページ転移する)わけですが、
そのウィンドウが開く先のURLを作っているところ。


encodeURIComponent とか decodeURIComponent とか名前が長いので、e とか d とか変数に置き換えて、
省略して書けるようになってますね。
d は 前半部分で document だったけど、ここにきたら上書きされてしまいます。
g っていうのが関数で、これは何をやってるのかというと、
放り込まれた文字列をデコードすることを試みます。
デコードできなければ文字列の長さを1個減らして(substring のところ)、もう一回自分自身にその文字列を放り込み、
デコードが出来るまでそれを繰り返しています。
で、その関数 g が出てくるのが次あたり。
変数 f はブックマークレット用のエンドポイントURL(っていうの?)、
変数 p は f のあとにくっつく文字列、つまり、ブックマークレットが開くURL (f + p) は、

 http://matome.nave.jp/bml?u= encodeURIComponent( 開いているページのURL ) &s= encodeURIComponent(前半で作った選択された文字列) 

になります。で、
変数 u で g が登場します。
ブラウザというのは、開けるURLの文字数が決まっているので、

 http://support.microsoft.com/kb/208427/ja
 http://www.connect-i.co.jp/tipsblog/?p=6

さっきの

 http://matome.nave.jp/bml?u= encodeURIComponent( 開いているページのURL ) &s= encodeURIComponent(前半で作った選択された文字列) 


こいつが、ブラウザの開けるURL文字数を超えているとマズいので、
g に 『 f + p して一端 2500 字でぶった切ったもの』 を投げて、
それが decodeURIComponent できるかどうか、URLとして成立するかをチェックし、
成立しなければ成立するまで文字数を減らしてから、変数 u に返します。

で、関数 a は、そんな変数 u を小窓で開ければ開いて、
ポップアップ禁止されてたりすれば、今開いてるページを、変数 u のアドレスに移動させます。

最後

    (/Firefox/.test(navigator.userAgent))?setTimeout(a,0):a();
    void(0)

ここがわからん。
ユーザエージェント、つまり今見ているブラウザが Firefox っぽかったら(ユーザエージェントを偽装することも出来るからね)、
何故かsetTimeoutで0秒待ってから、関数 a を実行してて、それ以外のブラウザは普通に関数 a を実行している。
この違いが良く分からないなぁ。なんざんしょ。Firefoxには特別な何かがあるのであろう。
調べるのめんどくさい。非同期ぽくしなきゃだめつーことですか?
ブックマークレットを書き換えてどうなるか実験君してみればいいんだけどねぇ。やらない。めんどいから。

そんな感じでした。嘘書いてたらごめんなさい。

開いたブックマークレットのウィンドウの中の

 http://static.naver.jp/matome_ver4/js/nj.matome.bookmarklet_xxxxxxxxxxxxxxx.js

これとかは、そのうち読んでみたいなーと思います。

久しぶりにブログ書いた。5000HIT超えました。
『上手くはないんだけどせっかくもらったしヘタとは言えないし飾らないわけにもいかない5000HITおめでとうトップ画像』
ネット友達から貰う感じだね。これは。