Skip to content

Instantly share code, notes, and snippets.

@azu
Created January 30, 2009 12:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save azu/55041 to your computer and use it in GitHub Desktop.
Save azu/55041 to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name favlist++
// @namespace http://web.zgo.jp/
// @include http://www.nicovideo.jp/mylist/*
// @include http://www.nicovideo.jp/user/*
// @include http://www.nicovideo.jp/myvideo/*
// @include http://www.nicovideo.jp/my*
// ==/UserScript==
(function () {
var w = (this.unsafeWindow || window), document = w.document;
var NicoNicoFavlist = {
version: "1.16",
getUserAgent: function () {
return "NicoNicoFavlist/" + NicoNicoFavlist.version + " Greasemonkey";
}
};
var Util = {
observe: function (elem, event, func, capture) {
capture = !!capture;
if (elem.attachEvent) {
elem.attachEvent("on" + event, func);
} else if (elem.addEventListener) {
elem.addEventListener(event, func, capture);
} else {
elem["on" + event] = func;
}
}
};
var Config = {
checkInterval: 30 * 60,
maxNewVideos: 10,
hideCheckedList: false,
showInAllTabs: false,
show: function (elem) {
var ul = document.createElement("ul");
ul.style.margin = "0px";
ul.style.padding = "8px";
ul.style.listStyleType = "none";
this.addTextInput(ul, "更新チェック間隔", "favlistCheckInterval", Config.checkInterval, "10", "秒");
this.addTextInput(ul, "新着動画数の上限", "favlistMaxNewVideos", Config.maxNewVideos, "10", "件まで");
this.addCheckBox(ul, "新着がないマイリストを隠す", "favlistHideCheckedList", Config.hideCheckedList);
this.addCheckBox(ul, "カテゴリをまたいで表示", "favlistShowInAllTabs", Config.showInAllTabs);
elem.appendChild(ul);
},
addTextInput: function (elem, label, name, value, size, unit) {
var li = document.createElement("li");
li.className = "TXT12";
li.style.fontWeight = "bold";
li.style.marginBottom = "8px";
li.innerHTML = '<label for="'+name+'">'+label+':</label><br>';
var input = document.createElement("input");
input.type = "text";
input.id = name;
input.name = name;
input.value = value;
input.size = size;
li.appendChild(input);
if (unit) {
var span = document.createElement("span");
span.innerHTML = unit;
span.style.marginLeft = "4px";
li.appendChild(span);
}
elem.appendChild(li);
},
addCheckBox: function (elem, label, name, value) {
var li = document.createElement("li");
li.className = "TXT12";
li.style.fontWeight = "bold";
li.style.marginBottom = "4px";
li.innerHTML = '<label for="'+name+'">'+label+'</label>';
var check = document.createElement("input");
check.type = "checkbox";
check.id = name;
check.name = name;
check.value = "1";
check.checked = !!value;
li.insertBefore(check, li.firstChild);
elem.appendChild(li);
},
load: function () {
var checkInterval = GM_getValue("checkInterval");
if (checkInterval !== undefined) Config.checkInterval = checkInterval;
var maxNewVideos = GM_getValue("maxNewVideos");
if (maxNewVideos !== undefined) Config.maxNewVideos = maxNewVideos;
var hideCheckedList = GM_getValue("hideCheckedList");
if (hideCheckedList !== undefined) Config.hideCheckedList = hideCheckedList;
var showInAllTabs = GM_getValue("showInAllTabs");
if (showInAllTabs !== undefined) Config.showInAllTabs = showInAllTabs;
},
save: function () {
var interval = document.getElementById("favlistCheckInterval").value;
try {
interval = w.parseInt(interval);
if (interval < 0) interval = 0;
Config.checkInterval = interval;
GM_setValue("checkInterval", interval);
} catch (e) {
w.alert("更新チェック間隔の値がおかしいです");
return;
}
var maxnewvideos = document.getElementById("favlistMaxNewVideos").value;
try {
maxnewvideos = w.parseInt(maxnewvideos);
if (maxnewvideos < 0) maxnewvideos = 0;
Config.maxNewVideos = maxnewvideos;
GM_setValue("maxNewVideos", maxnewvideos);
} catch (e) {
w.alert("新着動画数の上限の値がおかしいです");
return;
}
var hidechedkedlist = document.getElementById("favlistHideCheckedList").checked;
Config.hideCheckedList = hidechedkedlist;
GM_setValue("hideCheckedList", hidechedkedlist);
var showInAllTabs = document.getElementById("favlistShowInAllTabs").checked;
Config.showInAllTabs = showInAllTabs;
GM_setValue("showInAllTabs", showInAllTabs);
favlist.switchTab(0);
}
};
var Video = function () { this.initialize.apply(this, arguments); };
Video.prototype = {
initialize: function (mylist, id, title, uri, thumbnail, memo, timestamp) {
this.mylist = mylist;
this.id = id || false;
this.title = title || false;
this.uri = uri || false;
this.thumbnail = thumbnail || false;
this.memo = memo || false;
this.timestamp = timestamp || false;
this.container = false;
},
serialize: function () {
return [
this.id ? w.escape(this.id) : "",
this.title ? w.escape(this.title) : "",
this.uri ? w.escape(this.uri) : "",
this.thumbnail ? w.escape(this.thumbnail) : "",
this.memo ? w.escape(this.memo) : "",
this.timestamp ? w.escape(this.timestamp) : ""
].join("&");
},
unserialize: function (data) {
var r = [];
if (data) r = data.split(/&/);
this.id = r[0] ? w.unescape(r[0]) : false;
this.title = r[1] ? w.unescape(r[1]) : false;
this.uri = r[2] ? w.unescape(r[2]) : false;
this.thumbnail = r[3] ? w.unescape(r[3]) : false;
this.memo = r[4] ? w.unescape(r[4]) : false;
this.timestamp = r[5] ? w.unescape(r[5]) : false;
},
updateByAtomEntry: function (entry) {
var m;
if (m = entry.match(/<title>(.*?)<\/title>/)) this.title = m[1];
if (m = entry.match(/<link rel="alternate" type="text\/html" href="(.+?)"\/>/)) this.uri = m[1];
if (this.uri && (m = this.uri.match(/watch\/(.+)/))) this.id = m[1];
if (m = entry.match(/<img alt=".*?" src="(.+?)"/)) this.thumbnail = m[1];
if (m = entry.match(/<p class="nico-memo">(.*?)<\/p>/)) this.memo = m[1];
if (m = entry.match(/<published>(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}).*?<\/published>/)) {
this.timestamp = m[1]+"年"+m[2]+"月"+m[3]+"日 "+m[4]+":"+m[5]+":"+m[6];
}
},
getCaption: function () {
var caption = this.title || "(無題)";
if (caption.length > 26) {
caption = caption.substr(0, 13) + "..." + caption.substr(-13);
}
return caption;
},
show: function (elem) {
var li = document.createElement("li");
li.style.clear = "both";
li.style.padding = "4px 0px";
li.style.borderTop = "1px dotted #CCC";
var self = this;
var clearance = function () { self.mylist.clear(self); };
var thumbLink = document.createElement("a");
thumbLink.href = this.uri;
thumbLink.title = this.title;
try { thumbLink.style.cssFloat = "left"; }
catch (e) { thumbLink.style.styleFloat = "left"; }
thumbLink.style.marginRight = "4px";
Util.observe(thumbLink, "click", clearance);
var thumb = document.createElement("img");
thumb.className = "thumb_img";
thumb.src = this.thumbnail;
thumb.width = "46";
thumb.height = "34";
thumbLink.appendChild(thumb);
li.appendChild(thumbLink);
if (this.timestamp) {
var time = document.createElement("p");
var m = this.timestamp.split(/\D+/);
time.innerHTML = "<strong>" +
m[0].substr(-2) + "/" + m[1] + "/" + m[2] + " " +
m[3] + ":" + m[4] + ":" + m[5] + "</strong> 追加";
time.className = "TXT10";
li.appendChild(time);
}
var title = document.createElement("p");
title.className = "TXT12";
var titleLink = document.createElement("a");
titleLink.href = this.uri;
titleLink.title = this.title;
titleLink.className = "video";
titleLink.innerHTML = this.getCaption();
Util.observe(titleLink, "click", clearance);
title.appendChild(titleLink);
li.appendChild(title);
var breaker = document.createElement("p");
breaker.style.clear = "both";
breaker.innerHTML = '<img src="img/_.gif" width="1" height="1">';
li.appendChild(breaker);
if (this.memo) {
var memo = document.createElement("p");
memo.innerHTML = this.memo;
memo.className = "TXT12";
memo.style.backgroundColor = "#F7F7F7";
memo.style.border = "1px solid #CCC";
memo.style.padding = "4px";
memo.style.marginTop = "4px";
li.appendChild(memo);
}
elem.appendChild(li);
this.container = li;
},
remove: function () {
if (this.container) {
this.container.parentNode.removeChild(this.container);
this.container = false;
}
}
};
var Mylist = function () { this.initialize.apply(this, arguments); };
Mylist.prototype = {
baseUri: "http://www.nicovideo.jp",
initialize: function (favlist, listId, title) {
this.favlist = favlist;
this.listId = listId || false;
this.title = title || false;
this.checked = { };
this.newVideos = [ ];
this.caption = false;
this.container = false;
this.videoList = false;
this.titleBar = false;
this.counter = false;
this.statusBar = false;
this.buttons = false;
this.toRemove = false;
},
serialize: function () {
var checked = [ ];
for (var k in this.checked) { checked.push(k); }
var newVideos = [ ];
for (var i = 0, len = this.newVideos.length; i < len; i++) {
newVideos.push(this.newVideos[i].serialize());
}
return [
"0", /* for backward compatibility */
this.listId ? w.escape(this.listId) : "",
this.title ? w.escape(this.title) : "",
checked.join(":"),
newVideos.join(":"),
this.caption ? w.escape(this.caption) : ""
].join(";");
},
unserialize: function (data) {
var r = [];
if (data) r = data.split(/;/);
// r[0] is userId, but not in use
this.listId = r[1] ? w.unescape(r[1]) : false;
if (/^\d+$/.test(this.listId)) this.listId = "mylist/" + this.listId;
this.title = r[2] ? w.unescape(r[2]) : false;
this.checked = { };
if (r[3]) {
var checked = r[3].split(/:/);
for (var i = 0; i < checked.length; i++) {
if (checked[i]) {
this.checked[ checked[i] ] = true;
}
}
}
this.newVideos = [ ];
if (r[4]) {
var vids = r[4].split(/:/);
for (var i = 0; i < vids.length; i++) {
if (vids[i]) {
var v = new Video(this);
v.unserialize(vids[i]);
this.newVideos.push(v);
}
}
}
this.caption = r[5] ? w.unescape(r[5]) : false;
},
getUri: function () {
return this.baseUri + "/" + this.listId;
},
getCaption: function () {
var caption = this.caption || this.title || "(無題)";
if (caption.length > 26) {
caption = caption.substr(0, 13) + "..." + caption.substr(-13);
}
return caption;
},
update: function () {
this.setStatus("更新中", "#333");
this.newVideos = [ ];
this.videoList.innerHTML = "";
var self = this;
GM_xmlhttpRequest({
method: "GET",
url: this.getUri() + "?rss=atom&nodescription=1&noinfo=1&sort=1",
headers: { "User-Agent": NicoNicoFavlist.getUserAgent() },
onload: function (r) {
self.setStatus(false);
if (200 <= r.status && r.status < 300) {
self.updateByAtom(r.responseText);
} else if (r.status == 403) {
self.setStatus("非公開", "#C00", 3000);
}
},
onerror: function (r) {
self.setStatus("更新失敗", "#C00", 3000);
},
onreadystatechange: function (r) {
if (r.readyState == 4) {
self.favlist.updateCallback(this);
}
}
});
},
updateByAtom: function (xml) {
var m;
if (m = xml.match(/<title>(?:マイリスト )?(.+?)‐ニコニコ動画.*?<\/title>/)) {
this.title = m[1];
}
var oldChecked = this.checked;
this.checked = { };
var re_entry = /<entry>([\S\s]*?)<\/entry>/g;
while (m = re_entry.exec(xml)) {
var v = new Video(this);
v.updateByAtomEntry(m[1]);
if (v.id in oldChecked) {
this.checked[v.id] = true;
} else {
this.newVideos.push(v);
}
}
this.updateTitleBar();
this.updateVideoList();
this.favlist.save();
},
updateTitleBar: function () {
if (this.titleBar && this.titleBar.tagName.toUpperCase() == "A") {
this.titleBar.title = this.title;
this.titleBar.innerHTML = this.getCaption();
if (this.newVideos.length > 0) {
this.titleBar.style.fontWeight = "bold";
this.counter.innerHTML = "(" + this.newVideos.length + ")";
this.counter.style.display = "";
this.container.style.display = "";
} else {
this.titleBar.style.fontWeight = "";
this.counter.style.display = "none";
if (Config.hideCheckedList && this.statusBar.style.display == "none") {
this.container.style.display = "none";
}
}
}
},
updateVideoList: function () {
if (!this.videoList) return;
this.videoList.innerHTML = "";
var len = this.newVideos.length;//新着のサムネ数
if (0 < Config.maxNewVideos && Config.maxNewVideos < len) {
len = Config.maxNewVideos;
}
for (var i = 0; i < len; i++) {
this.newVideos[i].show(this.videoList);
}
},
show: function (elem, editting) {
var div = document.createElement("div");
div.style.clear = "both";
div.style.padding = "4px 0px";
div.style.borderBottom = "1px solid #999";
this.container = div;
var buttons = document.createElement("p");
try { buttons.style.cssFloat = "right"; }
catch (e) { buttons.style.styleFloat = "right"; }
div.appendChild(buttons);
this.buttons = buttons;
var self = this;
this.toRemove = false;
this.addButton(buttons, "削除", function () {
self.toRemove = true;
self.container.parentNode.removeChild(self.container);
self.container = false;
});
if (!editting) {
this.addButton(buttons, "クリア", function () { self.clearAll(); });
}
var status = document.createElement("p");
status.className = "TXT12";
try { status.style.cssFloat = "right"; }
catch (e) { status.style.styleFloat = "right"; }
status.style.color = "#FFF";
status.style.backgroundColor = "#666";
status.style.fontWeight = "bold";
status.style.padding = "0px 4px";
status.style.lineHeight = "22px";
status.style.display = "none";
div.appendChild(status);
this.statusBar = status;
var h = document.createElement("p");
h.className = "TXT12";
h.style.padding = "2px 0px";
div.appendChild(h);
if (editting) {
var input = document.createElement("input");
input.type = "text";
input.value = this.caption || this.title;
input.style.width = "170px";
h.appendChild(input);
this.titleBar = input;
this.counter = null;
} else {
var a = document.createElement("a");
a.href = this.getUri();
a.title = this.title;
a.innerHTML = this.getCaption();
h.appendChild(a);
this.titleBar = a;
var counter = document.createElement("span");
counter.style.color = "#F33";
counter.style.fontWeight = "bold";
counter.style.marginLeft = "4px";
counter.style.display = "none";
h.appendChild(counter);
this.counter = counter;
}
var breaker = document.createElement("p");
breaker.style.clear = "both";
breaker.innerHTML = '<img src="img/_.gif" width="1" height="1">';
div.appendChild(breaker);
if (editting) {
this.videoList = null;
} else {
var ul = document.createElement("ul");
ul.style.clear = "both";
ul.style.listStyleType = "none";
ul.style.margin = "0px";
ul.style.padding = "0px";
div.appendChild(ul);
this.videoList = ul;
}
this.updateTitleBar();
this.updateVideoList();
elem.appendChild(div);
},
showConfig: function (elem) {
this.show(elem, true);
},
addButton: function (elem, caption, func) {
var btn = document.createElement("input");
btn.type = "button";
btn.value = caption;
btn.className = "submit";
btn.style.marginLeft = "4px";
Util.observe(btn, "click", func);
elem.appendChild(btn);
return btn;
},
saveConfig: function () {
if (this.toRemove) {
this.remove();
return;
}
if (!this.titleBar.value || this.titleBar.value == this.title) {
this.caption = false;
} else {
this.caption = this.titleBar.value;
}
if (this.caption != this.titleBar.value) {
this.caption = this.titleBar.value;
}
},
remove: function () {
this.favlist.remove(this.listId);
if (this.container) {
this.container.parentNode.removeChild(this.container);
this.container = false;
}
},
clear: function (video) {
if (!video) return;
for (var i = 0, len = this.newVideos.length; i < len; i++) {
if (this.newVideos[i] == video) {
this.newVideos.splice(i, 1);
}
}
video.remove();
this.checked[video.id] = true;
this.updateTitleBar();
this.favlist.save();
},
clearAll: function () {
for (var i = 0, len = this.newVideos.length; i < len; i++) {
var v = this.newVideos[i];
v.remove();
this.checked[v.id] = true;
}
this.newVideos = [ ];
this.updateTitleBar();
this.favlist.save();
},
setStatus: function (status, color, timeout) {
if (status) {
this.statusBar.innerHTML = status;
this.statusBar.style.backgroundColor = color;
this.statusBar.style.display = "";
this.buttons.style.display = "none";
this.container.style.display = "";
if (timeout) {
var self = this;
w.setTimeout(function () { self.setStatus(false); }, timeout);
}
} else {
this.statusBar.style.display = "none";
this.buttons.style.display = "";
if (Config.hideCheckedList && this.newVideos.length == 0) {
this.container.style.display = "none";
}
}
}
};
var Favlist = function () { this.initialize.apply(this, arguments); };
Favlist.prototype = {
initialize: function () {
this.id = arguments[0] || "favlist";
this.list = { };
this.tabs = [ ];
this.container = false;
this.updateAllButton = false;
this.updateQueue = [ ];
},
save: function () {
GM_setValue(this.id, this.serialize());
},
load: function () {
this.unserialize(GM_getValue(this.id));
},
serialize: function () {
var data = [];
for (var k in this.list) {
data.push(this.list[k].serialize());
}
return data.join("#");
},
unserialize: function (data) {
this.list = { };
if (data) {
data = data.split(/#/);
for (var i = 0; i < data.length; i ++) {
var ml = new Mylist(this);
ml.unserialize(data[i]);
this.list[ml.listId] = ml;
}
}
},
get: function (listId) {
return this.list[listId];
},
add: function (listId, title) {
var ml = new Mylist(this, listId, title);
this.list[listId] = ml;
this.save();
},
remove: function (listId) {
var ml = this.list[listId];
if (ml) {
delete this.list[listId];
this.save();
}
},
updateAll: function () {
var first = false;
for (var k in this.list) {
if (!first) {
first = this.list[k];
} else {
this.updateQueue.push(this.list[k]);
this.list[k].setStatus("待機中", "#CCC");
}
}
if (first) {
if (this.updateAllButton) {
this.updateAllButton.disabled = true;
}
first.update();
}
},
updateCallback: function (ml) {
if (this.updateQueue.length > 0) {
var ml = this.updateQueue.shift();
ml.update();
} else {
if (this.updateAllButton) {
this.updateAllButton.disabled = false;
}
}
},
clearByVideoId: function (videoId) {
var toRemove;
if (videoId instanceof Array) {
var ids = { };
for (var i = 0, len = videoId.length; i < len; i++) {
ids[videoId[i]] = true;
}
toRemove = function (id) {
return ids[id];
}
} else {
toRemove = function (id) {
return (videoId == id);
}
}
var changed = false;
for (var k in this.list) {
var mylist = this.list[k], videos = mylist.newVideos;
var mylist_changed = false;
for (var i = videos.length - 1; i >= 0; i--) {
var video = videos[i];
if (toRemove(video.id)) {
video.remove();
mylist.checked[video.id] = true;
videos.splice(i, 1);
changed = true;
mylist_changed = true;
}
}
if (mylist_changed) mylist.updateTitleBar();
}
if (changed) favlist.save();
},
addToPlaylist: function () {
if (typeof w.gm_playlistController == "undefined") return;
var addVideos = [];
for (var k in this.list) {
var mylist = this.list[k], videos = mylist.newVideos;
for (var i = 0, len = videos.length; i < len; i++) {
addVideos.push(videos[i]);
}
mylist.clearAll();
}
if (addVideos.length > 0) {
w.gm_playlistController.pushVideos(addVideos);
}
},
show: function (elem) {
var div = document.createElement("div");
div.className = "mb16p4";
div.style.position = "relative";
var h = document.createElement("h2");
div.appendChild(h);
var self = this;
this.tabs = [];
this.addTab(h, "一覧", function () { self.showList(); });
this.addTab(h, "設定", function () { self.showConfig(); });
var span = document.createElement("span");
span.innerHTML = "favlist";
span.style.display = "block";
span.style.borderWidth = "2px";
span.style.borderColor = "#FFF #FFF #333 #FFF";
span.style.borderStyle = "solid";
h.appendChild(span);
var container = document.createElement("div");
container.style.clear = "both";
container.style.position = "relative";
container.style.paddingTop = "4px";
div.appendChild(container);
this.container = container;
elem.insertBefore(div, elem.firstChild);
this.switchTab(0);
},
addTab: function (elem, caption, func) {
var tab = document.createElement("a");
tab.href = "javascript:void(0);";
tab.innerHTML = caption;
tab.style.display = "block";
tab.style.textAlign = "center";
tab.style.textDecoration = "none";
try {
tab.style.cssFloat = "right";
} catch (e) {
tab.style.styleFloat = "right";
}
tab.style.width = "3em";
tab.style.color = "#333";
tab.style.backgroundColor = "#FFF";
tab.style.borderWidth = "2px";
tab.style.borderColor = "#FFF #FFF #333 #FFF";
tab.style.borderStyle = "solid";
elem.insertBefore(tab, elem.firstChild);
this.tabs.push({
tab: tab,
func: func
});
var self = this;
Util.observe(tab, "click", function () { self.switchTab(tab); });
return tab;
},
switchTab: function (selectTab) {
if (this.updateQueue.length > 0) return;
if (typeof selectTab == "number") selectTab = this.tabs[selectTab].tab;
var func = false;
for (var i = 0, len = this.tabs.length; i < len; i++) {
var tab = this.tabs[i].tab;
if (tab == selectTab) {
tab.style.borderColor = "#333 #333 #FFF #333";
func = this.tabs[i].func;
} else {
tab.style.borderColor = "#FFF #FFF #333 #FFF";
}
}
if (func) func();
},
showList: function () {
this.container.innerHTML = "";
for (var k in this.list) {
this.list[k].show(this.container);
}
var buttons = document.createElement("p");
buttons.style.clear = "both";
buttons.style.paddingTop = "4px";
var self = this;
this.updateAllButton = this.addButton(buttons, "いますぐ更新", function () { self.updateAll(); });
var checkPlaylist = function () {
if (typeof w.gm_playlistController != "undefined") {
var b = self.addButton(buttons, "プレイリストに移動", function () { self.addToPlaylist(); });
b.style.marginLeft = "5px";
return true;
}
}
var saveButton = document.createElement("input");
saveButton.className = "submit";
saveButton.type = "button";
saveButton.value = "保存";
saveButton.style.width = "5em";
saveButton.style.fontWeight = "bold";
var self = this;
Util.observe(saveButton, "click", function () {
for (var k in self.list) {
self.list[k].saveConfig();
}
self.save();
Config.save();
});
checkPlaylist() || setTimeout(checkPlaylist, 1);
this.container.appendChild(buttons);
this.container.appendChild(saveButton);
},
addButton: function (elem, caption, func) {
var btn = document.createElement("input");
btn.type = "button";
btn.value = caption;
btn.className = "submit";
Util.observe(btn, "click", func);
elem.appendChild(btn);
return btn;
},
showConfig: function () {
this.container.innerHTML = "";
for (var k in this.list) {
this.list[k].showConfig(this.container);
}
Config.show(this.container);
var p = document.createElement("p");
p.style.borderTop = "1px solid #999";
p.style.padding = "8px";
var saveButton = document.createElement("input");
saveButton.className = "submit";
saveButton.type = "button";
saveButton.value = "保存";
saveButton.style.width = "5em";
saveButton.style.fontWeight = "bold";
var self = this;
Util.observe(saveButton, "click", function () {
for (var k in self.list) {
self.list[k].saveConfig();
}
self.save();
Config.save();
});
p.appendChild(saveButton);
this.container.appendChild(p);
},
};
var NicoHistory = {
videoIds: [ ],
loadFromCookie: function () {
NicoHistory.videoIds = [ ];
if (w.document.cookie && /\bnicohistory\s*=\s*([^;]+)/.test(w.document.cookie)) {
var hist = RegExp.$1;
var m, re = /(?:^|%2C)(.+?)(?=%3A|$)/ig;
while (m = re.exec(hist)) {
this.videoIds.push(w.unescape(m[1]));
}
}
}
};
var RegisterButton = function () { this.initialize.apply(this, arguments); };
RegisterButton.prototype = {
initialize: function (favlist, listId, title) {
this.favlist = favlist;
this.listId = listId;
this.title = title;
this.button = false;
},
show: function (elem) {
if (this.button) return;
var a = document.createElement("a");
a.id = this.buttonId;
a.href = "javascript:void(0);";
a.className = "TXT12";
a.style.textDecoration = "none";
a.style.padding = "2px 4px";
a.style.margin = "3px 4px";
a.style.border = "1px solid #CCC";
a.style.backgroundColor = "#EEE";
var self = this;
Util.observe(a, "click", function () { self.execute(); });
elem.style.position = "relative";
elem.appendChild(a);
this.button = a;
this.update();
},
update: function () {
if (!this.button) return;
if (this.favlist.get(this.listId)) {
this.button.innerHTML = '<span style="color:#F00;">×</span>';
} else {
this.button.innerHTML = '<span style="color:#FC3;">★</span>';
}
},
execute: function () {
if (this.favlist.get(this.listId)) {
this.favlist.remove(this.listId);
} else {
this.favlist.add(this.listId, this.title);
GM_setValue("lastUpdate", 0);
}
this.update();
}
};
Config.load();
var favlist = new Favlist();
favlist.load();
var m;
if (m = w.location.href.match(/nicovideo\.jp\/mylist\/(?:\d+\/)?(\d+)(?!.*rss=)/)) {
var h1 = document.getElementsByTagName("h1");
if (h1 && h1.length > 0) {
var button = new RegisterButton(favlist, "mylist/" + m[1], h1[0].innerHTML);
button.show(h1[0]);
}
} else if (m = w.location.href.match(/nicovideo\.jp\/(?:myvideo|user)\/(\d+)(?!.*rss=)/)) {
var h1 = document.getElementsByTagName("h1");
if (h1 && h1.length > 0) {
var title = document.title.match(/^(.+)さんの/) ? RegExp.$1 + "さんの投稿動画" : "投稿動画(" + m[1] + ")";
var button = new RegisterButton(favlist, "myvideo/" + m[1], title);
button.show(h1[0]);
}
} else if (m = w.location.href.match(/nicovideo\.jp\/my?/)){
NicoHistory.loadFromCookie();
if (NicoHistory.videoIds.length > 0) {
favlist.clearByVideoId(NicoHistory.videoIds);
}
var showFavlist = function () {
var parentContainer;
var xp = "//div[@class='content_312']";
var r = document.evaluate(xp, document, null,
XPathResult.FIRST_ORDERED_NODE_TYPE, null);
if (r) parentContainer = r.singleNodeValue;
if (parentContainer) {
favlist.show(parentContainer);
return true;
} else {
return false;
}
}
if (showFavlist()) {
if (w.Category) {
var oldCategoryUpdate = w.Category.update;
if (oldCategoryUpdate) {
w.Category.update = function () {
oldCategoryUpdate.apply(w.Category, arguments);
if (Config.showInAllTabs) {
showFavlist();
} else {
w.Category.update = oldCategoryUpdate;
}
}
}
}
if (Config.checkInterval > 0) {
var now = w.Math.floor((new Date()).getTime() / 1000);
var last = GM_getValue("lastUpdate") || 0;
if (last + Config.checkInterval < now) {
GM_setValue("lastUpdate", now);
favlist.updateAll();
}
}
}
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment