# nlフィルタ定義(文字コード判定用なのでこの行は削除しないこと)
#original 20170602
#modified 20170603 js部の再実装, スライダーのスナップ, リセットボタン, 位置変更 by ◆2TK8xdazzp3d
#modified 20170603 スタイル最適化、ボタン追加等 by ◆awd5z.AlOFJq
#modified 20170603 CurrentTimeSeeker追加、wrapperをドラッグで移動可能に by ◆awd5z.AlOFJq
#modified 20170603 パネルの開閉, ボタンをコンパクト化, スナップをオプトイン化, 微修正 by ◆2TK8xdazzp3d
#modified 20170605 Fine-Grained Volume Controller追加 by ◆awd5z.AlOFJq
#modified 20170605 音量プログレスバーとシークバー及びシークバーハンドルを追従させる機能を試験的に追加（まだ動きません） by ◆awd5z.AlOFJq
#modified 20170607 デフォルトで非表示、ミニモード追加 by ◆awd5z.AlOFJq

# 注意1: 導入・除去にはwatchページのハード再読み込みが必要
#		大抵のモダンブラウザでは Ctrl + F5 でディスクキャッシュを上書きしつつ再読み込みする
# 注意2: 公式プレイヤーが動かなくなる可能性あり(ソースコードを無理やり書き換えているため)
# 注意3: 0.50,0.75,1.00,1.25,...へのスナップは「スナップを有効化するにはこのコメントアウトを解除」
#        部分を書き換えると有効になる(Chromeでのみ動作)

