Greasy Fork is available in English.

[Typing-Tube]試聴再生を追加

try to take over the world!

// ==UserScript==
// @name         [Typing-Tube]試聴再生を追加
// @namespace    http://tampermonkey.net/
// @version      4.1
// @description  try to take over the world!
// @author       You
// @include      https://typing-tube.net*
// @exclude      https://typing-tube.net/movie/*

// ==/UserScript==
let resize_dom

let demo_player_html = document.createElement('div');
demo_player_html.setAttribute("id", "player_demo");

const tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";

const firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);


const transparent_cover = document.createElement('div');
transparent_cover.setAttribute("id", "transparent_cover");

const loading_html = document.createElement('span');
loading_html.setAttribute("id", "loading_logo");
loading_html.setAttribute("class", "loader");

const speed_Fixed = [0.25,0.5,0.75,1.00,1.25,1.5,1.75,2]



class PreviewDemoVideo {

	constructro(){
		this.fixedSpeed
		this.player
		this.humenID = 0
		this.hoverID = 0
		this.startTime = 0
		this.previewTime = 0
		this.imgHeight = 0
		this.imgWidth = 0
		this.userNameSelector

	}

	addEvent(){
		this.Event = this.setPreviewVideo.bind(this)
		window.addEventListener('keyup',this.Event);
	}


	setPreviewVideo(event){

		if(event.key == "Shift"){

			if(this.hoverID && this.hoverID != this.humenID){

				this.humenID = this.hoverID

				$.ajax({

					type: 'POST',
					url: '/movie/lyrics/' + previewDemoVideo.humenID,

					success:function(data){

						const dataSplit = data.split("\n")

						previewDemoVideo.startTime = -1
						previewDemoVideo.fixedSpeed = dataSplit[0].match(/^【\d?\.?\d?\d倍速】/)

						if(previewDemoVideo.fixedSpeed){
							previewDemoVideo.fixedSpeed = parseFloat(previewDemoVideo.fixedSpeed[0].slice(1))

							if(!speed_Fixed.includes(previewDemoVideo.fixedSpeed)){
								previewDemoVideo.fixedSpeed = false
							}

						}

						for(let i=0;i<dataSplit.length;i++){

							if(i>0){

								if(previewDemoVideo.startTime == -1 && dataSplit[i].split("\t")[2]){
									previewDemoVideo.startTime = Math.floor(+dataSplit[i].split("\t")[0])
									previewDemoVideo.previewTime = +dataSplit[i].split("\t")[0]
								}else if(dataSplit[i].split("\t")[0].substr( -5, 1 ) == "."){
									previewDemoVideo.startTime = Math.floor(+dataSplit[i].split("\t")[0])
									previewDemoVideo.previewTime = +dataSplit[i].split("\t")[0]
									break;
								}

							}

						}

						deleteVideo()

						if(mouseEvent.timeLineFlag && !mouseEvent.userTimeLineFlag){
							transparent_cover.setAttribute("style", "left: 0;right: 0;margin: auto;");
						}else{
							demo_player_html.setAttribute("style", "opacity: 0;");
							transparent_cover.setAttribute("style", "z-index:1;");
						}

						previewDemoVideo.onYouTubeIframeAPIReady(data.match(/(v=).*\n/)[0].slice(2))
					}
				});

			}
		}
	}

