您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hugely improves load speed of pages with lots of embedded Youtube videos by instantly showing clickable and immediately accessible placeholders, then the thumbnails are loaded in background. A fast simple HTML5 direct playback (720p max) can be selected if available for the video.
当前为
// ==UserScript== // @name FYTE /Fast YouTube Embedded/ Player // @description Hugely improves load speed of pages with lots of embedded Youtube videos by instantly showing clickable and immediately accessible placeholders, then the thumbnails are loaded in background. A fast simple HTML5 direct playback (720p max) can be selected if available for the video. // @description:ru На порядок ускоряет время загрузки страниц с большим количеством вставленных Youtube-видео. С первого момента загрузки страницы появляются заглушки для видео, которые можно щелкнуть для загрузки плеера, и почти сразу же появляются кавер-картинки с названием видео. В опциях можно включить режим использования упрощенного браузерного плеера (макс. 720p). // @version 2.5.7 // @include * // @exclude https://www.youtube.com/* // @author wOxxOm // @namespace wOxxOm.scripts // @license MIT License // @grant GM_getValue // @grant GM_setValue // @grant GM_addStyle // @grant GM_xmlhttpRequest // @connect www.youtube.com // @connect youtube.com // @run-at document-start // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACABAMAAAAxEHz4AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAwUExURUxpcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJuxkb8AAAAPdFJOUwDvH0biMvjOZFW6pxJ6kh7r3iMAAAPDSURBVGje7ZlNaBNBFMeXhNDWpkKgFg9iYlBB6SGwiPQkftaCYATjTaRKiwi1xVaKXpqTpHhosR66p4pQhb209CQGbSweK/TiRYwfFy+NkWBM2pR2nHm73abJzuceRMj/kEzSvl92Z9689+atpjXUUEMN1WgpoRupbH41nTbNUaxzlkIhe0C+M810Ov8zmzL0RGeNeeDThUEkof72N/Fqe/8LJK07sR173yJS0EbEATxFSurZtm9DilqxAV9VAZuWfbPbLBOFqtSBP9f/WxIAV2Bc6H5owiKPG7p+IpFIRG11LsPbEfyVrhvTqeyX1dfmaBiM9gFgjgwrTzJSfncMFq7s3EExJuu5/rHte3hPBvfkff84sbuEBxPkUiLygCC5hDV7CvpUtt81axICZBN9UwHsxYalOMxhIaIC8IVhFlvJtlALIWQl57Um/LquBpjBpkOwin1qADKLB7RD9moqiPz2TcAMqQGa4OI9Av5op/DrMzXAHmz6mw4IxEQA67AW825/bhngAVoBMEHzZD+aFQCsQUCkAAor/M2wCYAVdwCqxJmANgD8cmJjPQDt5wK22AD0nAVoBsAiE1BMcgAbAJikAqoTYP1CA4BEtBgdgC6yARUuAC3QI7sDiLMAxUk2YAwiIwNAn4YAhGU+YKcOqAUMCgJQziugHGMALmNAhANAWxkaoEgABS4ADdMyiyiglPMIcJ0GKQAayDAAGQEAuu8VUB/gJAH1AS4IgLAwAA24AAoygAeuAPFbqHPHoNwc1HuCJCDncRl7NG8At7Ak48qugVEGsOBxO7snB58T0ngASlwWjomFpMegOusxrFOLBCexsFMbvUzxCyVXRqEkBpjlpXdOgcEqFlsEKpRynFviMIus0md+kcUEDAuUeaxCcysjUGgySt1yTKTUZRTbOaFim17unxUr92doBw4f9zTKObGInZl+//NTW592VP3g+Q4Onh6Ovjfgt5vsPoSCJuDuPRz/58CFmhEtKPIEvY8kZAd3VxRxRJJSyIXcUu0/VOz3okITJRC2ex9kGdB5ecBVZLtgCyt70fUB2nGTTjOu/HFZohsXXLoOrbQKfDps1ePtTj9wSter2oGWoBnYRZqB+bQ5OnLaShpnrNAz6N6R7OW1I1HJjnmPVFuit7eDV1jNvuAkpJNqgJ0DQPCHiv3dqmULfJe3P7hrB/oej3T0S/Tme7tf1Xp/MArPB/Ayp82X5OlAaJfI8wHsJ2/zWXg6EGV4XXB5CbuN3mUYxnQKNI6HU9i3op0y3tpQQw39b/oLfDt0HcsiqWsAAAAASUVORK5CYII= // @compatible chrome // @compatible firefox // @compatible opera // ==/UserScript== /* jshint lastsemic:true, multistr:true, laxbreak:true, -W030, -W041, -W084 */ var resizeMode = GM_getValue('resize', 'Fit to width'); if (typeof resizeMode != 'string') resizeMode = resizeMode ? 'Fit to width' : 'Original'; var resizeWidth = GM_getValue('width', 1280) |0; var resizeHeight = GM_getValue('height', 720) |0; updateCustomSize(); var playDirectly = !!GM_getValue('playHTML5', false); var skipCustom = !!GM_getValue('skipCustom', true); var showStoryboard = !!GM_getValue('showStoryboard', true); var pinnable = GM_getValue('pinnable', 'on'); if (!/^(on|hide|off)$/.test(pinnable)) pinnable = !!pinnable ? 'on' : 'hide'; var _ = initTL(); var imageLoader = document.createElement('img'); var imageLoader2 = document.createElement('img'); var fytedom = document.getElementsByClassName('instant-youtube-container'); var iframes = document.getElementsByTagName('iframe'); var oembeds = document.getElementsByTagName('embed'); var persite = (function() { var rules = [ {host: /(^|\.)google\.\w{2,3}(\.\w{2,3})?$/, class:'g-blk', query: 'a[href*="youtube.com/watch"][data-ved]', eatparent: 1}, {host: 'pikabu.ru', class:'b-video', match: '[data-url*="youtube.com/embed"]', attr: 'data-url'}, {host: 'androidauthority.com', tag:'iframe', match: '[src*="youtube.com/embed"]', eatparent: '.video-container'}, {host: 'reddit.com', tag:'iframe', match: '[data-url*="youtube.com/"] [src*="/mediaembed"], [data-url*="youtu.be/"] [src*="/mediaembed"]', src: function(e) { return e.closest('[data-url*="youtube.com/"], [data-url*="youtu.be/"]').dataset.url }}, ]; for (var i=0, rule; (i<rules.length) && (rule=rules[i]); i++) { var rx = rule.host instanceof RegExp ? rule.host : new RegExp('(^|\\.)' + rule.host.replace(/\./g, '\\.') + '$', 'i'); if (rx.test(location.hostname)) return { nodes: rule.class ? document.getElementsByClassName(rule.class) : document.getElementsByTagName(rule.tag), match: rule.match ? function(e) { return e.matches(rule.match) ? e : null } : function(e) { return e.querySelector(rule.query) }, attr: rule.attr, src: rule.src, eatparent: rule.eatparent, }; } })(); findEmbeds(); injectStylesIfNeeded(); new MutationObserver(findEmbeds).observe(document, {subtree:true, childList:true}); document.addEventListener('DOMContentLoaded', function(e) { injectStylesIfNeeded(); adjustNodesIfNeeded(e); }); window.addEventListener('resize', adjustNodesIfNeeded, true); window.addEventListener('message', function(e) { if (e.data == 'iframe-allowfs') { $$('iframe:not([allowfullscreen])').some(function(iframe) { if (iframe.contentWindow == e.source) { iframe.allowFullscreen = true; return true; } }); if (window != window.top) window.parent.postMessage('iframe-allowfs', '*'); } }); function findEmbeds(mutations) { var i, len, e; if (mutations && mutations.length == 1 && !mutations[0].addedNodes.length) return; if (persite) for (i=0, len=persite.nodes.length; (i<len) && (e=persite.nodes[i]); i++) if (e = persite.match(e)) processEmbed(e, persite.src && persite.src(e) || e.getAttribute(persite.attr)); for (i=0, len=iframes.length; (i<len) && (e=iframes[i]); i++) if (/youtube\.com(\/|%2F)(embed|v)(\/|%2F)/i.test(e.src)) processEmbed(e); for (i=0, len=oembeds.length; (i<len) && (e=oembeds[i]); i++) if (/youtube\.com(\/|%2F)(embed|v)\//i.test(e.src)) processEmbed(e); } function processEmbed(node, src) { function decodeEmbedUrl(url) { return url.indexOf('youtube.com%2Fembed') > 0 ? decodeURIComponent(url.replace(/^.*?(http[^&?=]+?youtube.com%2Fembed[^&]+).*$/i, '$1')) : url; } src = src || node.src || node.href || ''; var n = node; var np = n.parentNode, npw; var srcFixed = decodeEmbedUrl(src).replace(/\/(watch\?v=|v\/)/, '/embed/'); if (src.indexOf('cdn.embedly.com/') > 0 || resizeMode != 'Original' && np && np.children.length == 1 && !np.className && !np.id) { n = location.hostname == 'disqus.com' ? np.parentNode : np; np = n.parentElement; } if (!np || !np.parentNode || skipCustom && srcFixed.indexOf('enablejsapi=1') > 0 || node.matches('.instant-youtube-embed, .YTLT-embed') || node.onload // skip some retarded loaders ) return; var id = srcFixed.match(/(?:embed\/|v[=\/]|youtu\.be\/)([^\s,.()\[\]?]+?)(?:[&?\/].*|$)/); if (!id) return; id = id[1]; var autoplay = srcFixed.indexOf('autoplay=1') > 0; if (np.localName == 'object') n = np, np = n.parentElement; var eatparent = persite && persite.eatparent || 0; if (typeof eatparent == 'string') n = np.closest(eatparent) || n, np = n.parentElement; else while (eatparent--) n = np, np = n.parentElement; injectStylesIfNeeded('force'); var div = document.createElement('div'); div.className = 'instant-youtube-container'; div.FYTE = { state: 'querying', srcEmbed: srcFixed.replace(/&$/, ''), videoID: id, originalWidth: /%/.test(node.width) ? 320 : node.width|0 || n.clientWidth|0, originalHeight: /%/.test(node.height) ? 200 : node.height|0 || n.clientHeight|0, }; div.FYTE.srcEmbedFixed = div.FYTE.srcEmbed.replace(/^http:/, 'https:').replace(/&?wmode=\w+/, '').replace(/[?&]feature=oembed/, ''); div.FYTE.srcWatchFixed = div.FYTE.srcEmbedFixed.replace(/\/embed\//, '/watch?v='); var divSize = calcContainerSize(div, n); var origStyle = getComputedStyle(n); div.style.cssText = important('background-color:transparent; transition:background-color 2s;' + (origStyle.hasOwnProperty('position') ? Object.keys(origStyle) : Object.keys(origStyle.__proto__) /*FF*/) .filter(function(k) { return !!k.match(/^(position|left|right|top|bottom)$/) }) .map(function(k) { return k + ':' + origStyle[k] }) .join(';') .replace(/\b[^;:]+:\s*(auto|static|block)\s*(!\s*important)?;/g, '') + (origStyle.display == 'inline' ? ';display:inline-block;width:100%' : '') + ';min-width:' + Math.min(divSize.w, div.FYTE.originalWidth) + 'px' + ';min-height:' + Math.min(divSize.h, div.FYTE.originalHeight) + 'px' + (resizeMode == 'Fit to width' ? ';width:100%' : '') + ';max-width:' + divSize.w + 'px; height:' + divSize.h + 'px;'); if (!autoplay) { setTimeout(function() { div.style.backgroundColor = '' }, 0); setTimeout(function() { div.style.transition = '' }, 2000); } // consume parents of retardedly positioned videos if (div.style.position.match('absolute|relative')) { if (np.children.length == 1 && floatPadding(np, getComputedStyle(np, ':after'), 'Top') >= div.FYTE.originalHeight) n = np, np = n.parentElement; div.style.cssText = div.style.cssText.replace(/\b(position|left|top|right|bottom):[^;]+/g, ''); } var wrapper = div.appendChild(document.createElement('div')); wrapper.className = 'instant-youtube-wrapper'; var img = wrapper.appendChild(document.createElement('img')); img.className = 'instant-youtube-thumbnail'; img.src = 'https://i.ytimg.com/vi/' + id + '/maxresdefault.jpg'; img.style.cssText = important('transition:opacity 0.1s ease-out; opacity:0; padding:0; margin:auto; position:absolute; left:0; right:0; top:0; bottom:0; max-width:none; max-height:none;'); img.title = _('Shift-click to use alternative player'); img.onload = function(e) { if (img.naturalWidth <= 120) return img.onerror(e); var fitToWidth = true; if (img.naturalHeight) { var ratio = img.naturalWidth / img.naturalHeight; if (ratio > 4.1/3 && ratio < divSize.w/divSize.h) { img.style.cssText += important('width:auto; height:100%;'); fitToWidth = false; } } if (fitToWidth) { img.style.cssText += important('width:100%; height:auto;'); } if (div.FYTE.videoWidth) fixThumbnailAR(div); if (!autoplay) img.style.opacity = 1; }; img.onerror = function(e) { if (img.src.indexOf('maxresdefault') > 0) img.src = img.src.replace('maxresdefault','hqdefault'); }; GM_xmlhttpRequest({ method: 'GET', url: 'https://www.youtube.com/get_video_info?video_id=' + div.FYTE.videoID + '&el=detailpage', headers: {'Accept-Encoding': 'gzip'}, context: div, onload: parseVideoInfo }); translateHTML(wrapper, 'beforeend', '\ <a class="instant-youtube-title" target="_blank" href="' + div.FYTE.srcWatchFixed + '"> </a>\ <svg class="instant-youtube-play-button"><path fill-rule="evenodd" clip-rule="evenodd" fill="#1F1F1F" class="ytp-large-play-button-svg" d="M84.15,26.4v6.35c0,2.833-0.15,5.967-0.45,9.4c-0.133,1.7-0.267,3.117-0.4,4.25l-0.15,0.95c-0.167,0.767-0.367,1.517-0.6,2.25c-0.667,2.367-1.533,4.083-2.6,5.15c-1.367,1.4-2.967,2.383-4.8,2.95c-0.633,0.2-1.316,0.333-2.05,0.4c-0.767,0.1-1.3,0.167-1.6,0.2c-4.9,0.367-11.283,0.617-19.15,0.75c-2.434,0.034-4.883,0.067-7.35,0.1h-2.95C38.417,59.117,34.5,59.067,30.3,59c-8.433-0.167-14.05-0.383-16.85-0.65c-0.067-0.033-0.667-0.117-1.8-0.25c-0.9-0.133-1.683-0.283-2.35-0.45c-2.066-0.533-3.783-1.5-5.15-2.9c-1.033-1.067-1.9-2.783-2.6-5.15C1.317,48.867,1.133,48.117,1,47.35L0.8,46.4c-0.133-1.133-0.267-2.55-0.4-4.25C0.133,38.717,0,35.583,0,32.75V26.4c0-2.833,0.133-5.95,0.4-9.35l0.4-4.25c0.167-0.966,0.417-2.05,0.75-3.25c0.7-2.333,1.567-4.033,2.6-5.1c1.367-1.434,2.967-2.434,4.8-3c0.633-0.167,1.333-0.3,2.1-0.4c0.4-0.066,0.917-0.133,1.55-0.2c4.9-0.333,11.283-0.567,19.15-0.7C35.65,0.05,39.083,0,42.05,0L45,0.05c2.467,0,4.933,0.034,7.4,0.1c7.833,0.133,14.2,0.367,19.1,0.7c0.3,0.033,0.833,0.1,1.6,0.2c0.733,0.1,1.417,0.233,2.05,0.4c1.833,0.566,3.434,1.566,4.8,3c1.066,1.066,1.933,2.767,2.6,5.1c0.367,1.2,0.617,2.284,0.75,3.25l0.4,4.25C84,20.45,84.15,23.567,84.15,26.4z M33.3,41.4L56,29.6L33.3,17.75V41.4z"></path><polygon fill-rule="evenodd" clip-rule="evenodd" fill="#FFFFFF" points="33.3,41.4 33.3,17.75 56,29.6"></polygon></svg>\ <span tl class="instant-youtube-link">' + (playDirectly ? 'Play with Youtube player' : 'Play directly (up to 720p)') + '</span>\ <div tl class="instant-youtube-options-button">Options</div>\ '); np.insertBefore(div, n); n.remove(); if (autoplay) return startPlaying(div); div.addEventListener('click', clickHandler); } function adjustNodesIfNeeded(e) { if (!fytedom[0]) return; if (adjustNodesIfNeeded.scheduled) clearTimeout(adjustNodesIfNeeded.scheduled); adjustNodesIfNeeded.scheduled = setTimeout(function() { adjustNodes(e); adjustNodesIfNeeded.scheduled = 0; }, 16); } function adjustNodes(e, clickedContainer) { var force = !!clickedContainer; var nearest = force ? clickedContainer : null; var vids = $$('.instant-youtube-container:not([pinned])'); if (!nearest && e.type != 'DOMContentLoaded') { var minDistance = window.innerHeight*3/4 |0; var nearTargetY = window.innerHeight/2; vids.forEach(function(n) { var bounds = n.getBoundingClientRect(); var distance = Math.abs((bounds.bottom + bounds.top)/2 - nearTargetY); if (distance < minDistance) { minDistance = distance; nearest = n; } }); } if (nearest) { var bounds = nearest.getBoundingClientRect(); var nearestCenterYpct = (bounds.top + bounds.bottom)/2 / window.innerHeight; } var resized = false; vids.forEach(function(n) { var size = calcContainerSize(n); var w = size.w, h = size.h; // prevent parent clipping for (var e=n.parentElement, style; e; e=e.parentElement) if (e.style.overflow != 'visible' && (style=getComputedStyle(e))) if ((style.overflow+style.overflowX+style.overflowY).match(/hidden|scroll/)) if (n.offsetTop < e.clientHeight / 2 && n.offsetTop + n.clientHeight > e.clientHeight) e.style.cssText = e.style.cssText.replace(/\boverflow(-[xy])?:[^;]+/g, '') + important('overflow:visible;overflow-x:visible;overflow-y:visible;'); if (force && Math.abs(w - parseFloat(n.style.maxWidth)) <= 2) return; if (n.style.maxWidth != w + 'px') n.style.maxWidth = w + 'px'; if (n.style.height != h + 'px') n.style.height = h + 'px'; if (parseFloat(n.style.minWidth) > w) n.style.minWidth = n.style.maxWidth; if (parseFloat(n.style.minHeight) > h) n.style.minHeight = n.style.height; fixThumbnailAR(n); resized = true; }); if (resized && nearest) setTimeout(function() { var bounds = nearest.getBoundingClientRect(); var h = bounds.bottom - bounds.top; var projectedCenterY = nearestCenterYpct * window.innerHeight; var projectedTop = projectedCenterY - h/2; var safeTop = Math.min(Math.max(0, projectedTop), window.innerHeight - h); window.scrollBy(0, bounds.top - safeTop); }, 16); } function calcContainerSize(div, origNode) { var w, h; origNode = origNode || div; switch (resizeMode) { case 'Original': w = div.FYTE.originalWidth; h = div.FYTE.originalHeight; break; case 'Custom': w = resizeWidth; h = resizeHeight; break; case '1080p': case '720p': case '480p': case '360p': h = parseInt(resizeMode); w = h / 9 * 16; break; default: // fit-to-width mode var n = origNode; do { n = n.parentElement; // find parent node with nonzero width (i.e. independent of our video element) } while (n && !(w = n.clientWidth)); if (w) h = w / 16 * 9; else { w = origNode.clientWidth; h = origNode.clientHeight; } } var np = origNode.parentElement; var style = getComputedStyle(np); var parentWidth = parseFloat(style.width) - floatPadding(np, style, 'Left') - floatPadding(np, style, 'Right'); if (parentWidth > 0 && parentWidth < w) { h = parentWidth / w * h; w = parentWidth; } if (resizeMode == 'Fit to width' && h < div.FYTE.originalHeight*0.9) h = Math.min(div.FYTE.originalHeight, w / div.FYTE.originalWidth * div.FYTE.originalHeight); return {w: window.chrome ? w : Math.round(w), h:h}; } function parseVideoInfo(response) { var div = response.context; var txt = response.responseText; var info = tryCatch(function() { return JSON.parse(txt.replace(/(\w+)=?(.*?)(&|$)/g, '"$1":"$2",').replace(/^(.+?),?$/, '{$1}')) }) || {}; var videoSources = []; // parse width & height to adjust the thumbnail var m = decodeURIComponent(info.adaptive_fmts || '').match(/size=(\d+)x(\d+)\b/) || decodeURIComponent(txt).match(/\/(\d+)x(\d+)\//); if (m) fixThumbnailAR(div, m[1]|0, m[2]|0); // parse video sources if (info.url_encoded_fmt_stream_map && info.fmt_list) { var streams = {}; decodeURIComponent(info.url_encoded_fmt_stream_map).split(',').forEach(function(stream) { var params = {}; stream.split('&').forEach(function(kv) { params[kv.split('=')[0]] = decodeURIComponent(kv.split('=')[1]); }); streams[params.itag] = params; }); decodeURIComponent(info.fmt_list).split(',').forEach(function(fmt) { var itag = fmt.split('/')[0]; var dimensions = fmt.split('/')[1]; var stream = streams[itag]; if (stream) { videoSources.push({ src: stream.url, title: stream.quality + ', ' + dimensions + ', ' + stream.type }); } }); } else { var rx = /url=([^=]+?mime%3Dvideo%252F(?:mp4|webm)[^=]+?)(?:,quality|,itag|.u0026)/g; var text = decodeURIComponent(txt).split('url_encoded_fmt_stream_map')[1]; while (m = rx.exec(text)) { videoSources.push({ src: decodeURIComponent(decodeURIComponent(m[1])) }); } } var duration = div.FYTE.duration = info.length_seconds|0 || ''; if (duration) { var d = new Date(null); d.setSeconds(duration); duration = d.toISOString().replace(/^.+?T[0:]{0,4}(.+?)\..+$/, '<span>$1</span>'); } var title = decodeURIComponent(info.title || info.reason || '').replace(/\+/g, ' '); if (title || duration) $(div, '.instant-youtube-title').innerHTML = (title ? '<strong>' + title + '</strong>' : '') + duration; if (pinnable != 'off' && info.title) makeDraggable(div); if (info.reason) div.setAttribute('disabled', ''); if (videoSources.length) div.FYTE.videoSources = videoSources; if (info.storyboard_spec) { m = decodeURIComponent(decodeURIComponent(info.storyboard_spec)).split('|'); div.FYTE.storyboard = JSON.parse(m[m.length-1].replace(/^(\d+)#(\d+)#(\d+)#(\d+)#(\d+)#.+$/, '{"w":$1, "h":$2, "len":$3, "rows":$4, "cols":$5}')); div.FYTE.storyboard.url = m[0].replace('$L/$N.jpg', (m.length-2) + '/M0.jpg?sigh=' + m[m.length-1].replace(/^.+?#([^#]+)$/, '$1')); $(div, '.instant-youtube-options-button').insertAdjacentHTML('beforebegin', '<div class="instant-youtube-storyboard"' + (showStoryboard ? '' : ' disabled') + '>' + important('<div style="width:' + (div.FYTE.storyboard.w-1) + 'px; height:' + div.FYTE.storyboard.h + 'px;') + '"> </div>' + '</div>'); if (showStoryboard) updateHoverHandler(div); } injectStylesIfNeeded(); if (div.FYTE.state == 'scheduled play') setTimeout(function() { startPlayingDirectly(div) }, 0); div.FYTE.state = ''; } function fixThumbnailAR(div, w, h) { var img = $(div, 'img'); var thw = img.naturalWidth, thh = img.naturalHeight; if (w && h) { // means thumbnail is still loading div.FYTE.videoWidth = w; div.FYTE.videoHeight = h; } else { w = div.FYTE.videoWidth; h = div.FYTE.videoHeight; if (!w || !h) return; } var divw = div.clientWidth, divh = div.clientHeight; // if both video and thumbnail are 4:3, fit the image to height //console.log(div, divw, divh, thw, thh, w, h, h/w*divw / divh - 1, thh/thw*divw / divh - 1); if (Math.abs(h/w*divw / divh - 1) > 0.05 && Math.abs(thh/thw*divw / divh - 1) > 0.05) { img.style.maxHeight = img.clientHeight + 'px'; if (!div.FYTE.videoWidth) // skip animation if thumbnail is already loaded img.style.transition = 'height 1s ease, margin-top 1s ease'; setTimeout(function() { img.style.maxHeight = 'none'; img.style.cssText += important(h/w >= divh/divw ? 'width:auto; height:100%;' : 'width:100%; height:auto;'); setTimeout(function() { img.style.transition = ''; }, 1000); }, 0); } } function updateHoverHandler(div) { var sb = $(div, '.instant-youtube-storyboard'); if (!showStoryboard) { if (!sb.getAttribute('disabled')) sb.setAttribute('disabled', ''); return; } if (sb.hasAttribute('disabled')) sb.removeAttribute('disabled'); sb.addEventListener('click', storyboardClickHandler); var oldIndex = null; var style = sb.firstElementChild.style; sb.addEventListener('mousemove', storyboardHoverHandler); sb.addEventListener('mouseout', storyboardHoverHandler); div.addEventListener('mouseover', storyboardPreloader); div.addEventListener('mouseout', storyboardPreloader); var spinner = document.createElement('span'); spinner.className = 'instant-youtube-loading-button'; function storyboardClickHandler(e) { sb.removeEventListener('click', storyboardClickHandler); var offsetX = e.offsetX || e.clientX - this.getBoundingClientRect().left; div.FYTE.startAt = offsetX / this.clientWidth * div.FYTE.duration |0; div.FYTE.srcEmbedFixed = setUrlParams(div.FYTE.srcEmbedFixed, {start: div.FYTE.startAt}); startPlaying(div, {alternateMode: e.shiftKey}); } function storyboardPreloader(e) { if (e.type == 'mouseout') { imageLoader.onload = null; imageLoader.src = ''; spinner.remove(); return; } if (!div.FYTE.storyboard || div.FYTE.storyboard.preloaded) return; var lastpart = (div.FYTE.storyboard.len-1)/(div.FYTE.storyboard.rows * div.FYTE.storyboard.cols) |0; if (lastpart <= 0) return; var part = 0; imageLoader.src = setStoryboardUrl(part++); imageLoader.onload = function() { if (part > lastpart) { div.FYTE.storyboard.preloaded = true; div.removeEventListener('mouseover', storyboardPreloader); div.removeEventListener('mouseout', storyboardPreloader); imageLoader.onload = null; imageLoader.src = ''; spinner.remove(); return; } imageLoader.src = setStoryboardUrl(part++); }; } function setStoryboardUrl(part) { return div.FYTE.storyboard.url.replace(/M\d+\.jpg\?/, 'M' + part + '.jpg?'); } function storyboardHoverHandler(e) { if (!showStoryboard || !div.FYTE.storyboard) return; if (e.type == 'mouseout') return imageLoader2.onload && imageLoader2.onload(); var w = div.FYTE.storyboard.w; var h = div.FYTE.storyboard.h; var cols = div.FYTE.storyboard.cols; var rows = div.FYTE.storyboard.rows; var len = div.FYTE.storyboard.len; var partlen = rows * cols; var offsetX = e.offsetX || e.clientX - this.getBoundingClientRect().left; var left = Math.min(this.clientWidth - w, Math.max(0, offsetX - w)) |0; if (!style.left || parseInt(style.left) != left) { style.left = left + 'px'; if (spinner.parentElement) spinner.style.cssText = important('left:' + (left + w/2 - 10) + 'px; right:auto;'); } var index = Math.min(offsetX / this.clientWidth * (len+1) |0, len - 1); if (index == oldIndex) return; var part = index/partlen|0; if (!oldIndex || part != (oldIndex/partlen|0)) { style.cssText = style.cssText.replace(/$|background-image[^;]+;/, 'background-image: url(' + setStoryboardUrl(part) + ')!important;'); if (!div.FYTE.storyboard.preloaded) { if (spinner.timer) clearTimeout(spinner.timer); spinner.timer = setTimeout(function() { spinner.timer = 0; if (!imageLoader2.src) return; this.appendChild(spinner); spinner.style.cssText = important('left:' + (left + w/2 - 10) + 'px; right:auto;'); }.bind(this), 50); imageLoader2.onload = function() { clearTimeout(spinner.timer); spinner.remove(); spinner.timer = 0; imageLoader2.onload = null; imageLoader2.src = ''; }; imageLoader2.src = setStoryboardUrl(part); } } oldIndex = index; index = index % partlen; style.backgroundPosition = '-' + (index % cols) * w + 'px -' + (index / cols |0) * h + 'px'; } } function clickHandler(e) { if (e.target.href) return; if (e.target.matches('.instant-youtube-options-button')) { showOptions(e); e.preventDefault(); e.stopPropagation(); return; } if (e.target.matches('.instant-youtube-options, .instant-youtube-options *')) return; e.preventDefault(); e.stopPropagation(); var alternateMode = e.shiftKey || e.target.className == 'instant-youtube-link'; startPlaying(e.target.closest('.instant-youtube-container'), {alternateMode: alternateMode}); } function startPlaying(div, params) { div.removeEventListener('click', clickHandler); $$(div, '.instant-youtube-wrapper > *:not(img):not(a)').forEach(function(e) { e.style.cssText = 'display:none!important' }); $(div, 'svg').outerHTML = '<span class="instant-youtube-loading-button"></span>'; if (pinnable != 'off') { div.firstElementChild.insertAdjacentHTML('beforeend', '<div pin="top-left"></div><div pin="top-right"></div><div pin="bottom-right"></div><div pin="bottom-left"></div>'); $$(div, '[pin]').forEach(function(pin) { if (pinnable == 'hide') pin.setAttribute('transparent', ''); pin.onclick = function(e) { var pinIt = !div.hasAttribute('pinned') || !pin.hasAttribute('active'); var corner = pin.getAttribute('pin'); var video = $(div, 'video'); if (pinIt) { $$(div, '[pin][active]').forEach(function(p) { p.removeAttribute('active') }); pin.setAttribute('active', ''); if (!div.FYTE.unpinnedStyle) { div.FYTE.unpinnedStyle = div.style.cssText; var stub = div.cloneNode(); var img = $(div, 'img').cloneNode(); img.style.opacity = 1; img.style.display = 'block'; img.title = ''; stub.appendChild(img); stub.onclick = function(e) { $(div, '[pin][active]').onclick(e) }; stub.style.cssText += 'opacity:0.3!important;'; div.FYTE.stub = stub; div.parentNode.insertBefore(stub, div); } div.style.cssText = important( 'position: fixed;' + 'contain: inherit;' + 'width: 400px;' + 'z-index: 999999999;' + 'height:' + (400 / div.FYTE.videoWidth * div.FYTE.videoHeight) + 'px;' + 'top:' + (corner.indexOf('top') >= 0 ? '0' : 'auto') + ';' + 'bottom:' + (corner.indexOf('bottom') >= 0 ? '0' : 'auto') + ';' + 'left:' + (corner.indexOf('left') >= 0 ? '0' : 'auto') + ';' + 'right:' + (corner.indexOf('right') >= 0 ? '0' : 'auto') + ';' ); adjustPinnedOffset(div, corner); div.setAttribute('pinned', ''); if (video && document.body) document.body.appendChild(div); } else { pin.removeAttribute('active'); div.removeAttribute('pinned'); div.style.cssText = div.FYTE.unpinnedStyle; div.FYTE.unpinnedStyle = ''; if (div.FYTE.stub) { if (video && document.body) div.FYTE.stub.parentNode.appendChild(div, div.FYTE.stub); div.FYTE.stub.remove(); div.FYTE.stub = null; } } if (video && video.paused) video.play(); }; }); if (params && params.pin) $(div, '[pin="' + params.pin + '"]').click(); } if (window != window.top) window.parent.postMessage('iframe-allowfs', '*'); if ((!!playDirectly + (params && !!params.alternateMode) == 1) && (div.FYTE.videoSources || div.FYTE.state == 'querying')) { if (div.FYTE.videoSources) startPlayingDirectly(div); else { // playback will start in parseVideoInfo div.FYTE.state = 'scheduled play'; // fallback to iframe in 5s setTimeout(function() { if (div.FYTE.state) { div.FYTE.state = ''; switchToIFrame.call(div); } }, 5000); } } else switchToIFrame.call(div); } function startPlayingDirectly(div) { var video = document.createElement('video'); video.controls = true; video.autoplay = true; video.style.cssText = important( 'position:absolute; left:0; top:0; right:0; padding:0; margin:auto; opacity:0; transition:opacity 2s;' + 'width:100%; height:100%;'); video.className = 'instant-youtube-embed'; video.volume = GM_getValue('volume', 0.5); div.FYTE.videoSources.forEach(function(src) { var srcdom = video.appendChild(document.createElement('source')); Object.keys(src).forEach(function(k) { srcdom[k] = src[k] }); srcdom.onerror = switchToIFrame.bind(div); }); if (window.chrome) { video.addEventListener('click', function(e) { this.paused ? this.play() : this.pause(); }); } video.interval = (function() { return setInterval(function() { if (video.volume != GM_getValue('volume', 0.5)) GM_setValue('volume', video.volume); }, 1000); })(); var title = $(div, '.instant-youtube-title'); if (title) { video.onpause = function() { title.removeAttribute('hidden') }; video.onplay = function() { title.setAttribute('hidden', true) }; } video.onloadedmetadata = div.FYTE.startAt && function(e) { video.currentTime = div.FYTE.startAt; }; video.onloadeddata = function(e) { pauseOtherVideos(this); div.style.cssText += 'contain:inherit!important'; // allow fullscreen div.firstElementChild.appendChild(this); div.setAttribute('playing', ''); this.style.opacity = 1; var img = $(div, 'img'); img.style.transition = 'opacity 1s'; img.style.opacity = 0; }; } function switchToIFrame(e) { var div = this; var wrapper = div.firstElementChild; if (e) { console.log('[FYTE] Direct linking canceled on %s, switching to IFRAME player', div.FYTE.srcEmbed); var video = e.target ? e.target.closest('video') : e.path && e.path[e.path.length-1]; while (video.lastElementChild) video.lastElementChild.remove(); } ($(div, '[pin]') || wrapper).insertAdjacentHTML(pinnable != 'off' ? 'beforebegin' : 'beforeend', '<iframe class="instant-youtube-embed" allowtransparency="true" src="' + setUrlParams(div.FYTE.srcEmbedFixed, { html5: 1, autoplay: 1, autohide: 2, border: 0, controls: 1, fs: 1, showinfo: 1, ssl: 1, theme: 'dark', enablejsapi: 1, }) + '" frameborder="0" allowfullscreen width="100%" height="100%"></iframe>'); $(div, 'iframe').onload = function() { pauseOtherVideos(this); this.style.cssText = important( 'position:absolute; left:0; top:0; right:0; padding:0; margin:auto; opacity:1; transition:opacity 2s;'); div.setAttribute('iframe', ''); div.setAttribute('playing', ''); div.style.cssText += 'contain:none!important'; // allow fullscreen setTimeout(function() { $(div, 'img').style.display = 'none'; var title = $(div, '.instant-youtube-title'); if (title) title.remove(); }, 2000); }; } function setUrlParams(url, params) { var names = Object.keys(params); url = url.replace(new RegExp('[?&](' + names.join('|') + ')(=[^?&]*)?', 'gi'), ''); return url + (url.indexOf('?') > 0 ? '&' : '?') + names.map(function(n) { return n + '=' + params[n] }).join('&'); } function pauseOtherVideos(activePlayer) { $$(activePlayer.ownerDocument, '.instant-youtube-embed').forEach(function(v) { if (v == activePlayer) return; switch (v.localName) { case 'video': if (!v.paused) v.pause(); break; case 'iframe': try { v.contentWindow.postMessage('{"event":"command", "func":"pauseVideo", "args":""}', '*') } catch(e) {} break; } }); } function makeDraggable(div) { div.draggable = true; div.addEventListener('dragstart', function(e) { e.dataTransfer.setData('text/plain', ''); var dropZone = document.createElement('div'); var dropZoneHeight = 400 / div.FYTE.videoWidth * div.FYTE.videoHeight; dropZone.className = 'instant-youtube-dragndrop-placeholder'; document.body.addEventListener('dragenter', dragHandler); document.body.addEventListener('dragover', dragHandler); document.body.addEventListener('dragend', dragHandler); document.body.addEventListener('drop', dragHandler); function dragHandler(e) { e.stopImmediatePropagation(); e.stopPropagation(); e.preventDefault(); switch (e.type) { case 'dragover': var playing = div.hasAttribute('playing'); var gizmo = playing ? {left:0, top:0, right:innerWidth, bottom:innerHeight} : div.getBoundingClientRect(); var x = e.clientX, y = e.clientY; var cx = (gizmo.left + gizmo.right) / 2; var cy = (gizmo.top + gizmo.bottom) / 2; var stay = y >= cy-200 && y <= cy+200 && x >= cx-200 && x <= cx+200; overrideCSS(dropZone, { top: y < cy || stay ? '0' : 'auto', bottom: y > cy || stay ? '0' : 'auto', left: x < cx || stay ? '0' : 'auto', right: x > cx || stay ? '0' : 'auto', width: playing && stay ? (div.FYTE.stub || div).clientWidth+'px' : stay ? '100%' : '400px', height: playing && stay ? (div.FYTE.stub || div).clientHeight+'px' : stay ? '100%' : dropZoneHeight + 'px', margin: playing && stay ? 'auto' : '0', position: !playing && stay ? 'absolute' : 'fixed', 'background-color': stay ? 'rgba(255,255,0,0.2)' : 'rgba(0,255,0,0.2)', }); adjustPinnedOffset(dropZone); (stay && !playing ? div : document.body).appendChild(dropZone); break; case 'dragend': case 'drop': var corner = calcPinnedCorner(dropZone); dropZone.remove(); dropZone = null; document.body.removeEventListener('dragenter', dragHandler); document.body.removeEventListener('dragover', dragHandler); document.body.removeEventListener('dragend', dragHandler); document.body.removeEventListener('drop', dragHandler); if (e.type == 'dragend') break; if (div.hasAttribute('playing')) (corner ? $(div, '[pin="' + corner + '"]') : div.FYTE.stub).click(); else startPlaying(div, {pin: corner}); } } }); } function adjustPinnedOffset(el, corner) { var offset = 0; var inverse = el.style.top == '0px' ? 'bottom' : 'top'; $$('.instant-youtube-container[pinned] [pin="' + (corner || calcPinnedCorner(el)) + '"][active]').forEach(function(pin) { var container = pin.closest('[pinned]'); if (container != el) offset = Math.max(offset, container.getBoundingClientRect()[inverse]); }); if (offset) el.style[el.style.top == '0px' ? 'top' : 'bottom'] = offset + 'px'; } function calcPinnedCorner(el) { var t = el.style.top != 'auto'; var b = el.style.bottom != 'auto'; var l = el.style.left != 'auto'; var r = el.style.right != 'auto'; return t && b && l && r ? '' : (t ? 'top' : 'bottom') + '-' + (l ? 'left' : 'right'); } function showOptions(e) { var optionsButton = e.target; translateHTML(optionsButton, 'afterend', '\ <div class="instant-youtube-options">\ <label tl style="width: 100% !important;">Size:<br>\ <select data-action="size-mode" style="width:20ex!important">\ <option tl value="Original">Original\ <option tl value="Fit to width">Fit to width\ <option>360p\ <option>480p\ <option>720p\ <option>1080p\ <option tl value="Custom">Custom...\ </select>\ </label>\ <label data-action="size-custom" ' + (resizeMode != 'Custom' ? 'disabled' : '') + '>\ <input type="number" min="320" max="9999" tl-placeholder="width" data-action="width" step="1" value="' + (resizeWidth||'') + '">\ x\ <input type="number" min="240" max="9999" tl-placeholder="height" data-action="height" step="1" value="' + (resizeHeight||'') + '">\ </label>\ <label tl="content,title" title="msgStoryboardTooltip">\ <input data-action="storyboard" type="checkbox" ' + (showStoryboard ? 'checked' : '') + '>\ Storyboard thumbs\ </label>\ <label tl="content,title" title="msgDirectTooltip">\ <input data-action="direct" type="checkbox" ' + (playDirectly ? 'checked' : '') + '>\ Play directly\ </label>\ <label tl="content,title" title="Do not process customized videos with enablejsapi=1 parameter (requires page reload)">\ <input data-action="safe" type="checkbox" ' + (skipCustom ? 'checked' : '') + '>\ Safe\ </label>\ <label tl="content,title" title="msgPinningTooltip">Pinning:\ <select data-action="pinnable">\ <option tl value="on">On\ <option tl value="hide">On, hidden\ <option tl value="off">Off\ </select>\ </label>\ <span data-action="buttons">\ <button tl data-action="ok">OK</button>\ <button tl data-action="cancel">Cancel</button>\ </span>\ </div>\ '); var options = optionsButton.nextElementSibling; options.addEventListener('keydown', function(e) { if (e.target.localName == 'input' && !e.shiftKey && !e.altKey && !e.metaKey && !e.ctrlKey && e.key.match(/[.,]/)) return false; }); $(options, '[data-action="size-mode"]').value = resizeMode; $(options, '[data-action="size-mode"]').addEventListener('change', function() { var v = this.value != 'Custom'; var e = $(options, '[data-action="size-custom"]'); e.children[0].disabled = e.children[1].disabled = v; v ? e.setAttribute('disabled', '') : e.removeAttribute('disabled'); }); $(options, '[data-action="pinnable"]').value = pinnable; $(options, '[data-action="buttons"]').addEventListener('click', function(e) { if (e.target.dataset.action != 'ok') { options.remove(); return; } var v, shouldAdjust; if (resizeMode != (v = $(options, '[data-action="size-mode"]').value)) { GM_setValue('resize', resizeMode = v); shouldAdjust = true; } if (resizeMode == 'Custom') { var w = $(options, '[data-action="width"]').value |0; var h = $(options, '[data-action="height"]').value |0; if (resizeWidth != w || resizeHeight != h) { updateCustomSize(w, h); GM_setValue('width', resizeWidth); GM_setValue('height', resizeHeight); shouldAdjust = true; } } if (showStoryboard != (v = $(options, '[data-action="storyboard"]').checked)) { GM_setValue('showStoryboard', showStoryboard = v); $$('.instant-youtube-container').forEach(updateHoverHandler); } if (playDirectly != (v = $(options, '[data-action="direct"]').checked)) { GM_setValue('playHTML5', playDirectly = v); $$('.instant-youtube-container .instant-youtube-link').forEach(function(e) { e.textContent = playDirectly ? 'Play with Youtube player' : 'Play directly (up to 720p)'; }); } if (skipCustom != (v = $(options, '[data-action="safe"]').checked)) { GM_setValue('skipCustom', skipCustom = v); } if (pinnable != (v = $(options, '[data-action="pinnable"]').value)) { GM_setValue('pinnable', pinnable = v); } options.remove(); if (shouldAdjust) adjustNodes(e, e.target.closest('.instant-youtube-container')); }); } function updateCustomSize(w, h) { resizeWidth = Math.min(9999, Math.max(320, w|0 || resizeWidth|0)); resizeHeight = Math.min(9999, Math.max(240, h|0 || resizeHeight|0)); } function important(cssText) { return cssText.replace(/;/g, '!important;'); } function tryCatch(func) { try { return func(); } catch(e) { console.log(e); } } function getFunctionComment(fn) { return fn.toString().match(/\/\*([\s\S]*?)\*\/\s*\}$/)[1]; } function $(selORnode, sel) { return sel ? selORnode.querySelector(sel) : document.querySelector(selORnode); } function $$(selORnode, sel) { return Array.prototype.slice.call( sel ? selORnode.querySelectorAll(sel) : document.querySelectorAll(selORnode)); } function overrideCSS(e, params) { var names = Object.keys(params); var style = e.style.cssText.replace(new RegExp('(^|\s|;)(' + names.join('|') + ')(:[^;]+)', 'gi'), '$1'); e.style.cssText = style.replace(/[^;]\s*$/, '$&;').replace(/^\s*;\s*/, '') + names.map(function(n) { return n + ':' + params[n] + '!important' }).join(';') + ';'; } // fix dumb Firefox bug function floatPadding(node, style, dir) { var padding = style['padding' + dir]; if (padding.indexOf('%') < 0) return parseFloat(padding); return parseFloat(padding) * (parseFloat(style.width) || node.clientWidth) / 100; } function translateHTML(baseElement, place, html) { var tmp = document.createElement('div'); tmp.innerHTML = html; $$(tmp, '[tl]').forEach(function(node) { (node.getAttribute('tl') || 'content').split(',').forEach(function(what) { var child, src, tl; if (what == 'content') { for (var i = node.childNodes.length-1, n; (i>=0) && (n=node.childNodes[i]); i--) { if (n.nodeType == Node.TEXT_NODE && n.textContent.trim()) { child = n; break; } } } else child = node.getAttributeNode(what); if (!child) return; src = child.textContent; srcTrimmed = src.trim(); tl = src.replace(srcTrimmed, _(srcTrimmed)); if (src != tl) child.textContent = tl; }); }); baseElement.insertAdjacentHTML(place, tmp.innerHTML); } function initTL(src) { var tlSource = { 'watch on Youtube': { 'ru': 'открыть на Youtube', }, 'Play with Youtube player': { 'ru': 'Включить плеер Youtube', }, 'Play directly (up to 720p)': { 'ru': 'Включить напрямую (макс. 720p)', }, 'Shift-click to use alternative player': { 'ru': 'Shift-клик для смены типа плеера', }, 'Options': { 'ru': 'Опции', }, 'Size:': { 'ru': 'Размер:', }, 'Original': { 'ru': 'Исходный', }, 'Fit to width': { 'ru': 'На всю ширину', }, 'Custom...': { 'ru': 'Настроить...', }, 'width': { 'ru': 'ширина', }, 'height': { 'ru': 'высота', }, 'Storyboard thumbs': { 'ru': 'Раскадровка', }, 'msgStoryboardTooltip': { 'en': 'Show storyboard preview on mouse hover at the bottom', 'ru': 'Показывать миникадры при наведении мыши на низ кавер-картинки', }, 'Play directly': { 'ru': 'Плеер браузера', }, 'msgDirectTooltip': { 'en': 'Shift-clicking thumbnails will use alternative player', 'ru': 'Удерживайте клавишу Shift при щелчке на картинке для альтернативного плеера', }, 'Safe': { 'ru': 'Консервативный режим', }, 'Pinning': { 'ru': 'Закрепление', }, 'msgPinningTooltip': { 'en': 'Enable corner pinning controls when a video is playing. \nTo restore the video click the active corner pin or the original video placeholder.', 'ru': 'Включить шпильки по углам для закрепления видео во время просмотра. \nДля отмены можно нажать еще раз на активированный уголЪ или на заглушку, где исходно было видео', }, 'On': { 'ru': 'Да', }, 'On, hide': { 'ru': 'Да, невидимые', }, 'Off': { 'ru': 'Нет', }, 'msgSafe': { 'en': 'Do not process customized videos with enablejsapi=1 parameter (requires page reload)', 'ru': 'Не обрабатывать нестандартные видео с параметром enablejsapi=1 (подействует после обновления страницы)', }, 'OK': { 'ru': 'ОК', }, 'Cancel': { 'ru': 'Оменить', }, }; var browserLang = navigator.language || navigator.languages && navigator.languages[0] || ''; var browserLangMajor = browserLang.replace(/-.+/, ''); var tl = {}; Object.keys(tlSource).forEach(function(k) { var langs = tlSource[k]; var text = langs[browserLang] || langs[browserLangMajor]; if (text) tl[k] = text; }); return function(src) { return tl[src] || src }; } function injectStylesIfNeeded(force) { if (!fytedom[0] && !force) return; var styledom = $('style#instant-youtube-styles'); if (styledom) { // move our rules to the end of HEAD to increase CSS specificity if (styledom.nextElementSibling && document.head) document.head.insertBefore(styledom, null); return; } styledom = (document.head || document.documentElement).appendChild(document.createElement('style')); styledom.id = 'instant-youtube-styles'; styledom.textContent = important(getFunctionComment(function() { /* .instant-youtube-container { contain: strict; position: relative; overflow: hidden; cursor: pointer; padding: 0; margin: 0; font: normal 14px/1.0 sans-serif, Arial, Helvetica, Verdana; text-align: center; background: black; } .instant-youtube-container[disabled] { background: #888; } .instant-youtube-container[disabled] .instant-youtube-storyboard { display: none; } .instant-youtube-container[pinned] { box-shadow: 0 0 30px black; } .instant-youtube-container .instant-youtube-wrapper { width: 100%; height: 100%; } .instant-youtube-container .instant-youtube-play-button { display: block; position: absolute; width: 85px; height: 60px; left: 0; right: 0; top: 0; bottom: 0; margin: auto; } .instant-youtube-container .instant-youtube-loading-button { display: block; position: absolute; width: 20px; height: 20px; left: 0; right: 0; top: 0; bottom: 0; padding: 0; margin: auto; pointer-events: none; background: url("data:image/gif;base64,R0lGODlhFAAUAJEDAMzMzLOzs39/f////yH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgADACwAAAAAFAAUAAACPJyPqcuNItyCUJoQBo0ANIxpXOctYHaQpYkiHfM2cUrCNT0nqr4uudsz/IC5na/2Mh4Hu+HR6YBaplRDAQAh+QQFCgADACwEAAIADAAGAAACFpwdcYupC8BwSogR46xWZHl0l8ZYQwEAIfkEBQoAAwAsCAACAAoACgAAAhccMKl2uHxGCCvO+eTNmishcCCYjWEZFgAh+QQFCgADACwMAAQABgAMAAACFxwweaebhl4K4VE6r61DiOd5SfiN5VAAACH5BAUKAAMALAgACAAKAAoAAAIYnD8AeKqcHIwwhGntEWLkO3CcB4biNEIFACH5BAUKAAMALAQADAAMAAYAAAIWnDSpAHa4GHgohCHbGdbipnBdSHphAQAh+QQFCgADACwCAAgACgAKAAACF5w0qXa4fF6KUoVQ75UaA7Bs3yeNYAkWACH5BAUKAAMALAIABAAGAAwAAAIXnCU2iMfaRghqTmMp1moAoHyfIYIkWAAAOw=="); } .instant-youtube-container:hover .ytp-large-play-button-svg { fill: #CC181E; } .instant-youtube-container .instant-youtube-link { display: block; position: absolute; width: 20em; height: 20px; top: 50%; left: 0; right: 0; margin: 60px auto; padding: 0; border: none; text-align: center; text-decoration: none; text-shadow: 1px 1px 3px black; font-weight: bold; color: white; } .instant-youtube-container span.instant-youtube-link { z-index: 8; font-weight: normal; font-size: 12px; } .instant-youtube-container .instant-youtube-link:hover { text-decoration: underline; color: white; background: transparent; } .instant-youtube-container iframe { z-index: 10; } .instant-youtube-container .instant-youtube-title { z-index: 9; display: block; position: absolute; width: auto; top: 0; left: 0; right: 0; margin: 0; padding: 7px; border: none; text-shadow: 1px 1px 2px black; text-align: center; text-decoration: none; color: white; background-color: rgba(0, 0, 0, 0.5); } .instant-youtube-container .instant-youtube-title strong { font: bold 14px/1.0 sans-serif, Arial, Helvetica, Verdana; } .instant-youtube-container .instant-youtube-title strong:after { content: " - $tl:'watch on Youtube'"; font-weight: normal; margin-right: 1ex; } .instant-youtube-container .instant-youtube-title span { color: inherit; } .instant-youtube-container .instant-youtube-title span:before { content: "("; } .instant-youtube-container .instant-youtube-title span:after { content: ")"; } @-webkit-keyframes instant-youtube-fadein { from { opacity: 0 } to { opacity: 1 } } @-moz-keyframes instant-youtube-fadein { from { opacity: 0 } to { opacity: 1 } } @keyframes instant-youtube-fadein { from { opacity: 0 } to { opacity: 1 } } .instant-youtube-container:not(:hover) .instant-youtube-title[hidden] { display: none; margin: 0; } .instant-youtube-container .instant-youtube-title:hover { text-decoration: underline; } .instant-youtube-container .instant-youtube-title strong { color: white; } .instant-youtube-container .instant-youtube-options-button { opacity: 0.6; position: absolute; right: 0; bottom: 0; margin: 0; padding: 1.5ex 2ex; font-size: 11px; text-shadow: 1px 1px 2px black; color: white; } .instant-youtube-container .instant-youtube-options-button:hover { opacity: 1; background: rgba(0, 0, 0, 0.5); } .instant-youtube-container .instant-youtube-options { display: flex; position: absolute; right: 0; bottom: 0; margin: 0; padding: 2ex 1ex 2ex 2ex; flex-direction: column; align-items: flex-start; line-height: 1.5; text-align: left; opacity: 1; color: white; background: black; } .instant-youtube-container .instant-youtube-options * { width: auto; height: auto; margin: 0; padding: 0; font: inherit; font-size: 13px; vertical-align: middle; text-transform: none; text-align: left; border-radius: 0; text-decoration: none; color: white; background: black; } .instant-youtube-container .instant-youtube-options > label { margin-top: 1ex; } .instant-youtube-container .instant-youtube-options > label > * { display: inline; } .instant-youtube-container .instant-youtube-options select { padding: .5ex .25ex; border: 1px solid #444; -webkit-appearance: menulist; } .instant-youtube-container .instant-youtube-options [data-action="size-custom"] input { width: 9ex; padding: .5ex .5ex .4ex; border: 1px solid #666; } .instant-youtube-container .instant-youtube-options [data-action="buttons"] { margin-top: 1em; } .instant-youtube-container .instant-youtube-options button { margin: 0 1ex 0 0; padding: .5ex 2ex; border: 2px solid gray; font-weight: bold; } .instant-youtube-container .instant-youtube-options button:hover { border-color: white; } .instant-youtube-container .instant-youtube-options > [disabled] { opacity: 0.25; } .instant-youtube-container .instant-youtube-storyboard { height: 33%; max-height: 90px; display: block; position: absolute; left: 0; right: 0; bottom: 0; overflow: visible; overflow-x: visible; overflow-y: visible; } .instant-youtube-container .instant-youtube-storyboard:hover { background-color: rgba(0,0,0,0.3); } .instant-youtube-container .instant-youtube-storyboard[disabled] { display:none; } .instant-youtube-container .instant-youtube-storyboard div { display: block; position: absolute; bottom: 0px; pointer-events: none; border: 3px solid #888; box-shadow: 2px 2px 10px black; transition: opacity .25s ease; background-color: transparent; background-origin: content-box; opacity: 0; } .instant-youtube-container .instant-youtube-storyboard:hover div { opacity: 1; } .instant-youtube-container [pin] { position: absolute; width: 0; height: 0; margin: 0; padding: 0; opacity: 1; top: auto; bottom: auto; left: auto; right: auto; border-style: solid; transition: opacity 2.5s ease-in, opacity 0.4s ease-out; opacity: 0; z-index: 100; } .instant-youtube-container[playing]:hover [pin]:not([transparent]) { opacity: 1; } .instant-youtube-container[playing] [pin]:hover { cursor: alias; opacity: 1; transition: opacity 0s; } .instant-youtube-container [pin=top-left][active] { border-top-color: green; } .instant-youtube-container [pin=top-left]:hover { border-top-color: #fc0; } .instant-youtube-container [pin=top-left] { top: 0; left: 0; border-width: 10px 10px 0 0; border-color: red transparent transparent transparent; } .instant-youtube-container [pin=top-right][active] { border-right-color: green; } .instant-youtube-container [pin=top-right]:hover { border-right-color: #fc0; } .instant-youtube-container [pin=top-right] { top: 0; right: 0; border-width: 0 10px 10px 0; border-color: transparent red transparent transparent; } .instant-youtube-container [pin=bottom-right][active] { border-bottom-color: green; } .instant-youtube-container [pin=bottom-right]:hover { border-bottom-color: #fc0; } .instant-youtube-container [pin=bottom-right] { bottom: 0; right: 0; border-width: 0 0 10px 10px; border-color: transparent transparent red transparent; } .instant-youtube-container [pin=bottom-left][active] { border-left-color: green; } .instant-youtube-container [pin=bottom-left]:hover { border-left-color: #fc0; } .instant-youtube-container [pin=bottom-left] { bottom: 0; left: 0; border-width: 10px 0 0 10px; border-color: transparent transparent transparent red; } .instant-youtube-dragndrop-placeholder { z-index: 999999999; margin: 0; padding: 0; background: rgba(0, 255, 0, 0.1); border: 2px dotted green; box-sizing: border-box; } */}).replace(/\$tl:'(.+?)'/g, function(m, m1) { return _(m1) }) ); }