DOM Rangeを使って複数のノードを上の階層に上書きする
前回に引き続き http://upload0.dyndns.org/up/2/_/ を使い易いように改造する。
どのファイルでもいいので適当にクリックして、個別のページにいったら『ダウンロード』をクリックしてパスワードを求められるページに進む。
パスワード入力欄とボタンの部分だけ欲しい。
前回と同じように広告バナーを消すには、上の階層に移動するのが良さそう。複数のノードを扱うにはDOM Rangeが便利らしいのでそれを使ってみる。
ソースコード
var d = document.evaluate('//label[@for="download_pass"]', document, null, 7, null); var range = document.createRange(); range.setStart(d.snapshotItem(0), 0); range.setEnd(d.snapshotItem(0).nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, 0); var df = range.extractContents(); d.snapshotItem(0).parentNode.parentNode.replaceChild(df, d.snapshotItem(0).parentNode);
xpath一本釣り。まず基点となるlabelをxpathで補足する。次にRangeを組み立てていく。setStartとsetEndの第二引数のoffsetは今回必要がないので0。nextSiblingが並んでいるのはlabel→\n→input→\n→input→\n→inputという具合にDOMツリーを辿るため。formタグの外に置いたらpostできないので上げすぎに注意。
今回のミソはrange.extractContents()の部分。RengeはdocumentFragmentに変換しないとDOMツリー(?)に挿入することができないので、extractContents()かcloneContents()を使ってdocumentFragmentに変換する。
追記 こっちのほうがいいかな。xpathサビキ釣り。
//注意点は出力される順番を把握しておくこと。 //xpathはツリーの上から順に走査されるので今回の場合、 //divがsnapshotItem(0)、labelがsnapshotItem(1)、inputがsnapshotItem(2)となる。 var d = document.evaluate('//label[@for="download_pass"] | //input[@class="submit"] | //div[@class="input_download_pass"] ', document, null, 7, null); var range = document.createRange(); range.setStart(d.snapshotItem(1), 0); range.setEnd(d.snapshotItem(2), 0); var df = range.extractContents(); d.snapshotItem(0).parentNode.replaceChild(df, d.snapshotItem(0));
まとめ
// ==UserScript== // @name mod_index-uploader // @namespace http://d.hatena.ne.jp/Cherenkov/ // @include http://upload0.dyndns.org/up/2/_/* // ==/UserScript== //キーワードにヒットしたらハイライト var k = document.evaluate('//td[@class="name"]', document, null, 7, null); for(i=0;i<k.snapshotLength;i++){ //if(/hoge|fuga|kame|hige|cut/ig.test(k.snapshotItem(i).textContent)){ これ間違い if(/hoge|fuga|kame|hige|cut/i.test(k.snapshotItem(i).textContent)){ k.snapshotItem(i).style.backgroundColor = 'yellow'; } } //個別のファイルのページ if(/jump/.test(location.href)) { var c = document.evaluate('//a[@class="download"]', document, null, 7, null); //if(c) location.href = c.snapshotItem(0).href; //コメントアウトをはずせば自動でパスワード入力のページへ c.snapshotItem(0).parentNode.offsetParent.replaceChild(c.snapshotItem(0), c.snapshotItem(0).parentNode.parentNode.parentNode); GM_addStyle('.download { font-size:30pt }'); } //パスワード入力のページ if(/download/.test(location.href)) { var d = document.evaluate('//label[@for="download_pass"]', document, null, 7, null); var range = document.createRange(); range.setStart(d.snapshotItem(0), 0); range.setEnd(d.snapshotItem(0).nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling.nextSibling, 0); var df = range.extractContents(); d.snapshotItem(0).parentNode.parentNode.replaceChild(df, d.snapshotItem(0).parentNode); document.getElementById('download_pass').focus(); GM_addStyle('#download_pass { font-size:30pt }'); }
element.replaceChildを使って上の階層に上書きする
今回は http://upload0.dyndns.org/up/2/_/ を使い易いように改造していく。
どのファイルでもいいので、適当にクリックして個別のファイルのダウンロードページに進む。
広告バナーがたくさん
ダウンロードページにいくとバナーがたくさんある。目的のファイルをダウンロードするには『ダウンロード』と書かれたリンクをクリックしないといけない。(自動的に『ダウンロード』のリンク先に飛ぶ方法もあるけど。)
firebugでソースをみるとこうなっている。
バナーにid、class、nameが付いていれば、広告不可視化関数を使って簡単にdisplay:none出来るけど今回は使えない。DOM element - MDCを眺めていたらreplaceNodeというのが便利そうなので使ってみることにした。
アイディアとしては、ダウンロードのaタグの部分を上の階層に上げる。上位と下位を入れ替える。そうすれば上書きされて広告バナーの部分が消滅するはず。
ソースコード
var d = document.evaluate('//a[@class="download"]', document, null, 7, null); d.snapshotItem(0).parentNode.parentNode.parentNode.parentNode.replaceChild(d.snapshotItem(0), d.snapshotItem(0).parentNode.parentNode.parentNode);
まずxpathでaタグを補足する。入れ替え先の親ノードをreplaceChildの前に書いて、第一引数に入れ替えたいノード、第二引数に入れ替え先ノードを書く。
ちょっとだけダイエット。
var d = document.evaluate('//a[@class="download"]', document, null, 7, null); d.snapshotItem(0).parentNode.offsetParent.replaceChild(d.snapshotItem(0), d.snapshotItem(0).parentNode.parentNode.parentNode);
tdにいくとoffsetParentにtableタグが指定されているのでそれを利用した。(firebugでのDOMツリーツアーは楽しい。)
追記 xpathでor検索して二匹釣る。
snapshotはツリー順に作られるのでsnapshotItem(0)はtable。snapshotItem(1)はa。
var d = document.evaluate('//a[@class="download"]|//table[descendant::a/@class="download"]', document, null, 7, null); d.snapshotItem(0).parentNode.replaceChild(d.snapshotItem(1), d.snapshotItem(0));
結果
余計なものは消えた。ソースにGM_addStyle('.download { font-size:30pt }');を追加して『ダウンロード』の文字を大きくした。これが一番やりたかったこと。
tableの中身がすっきりした。
次回は、『ダウンロード』のリンク先に舞台を移して「ここから〜ここまで」のようにDOM Rangeを使って複数のノードを上の階層に上書きする方法を模索します。
関連
- mod_uploader系攻略法 - キーワードのハイライトは便利。
- DOM element.replaceChild - MDC