There are 21 previous versions of this script.
Add Syntax Highlighting (this will take a few seconds, probably freezing your browser while it works)
// ==UserScript==
// @name NicoNicoPlaylist mod
// @namespace oamaxa
// @original d.hatena.ne.jp/Sore_0
// @description List up the series of movies and play them all!
// @include http://www.nicovideo.jp/*
// @include http://ch.nicovideo.jp/*
// @include http://dic.nicovideo.jp/*
// @include https://secure.nicovideo.jp/secure/login_form*
// @exclude http://www.nicovideo.jp/api/*
// @exclude http://www.nicovideo.jp/thumb/*
// @version 1.7.3
// @update 2009/11/23
// ==/UserScript==
//var DEBUG=true;
var w=(unsafeWindow||window),document=w.document;
var $=function(id){return document.getElementById(id);};
var $n=function(tag){return document.createElement(tag);};
var $x=function(node){
var x=document.evaluate(node,document,null,7,null),array=new Array();
for(var i=0; i<x.snapshotLength; i++) array.push(x.snapshotItem(i));
return array;
};
var Util={
getElementPosition:function(e){
var offsetTrail=e,offsetTop=0;
while(offsetTrail){
offsetTop+=offsetTrail.offsetTop;
offsetTrail=offsetTrail.offsetParent;
}
return offsetTop;
},
xhr:function(e,f){
var f=(typeof f=="function")? f():function(){},r=new XMLHttpRequest();
r.open("GET",e,false);
r.onload=r.onerror=f;
r.send(null);
},
opacity:function(e){
if(e.className.indexOf(" opacity")>-1) return;
var opacity=0,css=e.style.cssText;
e.className+=" opacity";
var timer=setInterval(function(){
if(opacity==100){
clearInterval(timer);
e.style.cssText=css;
e.className=e.className.replace(" opacity","");
}
else{
opacity=(opacity>96)? 100:opacity+4;
e.style.cssText=[
css,
"-moz-opacity:"+opacity/100+";",
"opacity:"+opacity/100+";"
].join(" ");
}
},40);
}
};
var URL={
NICO:/^https?:\/\/.*?\.(?:nico|smile)video\.jp\//,
WATCH_REGEXP:/http:\/\/.*?\.nicovideo\.jp\/watch\/([^\/?<>\"\'#]+)/,
WATCH:"http://www.nicovideo.jp/watch/",
CACHE:"http://www.nicovideo.jp/cache/",
CHANNEL:"http://ch.nicovideo.jp/",
DIC:"http://dic.nicovideo.jp/",
MYLIST:"http://www.nicovideo.jp/mylist/",
GETTHUMB:"http://ext.nicovideo.jp/api/getthumbinfo/",
GETRELATION:"http://ext.nicovideo.jp/api/getrelation?sort=p&order=d&video=",
WHATPAGE:function(){
var m;
if(m=location.href.match(/http:\/\/.*?\.nicovideo\.jp\/([^\/]*)\/?/)) return m[1];
}
};
const playlistWidth=434;
const watchPage=location.href.match(URL.WATCH_REGEXP)? true:false;
const chPage=location.href.match(URL.CHANNEL)? true:false;
const dicPage=location.href.match(URL.DIC)? true:false;
var Video=function(){this.initialize.apply(this,arguments);};
Video.prototype={
initialize:function(){
this.id=arguments[0]||"";
this.title=arguments[1]||"";
},
serialize:function(){return [escape(this.id),escape(this.title)].join("&");},
unserialize:function(data){
var r=[];
if(data) r=data.split("&");
this.id=unescape(r[0]);
this.title=unescape(r[1]);
},
getPlayUri:function(){return URL.WATCH+this.id;},
play:function(e){location.href=this.getPlayUri()+e;},
getRelatedVideos:function(iterator,terminator){
GM_xmlhttpRequest({
method:"GET",
url:URL.GETRELATION+this.id,
headers:{"Content-type":"text/xml"},
onload:function(r){
var tags=r.responseText.match(/<video>((?:.|\r|\n)+?)<\/video>/gm);
if(tags){
for(var i=0,len=tags.length; i<len; i++){
var videoId=tags[i].match(URL.WATCH_REGEXP);
var title=tags[i].match(/<title>(.+?)<\/title>/);
iterator(videoId[1],title[1]);
}
}
terminator();
},
onerror:function(){terminator();}
});
}
};
var PlayList=function(){this.initialize.apply(this,arguments);};
PlayList.all=function(){
var list=GM_getValue("playlist.all");
return list? list.split(/,/):[];
};
PlayList.add=function(id){
GM_setValue("current",id);
if(PlayList.checker(id)) return;
var list=PlayList.all();
list.push(id);
GM_setValue("playlist.all",list.join(","));
};
PlayList.del=function(id){
var list=PlayList.all();
for(var i=0; i<list.length; i++) if(list[i]==id) list.splice(i,1);
GM_setValue("playlist.all",list.join(","));
var val=GM_listValues();
for(var i=0; i<val.length; i++) if(val[i].replace(/[a-z]+_/,"")==id) GM_deleteValue(val[i]);
};
PlayList.checker=function(id){
var m=false,list=PlayList.all();
for(var i=0; i<list.length; i++){
if(list[i]==id){
m=true;
break;
}
}
return m;
};
PlayList.videos=function(){
var list=PlayList.all(),meta,n=0;
for(var i=0; i<list.length; i++){
meta=GM_getValue("playlist_"+list[i]).split(/;/)[1].split(/:/);
n+=(meta[0]=="")? 0:meta.length;
}
return n;
};
PlayList.prototype={
initialize:function(){
this.id=arguments[0]||"default";
this.videos=[];
this.load();
},
serialize:function(){
var videos=[];
for(var i=0; i<this.videos.length; i++) videos.push(this.videos[i].serialize());
return [this.id,videos.join(":")].join(";");
},
unserialize:function(data){
var r=data.split(/;/)[1];
if(!r) return;
var vids=r.split(/:/);
for(var i=0; i<vids.length; i++){
if(vids[i]){
var v=new Video();
v.unserialize(vids[i]);
this.videos.push(v);
}
}
},
save:function(){GM_setValue("playlist_"+this.id,this.serialize());},
copy:function(id){GM_setValue("playlist_"+id,id+this.serialize().slice(this.id.length));},
load:function(){
var data=GM_getValue("playlist_"+this.id,false);
if(data) this.unserialize(data);
},
push:function(video){this.videos.push(video);},
unshift:function(video){this.videos.unshift(video);},
pop:function(){return this.videos.shift();},
popRandom:function(){
if(this.videos.length==0) return null;
var i=Math.floor(Math.random()*this.videos.length);
var v=this.videos[i];
this.videos.splice(i,1);
return v;
},
remove:function(a,b){
var start=a<b? a:b,end=a<b? b:a;
this.videos.splice(start,end-start+1);
},
move:function(a,b){
if(a<b){
this.videos.splice(b+1,0,this.videos[a]);
this.videos.splice(a,1);
}
else{
this.videos.splice(b,0,this.videos[a]);
this.videos.splice(a+1,1);
}
},
reverse:function(a,b){
var start=a<b? a:b,end=a<b? b:a,videos=this.videos.slice(start,end+1);
videos.reverse();
for(var i=0; i<videos.length; i++) this.videos.splice(start+i,1,videos[i]);
},
fetch:function(n,f){
var id=this.videos[n].id,self=this;
GM_xmlhttpRequest({
method:"GET",
url:URL.GETTHUMB+id,
headers:{"Content-type":"text/xml","User-agent":"Mozilla/5.0 Greasemonkey"},
onload:function(r){
var m,title=(m=r.responseText.match(/<title>(.+?)<\/title>/))? m[1]:id;
for(var i=0; i<self.videos.length; i++){
if(self.videos[i].id==id) self.videos[i].title=title;
}
f();
},
onerror:function(){return false;}
});
},
clear:function(){this.videos=[];}
};
var PlayListController=function(){this.initialize.apply(this,arguments);};
PlayListController.prototype={
initialize:function(playlist,continuity){
PlayList.add(playlist.id);
this.continuity=continuity;
this.scroll=GM_getValue("scroll",0);
this.delay=GM_getValue("delay",5000);
this.ls=[];
this.mark="del";
this.merge=[];
this.pick=false;
var data=["auto","extend","popmark","pause"];
for(var i=0; i<data.length; i++) this[data[i]]=GM_getValue(data[i],false);
this.bind(playlist);
var self=this;
document.addEventListener("click",function(e){
if(!self.pick||e.which==3) return;
var ee=e.target;
if(ee.tagName=="SPAN"&&ee.className=="vinfo_title") ee=ee.parentNode;
else if(ee.tagName!="A") return;
var video=ee.href.match(/watch\/([a-z]*\d+)$/)[1]||false;
if(video&&ee.className.indexOf("noadd")==-1){
e.preventDefault();
Util.opacity(ee);
self.pushVideo(video,dicPage? ee.textContent:ee.innerHTML,(e.which==2)? true:false);
}
},true);
},
bind:function(playlist){
this.playlist=playlist;
this.buffer={playlist:[],n:0};
this.color=GM_getValue("color_"+playlist.id,"#FFF0FC");
var data=["eco","com","vol","fs","random","loop","cache"];
for(var i=0; i<data.length; i++) this[data[i]]=GM_getValue(data[i]+"_"+playlist.id,false);
this.update();
},
change:function(id){
PlayList.add(id);
this.bind(playlist=new PlayList(id));
},
getPageVideoId:function(){
var m;
return (m=location.href.match(URL.WATCH_REGEXP))? m[1]:false;
},
isWatchPage:function(){return this.getPageVideoId()!=false;},
pushVideo:function(video,title,opt){
if(!video.match(/^[a-z]*\d+$/)) return;
this.clone();
if(!!opt) this.playlist.unshift(new Video(video,title));
else this.playlist.push(new Video(video,title));
this.buffer.playlist[-1]=Array.apply(null,this.playlist.videos);
this.playlist.save();
this.update();
},
pushVideos:function(videos){
this.clone();
for(var i=0,len=videos.length; i<len; i++){
if(!videos[i].id.match(/^[a-z]*\d+$/)) continue;
var video=new Video(videos[i].id,videos[i].title);
this.playlist.push(video);
}
this.buffer.playlist[-1]=Array.apply(null,this.playlist.videos);
this.playlist.save();
this.update();
},
pushThisVideo:function(){
var videoId=this.getPageVideoId();
if(videoId){
this.clone();
this.playlist.push(new Video(videoId,unescape(w.Video.title)));
this.buffer.playlist[-1]=Array.apply(null,this.playlist.videos);
this.playlist.save();
this.update();
}
},
pushAllVideos:function(){
this.clone();
var as=$x("//a[contains(concat(' ',normalize-space(@class),' '),' video ')]");
if(chPage) as=as.concat($x("//a[contains(normalize-space(@class),'community_video')]"));
else if(dicPage) as=as.concat($x("//a[@rel='nofollow']"));
for(var i=0, len=as.length; i<len; i++){
var a=as[i],m,title,t;
if(a.className.indexOf("noadd")>-1) continue;
if(m=a.href.match(URL.WATCH_REGEXP)){
if(dicPage) title=a.textContent;
else title=(t=a.innerHTML.match(/<span[^>]*?>(.*?)<\/span>/))? t[1]:a.innerHTML;
this.playlist.push(new Video(m[1],title));
}
}
var self=this;
if(watchPage){
var thisVideo=new Video(w.Video.id);
thisVideo.getRelatedVideos(function(videoId,title){
self.playlist.push(new Video(videoId,title));
},function(){
self.buffer.playlist[-1]=Array.apply(null,self.playlist.videos);
self.playlist.save();
self.update();
});
}
else{
self.buffer.playlist[-1]=Array.apply(null,self.playlist.videos);
self.playlist.save();
self.update();
}
},
pushMarkedVideos:function(){
var $marked=$x("//a[contains(concat(' ',normalize-space(@class),' '),' video ')][./ancestor::*[contains(concat(' ',normalize-space(@class),' '), ' marked ')]]");
if($marked.length==0) return;
this.clone();
for(var i=0; i<$marked.length; i++){
if($marked[i].href.match(URL.WATCH)&&!$marked[i].href.match($marked[i].textContent)){
var link=$marked[i].href.match(/watch\/([^\/?<>\"\'#]+)/)[1];
this.playlist.push(new Video(link,$marked[i].textContent));
if(this.popmark) this.popVideoMark();
}
}
this.buffer.playlist[-1]=Array.apply(null,this.playlist.videos);
this.playlist.save();
this.update();
},
popVideoMark:function(){
var $marked=$x("//*[contains(concat(' ',normalize-space(@class),' '),' marked ')]");
if($marked.length==0) return;
var page=URL.WHATPAGE();
for(var i=0; i<$marked.length; i++){
if($marked[i].className.indexOf("marking")>-1) $marked[i].className=$marked[i].className.replace(/\s+marked/,"");
else if(page.match(/ranking|tag|search|newarrival|recent|myvideo|hotlist|\?g=/g)||page=="") $marked[i].setAttribute("class","thumb_frm");
else for(var i=0; i<$marked.length; i++) $marked[i].setAttribute("class","");
}
},
playNext:function(){
var video=this.random? this.playlist.popRandom():this.playlist.pop();
if(video){
if(this.loop) this.playlist.push(video);
this.playlist.save();
window.name+=" continuity:\""+this.playlist.id+"\"";
if(this.eco&&this.ls.indexOf("eco=1")==-1) this.ls.unshift("eco=1");
video.play(this.ls[0]? "?"+this.ls.join("&"):"");
}
},
capture:function(e,video,f){
this.pin=true;
var mark=$x("//*[contains(concat(' ',normalize-space(@class),' '),' checked ')]")[0];
if(typeof mark!="undefined"){
var n=parseInt(mark.className.split(/\s+/)[2],10);
if(n!=video){
this.clone();
f(n,video);
this.buffer.playlist[-1]=Array.apply(null,this.playlist.videos);
this.playlist.save();
}
this.update();
}
else{
var n=$x("//a[@class='"+e+"']")[video];
n.className=e+" checked "+video;
n.parentNode.style.backgroundColor=n.parentNode.lastChild.style.backgroundColor=n.style.color;
n.parentNode.lastChild.style.color=n.style.color="white";
}
},
remove:function(video,event){
if(event=="contextmenu"){
var self=this;
this.capture("del",video,function(a,b){self.playlist.remove(a,b);});
}
else{
this.clone();
this.playlist.videos.splice(video,1);
this.buffer.playlist[-1]=Array.apply(null,this.playlist.videos);
this.playlist.save();
this.update();
}
},
move:function(video){
var self=this;
this.capture("move",video,function(a,b){self.playlist.move(a,b);});
},
reverse:function(video){
var self=this;
this.capture("rev",video,function(a,b){self.playlist.reverse(a,b);});
},
clear:function(){
this.clone();
this.playlist.clear();
this.buffer.playlist[-1]=Array.apply(null,this.playlist.videos);
this.playlist.save();
this.update();
},
fetch:function(video){
var self=this;
this.playlist.fetch(video,function(){
self.playlist.save();
self.update();
});
},
state:function(e,state){
this[e]=state;
GM_setValue(e,state);
},
_state:function(e,state){
this[e]=state;
GM_setValue(e+"_"+this.playlist.id,state);
},
copy:function(id){
var data=["color","eco","com","vol","vl","fs","random","loop","cache"];
for(var i=0; i<data.length; i++) if(typeof this[data[i]]!="undefined") GM_setValue(data[i]+"_"+id,this[data[i]]);
this.playlist.copy(id);
},
duplicate:function(id){
this.copy(id);
this.change(id);
},
rename:function(id){
this.copy(id);
PlayList.del(this.playlist.id);
this.change(id);
},
clone:function(){
this.buffer.playlist.splice(0,this.buffer.n,Array.apply(null,this.playlist.videos));
this.buffer.n=0;
},
track:function(back){
(back)? this.buffer.n++:this.buffer.n--;
this.playlist.videos=this.buffer.playlist[this.buffer.n-1];
this.playlist.save();
this.update();
},
marker:function(e){
var a={},mark=["del","move","rev","rename"];
for(var i=0; i<mark.length; i++) a[mark[i]]=$x("//a[contains(concat(' ',normalize-space(@class),' '),' "+mark[i]+" ')]");
for(var j=0; j<this.playlist.videos.length; j++){
for(var k in a) a[k][j].style.display="none";
a[e][j].style.display="inline";
}
this.mark=e;
this.update();
},
config:function(){
this.pin=true;
var self=this;
var box=$("playlistController");
box.innerHTML="";
var header=$n("p");
header.className="playlist-header";
header.style.margin="2px 10px 0px 10px";
header.style.fontSize="15px";
box.appendChild(header);
var title=$n("span");
title.style.fontWeight="bold";
title.style.color="#C9A9CC";
title.innerHTML="Playlist";
title.style.cursor="pointer";
title.addEventListener("click",function(){self.update();},false);
header.appendChild(title);
var conf=$n("span");
conf.style.marginLeft="10px";
conf.style.fontWeight="bold";
conf.innerHTML="Preference";
header.appendChild(conf);
var hr=$n("hr");
hr.style.margin="0px 10px";
box.appendChild(hr);
var div=$n("div");
div.style.margin="10px";
div.style.padding="0px";
box.appendChild(div);
var ul=$n("ul");
ul.className="font12";
ul.style.listStyleType="circle";
ul.style.margin="0px 10px 0px 20px";
ul.style.padding="0px";
ul.style.fontWeight="bold";
div.appendChild(ul);
var checkDef=[
{caption:"disable auto play",title:"自動再生を無効化",click:function(){
self.state("auto",this.checked);
},checked:this.auto},
{caption:"extend assistive functions",title:"プレイリスト外の動画に補助機能を適用",click:function(){
self.state("extend",this.checked);
},checked:this.extend},
{caption:"unmark after adding marked movies",title:"マークした動画を追加後、動画のマークを外す",click:function(){
self.state("popmark",this.checked);
},checked:this.popmark},
{caption:"enable auto login",title:"自動ログインを有効化",click:function(){
self.state("login",this.checked);
},checked:login}
];
for(var i=0, len=checkDef.length; i<len; i++){
var def=checkDef[i];
var list=$n("li");
list.style.marginTop="10px";
ul.appendChild(list);
var chk=$n("input");
chk.id="config_check_"+i;
chk.type="checkbox";
chk.style.marginTop="0px";
chk.style.verticalAlign="middle";
if(def.click) chk.addEventListener("click",def.click,false);
if(def.checked) chk.checked="checked";
list.appendChild(chk);
var label=$n("label");
label.htmlFor=chk.id;
label.innerHTML=def.caption;
label.style.verticalAlign="middle";
label.style.border="none";
list.appendChild(label);
chk.title=label.title=def.title;
}
var timer;
var textDef=[
{caption:"adjust scroll",title:"スクロール調整",click:function(e){
var value=e.target.previousSibling.value,span=e.target.nextSibling;
if(value.match(/^-?\d+$/)){
self.scroll=value;
GM_setValue("scroll",value);
if(value=="184") span.innerHTML="scroll disabled";
else{
e.target.style.display="none";
span.innerHTML="updated";
if(typeof player!="undefined") player.scroll(self.scroll);
}
}
else span.innerHTML="error";
timer=setTimeout(function(){
e.target.style.display="none";
span.innerHTML="";
},3000);
},init:"scroll"},
{caption:"delay for auto play",title:"自動再生までの遅延時間(ミリ秒)",click:function(e){
var value=e.target.previousSibling.value,span=e.target.nextSibling;
if(value.match(/^\d+$/)){
self.delay=value;
GM_setValue("delay",value);
e.target.style.display="none";
span.innerHTML="updated";
}
else span.innerHTML="error";
timer=setTimeout(function(){
e.target.style.display="none";
span.innerHTML="";
},3000);
},init:"delay"},
{caption:"chrome code",title:"背景色を変更",click:function(e){
var value=e.target.previousSibling.value,span=e.target.nextSibling;
if(value.match(/^#(?:[a-fA-F0-9]{6}|[a-fA-F0-9]{3})$/)){
box.style.backgroundColor=self.color=value;
GM_setValue("color_"+self.playlist.id,value);
e.target.style.display="none";
span.innerHTML="updated";
}
else span.innerHTML="error";
timer=setTimeout(function(){
e.target.style.display="none";
span.innerHTML="";
},3000);
},init:"color"}
];
for(var i=0, len=textDef.length; i<len; i++){
var def=textDef[i];
var list=$n("li");
list.style.paddingLeft="5px";
list.style.paddingTop="8px";
ul.appendChild(list);
var desc=$n("span");
desc.innerHTML=def.caption+" : ";
list.appendChild(desc);
var text=$n("input");
text.className="font12";
text.type="text";
text.size="7";
text.style.border="1px solid black";
text.style.padding="3px";
text.value=this[def.init];
text.addEventListener("keyup",function(e){
if(timer) clearTimeout(timer);
e.target.nextSibling.style.display="";
},false);
list.appendChild(text);
var button=$n("input");
button.className="_submit";
button.type="button";
button.value="save";
button.style.marginLeft="10px";
button.style.display="none";
button.addEventListener("click",def.click,false);
list.appendChild(button);
var span=$n("span");
span.style.marginLeft="10px";
span.style.color="red";
list.appendChild(span);
desc.title=text.title=def.title;
}
},
update:function(){
this.pin=(typeof DEBUG=="undefined")? false:true;
var self=this,listScrollTop=0,box=$("playlistController");
if(!box){
box=$n("div");
box.id="playlistController";
box.style.position="fixed";
box.style.width=playlistWidth+"px";
box.style.left=this.pin? "0px":4-playlistWidth+"px";
box.style.top="40px";
box.style.border="1px solid #CCC";
box.style.zIndex="100";
box.style.overflow="auto";
box.addEventListener("mouseover",function(e){this.style.left="0px";},false);
box.addEventListener("mouseout",function(e){
if(self.pin) return;
var x=e.clientX,y=e.clientY,top=this.offsetTop,height=this.offsetHeight;
if((x>=playlistWidth||y<=top||y>=top+height)&&e.relatedTarget) this.style.left=4-playlistWidth+"px";
},true);
document.body.appendChild(box);
}
else if($("listbox")) listScrollTop=$("listbox").scrollTop;
box.innerHTML="";
box.style.backgroundColor=this.color;
var header=$n("p");
header.className="playlist-header";
header.style.margin="2px 10px 0px 10px";
header.style.fontSize="15px";
header.style.fontWeight="bold";
header.innerHTML="Playlist";
box.appendChild(header);
var conf=$n("span");
conf.style.marginLeft="10px";
conf.style.fontWeight="bold";
conf.style.color="#C9A9CC";
conf.innerHTML="Preference";
conf.style.cursor="pointer";
conf.addEventListener("click",function(){self.config();},false);
header.appendChild(conf);
var hr=$n("hr");
hr.style.margin="0px 10px 3px 10px";
box.appendChild(hr);
var div2=$n("div");
div2.style.margin="0px 10px";
div2.style.padding="0px";
div2.style.cssFloat="left";
box.appendChild(div2);
var modeSelect=$n("select");
modeSelect.style.fontWeight="bold";
modeSelect.style.border="solid 1px #888";
modeSelect.title="編集モード";
var selectDefinition=[
{caption:"Delete",color:"red",value:"del"},
{caption:"Move",color:"blue",value:"move"},
{caption:"Reverse",color:"gray",value:"rev"},
{caption:"Rename",color:"#804000",value:"rename"}
];
for(var i=0; i<selectDefinition.length; i++){
var def=selectDefinition[i];
var opt=$n("option");
opt.value=def.value;
opt.innerHTML=def.caption;
opt.style.color=def.color;
if(def.value==this.mark){
opt.selected=true;
modeSelect.style.color=def.color;
}
modeSelect.appendChild(opt);
}
modeSelect.addEventListener("change",function(){self.marker(this.value);},false);
div2.appendChild(modeSelect);
if(this.playlist.videos.length>0){
var count=$n("span");
count.className="font10";
count.style.verticalAlign="middle";
count.style.marginLeft="7px";
count.style.padding="2px 3px 1px 3px";
count.style.border="solid 1px #888";
count.style.fontWeight="bold";
count.style.backgroundColor="white";
count.innerHTML=this.playlist.videos.length+" items";
div2.appendChild(count);
}
var changerDiv=$n("div");
changerDiv.style.margin="0px 10px 0px 0px";
changerDiv.style.padding="0px";
changerDiv.style.cssFloat="right";
box.appendChild(changerDiv);
var listSelect=$n("select");
listSelect.style.fontWeight="bold";
listSelect.style.border="solid 1px #888";
var playlist_all=PlayList.all();
playlist_all.push("new","delete","duplicate","rename");
for(var i=0,len=playlist_all.length; i<len; i++){
var opt=$n("option");
opt.value=(i<len-4)? playlist_all[i]:"_"+playlist_all[i];
opt.innerHTML=unescape(playlist_all[i]);
if(playlist_all[i]==this.playlist.id){
var selectValue=opt.value;
opt.selected=true;
}
switch(opt.value){
case "_new":opt.style.color="green"; break;
case "_delete":opt.style.color="red"; break;
case "_duplicate":opt.style.color="#886BFD"; break;
case "_rename":opt.style.color="#804000"; break;
}
listSelect.appendChild(opt);
}
listSelect.addEventListener("change",function(){
var ret,value=this.value,id=unescape(self.playlist.id),indicate="Please enter playlist name to ";
this.value=selectValue;
if(value=="_new"){
this.style.color="green";
var title=location.href.match(URL.MYLIST)? document.getElementsByTagName("h1")[0].innerHTML:"playlist ("+(PlayList.all().length+1)+")";
ret=prompt(indicate+"make it.",title);
(!ret||ret==null||ret=="")? self.update():self.change(escape(ret));
}
else if(value=="_delete"){
this.style.color="red";
ret=confirm("Do you want to delete \""+id+"\"?");
if(ret){
PlayList.del(self.playlist.id);
self.change(PlayList.all()[0]? PlayList.all()[0]:"default");
}
else self.update();
}
else if(value=="_duplicate"||value=="_rename"){
var val=value.slice(1);
this.style.color=(val=="duplicate")? "#886BFD":"#804000";
ret=prompt(indicate+val+" it.",id+" copy");
if(!ret||ret==null||ret==""||(val=="rename"&&ret==id)) self.update();
else if(PlayList.checker(escape(ret))){
var c=confirm("\""+ret+"\" already exists.\n\tDo you want to replace it?");
c? self[val](escape(ret)):self.update();
}
else self[val](escape(ret));
}
else self.change(value);
},false);
changerDiv.appendChild(listSelect);
if(listSelect.offsetWidth>200) listSelect.style.width="200px";
var buttons=$n("div");
buttons.style.margin="0px 10px 4px 10px";
buttons.style.padding="3px 0px 0px 0px";
buttons.style.color="#000000";
buttons.style.clear="both";
var empty=(this.playlist.videos.length==0);
var undo=(this.buffer.n==this.buffer.playlist.length||this.buffer.playlist.length==0);
var redo=(this.buffer.n==0);
var btnDef=[
{caption:"add marked",title:"マークした動画を追加",click:function(){self.pushMarkedVideos();}},
{caption:"add all",title:"ページ内の動画を追加",click:function(){self.pushAllVideos();}},
{caption:"next",title:"再生",click:function(){
if(typeof player!="undefined") player.hide();
self.playNext();
},disabled:empty},
{caption:"clear",title:"全て削除",click:function(){self.clear();},disabled:empty},
{caption:"undo",title:"戻る",click:function(){self.track(true);},disabled:undo},
{caption:"redo",title:"進む",click:function(){self.track(false);},disabled:redo},
{caption:"copy",title:"プレイリスト内の動画をコピー",click:function(){
self.merge=[];
for(var i=0; i<self.playlist.videos.length; i++) self.merge.push(self.playlist.videos[i]);
this.nextSibling.disabled=false;
this.blur();
},disabled:empty},
{caption:"merge",title:"コピーした動画を追加",click:function(){
self.pushVideos(self.merge);
},disabled:!this.merge[0]},
{caption:"update",title:"更新",click:function(){self.change(GM_getValue("current"));}}
];
if(watchPage) btnDef.splice(0,1,{caption:"add this",title:"この動画を追加",click:function(){
self.pushThisVideo();
}});
for(var i=0; i<btnDef.length; i++){
var def=btnDef[i];
var btn=$n("input");
btn.type="button";
btn.value=def.caption;
btn.title=def.title;
btn.className="_submit";
btn.style.padding="1px";
if(def.click) btn.addEventListener("click",def.click,false);
if(def.disabled) btn.disabled="disabled";
buttons.appendChild(btn);
}
box.appendChild(buttons);
var listbox=$n("div");
listbox.style.margin="0px 10px";
listbox.style.padding="0px";
listbox.style.border="1px solid #999";
listbox.style.height="200px";
listbox.style.backgroundColor="#FFF";
box.appendChild(listbox);
var list=$n("ul");
list.id="listbox";
list.className="font12";
list.style.listStyleType="none";
list.style.margin="0px";
list.style.padding="0px";
list.style.width="100%";
list.style.height="100%";
list.style.overflow="auto";
listbox.appendChild(list);
for(var i=0,len=this.playlist.videos.length; i<len; i++){
var v=this.playlist.videos[i];
var item=$n("li");
item.style.padding="2px 5px 2px 0px";
item.style.whiteSpace="nowrap";
var linkDef=[
{caption:"del",title:"左クリック:削除,右クリック:範囲削除",color:"red",click:function(index){
self.remove(index);
},context:function(index,e){
self.remove(index,e.type);
}},
{caption:"move",title:"移動",color:"blue",click:function(index){self.move(index);}},
{caption:"rev",title:"反転",color:"gray",click:function(index){self.reverse(index);}},
{caption:"rename",title:"リネーム",color:"#804000",click:function(index){
var ret=prompt("Please enter new video title.",self.playlist.videos[index].title);
if(ret){
self.playlist.videos[index].title=ret;
self.playlist.save();
}
self.update();
}}
];
for(var n=0; n<linkDef.length; n++){
var def=linkDef[n];
var a=$n("a");
a.href="javascript:void(0);";
a.innerHTML="\u2756";
a.title=def.title;
a.className=def.caption;
a.style.color=def.color;
a.style.display=(self.mark==def.caption)? "inline":"none";
if(def.click) a.addEventListener("click",(function(f,index){
return function(){f(index);};
})(def.click,i),false);
if(def.context) a.addEventListener("contextmenu",(function(f,index){
return function(e){
e.preventDefault();
e.stopPropagation();
f(index,e);
};
})(def.context,i),true);
item.appendChild(a);
}
var anchor=$n("a");
anchor.href=v.getPlayUri();
anchor.innerHTML=v.title;
anchor.className="video noadd";
anchor.style.marginLeft="5px";
anchor.style.textDecoration="none";
item.appendChild(anchor);
if(v.title==v.id||v.title==v.id+"low"||v.title.slice(-3)=="..."){
anchor.href="javascript:void(0);";
anchor.title="titleを取得";
anchor.className+=" fetch";
anchor.style.color="#A1FE9E";
anchor.addEventListener("click",(function(index){
return function(){self.fetch(index);};
})(i),false);
}
list.appendChild(item);
}
if(listScrollTop>0) list.scrollTop=listScrollTop;
var checkboxes=$n("div");
checkboxes.className="font10";
checkboxes.style.margin="5px 8px 6px 0px";
checkboxes.style.textAlign="right";
checkboxes.style.cssFloat="right";
var checkDef=[
{caption:"Eco",title:"強制エコノミー",init:"eco",click:function(){
self._state("eco",this.checked);
},checked:this.eco},
{caption:"Com",title:"コメント非表示",init:"com",click:function(){
self._state("com",this.checked);
},checked:this.com},
{caption:"Vol",title:"音量",init:"vol",click:function(){
self._state("vol",this.checked);
},checked:this.vol},
{caption:"Fit",title:"フルスクリーン",init:"fs",click:function(){
self._state("fs",this.checked);
},checked:this.fs},
{caption:"Ran",title:"ランダム",init:"random",click:function(){
self._state("random",this.checked);
},checked:this.random},
{caption:"Loop",title:"ループ",init:"loop",click:function(){
self._state("loop",this.checked);
},checked:this.loop},
{caption:"Cache",title:"キャッシュ削除",init:"cache",click:function(){
self._state("cache",this.checked);
if(player) player.state("cache",this.checked);
},checked:this.cache},
{caption:"Pause",title:"連続再生の停止",init:"pause",click:function(){
self.state("pause",this.checked);
},checked:this.pause},
{caption:"Pick",title:"リンク抽出",init:"pick",click:function(){
self.pick=this.checked;
},checked:this.pick}
];
if(!w.NicoCache) checkDef.splice(6,1);
for(var i=0, len=checkDef.length; i<len; i++){
var def=checkDef[i];
var chk=$n("input");
chk.id="playlist_check_"+def.init;
chk.type="checkbox";
chk.style.marginTop="0px";
chk.style.verticalAlign="middle";
if(def.click) chk.addEventListener("click",def.click,false);
if(def.disabled) chk.disabled="disabled";
if(def.checked) chk.checked="checked";
checkboxes.appendChild(chk);
var label=$n("label");
label.htmlFor=chk.id;
label.innerHTML=def.caption;
label.style.marginLeft="-2px";
label.style.marginRight="2px";
label.style.verticalAlign="middle";
label.style.border="none";
label.style.fontWeight="bold";
checkboxes.appendChild(label);
chk.title=label.title=def.title;
if(watchPage&&def.init=="vol"){
var vol=$n("span");
vol.className="font12";
vol.innerHTML="\u266A";
vol.title="音量を設定";
vol.style.cursor="pointer";
vol.addEventListener("click",function(){
if(player.getExt("getVolume")){
self._state("vl",player.node.ext_getVolume()|0);
player.driven.vol=true;
setTimeout(function(){vol.style.color="black";},2000);
this.style.color="red";
}
},true);
checkboxes.appendChild(vol);
}
}
box.appendChild(checkboxes);
}
};
var Player=function(){this.initialize.apply(this,arguments);};
Player.prototype={
initialize:function(){
this.driven={id:controller.playlist.id,vol:controller.vol,cache:controller.cache};
this.vl=GM_getValue("vl_"+controller.playlist.id,false);
this.node=document.getElementById("flvplayer");
var self=this;
w.addEventListener("beforeunload",function(){
self.hide();
if(w.NicoCache&&controller.continuity&&self.driven.cache) self.clearCache();
},true);
if(controller.extend||controller.continuity) this.ready();
},
bind:function(){
if(controller.vol) this.node.ext_setVolume(this.vl||this.defaultVol);
if(controller.fs) this.node.ext_setVideoSize("fit");
if(controller.com) this.node.ext_setCommentVisible(false);
},
ready:function(){
var self=this;
var timer=setInterval(function(){
if(!self.getExt("getLoadedRatio")) return;
if(self.node.ext_getLoadedRatio()>0&&self.getExt("getVolume")&&self.getExt("getVideoSize")&&self.getExt("isCommentVisible")){
clearInterval(timer);
if(controller.scroll!="184") self.scroll(controller.scroll);
self.defaultVol=self.node.ext_getVolume();
if(controller.continuity) self.bind();
if(!controller.auto) setTimeout(function(){self.node.ext_play(1);},controller.delay);
}
},250);
if(controller.continuity) this.observe();
},
observe:function(){
var self=this;
var timer=setInterval(function(){
if(!self.node||controller.pause) return;
else if(self.node.ext_getStatus()=="end"&&controller.playlist.id==self.driven.id){
clearInterval(timer);
if(controller.playlist.videos.length>0){
self.hide();
if(controller.continuity) controller.playNext();
}
}
},1000);
},
state:function(e,state){if(controller.playlist.id==this.driven.id) this.driven[e]=state;},
getExt:function(e){return (this.node&&typeof this.node["ext_"+e]!="undefined")? true:false;},
hide:function(){
if(this.driven.vol&&this.getExt("getVolume")){
if(this.node.ext_getStatus()=="playing") this.node.ext_play(0);
this.node.ext_setVolume(this.defaultVol);
}
this.node.style.display="none";
},
scroll:function(e){
var target=$x("//div[@id='video_controls']/../..")[0];
scrollBy(0,Util.getElementPosition(target)-document.documentElement.scrollTop-e);
},
clearCache:function(f){
var next=f? f:function(){};
var CacheProtect=(w.Video.isDeleted||w.Video.isMymemory||w.gm_CacheProtect)? true:false;
if(!CacheProtect) Util.xhr(URL.CACHE+"rm?"+w.Video.id,next());
else if(w.gm_removeEconomy) Util.xhr(URL.CACHE+"ajax_rm?"+w.Video.id+"low",Util.xhr(URL.CACHE+"ajax_rmtmp?"+w.Video.id+"low",next()));
}
};
var login=GM_getValue("login",false);
if(login&&location.href.indexOf("login_form")>-1){
if($x("//form[@id='login']")[0]&&$("mail").value!=""&&$("password").value!="") $("login").submit();
}
else if(login&&$x("//a[contains(normalize-space(@href),'login_form?')]")[0]){
location.href=$x("//a[contains(normalize-space(@href),'login_form?')]")[0].href;
}
else{
var continuity;
if(continuity=window.name.match(/ continuity:"(.*?)"/)){
continuity=continuity[1];
window.name=window.name.replace(/ continuity:".*?"/,"");
}
var playlistStyle=[
"#playlistController .font12{font-size:12px; line-height:1.375;}",
"#playlistController .font10{font-size:10px; line-height:1.25;}",
"#playlistController a.video{font-weight:bold;}",
"#playlistController a.video:link{color:#677;}",
"#playlistController a.video:visited{color:#233;}",
"#playlistController a.video:hover,a.video:active{color:#FFF; text-decoration:none; background:#455;}",
"#playlistController a.del,a.move,a.rev,a.rename{margin-left:5px; text-decoration:none; outline:none;",
"font-weight:bold; font-family:\"ヒラギノ角ゴ Pro W3\",\"メイリオ\",\"MS Pゴシック\",sans-serif;}",
"#playlistController a.video.noadd.fetch{color:#A1FE9E !important;}",
"#playlistController a.video.noadd.fetch:hover,a.video.noadd.fetch:active{",
"color:white !important; background:#A1FE9E !important;}",
"#playlistController input._submit{",
"background:#CCC url(http://res.nimg.jp/img/btn/bg_submit_01.gif) repeat-x; font-size:12px;",
"border-color:#CCC #999 #666; border-style:solid; border-width:1px; margin:0px; padding:2px 4px;}"
];
var altStyle=[];
if(chPage) altStyle=[
".playlist-header{padding:3px 0px;}",
"#playlistController input[type=\"checkbox\"]{margin-left:4px !important;}",
"#playlistController label{margin-left:2px !important;}"
];
else if(dicPage) altStyle=[
".playlist-header{padding:3px 0px;}",
"#playlistController p,#playlistController li{text-align:left;}"
];
for(var i=0; i<altStyle.length; i++) playlistStyle.push(altStyle[i]);
GM_addStyle(playlistStyle.join("\n"));
var playlist=new PlayList(continuity? continuity:GM_getValue("current","default"));
var controller=new PlayListController(playlist,!!continuity);
if(watchPage) var player=new Player();
w.gm_playlistController={
getName:function(){return unescape(controller.playlist.id);},
pushVideo:function(video,title,opt){setTimeout(function(){controller.pushVideo(video,title,opt);},0);},
pushVideos:function(videos){setTimeout(function(){controller.pushVideos(videos);},0);},
addParam:function(obj){
var ls=[];
for(var i in obj) ls.push(i+"="+obj[i]);
for(var i=0; i<ls.length; i++) if(controller.ls.indexOf(ls[i])==-1) controller.ls.push(ls[i]);
},
state:function(e,opt){
var id="playlist_check_"+e,check=(typeof opt=="undefined")? !$(id).checked:!!opt;
controller[e]=$(id).checked=check;
if(player&&e=="cache") player.state(e,check);
}
};
if(w.$key){
var keys=[
{code:78,f:function(){
if(controller.playlist.videos[0]){
if(player) player.hide();
setTimeout(function(){controller.playNext();},0);
}
},mod:"shift"},
{code:80,f:function(){w.gm_playlistController.state("pause");}},
{code:82,f:function(){
if(player.node) player.hide();
if(controller.continuity) window.name+=" continuity:\""+controller.playlist.id+"\"";
location.reload(true);
}},
{code:90,f:function(){
if(controller.pin) return;
var c=$("playlistController");
c.style.left=(c.style.left=="0px")? 4-playlistWidth+"px":"0px";
}}
];
w.$key.unshift("down",keys);
}
}