	onYouTubeIframeAPIReady(preview_videoid) {

		if(mouseEvent.tdFlag){
			PreviewDemoVideo.imgHeight = 60
			PreviewDemoVideo.imgWidth = 90
			document.getElementsByTagName('section')[0].insertAdjacentHTML('beforebegin', `<div id="player_demo" style="opacity: 0;"></div>`)
			document.getElementById("player_demo").parentNode.insertBefore(transparent_cover, document.getElementById("player_demo"));
			document.getElementById("transparent_cover").appendChild(loading_html);
			document.getElementById("loading_logo").style.top = "42px"
			document.getElementById("loading_logo").style.left = "88%"

			if(mouseEvent.tdFlag.classList[0] == "mt-5"){
				const elements = [].slice.call( document.querySelectorAll("li.mt-5") );

				// 要素の順番を取得
				if(elements.indexOf( mouseEvent.tdFlag )){
					document.getElementById("player_demo").classList.add('mt-5');
					document.getElementById("transparent_cover").classList.add('mt-5');
				}
			}

			demo_player_html.setAttribute("style", "position:absolute;opacity: 0;");
			document.getElementById("transparent_cover").setAttribute("style", "z-index:1;");
			transparent_cover.style.height = (PreviewDemoVideo.imgHeight)+"px"
			transparent_cover.style.width = (PreviewDemoVideo.imgWidth)+"px"

		}else if(mouseEvent.imgSelector){
			PreviewDemoVideo.imgHeight = mouseEvent.imgSelector.height
			PreviewDemoVideo.imgWidth = mouseEvent.imgSelector.width

			if(mouseEvent.timeLineFlag && !mouseEvent.userTimeLineFlag){
				mouseEvent.imgSelector.parentNode.classList.add('col-12');
				PreviewDemoVideo.userNameSelector = mouseEvent.imgSelector.parentNode.querySelector(".username")
				transparent_cover.style.top = (parseInt(getComputedStyle( PreviewDemoVideo.userNameSelector, null ).marginBottom)+PreviewDemoVideo.userNameSelector.offsetHeight)+"px"
			}

			transparent_cover.style.height = (PreviewDemoVideo.imgHeight)+"px"
			transparent_cover.style.width = (PreviewDemoVideo.imgWidth)+"px"

			if(previewDemoVideo.hoverID){
				transparent_cover.setAttribute("href", "https://typing-tube.net/movie/show/"+previewDemoVideo.humenID);
			}

			mouseEvent.imgSelector.parentNode.insertBefore(demo_player_html, mouseEvent.imgSelector);
			mouseEvent.imgSelector.parentNode.insertBefore(transparent_cover, mouseEvent.imgSelector);
			document.getElementById("transparent_cover").appendChild(loading_html);


			document.getElementById("loading_logo").style.top = ""
			document.getElementById("loading_logo").style.left = ""
			document.getElementById("transparent_cover").addEventListener("mousedown",mouseEvent.mouseDownEvent)
			demo_player_html = document.getElementById("player_demo").cloneNode(true)
			resize_dom = mouseEvent.imgSelector.parentNode.querySelector("img[src*='i.ytimg.com']")

		}

		this.player = new YT.Player('player_demo', {
			height: PreviewDemoVideo.imgHeight ,
			width: PreviewDemoVideo.imgWidth ,
			playerVars: {
				autoplay: 1,
				disablekb: 1,
				modestbranding:1,
				origin: location.protocol + '//' + location.hostname + "/",
				start: previewDemoVideo.startTime
			},
			videoId: preview_videoid,
			events: {
				'onReady': previewDemoVideo.onPlayerReady,
				'onStateChange': previewDemoVideo.onPlayerStateChange

			}
		});
	}


	onPlayerReady(event) {
		previewDemoVideo.player.setVolume(+document.getElementById("volume_control").value)
		window.addEventListener('keydown',escapeKeyDownEvent);
		previewDemoVideo.player.seekTo(previewDemoVideo.previewTime - 0.07)

	}


	onPlayerStateChange(event) {

			switch(event.data){
				case 0: //終了(最後まで再生した)
					deleteVideo();
					break;
				case 1://再生(player.playVideo)

					if(previewDemoVideo.fixedSpeed){
						previewDemoVideo.player.setPlaybackRate(previewDemoVideo.fixedSpeed);
					}

					document.getElementById("player_demo").style.opacity = 1
					break;
			}

	}



}


let previewDemoVideo = new PreviewDemoVideo()
previewDemoVideo.addEvent()



class MouseEvent {

	constructor(){
		this.tdFlag = false
		this.timeLineFlag = false
		this.userTimeLineFlag = false
		this.imgSelector
	}


	addEvent(){
		this.overEvent = this.mouseOverEvent.bind(this)
		this.outEvent = this.mouseOutEvent.bind(this)
		this.downEvent = this.mouseDownEvent.bind(this)

		let humenLink = document.querySelectorAll("[href*='movie/show/']")

		for(let n = 0; n < humenLink.length ; n++){
			humenLink[n].addEventListener("mouseout",this.outEvent)
			humenLink[n].addEventListener("mousedown",this.downEvent)
		}

		window.addEventListener("mouseover",this.overEvent)
	}