[Script]
Name = Playbackrate Changer[HTML5]
URL = www\.nicovideo\.jp\/watch\/
Require = 'html5';
Append<
window.addEventListener("load", function(){
"use strict";
const
	// 動画を切り替えた時にvideoが再生成されるので
	// videoの親要素を監視してvideoタグが作られたら再生速度を設定
	VideoContainerObserver = function(VideoContainer) {
		var
			F1 = function (mutation) {
				var video = VideoContainer[0].getElementsByTagName("video");
				if (video[0]) {
					video[0].playbackRate = +document.getElementById("pce-speed").value;
					return true;
				}
			},
			observer = new MutationObserver(F1);
		F1(); // 最初からvideoタグが存在する場合のために最初に一度走らせる
		observer.observe(VideoContainer[0], {childList: true});
	},
	setup = function() {
		var VideoContainer = document.getElementsByClassName("VideoContainer");
		if (VideoContainer[0] == null) return;
		
		var speed = document.getElementById("pce-speed");
		var output = document.getElementById("pce-value");
		// スライダーを動かした時の処理
		var speedChangedHandler = function() {
			var rate = +speed.value;
			output.innerText = rate;
			
			var video = document.getElementsByTagName("video");
			if (video[0]) video[0].playbackRate = rate;
		};
		//CurrentTimeをシークする処理
		//SeekBarとSeekBarHandleを追従させる機能も追加
		var currentTimeChangedHandler = function(HandedTime) {
			var video = document.getElementsByTagName("video");
			var SeekBar = document.getElementsByClassName("SeekBar-played");
			var Handle = document.getElementsByClassName("SeekBarHandle");
			if (video[0]) {
					video[0].currentTime = parseFloat(video[0].currentTime) + parseFloat(HandedTime);
					var s = parseFloat ( HandedTime / video[0].duration );
					SeekBar[0].style.transform = "scaleX( s )";
					var tX = parseFloat ( - ( HandedTime / video[0].duration ) );
					Handle[0].style.transform = "translateX( tX )";
					video[0].pause();
			}
		};
		speed.addEventListener('input', speedChangedHandler);
		
		// 初期値設定
		speed.value = 1.00;
		output.innerText = 1;
		
		// Resetボタンを押した時はスライダーを等速へ動かしたことにする
		// PlaybackRate Changer
		document.getElementById("pce-reset").addEventListener("click", function() {
			speed.value = 1.00;
			speedChangedHandler();
		});
		
		document.getElementById("pce-plus-0.01").addEventListener("click", function() {
			speed.value = parseFloat(speed.value) + parseFloat(0.01);
			speedChangedHandler();
		});
		
		document.getElementById("pce-plus-0.1").addEventListener("click", function() {
			speed.value = parseFloat(speed.value) + parseFloat(0.10);
			speedChangedHandler();
		});
		
		document.getElementById("pce-plus-1").addEventListener("click", function() {
			speed.value = parseFloat(speed.value) + parseFloat(1.00);
			speedChangedHandler();
		});
		
		document.getElementById("pce-minus-0.01").addEventListener("click", function() {
			speed.value -= 0.01;
			speedChangedHandler();
		});
		
		document.getElementById("pce-minus-0.1").addEventListener("click", function() {
			speed.value -= 0.10;
			speedChangedHandler();
		});
		
		document.getElementById("pce-minus-1").addEventListener("click", function() {
			speed.value -= 1.00;
			speedChangedHandler();
		});
		document.getElementById("pce-set-0.25").addEventListener("click", function() {
			speed.value = parseFloat(0.25);
			speedChangedHandler();
		});
		document.getElementById("pce-set-0.32").addEventListener("click", function() {
			speed.value = parseFloat(0.32);
			speedChangedHandler();
		});
		document.getElementById("pce-set-0.50").addEventListener("click", function() {
			speed.value = parseFloat(0.50);
			speedChangedHandler();
		});
		document.getElementById("pce-set-0.75").addEventListener("click", function() {
			speed.value = parseFloat(0.75);
			speedChangedHandler();
		});
		document.getElementById("pce-set-1.20").addEventListener("click", function() {
			speed.value = parseFloat(1.20);
			speedChangedHandler();
		});
		document.getElementById("pce-set-1.50").addEventListener("click", function() {
			speed.value = parseFloat(1.50);
			speedChangedHandler();
		});
		document.getElementById("pce-set-1.70").addEventListener("click", function() {
			speed.value = parseFloat(1.70);
			speedChangedHandler();
		});
		
		//Current Time Seeker
		document.getElementById("ct-plus-0.1").addEventListener("click", function() {
			currentTimeChangedHandler(0.10);
		});
		document.getElementById("ct-plus-1").addEventListener("click", function() {
			currentTimeChangedHandler(1.00);
		});
		document.getElementById("ct-plus-3").addEventListener("click", function() {
			currentTimeChangedHandler(3.00);
		});
		document.getElementById("ct-plus-5").addEventListener("click", function() {
			currentTimeChangedHandler(5.00);
		});
		document.getElementById("ct-minus-0.1").addEventListener("click", function() {
			currentTimeChangedHandler(-0.10);
		});
		document.getElementById("ct-minus-1").addEventListener("click", function() {
			currentTimeChangedHandler(-1.00);
		});
		document.getElementById("ct-minus-3").addEventListener("click", function() {
			currentTimeChangedHandler(-3.00);
		});
		document.getElementById("ct-minus-5").addEventListener("click", function() {
			currentTimeChangedHandler(-5.00);
		});
		document.getElementById("ct-reset").addEventListener("click", function() {
			var video = document.getElementsByTagName("video");
			if (video[0]) {
				video[0].pause();
				video[0].play();
			}
		});
		
		//Fine-Grained Volume Controller
		//Volume Progress Barを追従させる機能とか
		document.getElementById("fgvc-set-0.01").addEventListener("click", function() {
			var video = document.getElementsByTagName("video");
			var Vbar = document.querySelector(".VolumeBarContainer > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1)");
				Vbar.style.transform = "scaleX ( parseFloat ( video[0].volume - 0.01 ) )";
				video[0].volume = parseFloat(0.01);
		});
		
		document.getElementById("fgvc-plus-0.01").addEventListener("click", function() {
			var video = document.getElementsByTagName("video");
			var Vbar = document.querySelector(".VolumeBarContainer > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1)");
				Vbar.style.transform = "scaleX ( parseFloat ( video[0].volume - 0.01 ) )";
				video[0].volume = parseFloat(video[0].volume) + parseFloat(0.01);
		});
		
		document.getElementById("fgvc-minus-0.01").addEventListener("click", function() {
			var video = document.getElementsByTagName("video");
			var Vbar = document.querySelector(".VolumeBarContainer > div:nth-child(1) > div:nth-child(1) > div:nth-child(1) > div:nth-child(1)");
				Vbar.style.transform = "scaleX ( parseFloat ( video[0].volume - 0.01 ) )";
				video[0].volume = parseFloat(video[0].volume) - parseFloat(0.01);
		});
		
		// ウィンドウサイズ再計算
		var resizeWindow = function() {
			var pceWrapper = document.getElementById("pce-wrapper");
			var terminator = document.getElementById("pce-wrapper-terminator");
			pceWrapper.style.height = (terminator.offsetTop +
				pceWrapper.offsetHeight - pceWrapper.clientHeight) + "px";
		};
		resizeWindow();
		
		// 開閉処理
		
		document.getElementById("pce-wrapper-container-open").addEventListener("click", function() {
			var pwcContainer = document.getElementById("pce-wrapper-container");
			var wppContainer = document.getElementById("pce-wrapper");
			if (pwcContainer.style.display != "none") {
				pwcContainer.style.display = "none";
				wppContainer.style.borderWidth = "0px";
				wppContainer.style.width = "22px";
				wppContainer.style.height = "22px";
				this.style.backgroundColor = "Orchid";
				this.value = "▽";
			} else {
				pwcContainer.style.display = "block";
				wppContainer.style.borderWidth = "2px";
				wppContainer.style.width = "380px";
				wppContainer.style.height = "260px";
				this.style.backgroundColor = "initial";
				this.value = "△ Mini Mode Toggle △";
			}
			resizeWindow();
		});
		document.getElementById("pce-open").addEventListener("click", function() {
			var pceContainer = document.getElementById("pce-container");
			if (pceContainer.style.display != "none") {
				pceContainer.style.display = "none";
				this.value = "▽";
			} else {
				pceContainer.style.display = "block";
				this.value = "△";
			}
			resizeWindow();
		});
		document.getElementById("ct-open").addEventListener("click", function() {
			var ctContainer = document.getElementById("ct-container");
			if (ctContainer.style.display != "none") {
				ctContainer.style.display = "none";
				this.value = "▽";
			} else {
				ctContainer.style.display = "block";
				this.value = "△";
			}
			resizeWindow();
		});
		
		document.getElementById("fgvc-open").addEventListener("click", function() {
			var fgvcContainer = document.getElementById("fgvc-container");
			if (fgvcContainer.style.display != "none") {
				fgvcContainer.style.display = "none";
				this.value = "▽";
			} else {
				fgvcContainer.style.display = "block";
				this.value = "△";
			}
			resizeWindow();
		});
		
		
		//Currently not working functions
		/*
		document.getElementById("pce-open").addEventListener("click", closer("pce-open") );
		document.getElementById("ct-open").addEventListener("click", closer("ct-open") );
		document.getElementById("fgvc-open").addEventListener("click", closer("fgvc-open") );
		
		function closer(docID){
			var eContainer = document.getElementById( docID );
			if (eContainer.style.display != "none") {
				eContainer.style.display = "none";
				eContainer.value = "▽";
			} else {
				eContainer.style.display = "block";
				eContainer.value = "△";
			}
			resizeWindow();
		};
		*/
		
		// videoの親要素を監視開始
		VideoContainerObserver(VideoContainer);
	};
setup();

});
>

