- // ==UserScript==
- // @name Youtube Repeat button
- // @namespace
- // @version 0.1.6
- // @description Youtube動画プレイヤーにリピートボタンをつける(html5プレイヤーのみ動作)
- // @author Nobby
- // @include https://youtube.com/*
- // @include https://www.youtube.com/*
- // @grant GM_setValue
- // @grant GM_getValue
- // ==/UserScript==
-
- (function(){
- var addRepeatButton = function(){
- var player = document.getElementsByClassName('html5-video-player')[0];
- var video = document.querySelector('video');
- var repeat = GM_getValue('rpt',false);
- var control = document.getElementsByClassName('ytp-chrome-controls')[0];
- var yrb = document.createElement('button');
- var title = 'リピート';
- yrb.setAttribute('class', 'ytp-button ytp-repeat-button');
- yrb.setAttribute('style', 'float:right;');
-
- var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
- svg.setAttribute('width', '100%');
- svg.setAttribute('height', '100%');
- svg.setAttribute('viewBox', '-128 -128 768 768');
-
- var defs = document.createElementNS('http://www.w3.org/2000/svg', 'defs');
-
- var from = 'M363 363v0h0v0h0v0l0-0 0-0v0h0zM149 149v0h0v0h0v0l0 0-0 0v0h0zM469 256l-85 85v-64H64v-42h320v-64l85 85z';
- var to = 'M363 363v-86h42v128H149v64l-85-85 85-85v64h214zM149 149v86h-42V107h256V43l85 85-85 85v-64H149zM256 256l-0 0v-0H256v-0h0v-0l0 0z';
-
- if(repeat){
- from = [to, to = from][0];
- video.setAttribute('loop', '');
- title = 'リピート解除';
- }
- yrb.setAttribute('title', title);
-
- var path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
- path.setAttribute('id', 'ytp-repeat');
- path.setAttribute('d', from);
-
- var animate = document.createElementNS('http://www.w3.org/2000/svg', 'animate');
- animate.setAttribute('attributeType', 'XML');
- animate.setAttribute('attributeName', 'd');
- animate.setAttribute('fill', 'freeze');
- animate.setAttribute('dur', '0.2s');
- animate.setAttribute('keySplines', '.4 0 1 1');
- animate.setAttribute('repeatCount', '1');
- animate.setAttribute('begin', 'indefinite');
-
- var use1 = document.createElementNS('http://www.w3.org/2000/svg', 'use');
- use1.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#ytp-repeat');
- use1.setAttribute('class', 'ytp-svg-shadow');
-
- var use2 = document.createElementNS('http://www.w3.org/2000/svg', 'use');
- use2.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '#ytp-repeat');
- use2.setAttribute('class', 'ytp-svg-fill');
-
- path.appendChild(animate);
- defs.appendChild(path);
- svg.appendChild(defs);
- svg.appendChild(use1);
- svg.appendChild(use2);
- yrb.appendChild(svg);
-
- control.appendChild(yrb);
-
- var tooltext = document.getElementsByClassName('ytp-tooltip-text')[0];
- var tooltip = tooltext.parentNode.parentNode;
-
- var delay = null;
-
- yrb.addEventListener('mouseover', function(){
- yrb.removeAttribute('title');
- tooltip.setAttribute('aria-hidden', 'true');
- tooltip.setAttribute('class', 'ytp-tooltip ytp-bottom');
- delay = setTimeout(function() {
- tooltip.style.display = '';
- tooltext.textContent = title;
- var parentRect = player.getBoundingClientRect();
- var childRect = yrb.getBoundingClientRect();
- var tipRect = tooltip.getBoundingClientRect();
- var x_left = childRect.left - parentRect.left + (childRect.width - tipRect.width)/2;
- tooltip.setAttribute('style', 'left:'+x_left+'px');
- tooltip.removeAttribute('aria-hidden');
- }, 500);
- }, false);
-
- yrb.addEventListener('mouseleave', function(){
- clearTimeout(delay);
- tooltip.style.display = 'none';
- tooltip.setAttribute('aria-hidden', 'true');
- yrb.setAttribute('title', title);
- }, false);
-
- yrb.addEventListener('click', function(){
- if(repeat){
- video.removeAttribute('loop');
- title = 'リピート';
- }else{
- video.setAttribute('loop', '');
- title = 'リピート解除';
- }
- repeat = !repeat;
- tooltext.textContent = title;
- var parentRect = player.getBoundingClientRect();
- var childRect = yrb.getBoundingClientRect();
- var tipRect = tooltip.getBoundingClientRect();
- var x_left = childRect.left - parentRect.left + (childRect.width - tipRect.width)/2;
- tooltip.setAttribute('style', 'left:'+x_left+'px');
- setTimeout(function() {
- animate.setAttribute('from', from);
- animate.setAttribute('to', to);
- animate.beginElement();
- path.setAttribute('d', to);
- from = [to, to = from][0];
- }, 50);
- }, false);
-
- window.onbeforeunload = function(){
- GM_setValue('rpt',repeat);
- };
- };
-
- var observer = new MutationObserver(function(mutations){
- if(location.href.match(/youtube\.com\/(?:watch|embed)/)){
- addRepeatButton();
- observer.disconnect();
- }
- });
-
- var target = document.body;
- observer.observe(target, {childList:true});
- })();