	mouseOverEvent(event) {
		const hoverLink = event.target.closest("[href*='movie/show/']")?event.target.closest("[href*='movie/show/']"):event.target.closest("[href*='edit?']")

		if(hoverLink){

			if(hoverLink.href){
				this.imgSelector = this.getImg()

				if(hoverLink.closest("[style*='i.ytimg.com']")){
					this.tdFlag = hoverLink.closest("[style*='i.ytimg.com']")
				}else if(hoverLink.querySelector("[style*='i.ytimg.com']")){
					this.tdFlag = hoverLink.querySelector("[style*='i.ytimg.com']")
				}else{
					this.tdFlag = false
				}

				previewDemoVideo.hoverID = hoverLink.href.match(/[0-9]+\.?[0-9]*/g)[0]
			}

		}
	}


	mouseOutEvent(event) {
		this.imgSelector = false
		this.tdFlag = false
		previewDemoVideo.hoverID = previewDemoVideo.humenID
	}


	mouseDownEvent(event){

		if(event.shiftKey || event.ctrlKey || event.button == 2){
			previewDemoVideo.humenID = 0
			previewDemoVideo.hoverID = 0
			deleteVideo()
		}

	}


	getImg(){
		const find_selector_word = ["timeline","mt-3","col"]

		for(let i=0;i<find_selector_word.length;i++){

			if(event.target.closest("[class*="+find_selector_word[i]+"]") && event.target.closest("[class*="+find_selector_word[i]+"]").querySelector("img[src*='i.ytimg.com']")){

				if(find_selector_word[i] == "timeline" && location.href.match("user")){
					this.timeLineFlag = true
					this.userTimeLineFlag = true
				}else if(find_selector_word[i] == "timeline"){
					this.timeLineFlag = true
					this.userTimeLineFlag = false
				}else{
					this.timeLineFlag = false
					this.userTimeLineFlag = false
				}

				return event.target.closest("[class*="+find_selector_word[i]+"]").querySelector("img[src*='i.ytimg.com']")
			}
		}
		return false
	}

}

let mouseEvent = new MouseEvent()
mouseEvent.addEvent()


function escapeKeyDownEvent(event){

	if(event.key == "Escape"){
		deleteVideo()
		previewDemoVideo.humenID = 0

		if(!mouseEvent.imgSelector){
			previewDemoVideo.hoverID = 0
		}

		window.removeEventListener('keydown',escapeKeyDownEvent,true);
	}

}

function deleteVideo(){

	if(previewDemoVideo.player){

		if(resize_dom){
			resize_dom.style.opacity = 1
			resize_dom = 0
		}

		if(document.getElementById("loading_logo") != null){
			document.getElementById("loading_logo").remove()
		}

		if(document.getElementById("player_demo") != null){
			document.getElementById("player_demo").remove()
		}

		previewDemoVideo.player = false
	}

}


window.addEventListener( 'resize', function() {

	if(resize_dom && document.getElementById("player_demo") != null && PreviewDemoVideo.imgHeight != 60){
		PreviewDemoVideo.imgHeight = resize_dom.height
		PreviewDemoVideo.imgWidth = resize_dom.width
		document.getElementById("transparent_cover").style.height = PreviewDemoVideo.imgHeight+"px"
		document.getElementById("transparent_cover").style.width = PreviewDemoVideo.imgWidth+"px"
		document.getElementById("player_demo").setAttribute("height",PreviewDemoVideo.imgHeight)
		document.getElementById("player_demo").setAttribute("width",PreviewDemoVideo.imgWidth)

		if(mouseEvent.timeLineFlag && !mouseEvent.userTimeLineFlag){
				document.getElementById("player_demo").style.top = (parseInt(getComputedStyle( PreviewDemoVideo.userNameSelector, null ).marginBottom)+PreviewDemoVideo.userNameSelector.offsetHeight)+"px"
				document.getElementById("transparent_cover").style.top = (parseInt(getComputedStyle( PreviewDemoVideo.userNameSelector, null ).marginBottom)+PreviewDemoVideo.userNameSelector.offsetHeight)+"px"
		}

	}
});


