您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
動画クリックで一時停止/再開 ダブルクリックでフルスクリーン切換え
当前为
// ==UserScript== // @name Nicorenizer // @namespace https://github.com/segabito/ // @description 動画クリックで一時停止/再開 ダブルクリックでフルスクリーン切換え // @include http://www.nicovideo.jp/watch/* // @version 0.1.7 // @grant none // ==/UserScript== // TODO: // ダブルクリック時にフルスクリーンにする設定を無効・ブラウザ全体・モニター全体から選べるようにする // ver 0.1.2 // - Watch It Laterと併用時、動画選択画面でのダブルクリックでフルスクリーンにならないのを修正 // ver 0.1.0 最初のバージョン (function() { var monkey = (function(){ 'use strict'; if (!window.WatchApp || !window.WatchJsApi) { return; } window.Nicorenizer = {}; window.WatchApp.mixin(window.Nicorenizer, { initialize: function() { this._watchInfoModel = require('watchapp/model/WatchInfoModel').getInstance();//window.WatchApp.ns.init.CommonModelInitializer.watchInfoModel; var PlayerInitializer = require('watchapp/init/PlayerInitializer'); this._playerAreaConnector = PlayerInitializer.playerAreaConnector; this._nicoPlayerConnector = PlayerInitializer.nicoPlayerConnector; this._playerScreenMode = PlayerInitializer.playerScreenMode; this._videoExplorer = require('watchapp/init/VideoExplorerInitializer').videoExplorer; this._vastStatus = this._nicoPlayerConnector.vastStatus; this.initializeUserConfig(); this.initializeSettingPanel(); this.initializeShield(); this.initializePlayerApp(); this.initializeCss(); }, addStyle: function(styles, id) { var elm = document.createElement('style'); elm.type = 'text/css'; if (id) { elm.id = id; } var text = styles.toString(); text = document.createTextNode(text); elm.appendChild(text); var head = document.getElementsByTagName('head'); head = head[0]; head.appendChild(elm); return elm; }, initializeCss: function() { var __css__ = (function() {/* #nicorenaiShield { display: none; position: absolute; top: 0; left: 0; right: 0; bottom: 85px; z-index: 9950; cursor: none; } #nicorenaiShield.disable, #nicorenaiShield.vast, #nicorenaiShield.disableTemp { display: none !important; } #nicorenaiShield.debug { background: red; opacity: 0.5; } #nicorenaiShield.initialized { display: block; } #nicorenaiShield.showCursor { cursor: crosshair; {* 現在有効である事をわかりやすくするためにcrosshair。本当はオリジナルのカーソルを用意したいところ *} } body.setting_panel #nicorenaiShield, body.videoErrorOccurred #nicorenaiShield, body.setting_panel #nicorenaiShield, body.videoErrorOccurred #nicorenaiShieldToggle { display: none; } body.videoExplorer #content:not(.w_adjusted) #nicorenaiShield { {* 動画選択画面ではクリックで解除させるために邪魔なので消す *} {* ただしWatch It Lterの検索モードでは有効にする *} display: none; } #nicorenaiShieldToggle { position: absolute; z-index: 9951; top: 10px; left: 10px; border-color: blue; opacity: 0; cursor: pointer; transition: opacity 0.5s ease; padding: 4px 8px; } #nicorenaiShieldToggle.disable, #nicorenaiShieldToggle.disableTemp { border-color: black; } #nicorenaiShieldToggle.debug { opacity: 1 !important; } #nicorenaiShieldToggle.initialized:hover, #nicorenaiShieldToggle.show, #nicorenaiShieldToggle.disableTemp { opacity: 1; transition: none; } #nicorenaiShieldToggle:after { content: ':ON'; } #nicorenaiShieldToggle.disable:after, #nicorenaiShieldToggle.disableTemp:after { content: ':OFF'; } #nicorenizerSettingPanel { position: fixed; bottom: 2000px; right: 8px; z-index: -1; width: 500px; background: #f0f0f0; border: 1px solid black; padding: 8px; transition: bottom 0.4s ease-out; } #nicorenizerSettingPanel.open { display: block; bottom: 8px; box-shadow: 0 0 8px black; z-index: 10000; } #nicorenizerSettingPanel .close { position: absolute; cursor: pointer; right: 8px; top: 8px; } #nicorenizerSettingPanel .panelInner { background: #fff; border: 1px inset; padding: 8px; min-height: 300px; overflow-y: scroll; max-height: 500px; } #nicorenizerSettingPanel .panelInner .item { border-bottom: 1px dotted #888; margin-bottom: 8px; padding-bottom: 8px; } #nicorenizerSettingPanel .panelInner .item:hover { background: #eef; } #nicorenizerSettingPanel .windowTitle { font-size: 150%; } #nicorenizerSettingPanel .itemTitle { } #nicorenizerSettingPanel label { } #nicorenizerSettingPanel small { color: #666; } #nicorenizerSettingPanel .expert { margin: 32px 0 16px; font-size: 150%; background: #ccc; } {* Chromeの不具合対策 *} body.full_with_browser { width: 100%; } */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1].replace(/\{\*/g, '/*').replace(/\*\}/g, '*/'); this.addStyle(__css__, 'NicorenizerCss'); }, initializeUserConfig: function() { var prefix = 'Nicorenizer_'; var conf = { fullScreenType: 'browser', // none, browser, monitor togglePlay: true }; this.config = { get: function(key) { try { if (window.localStorage.hasOwnProperty(prefix + key)) { return JSON.parse(window.localStorage.getItem(prefix + key)); } return conf[key]; } catch (e) { return conf[key]; } }, set: function(key, value) { window.localStorage.setItem(prefix + key, JSON.stringify(value)); } }; }, initializeSettingPanel: function() { var $menu = $('<li class="nicorenizerSettingMenu"><a href="javascript:;" title="Nicorenizerの設定変更">Nicorenizer設定</a></li>'); var $panel = $('<div id="nicorenizerSettingPanel" />');//.addClass('open'); var $button = $('<button class="toggleSetting playerBottomButton">設定</botton>'); $button.on('click', function(e) { e.stopPropagation(); e.preventDefault(); $panel.toggleClass('open'); }); var config = this.config; $menu.find('a').on('click', function() { $panel.toggleClass('open'); }); var __tpl__ = (function() {/* <div class="panelHeader"> <h1 class="windowTitle">Nicorenizerの設定</h1> <button class="close" title="閉じる">×</button> </div> <div class="panelInner"> <div class="item" data-setting-name="togglePlay" data-menu-type="radio"> <h3 class="itemTitle">画面クリックで一時停止/再生</h3> <label><input type="radio" value="true" >する</label> <label><input type="radio" value="false">しない</label> </div> <div class="item" data-setting-name="fullScreenType" data-menu-type="radio"> <h3 class="itemTitle">ダブルクリック時のフルスクリーン</h3> <label><input type="radio" value=""browser"" >ブラウザ全体</label> <label><input type="radio" value=""monitor"">モニター全体</label> <label><input type="radio" value=""none"">切り換えない</label> </div> </div> */}).toString().match(/[^]*\/\*([^]*)\*\/\}$/)[1].replace(/\{\*/g, '/*').replace(/\*\}/g, '*/'); $panel.html(__tpl__); $panel.find('.item').on('click', function(e) { var $this = $(this); var settingName = $this.attr('data-setting-name'); var value = JSON.parse($this.find('input:checked').val()); console.log('seting-name', settingName, 'value', value); config.set(settingName, value); }).each(function(e) { var $this = $(this); var settingName = $this.attr('data-setting-name'); var value = config.get(settingName); $this.addClass(settingName); $this.find('input').attr('name', settingName).val([JSON.stringify(value)]); }); $panel.find('.close').click(function() { $panel.removeClass('open'); }); $('#playerAlignmentArea').append($button); $('#siteHeaderRightMenuFix').after($menu); $('body').append($panel); }, initializeShield: function() { var nicoPlayerConnector = this._nicoPlayerConnector; var playerAreaConnector = this._playerAreaConnector; var playerScreenMode = this._playerScreenMode; var videoExplorer = this._videoExplorer; var nicoPlayer = $("#external_nicoplayer")[0]; var $shield = $('<div id="nicorenaiShield"></div>'); var $toggle = $('<button id="nicorenaiShieldToggle">シールド</botton>'); var config = this.config; var FullScreen = { now: function() { if (document.fullScreenElement || document.mozFullScreen || document.webkitIsFullScreen) { return true; } return false; }, request: function(target) { var elm = typeof target === 'string' ? document.getElementById(target) : target; if (!elm) { return; } if (elm.requestFullScreen) { elm.requestFullScreen(); } else if (elm.webkitRequestFullScreen) { elm.webkitRequestFullScreen(); } else if (elm.mozRequestFullScreen) { elm.mozRequestFullScreen(); } }, cancel: function() { if (!this.now()) { return; } if (document.cancelFullScreen) { document.cancelFullScreen(); } else if (document.webkitCancelFullScreen) { document.webkitCancelFullScreen(); } else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); } } }; var toggleMonitorFull = function(v) { var now = FullScreen.now(); if (now || v === false) { FullScreen.cancel(); } else if (!now || v === true) { FullScreen.request(document.body); } }; var lastScreenMode = ''; var onScreenModeChange = function(sc) { var mode = sc.mode; if (lastScreenMode === 'browserFull' && mode !== 'browserFull') { toggleMonitorFull(false); } lastScreenMode = mode; }; playerScreenMode.addEventListener('change', onScreenModeChange); var click = function(e) { // TODO: YouTubeみたいに中央に停止/再生マーク出す? if (e.button !== 0) { return; } if (!config.get('togglePlay')) { return; } //var $shield = $(this).addClass('showCursor'); var status = nicoPlayer.ext_getStatus(); if (status === 'playing') { nicoPlayerConnector.stopVideo(); } else { nicoPlayerConnector.playVideo(); } }; var dblclick = function(e) { if (e.button !== 0) return; e.preventDefault(); e.stopPropagation(); var fullScreenType = config.get('fullScreenType'); if (fullScreenType === 'none') { return; } if (videoExplorer.isOpen()) { videoExplorer.changeState(false); if (fullScreenType === 'monitor') { window.WatchJsApi.player.changePlayerScreenMode('browserFull'); toggleMonitorFull(true); } else { window.WatchJsApi.player.changePlayerScreenMode('browserFull'); } } else if ($('body').hasClass('full_with_browser')) { window.WatchJsApi.player.changePlayerScreenMode('notFull'); toggleMonitorFull(false); } else { if (fullScreenType === 'monitor') { window.WatchJsApi.player.changePlayerScreenMode('browserFull'); toggleMonitorFull(true); } else { window.WatchJsApi.player.changePlayerScreenMode('browserFull'); } } }; var cursorHideTimer = null; var mousemove = function() { $shield.addClass('showCursor'); if (cursorHideTimer) { window.clearTimeout(cursorHideTimer); cursorHideTimer = null; } cursorHideTimer = window.setTimeout(function() { $shield.off('mousemove', mousemove); $shield.removeClass('showCursor'); window.setTimeout(function() { $shield.on('mousemove', mousemove); }, 500); }, 3000); }; var mousedown = function(e) { if (e.button === 0) return; // 左ボタン以外でクリックされたら5秒間だけシールドを解除するよ e.preventDefault(); e.stopPropagation(); $shield.addClass('disableTemp'); $toggle.addClass('disableTemp'); $toggle .css('opacity', 1) .animate({'opacity': 0.3}, 5000, function() { $toggle.css('opacity', ''); }); window.setTimeout(function() { $toggle.removeClass('disableTemp'); $shield.removeClass('disableTemp'); $toggle.css('opacity', ''); }, 5000); }; var toggleDisable = function(f, showButtonTemporary) { var isDisable = $toggle.toggleClass('disable', f).hasClass('disable'); $shield.toggleClass('disable', isDisable); if (showButtonTemporary) { // 状態が変わった事を通知するために一時的に表示する $toggle.addClass('show'); window.setTimeout(function() { $toggle.removeClass('show'); }, 2000); } }; // 最初に再生開始されるまでは表示しない。 ローカルストレージ~が出たときにクリックできるようにするため。 // でも自動再生にしてると詰む。 playerAreaConnector.addEventListener( 'onVideoStarted', function() { $shield.addClass('initialized'); $toggle.addClass('initialized'); toggleDisable(false); } ); // 再生後メニューがクリックできないのも困るので無効化する playerAreaConnector.addEventListener( 'onVideoEnded', function() { toggleDisable(true, true); } ); playerAreaConnector.addEventListener( 'onVideoSeeked', function(vpos, b, c) { // もう一度再生する場合など if (parseInt(vpos, 10) === 0) toggleDisable(false); } ); $shield .on('click' , click) .on('dblclick', dblclick) .on('mousedown', mousedown) .on('mousemove', mousemove); $toggle .attr('title', 'クリックで無効化ON/OFF') .on('click', toggleDisable); var vastStatus = this._vastStatus; vastStatus.addEventListener('linearStart', function() { $shield.addClass('vast'); }); vastStatus.addEventListener('linearEnd', function() { $shield.removeClass('vast'); }); $('#external_nicoplayer').after($shield).after($toggle); }, initializePlayerApp: function() { // 実装が漏れててエラーが出てるっぽいのを修正 // フルスクリーン時に動画プレイヤー以外にフォーカスがある時に出る var np = window.PlayerApp.ns.player.Nicoplayer.getInstance(); var ep = $('#external_nicoplayer')[0]; if (!np.ext_getVolume) { np.ext_getVolume = function() { return ep.ext_getVolume(); }; } if (!np.ext_setVolume) { np.ext_setVolume = function(v) { ep.ext_setVolume(v); }; } if (!np.ext_getStatus) { np.ext_getStatus = function() { return ep.ext_getStatus(); }; } } }); if (window.PlayerApp) { (function() { var watchInfoModel = WatchApp.ns.model.WatchInfoModel.getInstance(); if (watchInfoModel.initialized) { window.Nicorenizer.initialize(); } else { var onReset = function() { watchInfoModel.removeEventListener('reset', onReset); window.setTimeout(function() { watchInfoModel.removeEventListener('reset', onReset); window.Nicorenizer.initialize(); }, 0); }; watchInfoModel.addEventListener('reset', onReset); } })(); } }); var script = document.createElement("script"); script.id = "NicorenizerLoader"; script.setAttribute("type", "text/javascript"); script.setAttribute("charset", "UTF-8"); script.appendChild(document.createTextNode("(" + monkey + ")()")); document.body.appendChild(script); })();