/*jslint indent: 4, maxerr: 50, browser: true, devel: true, sub: false, fragment: false, nomen: true, plusplus: true, bitwise: true, regexp: true, newcap: true */ // ==UserScript== // Do not modify and re-release this script! // If you would like to add support for other sites, please tell me and I'll put it in the includes. // @id youtube-me-again // @name YouTube Me Again! // @namespace hateradio))) // @author hateradio // @version 6 // @description ytma! automatically converts YouTube(TM), Vimeo, Vine, Soundcloud, WebM, and MP4 links into real embedded videos. // @homepage https://greasyfork.org/en/scripts/1023-youtube-me-again // @icon https://dl.dropboxusercontent.com/u/14626536/userscripts/i/ytma/ytma32.png // @icon64 https://dl.dropboxusercontent.com/u/14626536/userscripts/i/ytma/ytma64.png // @screenshot https://dl.dropboxusercontent.com/u/14626536/userscripts/i/ytma/ytmascreen5.png // @include https://vine.co/v/*/embed/simple // @match https://vine.co/v/*/embed/simple // @include http*://*youtube-nocookie.com/embed/* // @match *://*.youtube-nocookie.com/embed/* // @include http*://*youtube.com/embed/* // @match *://*.youtube.com/embed/* // @include https://gfycat.com/iframe/* // @match https://gfycat.com/iframe/* // @include http://*.neogaf.com/forum/showthread.php* // @include http://*.neogaf.com/forum/showpost.php?p* // @include http://*.neogaf.com/forum/newreply.php* // @include http://*.neogaf.com/forum/editpost.php* // @include http://*.neogaf.com/forum/private.php* // @match http://*.neogaf.com/forum/showthread.php* // @match http://*.neogaf.com/forum/showpost.php?p* // @match http://*.neogaf.com/forum/newreply.php* // @match http://*.neogaf.com/forum/editpost.php* // @match http://*.neogaf.com/forum/private.php* // @include http*://*what.cd/forums.php?*viewthread* // @include http*://*what.cd/torrents.php?* // @include http*://*what.cd/user.php?* // @match *://*.what.cd/forums.php?*viewthread* // @match *://*.what.cd/torrents.php?* // @match *://*.what.cd/user.php?* // @updated 10 May 2015 // @grant GM_xmlhttpRequest // @grant unsafeWindow // @run-at document-end // @downloadURL none // ==/UserScript== /* Changes: Removes Flash/Object tag Removes "batch" loading of descriptions New: Imgur GIFV (WEBM/MP4) support Soundcloud now uses HTML5 player Players that open on scroll will no longer trigger the opening of players higher on the page Adds HTML5, Gfycat, Imgur icons on links Improved Soundcloud and GfyCat URL matchers Restructured code base to simplify creation of media controls Restructured CSS Safari Gfycat iframe SoundCloud playlist support Default quality is 720p/HD Whitelist these sites on NoScript/NotScript/etc. ------------------------------------------------ * neogaf.com * youtube.com * youtube-nocookie.com * googlevideo.com (HTML5 player sends videos from this domain) * googleapis.com (YT video data) * vimeo.com * vimeocdn.com * soundcloud.com * sndcdn.com * vineco.com * vine.com * vine.co * gfycat.com * dropboxusercontent.com Whitelist these on Ghostery --------------------------- * SoundCloud (Widgets, Audio / Music Player) */ (function () { 'use strict'; var $$, strg, update; if (!Function.prototype.bind) { Function.prototype.bind = function (self) { var args = [].slice.call(arguments, 1), fn = this; return function () { return fn.apply(self, args.concat([].slice.call(arguments))); }; }; } function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } function inject(func) { var script = document.createElement('script'); script.type = 'text/javascript'; script.textContent = '(' + func + ')();'; document.body.appendChild(script); document.body.removeChild(script); } // D O M Handle $$ = { s: function (selector, cb) { var s = document.querySelectorAll(selector), i = -1; while (++i < s.length) { if (cb(s[i], i, s) === false) { break; } } }, o: function (object, cb) { var i; for (i in object) { if (object.hasOwnProperty(i)) { if (cb(i, object[i], object) === false) { break; } } } }, a: function (e) { var i = 1, j = arguments.length, f = document.createDocumentFragment(); for (i; i < j; i++) { if (arguments[i]) { f.appendChild(arguments[i]); } } e.appendChild(f); return e; }, e: function (t, o, e, p) { var c = document.createElement(t); $$.o(o, function (k, v) { var b = k.charAt(0); switch (b) { case '_': c.dataset[k.substring(1)] = v; break; case '$': c.setAttribute(k.substring(1), v); break; default: c[k] = v; } }); if (e && p) { c.appendChild(e); } else if (e) { e.appendChild(c); } return c; }, x: function (selector) { return this.ary(document.querySelectorAll(selector)); }, ary: function (ary) { return Array.from ? Array.from(ary) : Array.prototype.slice.call(ary); } }; // S T O R A G E HANDLE strg = { MAX: 6000, on: false, test: function () { try { var a, b = localStorage, c = Math.random().toString(16).substr(2, 8); b.setItem(c, c); a = b.getItem(c); return a === c ? !b.removeItem(c) : false; } catch (e) { return false; } }, read: function (key) { return this.on ? JSON.parse(localStorage.getItem(key)) : false; }, save: function (key, val) { return this.on ? !localStorage.setItem(key, JSON.stringify(val)) : false; }, wipe: function (key) { return this.on ? !localStorage.removeItem(key) : false; }, zero: function (o) { var k; for (k in o) { if (o.hasOwnProperty(k)) { return false; } } return true; }, grab: function (key, def) { var s = strg.read(key); return strg.zero(s) ? def : s; }, size: function () { var length = 0, key; try { for (key in window.localStorage) { if (window.localStorage.hasOwnProperty(key)) { length += window.localStorage[key].length; } } } catch (e) {} return 3 + ((length * 16) / (8 * 1024)); }, full: function () { try { var date = +(new Date()); localStorage.setItem(date, date); localStorage.removeItem(date); return false; } catch (e) { if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') { return true; } } }, init: function () { this.on = this.test(); } }; strg.init(); // U P D A T E HANDLE update = { name: 'ytma!', version: 5100, key: 'ujs_YTMA_UPDT_HR', callback: 'ytmaupdater', page: 'https://greasyfork.org/scripts/1023-youtube-me-again', uric: 'https://dl.dropboxusercontent.com/u/14626536/userscripts/updt/ytma/ytma.js', // If you get "Failed to load source for:" in Firebug, allow dropboxusercontent.com to run scripts. interval: 5, day: (new Date()).getTime(), time: function () { return new Date(this.day + (1000 * 60 * 60 * 24 * this.interval)).getTime(); }, top: document.head || document.body, css: function (t) { if (!this.style) { this.style = document.createElement('style'); this.style.type = 'text/css'; this.top.appendChild(this.style); } this.style.appendChild(document.createTextNode(t + '\n')); }, js: function (t) { var j = document.createElement('script'); j.type = 'text/javascript'; j[/^https?\:\/\//i.test(t) ? 'src' : 'textContent'] = t; this.top.appendChild(j); }, notification: function (j) { if (j) { if (this.version < j.version) { window.localStorage.setItem(this.key, JSON.stringify({date: this.time(), version: j.version, page: j.page })); } else { return true; } } var a = document.createElement('a'), b = JSON.parse(window.localStorage.getItem(this.key)); a.href = b.page || '#'; a.target = '_blank'; a.id = 'userscriptupdater'; a.title = 'Update now.'; a.textContent = 'An update for ' + this.name + ' is available.'; document.body.appendChild(a); return true; }, check: function (opt) { if (!strg.on) { return; } // typeof (GM_updatingEnabled) === 'boolean' || var stored = strg.read(this.key), j, page; this.csstxt(); if (opt || !stored || stored.date < this.day) { page = stored && stored.page ? stored.page : '#'; strg.save(this.key, {date: this.time(), version: this.version, page: page}); j = this.notification.toString() .replace('function', 'function ' + this.callback) .replace('this.version', this.version) .replace(/(?:this\.key)/g, "'" + this.key + "'") .replace('this.time()', this.time()) .replace('this.name', "'" + this.name + "'"); this.js(j); this.js(this.uric); } else if (this.version < stored.version) { this.notification(); } }, csstxt: function () { if (!this.pop) { this.pop = true; this.css('#userscriptupdater,#userscriptupdater:visited{-moz-box-shadow:0 0 6px #787878;-webkit-box-shadow:0 0 6px #787878;box-shadow:0 0 6px #787878;border:1px solid #777;-moz-border-radius:4px;border-radius:4px;cursor:pointer;color:#555;font-family:Arial, Verdana, sans-serif;font-size:11px;font-weight:700;text-align:justify;min-height:45px;position:fixed;z-index:999999;right:10px;top:10px;width:170px;background:#ebebeb url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAACLCAYAAAD4QWAuAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2RpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDo1NUIzQjc3MTI4N0RFMDExOUM4QzlBNkE2NUU3NDJFNCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpGN0Q1OEQyNjdEQzUxMUUwQThCNEE3MTU1NDU1NzY2OSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpGN0Q1OEQyNTdEQzUxMUUwQThCNEE3MTU1NDU1NzY2OSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M1IFdpbmRvd3MiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo1NUIzQjc3MTI4N0RFMDExOUM4QzlBNkE2NUU3NDJFNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo1NUIzQjc3MTI4N0RFMDExOUM4QzlBNkE2NUU3NDJFNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Po6YcvQAAAQFSURBVHja7JzBSxRRHMdnp+gkiLdOgtshKGSljQVF8CK0biEErYfwFmT+BQpdA0MIBEFtTx2qSxESaAt5ioUQFDp5sjl06rbnumzfp7+VbZx5M+/Nb9wZ+f3g56wzO28//ua93/u9J/stdDodx2/P3o85llaFT8JvwlvwTfhf00a2Hv8IPO86PHYHvg//An8OfwRfg/9RfzvTZ7DBvoZXQq6p6D7MCuwT+N2I92zAB/sNO0yPO8quwxf7DasABmK+d0XTVVKHnYIvG96z1i9Ymw8ep/R2obAqNdkm41e2sFct71v1/f4BiXyOJpRpHKZ918s9527B5+FvLwJWDaoR3zmvZ/bZw2HPNyMeBOTeb/BfaXaDEuVMvx2G3QDQMkW21wZsUpkp7GbIeU9zz3TI+WXTVGYCW6XRbApb1lxbTwt2VVMltS1hVWRnuWFVqhoNudbW9NchHIpc+ToO7GDE49JFtRij/ZG4gy0O7CIVIjZWNuhiw0lhK1SA6GzI8ppxKouCjTNaOWC7qWzKFrYaNw/SQOKwNVtYk4KjyAQ7RpnHCHaeCg7ugZQon7sBj3RYM62mHdmTVAaGxbiRNVmqRM3/bUvgDQCX/CcLvZsceEOF1v82dgPTrkdVVp2iXU8Q4e9ob0IHu59gUecxdwdlMwBunusGAJ1NuPr0KLoFdYQ3GGBXAiMLWC9gBRDX2gTa9g3Wp7Rbk8TqaPfjWWRp9I0kaLARVCbiXMO/xLGwdfCd7Oa4eDGQdD0fYYcJ7z/bzXHpxbWEDRaddO1FF3aSobE6pazAawztX0H7465mXWVqB2hwqWdwFeFfGaM+Wlh4V/rkMO2fpmy3VWTf5AD0NzLLkYsfn53T7fUs21k2UPmw5jBs9qZgx/AH4Ns+VxvQwJg0rGXTMPUfnhYgj0MLmayb6+TIBFZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBVZgBTZzVrg3U+Nsz1iTo7m7c+GRFU2ONGBFkyMNWNHkSANWNDl0xqbJAZ+j1/nR5HBOv6zm/8JaPjQ5KKqiyRFVpORfk8PRf3NZq8lRrd3PhiaHc6pvcLk0ORDdfGlyAFg0OdKAPUlliG76mhyGUNaDLXOaHIjuJdXkoKVKXzU5wlJZZjU5AFyKKhErFkuVbjcoUo3Apcmhnu6Ebkcmc5oczd2dZlA3YNHkUAFwUtLkcJlWnm1a1ng94AvkbKnM1SxVTKwRMphYNDkAPNiFFU0OZuPV5NDMYiyaHOgKvJoc8CVftFk1ORRsi/FxvYR3yH9qZjYba+VGkwOTw5GCzZcmByzTmhyI6ra/kNkiz4wmByD/0+T4J8AAyDkZArebBxMAAAAASUVORK5CYII=) no-repeat 13px 15px;padding:12px 20px 10px 65px}#userscriptupdater:hover,#userscriptupdater:visited:hover{color:#55698c!important;background-position:13px -85px;border-color:#8f8d96}'); } } }; /** Y T M A CLASS * Bare YTMA class, filled through _new() or _reactivate() */ function YTMA() {} YTMA.events = { clicks: function (e) { // YTMA global click dispatcher var t = e.target; if (t) { // console.log('YTMA.clicks'); if (t.tagName === 'VAR' && t.hasAttribute('data-ytmuid')) { // trigger the ui console.log('show', t.dataset.ytmuid); YTMA.UI.createFromTrigger(t).showPlayer(); } else if (t.hasAttribute('data-ytmdescription')) { console.log('load', t.dataset.ytmid); YTMA.external.events.manualLoad(e); } } }, thumb: { start: function (e) { var el = e.target; el.dataset.thumb = el.dataset.thumb > 0 ? (el.dataset.thumb % 3) + 1 : 2; el.style.backgroundImage = ['url(https://i3.ytimg.com/vi/', el.dataset.ytmid, '/', el.dataset.thumb, '.jpg)'].join(''); el.dataset.timeout = window.setTimeout(YTMA.events.thumb.start.bind(this, e), 800); }, stop: function (e) { window.clearTimeout(e.target.dataset.timeout); } } }; YTMA.num = 0; YTMA.create = function (link) { var data = YTMA.grabIdAndSite(link), id, y; if (data.valid === true) { y = new YTMA()._new(data.id, data.site, link); id = y.data.uid; YTMA.set[id] = y; YTMA.set[id].setup(); return y; } return {}; }; YTMA.grabIdAndSite = function (link) { var uri = link.href, id, site, match; try { site = YTMA.reg.siteByTest[YTMA.reg.site.test(uri) ? RegExp.lastMatch : '']; // console.log(site); if (site === 'html5') { // || site === 'html5-audio' id = uri.slice(-15); } else if (site === 'soundcloud') { if (!YTMA.reg.extra.soundcloud.playlist.test(uri)) { link.href = uri = YTMA.reg.fix.soundcloud(uri); } match = YTMA.reg.matchers.soundcloud.exec(uri); if (match) { id = YTMA.escapeId(match[1]).slice(-50); } } else { id = uri.match(YTMA.reg.matchers[site])[1]; } if (id && YTMA.DB.sites[site]) { return {id: id, site: site, valid: true}; } throw TypeError('Invalid ID/Site: ' + id + ' @ ' + site); } catch (e) { console.error(uri, e); return {valid: false}; } }; YTMA.escapeId = function (id) { return (id += '').replace(/(?:\W)/g, '_'); }; YTMA.route = { host: document.location.host.replace('www.', ''), control: { $: { patchSafari: function () { YTMA.DB.videoTag.gfycat = false; YTMA.DB.sources.gfycat = YTMA.DB.sources.$gfycatFrame; }, checkStorage: function () { if (strg.full() === true) { try { localStorage.removeItem(YTMA.external.version); strg.on = strg.test(); } catch (e) {} } }, runOnce: function () { if (!document.body.hasAttribute('ytma-enabled')) { document.body.setAttribute('ytma-enabled', true); this.checkStorage(); if (!YTMA.DB.extension) { update.check(); } YTMA.css(); YTMA.user.init(); YTMA.DB.postInit(); document.body.addEventListener('click', YTMA.events.clicks, false); } } }, go: function (host) { if (/(?:googlevideo|youtube-nocookie\.com|youtube\.com\.?)/i.test(host)) { this.sites.youtube(); } else if (this.sites[host]) { this.sites[host](); } else { this.sites.$generic(); } }, sites: { $generic: function () { YTMA.route.control.$.runOnce(); if (YTMA.DB.browser.safari) { // safari patch YTMA.route.control.$.patchSafari(); } if (YTMA.selector.processor() > 0) { YTMA.user.fn.loadPreferences(); } }, 'gfycat.com': function () { var v = document.querySelector('video'); v.controls = true; update.css('body,html {overflow:hidden;height:100%;width:100%} video {display:table;height:100%;margin:0 auto;}'); document.body.appendChild(v); }, 'vine.co': function () { // console.log('vine.co'); window.addEventListener('resize', function () { $$.s('[style]', function (e) { e.removeAttribute('style'); }); }); }, youtube: function () { // lets force some quality parity console.log('now inside youtube . . .', document.location); if (/(?:vq=(\w+))/.test(document.location.search)) { document.body.setAttribute('gm-player-quality', RegExp.lastParen); } if (/(?:volume=(\d+))/.test(document.location.search)) { document.body.setAttribute('gm-player-volume', RegExp.lastParen); } inject(function () { var max = 10, count = 1, intr = window.setInterval(function () { console.log('inside says: ', count, !!window.yt); if (window.yt && window.player) { var p = window.yt.player.getPlayerByElement(window.player); if (document.body.hasAttribute('gm-player-quality')) { console.log('inside says: setting quality to ', document.body.getAttribute('gm-player-quality')); p.setPlaybackQuality(document.body.getAttribute('gm-player-quality')); } if (document.body.hasAttribute('gm-player-volume')) { console.log('inside says: setting volume to ', document.body.getAttribute('gm-player-volume')); p.setVolume(document.body.getAttribute('gm-player-volume')); } window.clearInterval(intr); } else { console.log(count); count += 1; if (count > max) { window.clearInterval(intr); } } }, 500); }); } } }, load: function () { this.control.go(this.host); } }; YTMA.main = function () { YTMA.route.load(); }; YTMA.set = {}; YTMA.collect = function (id) { var i, a = []; for (i in YTMA.set) { if (YTMA.set.hasOwnProperty(i) && YTMA.set[i].data.id === id) { a.push(YTMA.set[i]); } } return a; }; YTMA.reg = { site : /\b(youtu)|(vimeo)|(vine)|(soundcloud)|(gfycat)|(imgur)|(\.webm$)|(\.mp4$)|(\.gifv$)/, time : /(?:t\=(?:(\d+)m)?(\d+))/, ios : /(?:\b(?:ipod|iphone|ipad))\b/i, matchers: { youtube: /(?:(?:(?:v\=|#p\/u\/\d*?\/)|(?:v\=|#p\/c\/[a-zA-Z0-9]+\/\d*?\/)|(?:embed\/)|(?:v\/)|(?:\.be\/))([A-Za-z0-9-_]{11}))/i, vimeo: /(?:vimeo\.com\/(\d+))/i, vine: /(?:vine\.co\/v\/([A-Za-z0-9-_]{11}))/i, soundcloud: /(?:\/\/(?:\bwww|m\.\b)?soundcloud\.com\/(.+?\/.+))/i, gfycat: /(?:gfycat\.com\/(?:(\b(?:[A-Z][a-z]*){3,}\b)))/, imgur: /(?:imgur\.com\/(\w+)\.(?:gifv|mp4|webm))/i }, extra: { soundcloud: { playlist: /(?:soundcloud\.com\/.+\/sets\/)/ } }, siteByTest: { youtu: 'youtube', vimeo: 'vimeo', vine: 'vine', gfycat: 'gfycat', imgur: 'imgur', '.webm': 'html5', '.mp4': 'html5', // '.mp3': 'html5-audio', '.gifv': 'html5', soundcloud: 'soundcloud' }, fix: { $removeSearch: function (uri, keepHash) { var s = uri.indexOf('?'), h = uri.indexOf('#'), hash = ''; if (s > -1) { if (keepHash && h > -1) { hash = uri.substr(h); } uri = uri.substr(0, s) + hash; } return uri; }, soundcloud: function (uri) { var match = YTMA.reg.matchers.soundcloud.exec(uri), id; if (match) { id = match[1].split('/', 2).join('/'); uri = this.$removeSearch('https://soundcloud.com/' + id, true); } return uri; } } }; YTMA.img = { fav: { soundcloud : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXZJREFUeNp0UjFOw0AQnD3bCYaEoIgiUIQKikiAKKGgSAkFL0BQ0FEgUfECShpewB+QEE+gokDiBxGRiCCEBBzHd8ucLYGQ4Kw7+9azc7OzJ6oKnFYUxgD+W/DHYNA54GIooifTitYqg1okaPFff6BcTLF5fECYb5IJNJ3kMfUP2dxHPycwcQ0SliARocSGsA46YkKWQW0GS6BDAGlu5Myu84AgSmHKM/DY0NegwwR2+AJrSjBre5BaA1H7GFKpI729QHp9jqiaeTBn5mB7fWirjWB9B9JYBrwEMnop5d0zfD53YO9vYMY8SQcpZGkTZvsIstiivDfoaxfIxt8exYeXCLYOSOwlJZQ6twSpL0DfX4EoZtkCqc7/Njalbxnfdt+oSwhurkBnCWI/1FlgqgKNZ3JnZDSA3FFSpYdQAoF56tKNDmhOYTzJ3OSHXZkflJhYEyawcnH02HpmxZ+DrRJlgmacvrsHRmHln2tRnIiAy5WTLwEGAK4QoBQmtGHkAAAAAElFTkSuQmCC', youtube : 'https://www.youtube.com/favicon.ico', vimeo : 'https://vimeo.com/favicon.ico', vine : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABcklEQVQ4jX2SvyvFYRTGP+9NdzAYbpIkysA/ICnKoEwvA4vlUkoyGQzvoOiK4R0YbDLhDhbi9maWIjEqcScWkyRhMNzXcM/3On39OMt5nvOe85wfvSbGyH9mgs8Cq8AUkAMegU1gJVpXqfu3umpbwITiLUBB8HJGuryb4KMJ/izVvUMVnwNjwJPwGYCMkLL4zlT3XoUL0boD4FBNUhO4Fd9ogm9SRVmFn8Una79qgWuV2K3wvcLJdG3iL7TaiUocAI4Fn0vnHDBrgt+L1g2q3NoEl8CH4KHkMVr3CSwI7QeOTPA9WsAk/8AEvw+MSrwrWleuJQVfABZJWbTOZBTfVXg6lbgEHKjQTcL1BFngAWimeuH2aN2LvHUDV1JcjNbl0zdI9l0T2pDsboKvB7Yl/ga4X2+gku+AVqAC9AFzwLik5KN1xT8FRGQEOBL6yfdn2onWTZKyTDoQrSsB60KT4lNSh/1TQETmgQ1ZowQMy41+2BeLRXeRaKuHSAAAAABJRU5ErkJggg==', html5 : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAANCAYAAABy6+R8AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAdlJREFUeNpcks9rE0EUx7+b3TRktxvbhUhrNm6SrUWtxxbxJ9iLl0JFKWg8WLD05EWhIuRieogXwYPX4tGb/gPSq/oP6KH+uG2MFaRJJXaTbp7fWbsl+uDDzLx533lv3ozmeyUM2VlSJxeISULygTwhr5Og1JDgOXlPrpLRMAxTIpLlfJa8Ipv/i56Re4lT07SYKIqQSh2eO0/eqYnujI35HF8O19jr9XBneRmt1je0d3ag63qy5ZIAvNObE+WKTJXKktENoVPsrCntdlsWFxbiNXNJyS3KdMUXxv8w6LzY7XZhmiYer9fBYOTzR5HL5XCzWsWxYhFnTs/gxcYGgiCAZVmOyhR5BVcm8nlZvbsi29+3ZdgGg4Gs1+viua4UJiZVpkiJeqo0VaIqxbGPSKfTORRduXQ59peLx5PyItWaj9yDQtmt21XYto1GoxGvbywtxaNhGHE3ab+V6L6aKYczPo7ZuTk8WnuIWq2G64vX4JU8zJw8BXXv5D21gx+xydrn7VEb/f0+tj5twa/4+Pz1C6Y4Oo6DZrOJdDrdYuxkIlKP+ZbZzoV7e8iyk8kD/9rdRXpkBJlMpsmDC/98I97pPF//AQUBl/2/jRvsm5b1kxmeJgJlfwQYAKZQxgzeI6/EAAAAAElFTkSuQmCC', gyfcat : 'https://gfycat.com/favicon.ico', imgur : 'https://imgur.com/favicon.ico' }, css: { load : 'data:image/gif;base64,R0lGODlhDgAKAJEAAP///+BKV////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAADgAKAAACHFSOeQYI71p6MtAJz41162yBH+do5Ih1kKG0QgEAIfkEBQoAAgAsAAABAA0ACAAAAhSUYGEoerkgdIzKGlu2ET/9ceJmFAAh+QQFCgACACwAAAEADQAIAAACFJRhcbmiglx78SXKYK6za+NxHyYVACH5BAUKAAIALAAAAQANAAgAAAIWVCSAl+hqEGRTLhtbdvTqnlUf9nhTAQAh+QQFCgACACwAAAEADQAIAAACFZRiYCh6uaCRzNXYsKVT+5eBW3gJBQAh+QQJCgACACwAAAAADgAKAAACGpSPaWGwfZhwQtIK8VTUvuxpm9Yp4XlmpiIUADs=' } }; YTMA.selector = { // to build the selector all: 'a[href*="youtube."], a[href*="youtu.be/"], a[href*="vimeo.com/"], a[href*="vine.co/"], a[href*="gfycat.com/"], a[href*=".webm"], a[href*=".mp4"], a[href*=".mp3"], a[href*=".gifv"], a[href*="soundcloud.com/"]', parentBlacklist: ['.smallfont', '.colhead_dark', '.spoiler', 'pre'], chrome37Blacklist: 'a[href*="pomf.se/"]', ignore: function () { var i, j, ignore = [], all = this.all.split(','), blacklist = this.parentBlacklist; for (i = 0; i < blacklist.length; i++) { for (j = 0; j < all.length; j++) { ignore.push(blacklist[i] + ' ' + all[j]); } } //console.log(ignore); return ignore.join(','); }, links: function () { var links; $$.x(YTMA.selector.ignore()).map(function (el) { el.setAttribute('ytmaignore', true); }); links = $$.x(YTMA.selector.all).filter(function (el) { var r = !el.hasAttribute('ytmaprocessed') && !el.hasAttribute('ytmaignore'); el.setAttribute('ytmaprocessed', true); return r; }); return links; }, processor: function () { var links = this.links(); if (links.length > 0) { if (window.chrome && (/(?:Chrome\/(\d+))/.exec(window.navigator.appVersion) && RegExp.lastParen < 38)) { $$.s(YTMA.selector.chrome37Blacklist, function (a) { if (/(?:\.webm)/i.test(a.href)) { a.dataset.ytmscroll = false; } }); } links.forEach(YTMA.create); } return links.length; } }; /** * User Preferences * size: Small (240p), Medium (360p), Large (480p), XL (720p) * ratio: 1 4:3, 2 16:9 * quality: 240, 360, 480, 720, 1080 * focus: 0/1; Will attempt to set the window's focus near the video * autoShow: 0/1; Will automatically display HTML5 videos, which currently lack descriptions and thumbnails * desc: (Descriptions) 0 None; 1 Yes on scroll; 2 Yes all at once * yt_nocookie: 0/1; Will disable/enable youtube-nocookie.com * yt_volume: positive number; youtube volume * yt_annotation: 0/1; youtube annotations */ YTMA.user = { KEY: 'ytmasetts', $form: null, init: function () { this.load(); if (strg.on) { this.fn.makeForm(); this.mark(); } }, valid: { focus: [0, 1], desc: [0, 1, 2], ratio: [1, 2], size: [240, 360, 480, 720], quality: [240, 360, 480, 720, 1080], autoShow: [0, 1], yt_nocookie: [0, 1], yt_annotation: [0, 1], // hide | show yt_volume: 100 // todo? function () { a = []; for (i = 0; i < 100; i++) { a[i] = i; } } }, mapping: { // map values to some other values used by an external API, for example yt_annotation: [3, 1] // 3 = hide | 1 = show }, validate: function (property, n) { n = +n; if (property === 'yt_volume') { return n >= 0 && n <= 100 ? (+n) : YTMA.user.defaults()[property]; } return YTMA.user.valid[property].indexOf(n) > -1 ? n : YTMA.user.defaults()[property]; }, defaults: function () { return { focus : 0, desc : 1, ratio : 2, size : 360, quality : 720, autoShow : 1, yt_nocookie : 0, yt_annotation : 1, yt_volume : 100 }; }, load: function () { var s = strg.grab(YTMA.user.KEY, {}); YTMA.user.preferences = { size : YTMA.user.validate('size', s.size), ratio : YTMA.user.validate('ratio', s.ratio), desc : YTMA.user.validate('desc', s.desc), focus : YTMA.user.validate('focus', s.focus), quality : YTMA.user.validate('quality', s.quality), autoShow : YTMA.user.validate('autoShow', s.autoShow), yt_nocookie : YTMA.user.validate('yt_nocookie', s.yt_nocookie), yt_annotation : YTMA.user.validate('yt_annotation', s.yt_annotation), yt_volume : YTMA.user.validate('yt_volume', s.yt_volume) }; $$.o(YTMA.user.mapping, function (key, val) { if (!val.hasOwnProperty('indexOf')) { YTMA.user.preferences[key] = val[YTMA.user.valid[key].indexOf(YTMA.user.preferences[key])]; } }); console.log('loaded: ', YTMA.user.preferences); }, mark: function () { var a = {}; a.ytma__focus = !!YTMA.user.preferences.focus; a.ytma__autoShow = !!YTMA.user.preferences.autoShow; a.ytma__yt_nocookie = !!YTMA.user.preferences.yt_nocookie; a.ytma__yt_annotation = !!YTMA.user.preferences.yt_annotation; a.ytma__yt_volume = YTMA.user.preferences.yt_volume; a['ytma__ratio' + YTMA.user.preferences.ratio] = true; a['ytma__size' + YTMA.user.preferences.size] = true; a['ytma__desc' + YTMA.user.preferences.desc] = true; a['ytma__quality' + YTMA.user.preferences.quality] = !!YTMA.user.preferences.quality; // console.log('marking', a); $$.o(a, function (id, val) { try { var el = document.getElementById(id); el.checked = val; el.value = val; } catch (e) { // console.log(id, e); } }); }, events: { save: function (e) { var o = {}; if (e && /(?:INPUT|LABEL)/i.test(e.target.nodeName)) { // console.log(YTMA.user.$form.querySelectorAll('[data-key]')); // [data-key]:checked $$.ary(YTMA.user.$form.querySelectorAll('[data-key]')).forEach(function (e) { var key; key = e.dataset.key; if (e.type === 'checkbox') { o[key] = +e.checked; } else if (e.type === 'radio') { if (e.checked) { if (e.hasAttribute('data-num')) { o[key] = +e.dataset.num; } } } else { o[key] = +e.value; } }); if (strg.save(YTMA.user.KEY, o)) { YTMA.user.load(); } else { YTMA.user.error.classList.remove('ytm_none'); } } }, reset: function () { YTMA.user.preferences = YTMA.user.defaults(); YTMA.user.mark(); strg.wipe(YTMA.user.KEY); YTMA.user.error.classList.add('ytm_none'); }, formToggle: function (e) { if (!e || (e && e.target && !/(?:INPUT|LABEL)/i.test(e.target.nodeName))) { YTMA.user.$form.classList.toggle('ytm_none'); } }, formToggleKeyboard: function (e) { // press CTRL+SHIFT+Y (META+SHIFT+Y) to display settings form if ((e.ctrlKey || e.metaKey) && e.shiftKey && String.fromCharCode(e.which).toLowerCase() === 'y') { e.preventDefault(); YTMA.user.events.formToggle(); } } }, fn: { $scroller: null, $once: false, loadPreferences: function () { if (YTMA.user.preferences.desc === 1) { YTMA.user.fn.onScrollViewDescriptions(); } this.loadPreferencesOnce(); }, loadPreferencesOnce: function () { if (this.$once) { return; } this.$once = true; if (YTMA.user.preferences.autoShow === 1) { YTMA.user.fn.onScrollViewMedia(); } }, showMedia: function () { console.log('showMedia'); return new YTMA.Scroll('a.ytm_scroll:not([data-ytmscroll="false"])', function (link) { if (YTMA.Scroll.visibleAll(link, 50)) { $$.s('var[data-ytmsid="' + link.dataset.ytmsid + '"]:not([data-ytmscroll="false"])', function (trigger) { var ui = YTMA.UI.createFromTrigger(trigger); ui.showOnScroll(link); }); } }); }, toggleMedia: function () { return new YTMA.Scroll('div.ytm_panel_switcher', function (div) { var v = div.querySelector('video'), paused = v && (v.paused || v.ended), ui = YTMA.set[div.dataset.ytmuid].getUI(); if (paused && !YTMA.Scroll.visibleAll(div, 0)) { return ui.play.switchStandby(); } if (ui.play.isStandby() && YTMA.Scroll.visibleAll(div, 200)) { return ui.play.switchOn(); } // todo ascertain embedded player properties // f = div.querySelector('iframe, object'); // if (f && !YTMA.Scroll.visibleAll(div, 200)) { // y.hidePlayer(); // } }); }, onScrollViewMedia: function () { this.showMedia(); this.toggleMedia(); }, onScrollViewDescriptions: function () { if (YTMA.user.fn.$scroller) { YTMA.user.fn.$scroller.stop(); } YTMA.user.fn.$scroller = new YTMA.Scroll('span.ytm_manual > a.ytm_title:not(.ytm_error)', function (a) { if (YTMA.Scroll.visibleAll(a, 200)) { YTMA.ajax.loadFromDataset(a.dataset); // console.log('doc', document.querySelectorAll(YTMA.user.fn.$scroller.selector).length, a.dataset.id); } if (document.querySelectorAll(YTMA.user.fn.$scroller.selector).length === 0) { YTMA.user.fn.$scroller.stop(); } }); }, makeForm: function () { var e, f = [ '
' ].join(''); YTMA.user.$form = $$.e('div', {className: 'ytm_fix_center ytm_none ytm_box', innerHTML: f}, document.body); YTMA.user.error = document.getElementById('ytm_settings_error'); e = YTMA.Scroll.debounce(YTMA.user.events.save, 500); YTMA.user.$form.addEventListener('submit', function (evt) { evt.preventDefault(); }, false); YTMA.user.$form.addEventListener('keyup', e, false); YTMA.user.$form.addEventListener('click', e, false); YTMA.user.$form.addEventListener('dblclick', YTMA.user.events.formToggle, false); document.getElementById('ytmaclose').addEventListener('click', YTMA.user.events.formToggle, false); document.getElementById('ytmareset').addEventListener('click', YTMA.user.events.reset, false); document.body.addEventListener('keydown', YTMA.user.events.formToggleKeyboard, false); } } }; YTMA.css = function () { var playerCss = YTMA.Player.css.generator(); // console.log(playerCss); update.css(playerCss); // images update.css([ '.ytm_loading{background:url(', YTMA.img.css.load, ') 0 3px no-repeat;}', '.ytm_link{background:url(', YTMA.img.fav.youtube, ') 0 center no-repeat !important;margin-left:4px;padding-left:20px!important;}', '.ytm_link.ytm_link_vimeo{background-image:url(', YTMA.img.fav.vimeo, ') !important;background-size:12px 12px !important;padding-left:18px!important}', '.ytm_link.ytm_link_vine{background-image:url(', YTMA.img.fav.vine, ') !important;background-size:10px 10px!important;padding-left:16px!important}', '.ytm_link.ytm_link_soundcloud{background-image:url(', YTMA.img.fav.soundcloud, ')!important;padding-left:17px!important}', '.ytm_link.ytm_link_html5{background-image:url(', YTMA.img.fav.html5, ') !important;padding-left:16px!important}', '.ytm_link.ytm_link_gfycat{background-image:url(', YTMA.img.fav.gyfcat, ') !important;background-size:12px 12px !important;padding-left:16px!important;}', '.ytm_link.ytm_link_imgur{background-image:url(', YTMA.img.fav.imgur, ') !important;background-size:12px 12px !important;padding-left:16px!important}' ].join('')); // todo // if (window.NO_YTMA_CSS) { return; } update.css('.ytm_none,.ytm_link br{display:none!important}.ytm_box{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.ytm_block{display:block;position:relative;clear:both;text-align:left;border:0;margin:0;padding:0;overflow:hidden}.ytm_normalize{font-weight:400!important;font-style:normal!important;line-height:1.2!important}.ytm_sans{font-family:Arial,Helvetica,sans-serif!important}.ytm_spacer{overflow:auto;margin:0 0 6px;padding:4px}.ytm_spacer.ytm_site_slim{display:inline}.ytm_clear:after{content:"";display:table;clear:both}.ytm_center{text-align:center}.ytm_link b,.ytm_link strong{font-weight:400!important}.ytm_link u{text-decoration:none!important}.ytm_link i,.ytm_link em{font-style:normal!important}.ytm_trigger{width:118px;height:66px;background-color:#262626!important;cursor:pointer;background-position:-1px -12px;float:left;box-shadow:2px 2px rgba(0,0,0,.3);background-size:auto 90px!important;color:#fff;text-shadow:#333 0 0 2px;font-size:13px}.ytm_trigger:hover{box-shadow:2px 2px #9eae9e;opacity:.95}.ytm_trigger var{z-index:2;height:100%;width:100%;position:absolute;left:0;top:0;text-align:right}.ytm_label{display:block;padding:3px 6px;line-height:1.2;font-style:normal}.ytm_init{height:22px;background:rgba(11,11,11,.62);padding:4px 25px 6px 6px}.ytm_site_vine .ytm_trigger{background-color:#90ee90!important;background-size:120px auto!important}.ytm_site_slim .ytm_trigger{background:#e34c26!important;height:auto;box-shadow:0 0 2px #ffdb9d inset,2px 2px rgba(0,0,0,.3);margin:0 3px 0 0;width:auto;transition:all .3s ease-in-out 0s}.ytm_site_slim .ytm_trigger:hover{opacity:.8}.ytm_site_slim .ytm_label{text-shadow:0 0 1px #f06529}.ytm_site_slim .ytm_init{background:transparent}.ytm_bd{float:left;max-width:500px;margin:2px 10px;font-size:90%}.ytm_title{font-weight:700}.ytm_error{color:#cc2f24;font-style:italic}.ytm_loading{font-style:italic;padding:1px 1.5em}.ytm_descr{word-wrap:break-word;max-height:48px;overflow:auto;padding-right:20px}.ytm_descr[data-full]{cursor:pointer}.ytm_descr_open{resize:both;white-space:pre-line}.ytm_descr_open[style]{max-height:none}.ytm_projector{margin-bottom:4px}ul.ytm_control{overflow:hidden;margin:0!important;padding:3px 0 1px;list-style-position:outside!important}.ytm_control li{display:inline;margin:0!important;padding:0!important}.ytm_control li>ul{display:inline-block;margin:0;padding:0 1px 0 0}.ytm_control li ul li{-webkit-user-select:none;-moz-user-select:none;-o-user-select:none;user-select:none;list-style-type:none;cursor:pointer;float:left;color:#858585;border:1px solid #1d1d1d;border-bottom:1px solid #000;border-top:1px solid #292929;box-shadow:0 0 1px #555;height:14px;font-size:12px!important;line-height:12px!important;background:#222;background:linear-gradient(#2d2c2c,#222);margin:0!important;padding:5px 9px 3px!important}.ytm_control li ul li:first-child{border-radius:2px 0 0 2px}.ytm_control li ul li:last-child{border-left:0!important;border-radius:0 2px 2px 0;margin:0 2px 0 0!important}.ytm_control li ul li:first-child:last-child,.ytm_li_setting{border-radius:2px}.ytm_control li ul li:hover{color:#ccc;text-shadow:1px 1px 0 #333;background:#181818}.ytm_control li ul li[id]{color:#ddd;text-shadow:0 0 2px #444}.ytm_panel_size{background:#000}.ytm_panel_switcher[data-standby="true"]{background:#111}.ytm_panel_switcher[data-standby="true"]:after{cursor:cell;color:#0e0e0e;content:"ytma!";display:block;font-size:85px;font-style:italic;font-weight:700;left:50%;position:absolute;text-shadow:2px 1px #181818,-1px -1px #0a0a0a;top:50%;transform:translate(-50%,-50%)}.ytm_site_soundcloud .ytm_panel_size.ytm_soundcloud-playlist{height:334px!important}.ytm_fix_center{background:rgba(51,51,51,.41);height:100%;left:0;position:fixed;top:0;width:100%;z-index:99998}#ytm_settings{z-index:99999;max-width:500px;max-height:85%;overflow:auto;background:#fbfbfb;border:1px solid #bbb;color:#444;box-shadow:0 0 5px rgba(0,0,0,.2),0 0 3px rgba(239,239,239,.1) inset;margin:4% auto;padding:4px 8px 0}#ytm_settings p{margin:5px 0;padding:0}#ytm_settings fieldset{vertical-align:top;border-radius:3px;border:1px solid #ccc;margin:0 0 5px}#ytm_settings fieldset span{display:inline-block;min-width:5em}#ytm_settings input{vertical-align:baseline!important;margin:3px 5px!important}#ytm_settingst{font-size:110%;border-bottom:1px solid #d00;margin:3px 0 9px;padding:0 3px 3px}#ytm_settings label{cursor:pointer}#ytm_settings small{font-size:90%}#ytm_opts button{cursor:pointer;margin:10px 5px 8px 2px;padding:3px;border:1px solid #adadad;border-radius:2px;background:#eee;font-size:90%}#ytm_opts button:hover{background:#ddd}'); }; YTMA.ajax = { load: function (site, id, uri) { var cache = YTMA.external.dataFromStorage(site, id); console.log('YTMA.ajax.load:', site, id, uri); console.log('@cache:', cache); if (cache) { return YTMA.external.populate(cache); } if (YTMA.DB.ajaxExtension[site]) { return this.gmxhr(uri, site, id); } console.log('ajax.site?', YTMA.DB.ajax[site].replace('%key', id).replace('%uri', uri)); if (YTMA.DB.ajax[site]) { console.log('preping uri'); uri = YTMA.DB.ajax[site].replace('%key', id).replace('%uri', uri); return this.xhr(uri, site, id); } return null; }, loadFromDataset: function (dataset) { return this.load(dataset.ytmsite, dataset.ytmid, dataset.ytmuri); }, gmxhr: function (uri, site, id) { try { // alert('gmxhr starting!'); // console.log('gmxhr starting!'); GM_xmlhttpRequest({ method: 'GET', url: uri, onload: function (response) { console.log(response); YTMA.external.parse(response.responseText, site, id); }, onerror: function () { console.log('GM Cannot XHR'); YTMA.ajax.failure.call({id: id}); } }); YTMA.ajax.preProcess(id); } catch (e) { if (YTMA.DB.extension) { console.log('attempting cs xhr'); this.xhr(uri, site, id); } else { console.log('No applicable CORS request available.'); this.failure.call({id: id}); } } }, xhr: function (uri, site, id) { var x = new XMLHttpRequest(); console.log('xhr', uri, id, site); YTMA.ajax.preProcess(id); x.onreadystatechange = function () { if (this.readyState === this.DONE) { // console.log(this.readyState, this.status); if (this.status === 200) { YTMA.external.parse(this.responseText, site, id); } else if (this.status === 403) { YTMA.external.populate({site: site, id: id, title: 'Error 403', desc: ''}); YTMA.external.save({site: site, id: id, title: 'Error 403', desc: ''}); } else { // if (this.status >= 400 || this.status === 0) { YTMA.ajax.failure.call({id: id}); } } }; try { console.log('sending'); x.open('get', uri, true); x.send(); } catch (e) { console.error('Cannot send xhr', uri); YTMA.ajax.failure.call({id: id}); throw e; } }, failure: function () { $$.s('.ytm_bd._' + YTMA.escapeId(this.id), function (el) { var a = el.querySelector('a'); a.dataset.tries = a.dataset.tries ? parseFloat(a.dataset.tries) + 1 : 1; a.textContent = 'Error, unable to load data. [Retry ' + (a.dataset.tries > 0 ? a.dataset.tries : '') + ']'; a.className = 'ytm_error ytm_title'; }); }, preProcess: function (id) { $$.s('.ytm_manual._' + YTMA.escapeId(id) + ' a', function (el) { el.classList.add('ytm_loading'); el.textContent = 'Loading data . . .'; el.title = 'Retry loading data.'; }); } }; /** E X T E R N A L Apparatus * Data from external sites */ YTMA.external = { version: 'ytma.4.1.dat', parse: function (response, site, id) { if (this.parsers[site]) { response = YTMA.DB.ajax[site] ? JSON.parse(response) : response; this.populate(this.helper.cutDescription(this.parsers[site](response, id))); } }, parsers: { soundcloud: function (j, id) { return { site: 'soundcloud', id: id, //unescape(j.html).match(/tracks\/(\d+)/)[1], title: j.title, desc: j.description, th: YTMA.reg.fix.$removeSearch(j.thumbnail_url) }; }, vimeo: function (j) { j = j[0]; return { site: 'vimeo', id: j.id, title: j.title + ' ' + YTMA.external.helper.time(j.duration), desc: j.description.replace(/