[Replace]
Name = Kill official playbackRate controller[HTML5]
URL = [^/]+.nimg.jp/(?:web/)?scripts/pages/watch/watch_(?:app|dll).js
Multi = TRUE
Match<
playbackRate
>
Replace<
pbR_
>

[Replace]
Name = Pl-Ch-Elem-draggable with Styles
URL = www\.nicovideo\.jp\/watch\/
Require = 'html5';
Match<
<\/head>
>
Replace<
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script>
\$(function() {
        //id:pce-wrapperをdrag可能に
    \$("#pce-wrapper").draggable();
});
</script>
<style>
#pce-wrapper::before{
display:block;
position:absolute;
top:0;bottom:0;left:0;right:0;
background:white;
filter: blur(7px);
opacity: .9;
content:' ';
z-index: -1;
}
#pce-wrapper{
position:absolute;
z-index: 10000; /*siteHeader.css line84 override*/
right:1px;
bottom:30px;
width: 380px;
height: 260px;
border-style: solid;
border-width: 2px;
border-color: lightblue;
padding: 3px;
}
#pce-wrapper input[type="button"]{
padding: 3px;
border-style: outset;
border-width: 1px;
border-color: black;
}
.pce-fixed-size {
width: 47px
}
#pce-value{
margin-left: 47%
}
#pce-header input[type="button"], #ct-header input[type="button"],#fgvc-header input[type="button"]{
font-size: 9px;
}
#pce-title, #ct-title,#fgvc-title{
font-weight: bold;
font-size: 11pt;
}
#pce-speed{
width: 100%;
}
#pce-wrapper input[type="button"]:active{
border-style: inset;
}
#ct-header , #fgvc-header{
margin-top: 5px;
}
#ct-container,#fgvc-container{
margin-top: 10px;
}
@-moz-document url-prefix() {
	#ct-minus-0\.1{
	width: 57px
	}
}
@media screen and (-webkit-min-device-pixel-ratio:0){
	#ct-minus-0\.1{
	width: 48px
	}
}
</style>
</head> 
>