(function addDom () {
	const set_selector = document.getElementsByClassName("level_image")[0] != null ? document.getElementsByClassName("level_image")[0] : document.getElementById("main_content")
	set_selector.insertAdjacentHTML('afterbegin', `<div id="demo_play_container" style="
    display: flex;
margin-top: 25px;
margin-left: 30px;
"><label id="volume_control_area" style="
    display: flex;
justify-content: flex-end;
    position: relative;
    align-items: baseline;
    margin-right: 42px;
    "><span style="/* position:absolute; */"><span style="
    position: absolute;
    z-index: -1;
    top: -22px;
    /* left: 3px; */
    color: #FFFFFF88;
">Volume</span><input type="range" id="volume_control" value="70" step="1" max="100"><span style="margin-left: 10px;    position: absolute;
    top: 5px;"><span id="volume" style="
    background: #00000088;
    padding: 3px;
    border: solid thin;
    border-radius: 5px;
    position: absolute;
    top: -10px;
    min-width: 25px;
    text-align: center;
">`+localStorage.getItem("volume_storage")+`</span></span></span></label>
<span style="
    display: flex;
    flex-direction: column;
    position: relative;
    top: -13px;
    margin-left: 25px;
    background: #111111b5;
    padding: 3px 7px 2px 7px;
    border-radius: 11px;
"><span>再生したい動画にカーソルを合わせてShiftキー:再生</span><span>再生中にEscapeキー:停止</span></span></div>
<style>
#volume_control {
  -webkit-appearance: none;
  width: 11rem;
  background: transparent;
}

#volume_control:focus {
  outline: none;
}

#volume_control::-webkit-slider-runnable-track {
  height: 1.5rem;
  margin: 0;
  width: 100%;
  cursor: pointer;
  background: #464646;
  background: linear-gradient(
    to bottom right,
    transparent 50%,
    #000000bb 50%
  );
}

#volume_control::-moz-range-track {
  height: 1.5rem;
  margin: 0;
  width: 100%;
  cursor: pointer;
  background: #464646;
  background: linear-gradient(
    to bottom right,
    transparent 50%,
     #000000bb 50%
  );
}


#volume_control::-webkit-slider-thumb {
  -webkit-appearance: none;
  height: 1.9rem;
  width: 0.5rem;
  background: #ffffff;
  border: 1px solid;
  margin-top: -3px;
  border-radius: 3px;
  cursor: pointer;
}



#volume_control::-moz-range-thumb {
  -webkit-appearance: none;
  height: 1.9rem;
  width: 0.5rem;
  background: #ffffff;
  border: 1px solid;
  border-radius: 3px;
  cursor: pointer;
  margin-top: 0;
}

#volume_control:focus::-moz-range-thumb {
  box-shadow: 0px 0px 7px 3px #0065c4;
}
#transparent_cover{
position:absolute;
cursor:pointer;
}
#player_demo{
    position: fixed;
    z-index: 103;
    width: 355px;
    height: 200px;
    bottom: 30px;
    right: 17px;
}
.loader,
.loader:before,
.loader:after {
  background: #ffffff;
  -webkit-animation: load1 1s infinite ease-in-out;
  animation: load1 1s infinite ease-in-out;
  width: 1em;
  height: 4em;
}
.loader {
left: 95%;
    top: -20px;
  color: #ffffff;
  text-indent: -9999em;
  z-index:1;
  position: absolute;
  font-size: 3px;
  -webkit-transform: translateZ(0);
  -ms-transform: translateZ(0);
  transform: translateZ(0);
  -webkit-animation-delay: -0.16s;
  animation-delay: -0.16s;
}
.loader:before,
.loader:after {
  position: absolute;
  top: 0;
  content: '';
}
.loader:before {
  left: -1.5em;
  -webkit-animation-delay: -0.32s;
  animation-delay: -0.32s;
}
.loader:after {
  left: 1.5em;
}


[href*="/movie/show/"] img:hover{
outline:solid thin #ffffff50;
}
@-webkit-keyframes load1 {
  0%,
  80%,
  100% {
    box-shadow: 0 0;
    height: 4em;
  }
  40% {
    box-shadow: 0 -2em;
    height: 5em;
  }
}
@keyframes load1 {
  0%,
  80%,
  100% {
    box-shadow: 0 0;
    height: 4em;
  }
  40% {
    box-shadow: 0 -2em;
    height: 5em;
  }
}

</style>`)
	document.getElementById("volume_control").addEventListener("input", video_volume_change);
	document.getElementById("volume_control").setAttribute("value",localStorage.getItem('volume_storage'))

})();


function video_volume_change(){

	if(document.getElementById("player_demo") != null){
		previewDemoVideo.player.setVolume(+document.getElementById("volume_control").value)
	}

	localStorage.setItem('volume_storage',document.getElementById("volume_control").value)
	document.getElementById("volume").textContent = document.getElementById("volume_control").value;
}