livedoor Reader で既読記事を非表示にする
livedoor Reader で特定のサイトや記事の本文を非表示にする に関して、はてブコメントにて表題のアイデアを提案していただきました。ちょうど、サイトの既読判定をスクリプトで行う手法が考案されて (g:subtech:id:secondlife:20060812:1155379084 id:brazil:20060812:1155388762)、面白いなぁと思っていたところで、絶妙のタイミングでした。
(以下、既読判定の実装について、直接的にははてなアンテナのコードを参考にさせてもらいました)
フィード表示前のフックを使って、既読であればその記事を削除する、という方法を考えてみます。
概要としては:
register_hook("before_printfeed", function(feed) { for (var i = 0; i < feed.items.length; i++) if (既読判定(feed.items[i].link)) feed.items.splice(i--, 1); });
となります。
この既読判定の仕組みについてなんですが、フィードの表示の度に呼び出されるということで、一つの判定オブジェクト (VisitedCheck) を常駐させておくことにします。
動作版:
// ==UserScript== // @name LDR Visited Checker // @namespace http://d.hatena.ne.jp/reinyannyan/20060820/ // @include http://reader.livedoor.com/reader/* // @version 0 // ==/UserScript== (function() { // Based on: http://a.hatena.ne.jp/js/VisitedCheck.js var VisitedCheck = new (function() { this.div = document.createElement("div"); this.div.className = "visited_check"; document.body.appendChild(this.div); this.check = function(url) { if (window.opera) return false; this.div.innerHTML = '<a href="'+url+'" class="visited_check">string</a>'; return this.div.childNodes[0].offsetWidth <= 0; } }); LDR_addStyle("div.visited_check", "position:relative !important;top:-10000px !important"); LDR_addStyle("a.visited_check", ""); LDR_addStyle("a.visited_check:visited", "display:none !important"); register_hook("before_printfeed", function(feed) { for (var i=0,items=feed.items,len=items.length; i<len; i++) if (VisitedCheck.check(items[i].link)) { items.splice(i--, 1); len--; } }); })();
(isVisited というメソッドを check に変えてみました。主語と述語の関係が合ってないような気がしたもので)
IE でしかテストしていませんが、with(unsafeWindow){} で全体 (無名関数の内側) を囲えば Firefox でも動作するんじゃないかなと期待します。
ついでに、オン・オフの機能を加えたより完全なバージョンも併記しておきます (これもコード自体はプレーンな IE 用です)。
// ==UserScript== // @name LDR Visited Checker // @namespace http://d.hatena.ne.jp/reinyannyan/20060820/ // @include http://reader.livedoor.com/reader/* // @version 1 // ==/UserScript== (function() { var check_visited = false; // Based on: http://a.hatena.ne.jp/js/VisitedCheck.js var VisitedCheck = new (function() { this.div = document.createElement("div"); this.div.className = "visited_check"; document.body.appendChild(this.div); this.check = function(url) { if (window.opera) return false; this.div.innerHTML = '<a href="'+url+'" class="visited_check">string</a>'; return this.div.childNodes[0].offsetWidth <= 0; } }); LDR_addStyle("div.visited_check", "position:relative !important;top:-10000px !important"); LDR_addStyle("a.visited_check", ""); LDR_addStyle("a.visited_check:visited", "display:none !important"); register_command("cv|checkvisited", function() { check_visited = !check_visited; message("VisitedCheck: o"+(check_visited ? "n" : "ff")); var sid = State.now_reading; if (sid) { if (check_visited) rewrite_feed(); else { delete get_unread.cache._index["_" + sid]; State.last_element = null; get_unread(sid); } } }); register_hook("before_printfeed", function(feed) { if (!check_visited) return; var dels = []; for (var i=0,items=feed.items,len=items.length; i<len; i++) if (VisitedCheck.check(items[i].link)) { dels.push(items[i].title); items.splice(i--, 1); len--; } if (dels.length) message("Deleted: "+dels.map(function(v){return v.ry(20,"..")})); }); })();