[Replace]
Name = Pl-Ch-Elem[HTML5]
URL = www\.nicovideo\.jp\/watch\/
Require = 'html5';
Match<
</body>
>
Replace<
<!-- Playbackrate-Changer-Element(pce) -->
<div id="pce-wrapper">
<input id="pce-wrapper-container-open" type="button" value="△ Mini Mode Toggle △">
<div id="pce-wrapper-container">
<div id="pce-header">
<input id="pce-open" type="button" value="▽">
<span id="pce-title">Playbackrate Changer</span>
</div>
<div id="pce-container" style="display: none;">
<div>
<input id="pce-speed" type="range" min="0.25" max="5" step="0.01" value="1" list="pce-speed-list">
</div>
<datalist id="pce-speed-list">
<!-- スナップを有効化するにはこのコメントアウトを解除
<option value="0.50">
<option value="0.75">
<option value="1.00">
<option value="1.25">
<option value="1.50">
<option value="2.00">
<option value="3.00">
-->
</datalist>
<div id="pce-value">
1
</div>
<input id="pce-minus-0.01" type="button" class="pce-fixed-size" value="-0.01">
<input id="pce-minus-0.1" type="button" class="pce-fixed-size" value="-0.1">
<input id="pce-minus-1" type="button" class="pce-fixed-size" value="-1">
<input id="pce-reset" type="button" class="pce-fixed-size" value="reset">
<input id="pce-plus-1" type="button" class="pce-fixed-size" value="+1">
<input id="pce-plus-0.1" type="button" class="pce-fixed-size" value="+0.1">
<input id="pce-plus-0.01" type="button" class="pce-fixed-size" value="+0.01"><br>
<input id="pce-set-0.25" type="button" class="pce-fixed-size" value="x0.25">
<input id="pce-set-0.32" type="button" class="pce-fixed-size" value="x0.32">
<input id="pce-set-0.50" type="button" class="pce-fixed-size" value="x0.50">
<input id="pce-set-0.75" type="button" class="pce-fixed-size" value="x0.75">
<input id="pce-set-1.20" type="button" class="pce-fixed-size" value="x1.20">
<input id="pce-set-1.50" type="button" class="pce-fixed-size" value="x1.50">
<input id="pce-set-1.70" type="button" class="pce-fixed-size" value="x1.70">
</div>
<div id="ct-header">
<input id="ct-open" type="button" value="▽">
<span id="ct-title">
Current Time Seeker
</span>
</div>
<div id="ct-container" style="display: none;">
<input id="ct-plus-0.1" type="button" value="+0.1(s)">
<input id="ct-plus-1" type="button" class="pce-fixed-size" value="+1(s)">
<input id="ct-plus-3" type="button" class="pce-fixed-size" value="+3(s)">
<input id="ct-plus-5" type="button" class="pce-fixed-size" value="+5(s)"><br>
<input id="ct-minus-0.1" type="button" value="-0.1(s)">
<input id="ct-minus-1" type="button" class="pce-fixed-size" value="-1(s)">
<input id="ct-minus-3" type="button" class="pce-fixed-size" value="-3(s)">
<input id="ct-minus-5" type="button" class="pce-fixed-size" value="-5(s)">
<input id="ct-reset" type="button" value="reset and play">
</div>
<div id="fgvc-header">
<input id="fgvc-open" type="button" value="▽">
<span id="fgvc-title">
Fine-Grained Volume Controller
</span>
</div>
<div id="fgvc-container" style="display: none;">
<input id="fgvc-set-0.01" type="button" value="set to minimum">
<input id="fgvc-plus-0.01" type="button" class="pce-fixed-size" value="+0.01">
<input id="fgvc-minus-0.01" type="button" class="pce-fixed-size" value="-0.01">
</div>
<div id="pce-wrapper-terminator">
<!-- pce-wrapperの最後に配置して空にしておくこと 高さ計算に使用 -->
</div>
</div>
</div>
<!-- pce -->
</body>
>

