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,"..")}));
});
})();