// ==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 5.1 // @description ytma! automatically converts YouTube(TM), Vimeo, Vine, Soundcloud, WebM, and MP4 links into real embedded videos. // @homepage https://userscripts.org/scripts/show/60843 // @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 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 21 July 2014 | // -updated 24 Aug 2013 | 17,400 // -updated 04 June 2013 | 13,586 // @grant GM_xmlhttpRequest // @downloadURL none // ==/UserScript== /** Whitelist these sites on NoScript/NotScript/etc. neogaf.com youtube.com youtube-nocookie.com vimeo.com vimeocdn.com vineco.com soundcloud.com vine.com vine.co gfycat.com dropboxusercontent.com */ /*jslint indent: 4, maxerr: 50, browser: true, devel: true, nomen: true, plusplus: true, regexp: true, newcap: true */ (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); } // DOM 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++) { f.appendChild(arguments[i]); } e.appendChild(f); return e; }, e: function (t, o, e, p) { var a, b, c = document.createElement(t); if (typeof (o) === 'object') { for (a in o) { if (o.hasOwnProperty(a)) { b = a.charAt(0); switch (b) { case '_': c.style[a.substring(1)] = o[a]; break; case '$': c.setAttribute(a.substring(1), o[a]); break; default: c[a] = o[a]; break; } } } } if (e && p) { c.appendChild(e); } else if (e) { e.appendChild(c); } return c; } }; // S T O R A G E HANDLE strg = { on: (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; } }; // 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 * Should not be used directly, only through YTMA.create() * @param id Unique ID * @param site Website eg: youtube, vimeo * @param a Anchor element */ function YTMA(id, site, a, uid) { this.data = { id: id, uid: YTMA.escapeId(uid), sid: YTMA.escapeId(id), site: site, uri: a.href }; this.a = a; this.spn = $$.e('span', {title: 'YTMA!', className: 'ytm_links', '$data-ytmid': this.data.id, '$data-ytmuid': this.data.uid}); this.spn.addEventListener('click', this.show.bind(this), false); this.wrp = $$.e('div', {className: 'ytm_wrap'}); this.wrs = $$.e('div', {id: 'w' + this.data.uid, className: 'ytm_clear ytm_site_' + this.data.site}); this.ul = $$.e('ul', {className: 'ytm_bar arialsans'}); this.setup(a); } YTMA.num = 0; YTMA.create = function (link) { var data = YTMA.getIdAndSite(link.href), id; if (data.valid === true) { id = YTMA.escapeId(data.id + '_' + (YTMA.num += 1)); YTMA.set[id] = new YTMA(data.id, data.site, link, id); return YTMA.set[id]; } return {}; }; YTMA.getIdAndSite = function (uri) { var id, site; try { site = YTMA.reg.siteByTest[YTMA.reg.site.test(uri) ? RegExp.lastMatch : '']; // console.log(uri, site); if (site === 'html5') { id = uri.slice(-15); } else if (site === 'soundcloud') { id = YTMA.escapeId(uri).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: ' + site + ' % ' + id); } catch (e) { // console.info(uri, e); return {valid: false}; } }; YTMA.route = { host: document.location.host, control: { go: function (host) { (this[host] || this.generic)(); }, generic: function () { if (!YTMA.DB.extension) { update.check(); } YTMA.user.init(); YTMA.css(); YTMA.ajaxQueue.init(); YTMA.factory(); }, 'gfycat.com': function () { update.css('body,html {overflow:hidden} video {width: 100% }'); }, 'vine.co': function () { // console.log('vine.co'); // YTMA.user.init(); // if (YTMA.user.preferences.autoShow === 1) { return; } var video = document.getElementById('video'); if (video) { video.muted = false; } } }, start: function () { this.control.go(this.host); } }; YTMA.main = function () { if (!this.initializer) { this.initializer = true; YTMA.route.start(); } }; 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 : /(youtu)|(vimeo)|(vine)|(soundcloud)|(gfycat)|(\.webm$)|(\.mp4$)/, time : /(?:t\=(?:(\d+)m)?(\d+)?s?)/, ios : /(?:\b(?:ipod|iphone|ipad))\b/i, matchers: { youtubeOld: /(?:(?:youtu)(?:\.be\/|.*?(?:v\=|#p\/u\/\d*?\/)|.*?(?:v\=|#p\/c\/[a-zA-Z0-9]+\/\d*?\/)|.*?(?:embed\/))([A-Za-z0-9-_]{11}))/i, youtube: /(?:(?:(?:v\=|#p\/u\/\d*?\/)|(?:v\=|#p\/c\/[a-zA-Z0-9]+\/\d*?\/)|(?:embed\/)|(?:\.be\/))([A-Za-z0-9-_]{11}))/i, vimeo: /(?:vimeo\.com\/(\d+))/i, vine: /(?:vine\.co\/v\/([A-Za-z0-9-_]{11}))/i, soundcloud: /(?:soundcloud\.com\/(.+?\/.+))/i, gfycat: /(?:gfycat.com\/(\w+))/i // /(?:gfycat.com\/(.+)(?!\.))/i }, siteByTest: { youtu: 'youtube', vimeo: 'vimeo', vine: 'vine', gfycat: 'gfycat', '.webm': 'html5', '.mp4': 'html5', soundcloud: 'soundcloud' } }; YTMA.img = { fav: { soundcloud : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAwAAAAMCAYAAABWdVznAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAXZJREFUeNp0UjFOw0AQnD3bCYaEoIgiUIQKikiAKKGgSAkFL0BQ0FEgUfECShpewB+QEE+gokDiBxGRiCCEBBzHd8ucLYGQ4Kw7+9azc7OzJ6oKnFYUxgD+W/DHYNA54GIooifTitYqg1okaPFff6BcTLF5fECYb5IJNJ3kMfUP2dxHPycwcQ0SliARocSGsA46YkKWQW0GS6BDAGlu5Myu84AgSmHKM/DY0NegwwR2+AJrSjBre5BaA1H7GFKpI729QHp9jqiaeTBn5mB7fWirjWB9B9JYBrwEMnop5d0zfD53YO9vYMY8SQcpZGkTZvsIstiivDfoaxfIxt8exYeXCLYOSOwlJZQ6twSpL0DfX4EoZtkCqc7/Njalbxnfdt+oSwhurkBnCWI/1FlgqgKNZ3JnZDSA3FFSpYdQAoF56tKNDmhOYTzJ3OSHXZkflJhYEyawcnH02HpmxZ+DrRJlgmacvrsHRmHln2tRnIiAy5WTLwEGAK4QoBQmtGHkAAAAAElFTkSuQmCC', youtube : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAABUUlEQVQ4y8WTP0sDQRDFf3e3iQlBIQeCYAgaEVGMTRr9AKnERtTCwg9hYWkRBBEFEf+g4OcwgWgTRSy0EhTBKmAnsYiex2Yva2GUZCMRKxceu8O893YGZuC/j3XlxqLAMTACpIHwL5pbQAJ3k5W3JaE0q8DiHz5NN+7MRTz2ZCt0VqFpRhAOMbR3SCiVwswZyNo1SNaAZgSRCO7cAhOnJeKz85j5JiRtqXGlhma818H3faRtM7i9y8DWDqorgsmTGldIcNrb1Hie9x11T8+QCAIeV5ZNoiNqWrfL660GL+UypYN9Ej9whYQAowqNxvd9AO4Lec7X1xiVPtKyTH0gpKYC9LYYqDpetcrZ5gbP+RPGhY2DhWwvoGId9USvgUyLLXApFcPCoc+2Os3EjVDoomkAMBX+7EqhOxkUhdLkgH5g7GvCOggegNfGuwDk/n0Z+QAjkqDhSKnyRwAAAABJRU5ErkJggg==', vimeo : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABhQTFRFutjhDKrTKqzN+Pz9H5CxT7nVis7g////lqc5nAAAAAh0Uk5T/////////wDeg71ZAAAAP0lEQVR42iTMyREAMAgCQASP/jsOGj7s8AATPxzwUDai0AG1SQhsYdeEolVLt8c8llZHYuXyTeb9YYo/8wQYAC81AOQXjj+CAAAAAElFTkSuQmCC', vine : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABcklEQVQ4jX2SvyvFYRTGP+9NdzAYbpIkysA/ICnKoEwvA4vlUkoyGQzvoOiK4R0YbDLhDhbi9maWIjEqcScWkyRhMNzXcM/3On39OMt5nvOe85wfvSbGyH9mgs8Cq8AUkAMegU1gJVpXqfu3umpbwITiLUBB8HJGuryb4KMJ/izVvUMVnwNjwJPwGYCMkLL4zlT3XoUL0boD4FBNUhO4Fd9ogm9SRVmFn8Una79qgWuV2K3wvcLJdG3iL7TaiUocAI4Fn0vnHDBrgt+L1g2q3NoEl8CH4KHkMVr3CSwI7QeOTPA9WsAk/8AEvw+MSrwrWleuJQVfABZJWbTOZBTfVXg6lbgEHKjQTcL1BFngAWimeuH2aN2LvHUDV1JcjNbl0zdI9l0T2pDsboKvB7Yl/ga4X2+gku+AVqAC9AFzwLik5KN1xT8FRGQEOBL6yfdn2onWTZKyTDoQrSsB60KT4lNSh/1TQETmgQ1ZowQMy41+2BeLRXeRaKuHSAAAAABJRU5ErkJggg==' }, css: { load : 'data:image/gif;base64,R0lGODlhDgAKAJEAAP///+BKV////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAADgAKAAACHFSOeQYI71p6MtAJz41162yBH+do5Ih1kKG0QgEAIfkEBQoAAgAsAAABAA0ACAAAAhSUYGEoerkgdIzKGlu2ET/9ceJmFAAh+QQFCgACACwAAAEADQAIAAACFJRhcbmiglx78SXKYK6za+NxHyYVACH5BAUKAAIALAAAAQANAAgAAAIWVCSAl+hqEGRTLhtbdvTqnlUf9nhTAQAh+QQFCgACACwAAAEADQAIAAACFZRiYCh6uaCRzNXYsKVT+5eBW3gJBQAh+QQJCgACACwAAAAADgAKAAACGpSPaWGwfZhwQtIK8VTUvuxpm9Yp4XlmpiIUADs=' } }; YTMA.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*="soundcloud.com/"]', parentBlacklist: ['.smallfont', '.colhead_dark', '.spoiler'], chromeBlacklist: 'a[href*="pomf.se/"]' }; YTMA.selector.ignore = (function (all, blacklist) { var i, j, ignore = []; 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(','); }(YTMA.selector.all.split(','), YTMA.selector.parentBlacklist)); YTMA.links = (function () { var links = []; $$.s(YTMA.selector.ignore, function (el) { el.setAttribute('ytmaignore', true); }); if (window.chrome) { $$.s(YTMA.selector.chromeBlacklist, function (el) { if (/(?:.\webm)/i.test(el.href)) { el.dataset.scroll = false; } }); } $$.s(YTMA.selector.all, function (el) { if (!el.hasAttribute('ytmaignore')) { links.push(el); } }); return links; }()); YTMA.factory = function () { if (YTMA.links.length === 0) { return; } YTMA.links.forEach(YTMA.create); if (YTMA.user.preferences.desc === 1) { YTMA.user.fn.onScrollViewDescriptions(); } if (YTMA.user.preferences.desc === 2) { YTMA.ajax.start(); } if (YTMA.user.preferences.autoShow === 1) { YTMA.user.fn.onScrollViewMedia(); } }; YTMA.escapeId = function (id) { return (id += '').replace(/(?:\W)/g, '_'); }; /** * User Preferences * flash: 0 "Frame"; 1 "Object" * 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 */ YTMA.user = { init: function () { this.load(); if (strg.on) { this.form(); this.mark(); } }, valid: { focus: [0, 1], desc: [0, 1, 2], flash: [0, 1], ratio: [1, 2], size: [240, 360, 480, 720], quality: [240, 360, 480, 720, 1080], autoShow: [0, 1] }, validate: function (property, n) { n = +n; return YTMA.user.valid[property].indexOf(n) > -1 ? n : YTMA.user.defaults()[property]; }, defaults: function () { return { focus : 0, desc : 1, flash : YTMA.DB.browser.pod || YTMA.DB.browser.ie ? 0 : 1, // if iOS or IE9+, use "html5" player ratio : 2, size : 360, quality : 360, autoShow : 1 }; }, load: function () { var s = strg.grab('ytmasetts', {}); YTMA.user.preferences = { flash : YTMA.user.validate('flash', s.flash), 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) }; // console.log(YTMA.user.preferences); }, save: function (evt) { var e = evt.target; if (e.tagName.toLowerCase() === 'input') { switch (e.name) { case 'ytmaflash': YTMA.user.preferences.flash = +e.checked; break; case 'ytmasize': YTMA.user.preferences.size = +e.value; break; case 'ytmaratio': YTMA.user.preferences.ratio = +e.value; break; case 'ytmainfo': YTMA.user.preferences.desc = +e.value; break; case 'ytmafocus': YTMA.user.preferences.focus = +e.checked; break; case 'ytmaiq': YTMA.user.preferences.quality = +e.value; break; case 'ytmaautoshow': YTMA.user.preferences.autoShow = +e.checked; break; default: return; } YTMA.user.error.className = strg.save('ytmasetts', YTMA.user.preferences) ? 'ytm_none' : ''; YTMA.user.load(); // console.log('n', YTMA.user.preferences); } }, mark: function () { var a = {}; a.ytmaflash = !!YTMA.user.preferences.flash; a.ytmafocus = !!YTMA.user.preferences.focus; a.ytmaautoshow = !!YTMA.user.preferences.autoShow; a['ytmaratio' + YTMA.user.preferences.ratio] = true; a['ytmasize' + YTMA.user.preferences.size] = true; a['ytmainfo' + YTMA.user.preferences.desc] = true; a['ytmaiq' + YTMA.user.preferences.quality] = !!YTMA.user.preferences.quality; $$.o(a, function (id, bool) { try { document.getElementById(id).checked = bool; } catch (e) {} }); }, reset: function () { YTMA.user.preferences = YTMA.user.defaults(); YTMA.user.mark(); strg.wipe('ytmasetts'); }, form: function () { var f = [ '
ytma! Site Settings
', '
Get Descriptions

', '
Flash Support

', '
Player Size

', '
Quality

', '
Aspect Ratio

', '
Player On Scroll

', '
Window Focus

', '

Error! Your settings could not be saved.

Close Reset *Disable this option for iOS and other devices.

' ].join(''); YTMA.form = $$.e('div', {className: 'ytm_fix_center ytm_none', innerHTML: f}, document.body); YTMA.user.error = document.getElementById('ytm_settings_error'); YTMA.form.addEventListener('click', YTMA.user.save, false); document.getElementById('ytmaclose').addEventListener('click', YTMA.user.fn.formToggle, false); document.getElementById('ytmareset').addEventListener('click', YTMA.user.reset, false); document.body.addEventListener('keydown', YTMA.user.fn.formToggleKey, false); }, fn: { formToggleKey: function (e) { // press CTRL+SHIFT+Y (or META instead of CTRL) to display settings form if ((e.ctrlKey || e.metaKey) && e.shiftKey && String.fromCharCode(e.which).toLowerCase() === 'y') { e.preventDefault(); YTMA.user.fn.formToggle(); } }, formToggle: function () { YTMA.form.classList.toggle('ytm_none'); }, showMedia: function () { return new YTMA.Scroll('.ytm_scroll:not([data-scroll="false"])', function (link) { if (YTMA.Scroll.visibleAll(link, 50)) { $$.s('a[data-ytmsid="' + link.dataset.ytmsid + '"]:not([data-scroll="false"])', function (a) { var y = YTMA.set[a.dataset.ytmuid]; if (!y.data.open) { // console.log('show'); y.show(); } }); } }); }, toggleMedia: function () { return new YTMA.Scroll('.ytm_wrap .ytm_player', function (div) { var v = div.querySelector('video'), paused = v && (v.paused || v.ended), y = YTMA.set[div.dataset.ytmuid]; if (paused && !YTMA.Scroll.visibleAll(div, 0)) { return y.player.switchToPlaceholder(); } if (y.player.isPlaceholder() && YTMA.Scroll.visibleAll(div, 200)) { return y.player.switchToMedia(); } // todo ascertain embedded player properties // f = div.querySelector('iframe, object'); // if (f && !YTMA.Scroll.visibleAll(div, 200)) { // y.toggle(); // } }); }, onScrollViewMedia: function () { this.showMedia(); this.toggleMedia(); }, onScrollViewDescriptions: function () { var scroller = new YTMA.Scroll('.ytm_manual a:not(.ytm_error)', function (a) { if (YTMA.Scroll.visibleAll(a, 200)) { var d = a.dataset; YTMA.ajax.load(d.site, d.id, d.uri); // console.log('doc', document.querySelectorAll(scroller.selector).length, a.dataset.id); } if (document.querySelectorAll(scroller.selector).length === 0) { scroller.stop(); } }); } } }; YTMA.css = function () { update.css(['\n/* ytma! */\n.ytm_clear,.ytm_wrap,.ytm_video{position:relative;clear:both;text-align:left;border:0;margin:0;padding:0;display:block}.ytm_clear{overflow:auto;margin:0 0 6px}#ytm_settings,.arialsans{font-family:Arial,Helvetica,sans-serif!important}.ytm_links{line-height: 1.2;display:block;width:118px;height:66px;overflow:hidden;font-style:normal;background-color:#262626!important;cursor:pointer;background-position:-1px -12px;position:relative;float:left;box-shadow:2px 2px rgba(0, 0, 0, 0.3);margin:4px;background-size:auto 90px !important;}.ytm_links:hover{box-shadow: 2px 2px #9eae9e;opacity:.95}.ytm_links img{border:0;opacity:1;top:28px;left:42px;z-index:9;position:absolute}.ytm_links:hover img{opacity:.9}.ytm_init{display:block;background:rgba(11, 11, 11, 0.62);color:#fff;text-shadow:#333 0 0 2px;text-align:left;font-size:11px;margin:0;padding:3px 6px;height:12px;}.ytm_wrap{overflow:hidden;font-style:normal;margin:3px 0 0;padding:1px 2px} ul.ytm_bar{overflow:hidden;margin:0 !important;padding:3px 0 1px;list-style-position:outside !important}.ytm_bar li{display: inline;margin:0!important;padding:0!important}.ytm_bar li > ul {display: inline-block; margin: 0; padding: 0 1px 0 0;}.ytm_bar 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, #222222);margin:0 !important;padding:5px 9px 3px !important}.ytm_bar li ul li:first-child{border-radius:2px 0 0 2px}.ytm_li_mid{border-left:0!important}.ytm_bar li ul li:last-child{border-left:0!important;border-radius:0 2px 2px 0;margin:0 2px 0 0 !important}.ytm_bar li ul li:first-child:last-child{border-radius: 2px;}.ytm_li_setting{border-radius:2px}.ytm_bar li ul li:hover{color:#ccc;text-shadow:1px 1px 0 #333;background:#181818} .ytm_bar li ul li[id]{color:#ddd;text-shadow:0 0 2px #444} .ytm_loading{font-style:italic;background:url(', YTMA.img.css.load, ') 0 3px no-repeat;padding: 1px 1.5em}.ytm_link{background:url(', YTMA.img.fav.youtube, ') 2px -1px no-repeat !important;border-radius:1px;padding:0 3px 0 21px !important}.ytm_link.ytm_link_vimeo{background:url(', YTMA.img.fav.vimeo, ') 3px 2px no-repeat !important;padding:0 3px 0 16px !important}.ytm_link.ytm_link_vine{background:url(', YTMA.img.fav.vine, ') 3px 2px no-repeat !important;background-size: 10px 10px !important;padding:0 3px 0 16px !important}.ytm_link.ytm_link_soundcloud{background:url(', YTMA.img.fav.soundcloud, ') 1px 1px no-repeat !important;padding:0 0 0 16px !important}.ytm_link b,.ytm_link strong{font-weight:400!important}.ytm_link u{text-decoration:none}.ytm_link i,.ytm_link em{font-style:normal}.ytm_link:hover{background-color:#fff}.ytm_title{float:left;max-width:500px;font-style:normal;font-weight:700;margin:5px 0 0 3px;font-size:.9em}.ytm_error{color:#CC2F24;font-style:italic} q[ondblclick]{cursor:pointer}.ytm_descr{display:block;word-wrap:break-word;font-weight:400;max-height:48px;overflow:auto;padding-right:20px}.ytm_descr_open{resize:both;white-space:pre-line;}.ytm_descr_open[style]{max-height:none}#ytm_settings{z-index: 99999;font-size:12px;max-width:410px;border-radius:3px;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:10% auto;padding:4px 8px 0}#ytm_settings *{font-weight:400}#ytm_settings p{font-size:12px;clear:both;margin:5px 0;padding:0}#ytmaclears{overflow:hidden}#ytm_settings fieldset{vertical-align:top;border-radius:3px;border:1px solid #ccc;display:inline-block;width:180px;margin:0 2px}#ytm_settings p>input{margin:3px 3px 0 4px !important}#ytm_settings p>span>input[type=radio]{margin:3px 5px!important}#ytm_settingst{font-size:14px;border-bottom:1px solid #D00;margin:3px 0 9px;padding:0 3px 3px}#ytm_settings .ytmahalf{width:80px;display:inline-block}#ytm_settings .ytmahalf label{width:50px;display:inline-block;cursor:pointer}#ytm_settings_error{font-weight:700;color:#d00}#ytm_settings small{font-size:11px}#ytm_opts small[id]{cursor:pointer;display:inline-block;margin:10px 5px 8px 2px;padding:0 3px; border: 1px solid #adadad; border-radius:2px}#ytm_opts small[id]:hover{background:#ddd}.ytm_none,.ytm_link br{display:none} .ytm_fix_center {position:fixed; left:0; top:0; height:90%; width:90%}', '.ytm_video{background:#000}.ytm_placeholder[data-empty="true"]{background:#111}.ytm_placeholder[data-empty="true"]:after{cursor:cell; color: #0E0E0E; content: "YTMA!"; display: block; font-size: 85px; font-style: italic; font-weight: bold; left: 50%; position: absolute; text-shadow:2px 1px #181818, -1px -1px #0A0A0A; top: 50%; transform: translate(-50%, -50%); }', '.ytm_player_s .ytm_video {width:426px;height:240px} .ytm_player_m .ytm_video {width:640px;height:360px} .ytm_player_l .ytm_video {width:853px;height:480px} .ytm_player_xl .ytm_video {width:1280px;height:720px}', '.ytm_player_s.ytm_player_sd .ytm_video{width:320px} .ytm_player_m.ytm_player_sd .ytm_video{width:480px} .ytm_player_l.ytm_player_sd .ytm_video{width:640px} .ytm_player_xl.ytm_player_sd .ytm_video{width:960px}', '.ytm_player_s.ytm_player_pr .ytm_video{height:320px;width:180px} .ytm_player_m.ytm_player_pr .ytm_video{height:480px;width:270px} .ytm_player_l.ytm_player_pr .ytm_video{height:640px;width:360px} .ytm_player_xl.ytm_player_pr .ytm_video{height:960px;width:540px}', '.ytm_site_vine .ytm_links {background-color:lightgreen !important;background-size: 120px auto !important;}', '.ytm_site_vine .ytm_player_s .ytm_video{width:240px;height:240px} .ytm_site_vine .ytm_player_m .ytm_video{width:360px;height:360px} .ytm_site_vine .ytm_player_l .ytm_video{width:480px;height:480px} .ytm_site_vine .ytm_player_xl .ytm_video{width:720px;height:720px}', '.ytm_site_vine .ytm_bar :first-child ul, .ytm_site_soundcloud .ytm_bar ul:not(.ytm_options){display:none} .ytm_site_soundcloud .ytm_video{height: 81px !important;}', '.ytm_link.ytm_link_html5 {background: none !important;margin:0 4px;padding: 0 !important;} .ytm_clear.ytm_site_slim {display:inline} .ytm_site_slim .ytm_links{background:#E34C26 !important;height: auto;box-shadow: 0 0 2px #FFDB9D inset, 2px 2px rgba(0, 0, 0, 0.3); margin: 0 3px 0 0;width: auto; transition:all 0.3s ease-in-out 0s} .ytm_site_slim .ytm_links:hover { opacity:.8 } .ytm_site_slim .ytm_init{background:transparent;text-shadow:0 0 1px #f06529;border: 1px solid #f06529; padding: 2px 5px}.ytm_init:after{ content: "\\25B6"; float: right; font-size: 110%;line-height:1em; padding: 0 0 0 6px; }', '.ytm_player_h{height:0 !important;width:0 !important}'].join('')); }; YTMA.ajaxQueue = { init: function () { $$.o(YTMA.DB.ajax, function (site) { YTMA.ajaxQueue.sites[site] = { set: {}, current: 0, length: 0, throttle: null, timeout: 10000 }; }); }, sites: {}, add: function (site, id, uri) { if (this.sites[site] && !this.sites[site].set[id]) { this.sites[site].set[id] = uri; this.sites[site].length += 1; } }, remove: function (site, id) { if (this.sites[site] && this.sites[site].set[id]) { delete this.sites[site].set[id]; this.sites[site].length -= 1; } } }; YTMA.ajax = { maxBatch: 50, interval: 250, start: function () { var time = 100; if (YTMA.ajaxQueue.sites.youtube.length > 100) { time = 2500; YTMA.ajaxQueue.sites.youtube.timeout = 15000; } $$.o(YTMA.DB.ajax, function (site) { return new YTMA.ajax.Batch(site, time); }); }, load: function (site, id, uri) { var cache = YTMA.external.dataFromStorage(site, id); // console.log('load', site, id, uri, cache); if (cache) { return YTMA.external.populate(cache); } if (YTMA.DB.csr[site]) { return this.gmxhr(uri, site, id); } if (YTMA.DB.ajax[site]) { uri = YTMA.DB.ajax[site].replace('%key', id).replace('%uri', uri); return this.xhr(uri, site, id); } }, gmxhr: function (uri, site, id) { if (typeof GM_xmlhttpRequest === 'function') { // alert('gmxhr starting!'); // console.log('gmxhr starting!'); YTMA.ajax.preProcess(id); GM_xmlhttpRequest({ method: 'GET', url: uri, onload: function (response) { YTMA.external.parse(response.responseText, site, id); }, onerror: function () { // console.log('GM Cannot XHR'); YTMA.ajax.failure.call({id: id}); } }); } else if (YTMA.DB.extension) { // console.log('attempting cs xhr'); this.xhr(uri, site, 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 { x.open('get', uri, true); x.send(); } catch (e) { // console.error('Cannot send xhr', e.message); YTMA.ajax.failure.call({id: id}); } }, failure: function () { $$.s('.ytm_title._' + 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'; }); }, 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.'; }); } }; /** B A T C H Class * Creates and loads Cross-site XHR in batches * @param site Site * @param time Milliseconds to start loading the queue */ YTMA.ajax.Batch = function (site, time) { this.site = site; this.queue = YTMA.ajaxQueue.sites[site]; // console.log(site, this.queue); this.descriptionsFromStorage(); if (YTMA.user.preferences.desc === 2) { this.pause(time); } }; YTMA.ajax.Batch.prototype = { constructor: YTMA.ajax.Batch, descriptionsFromStorage: function () { $$.o(this.queue.set, this.loadDescription.bind(this)); }, clear: function () { // console.log('clear', this.queue.throttle); window.clearInterval(this.queue.throttle); }, pause: function (ms) { // console.log('pause queue.throttle'); this.clear(); if (this.queue.length > 0) { // console.log('throttling: ' + ms); window.setTimeout(this.start.bind(this), ms); } }, start: function () { this.clear(); // console.log('start', this.queue.length); this.queue.throttle = window.setInterval(this.loader.bind(this), YTMA.ajax.interval); }, loader: function () { if (this.queue.length > 0) { $$.o(this.queue.set, this.next.bind(this)); } else { this.clear(); // console.log('loader queue.throttle'); } }, loadDescription: function (id) { // console.log('current:', id, this.queue.current); var data = YTMA.external.dataFromStorage(this.site, id); if (data) { // console.log('from strg', id); YTMA.external.populate(data); YTMA.ajaxQueue.remove(this.site, id); } }, next: function (id) { //console.log('nx current:', id, this.queue.length, this.queue.current); this.queue.current += 1; YTMA.ajax.load(this.site, id, this.queue.set[id]); YTMA.ajaxQueue.remove(this.site, id); if (this.queue.current > 0 && this.queue.current % YTMA.ajax.maxBatch === 0) { this.pause(this.queue.timeout); return false; } } }; /** E X T E R N A L Access * Data from external sites */ YTMA.external = { version: 'ytma.4.1.dat', parse: function (response, site, id) { if (this.parsers[site]) { response = YTMA.DB.csr[site] ? response : JSON.parse(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: j.thumbnail_url //, // embd: j.html }; }, 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(//g, ''), th: unescape(j.thumbnail_medium) }; }, youtube: function (j) { j = j.entry; var o = { site: 'youtube', id: j.media$group.yt$videoid.$t, error: !j.media$group.yt$duration }; if (!o.error) { o.title = j.title.$t + ' ' + YTMA.external.helper.time(j.media$group.yt$duration.seconds); o.desc = j.media$group.media$description.$t; } return o; }, vine: function (html, id) { var o, doc = document.implementation.createHTMLDocument(""); doc.documentElement.innerHTML = html; o = { site: 'vine', id: id, //doc.querySelector('meta[property="twitter:app:url:googleplay"]').content.split('/').slice(-1), title: doc.querySelector('meta[property="twitter:title"]').content, desc: doc.querySelector('meta[property="twitter:description"]').content, th: doc.querySelector('meta[property="twitter:image"]').content.split('?')[0] }; doc = null; return o; } }, set: function (data) { if (!this.db[data.site]) { this.db[data.site] = {}; } this.db[data.site][data.id] = data; return this.save(); }, unset: function (data) { // console.log('unset', data.id); if (data.site) { delete this.db[data.site][data.id]; return this.save(); } }, limitDB: function (max) { var i, x = 0, half = Math.round(max / 2), db = {}; if (Object.keys(this.db).length >= max) { for (i in this.db) { if (this.db.hasOwnProperty(i)) { if (x >= half) { break; } db[i] = this.db[i]; x++; } } this.db = db; } return this.db; }, save: function () { return strg.save(this.version, this.limitDB(1200)); }, helper: { cutDescription: function (data) { if (data.desc && data.desc.length > 140) { data.full = data.desc; data.desc = data.desc.substr(0, 130) + ' . . .'; } return data; }, time: function (secs) { var p = '', H, M, S; try { H = Math.floor(secs / 3600) % 60; M = H ? ('0' + Math.floor(secs / 60) % 60).slice(-2) : Math.floor(secs / 60) % 60; S = ('0' + secs % 60).slice(-2); p = [' (', H ? H + ':' : '', M, ':', S, ')'].join(''); } catch (e) {} return p; }, thumbnail: function (data) { $$.s('[data-ytmid="%id"].ytm_links'.replace('%id', data.id), function (el) { el.setAttribute('style', 'background: url(' + data.th + ')'); }); }, titleToggle: function () { this.className = this.className === 'ytm_descr' ? 'ytm_descr ytm_descr_open' : 'ytm_descr'; this.textContent = this.textContent.length < 140 ? this.dataset.full : this.dataset.full.substr(0, 130) + ' . . .'; this.removeAttribute('style'); } }, validate: function (data) { if (!data || !data.id || data.error) { return YTMA.ajax.failure.call(data); } if (data.id && !data.title && !data.desc) { this.unset(data.id); return YTMA.ajax.failure.call(data); } return true; }, populate: function (data, ignoreValidation) { if (!ignoreValidation && !this.validate(data)) { return; } this.set(data); if (data.th) { this.helper.thumbnail(data); } $$.s('.ytm_title._' + YTMA.escapeId(data.id), function (el) { var q; el.textContent = data.title; if (data.desc) { q = $$.e('q', { className: 'ytm_descr', textContent: data.desc }, el); if (data.full) { q.dataset.full = data.full; q.title = 'Click to toggle the length of the description.'; q.ondblclick = YTMA.external.helper.titleToggle; } } }); }, dataFromStorage: function (site, id) { if (this.db && this.db[site]) { return this.db[site][id]; } } }; YTMA.external.db = strg.grab(YTMA.external.version, {}); /** Database */ YTMA.DB = { extension: window.chrome && window.chrome.extension, slim: { html5: true }, dataless: { html5: true, gfycat: true }, scroll: { html5: true, soundcloud: true }, sites: { youtube: 'https://www.youtube-nocookie.com/', vimeo: 'http://vimeo.com/', vine: 'https://vine.co/', gfycat: 'https://gfycat.com/', html5: true, soundcloud: 'https://soundcloud.com' }, browser: { pod: YTMA.reg.ios.test(navigator.userAgent), ie: !document.body.addEventListener && document.selection // IE, basically | window.navigator.cpuClass }, player: { ratio: { SD: 1, HD: 2, PORTRAIT: 3 }, size: { HIDDEN: 0, S: 240, M: 360, L: 480, X: 720 } }, playerSize: { ratios: { 1: 'sd', 2: '', 3: 'pr' }, sizes: { 0 : 'h', 240 : 's', 360 : 'm', 480 : 'l', 720 : 'xl' }, get: function (ratio, size) { return 'ytm_player ytm_player_' + this.ratios[ratio] + ' ytm_player_' + this.sizes[size]; } }, ratios: { 1: 3 / 4, 2: 9 / 16, 3: 16 / 10 }, sizes: { 0 : 0, 240 : 360, 360 : 640, 480 : 853, 720 : 1280 }, qualities: { 240 : 'small', 360 : 'medium', 480 : 'large', 720 : 'hd720', 1080 : 'hd1080', 1081 : 'highres', get: function (quality) { return this[quality] || this[360]; } }, ajax: { youtube: 'https://gdata.youtube.com/feeds/api/videos/%key?v=2&alt=json', vimeo: 'https://vimeo.com/api/v2/video/%key.json', soundcloud: 'https://soundcloud.com/oembed?format=json&url=%uri' // vine: 'https://vine.co/v/%key' }, csr: { // cross-site request vine: true }, sources: { html5: function () { return [{src: this.parent.data.uri}]; }, gfycat: function () { return [{type: 'text/html', src: 'https://gfycat.com/iframe/' + this.parent.data.id }, false]; }, youtube: function () { return [ {type: 'text/html', src: YTMA.DB.sites[this.parent.data.site] + 'embed/' + this.parent.data.id + '?version=3&theme=dark&color=white&showinfo=1&vq=' + this.$quality + '#at=' + this.$start}, {type: 'application/x-shockwave-flash', src: YTMA.DB.sites[this.parent.data.site] + 'v/' + this.parent.data.id + '?version=3&theme=dark&color=white&showinfo=1&vq=' + this.$quality + '&start=' + this.$start} ]; }, vimeo: function () { return [{type: 'text/html', src: 'http://player.vimeo.com/video/' + this.parent.data.id + '?badge=0'}, false]; }, vine: function () { return [{type: 'text/html', src: 'https://vine.co/v/' + this.parent.data.id + '/embed/simple'}, false]; // card }, soundcloud: function () { // https://p1.soundcloud.com/player.swf?referer=&url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F101399476 return [{type: 'application/x-shockwave-flash', src: 'https://p1.soundcloud.com/player.swf?show_comments=false&url=' + this.parent.data.uri}, false]; } } }; /** P L A Y E R CLASS * @param parent YTMA instance */ YTMA.Player = function (parent) { this.parent = parent; this.$quality = this.$size = this.$ratio = this.$source = null; this.$start = this.time(); this.$quality = YTMA.DB.qualities.get(YTMA.user.preferences.quality); this.$source = YTMA.DB.sources[this.parent.data.site].call(this); this.$media = this.mediaFrame(); this.$proxy = $$.e('div', {className: 'ymt_proxy'}, this.$media, true); this.$placeholder = $$.e('div', {className: 'ytm_placeholder ytm_video'}); this.$placeholder.dataset.empty = true; this.$player = $$.e('div', {className: 'ytm_player', '$data-ytmuid': this.parent.data.uid}, this.$placeholder, true); this.dimmensions(YTMA.user.preferences.ratio, YTMA.user.preferences.size); }; YTMA.Player.prototype = { constructor: YTMA.Player, dimmensions: function (ratio, size) { this.$ratio = isNumber(ratio) ? ratio : this.$ratio; this.$size = isNumber(size) ? size : this.$size; this.$player.className = YTMA.DB.playerSize.get(this.$ratio, this.$size); }, reset: function () { this.dimmensions(); this.parent.events.select.call(this.parent, this.parent.ul.querySelector('li[data-value="' + this.$size + '"]'), 'size'); }, time: function () { try { var m = this.parent.data.uri.match(YTMA.reg.time).slice(1, 3); return ((+m[0] || 0) * 60) + (+m[1] || 0); } catch (e) { return 0; } }, mediaFrame: function () { if (this.parent.data.site === 'html5') { return $$.e('video', { src: this.$source[0].src, controls: true, autoplay: false, loop: true, className: 'ytm_video', $allowscriptaccess: true, preload: 'metadata' }); } if (YTMA.user.preferences.flash === 1 && this.$source[1]) { return $$.a($$.e('object', {$type: this.$source[1].type, data: this.$source[1].src, className: 'ytm_video'}), $$.e('param', {name: 'movie', value: this.$source[1].src}), $$.e('param', {name: 'AllowScriptAccess', value: 'always'}), $$.e('param', {name: 'wmode', value: 'opaque'}), $$.e('param', {name: 'allowFullScreen', value: 'true'})); } return $$.e('iframe', {$allowfullscreen: true, $type: this.$source[0].type, src: this.$source[0].src, className: 'ytm_video'}); }, removeMedia: function () { this.mode = 'remove'; try { this.$placeholder.removeChild(this.$proxy); } catch (e) { // console.error(e); } // console.log('removed media'); }, switchToMedia: function () { if (this.$size === 0) { this.reset(); } this.mode = 'media'; // console.log('switch to media'); this.$placeholder.appendChild(this.$proxy); this.$placeholder.dataset.empty = false; }, switchToPlaceholder: function () { this.mode = 'placeholder'; // console.log('switch to placeholder'); this.$placeholder.removeChild(this.$proxy); this.$placeholder.dataset.empty = true; }, isPlaceholder: function () { return this.mode === 'placeholder'; } }; YTMA.prototype = { constructor: YTMA, events: { videoBar: function (evt) { var e = evt.target, n = parseInt(e.dataset.value, 10), t = e.dataset.type; if (e.tagName.toLowerCase() === 'li') { // maybe: this.settings.fire[t].call(this, e, n) if (t === 'settings') { YTMA.user.fn.formToggle(); } else if (t === 'close') { if (this.data.site === 'html5') { this.dom.closeAll(this.data.id); } else { this.dom.disableOpenOnScroll.call(this); this.toggle(); } } else if (t === 'ratio') { this.player.dimmensions(n); this.events.select.call(this, e, 'ratio'); } else if (t === 'size') { this.player.dimmensions(null, n); this.events.select.call(this, e, 'size'); } } }, select: function (e, type) { e.id = type + this.data.uid; try { this.selected[type].removeAttribute('id'); } catch (er) {} this.selected[type] = e; }, manualLoad: function (e) { // console.log(this); e.preventDefault(); var d = e.target.dataset; YTMA.ajax.load(d.site, d.id, d.uri); } }, selected: { size: null, ratio: null }, setup: function (link) { this.dom.mod[this.data.site].call(this, link); this.dom.link.call(this, link); this.dom.span.call(this); }, dom: { closeAll: function (id) { var group = YTMA.collect(id); // console.log('closing', group.length); group.forEach(function (y) { // y.dom.disableOpenOnScroll.call(y); y.a.dataset.scroll = false; y.toggle(); }); }, disableOpenOnScroll: function () { this.a.dataset.scroll = false; }, list: function (className, elements) { var li = $$.e('li'), ul = $$.e('ul', {className: className}, li), f = document.createDocumentFragment(), i, e; for (i = 0; i < elements.length; i++) { e = elements[i]; if (e) { f.appendChild(this.dom.li.call(this, e.type, e.text, e.value, e.title)); } } ul.appendChild(f); return li; }, li: function (type, txt, value, title) { var l = $$.e('li', {'$data-type': type, textContent: txt, '$data-value': value, title: title}); if ((type === 'size' && this.player.$size === value) || (type === 'ratio' && this.player.$ratio === value)) { this.events.select.call(this, l, type); } return l; }, link: function (link) { if (link.getElementsByTagName('img').length === 0) { link.className += ' ytm_link ytm_link_' + this.data.site + ' '; } link.dataset.ytmid = this.data.id; link.dataset.ytmuid = this.data.uid; link.dataset.ytmsid = this.data.sid; link.title = 'Visit the video page.'; link.parentNode.insertBefore(this.wrs, link.nextSibling); }, mod: { // modifies the link and other site-specific items youtube: function (a) { this.spn.title = 'YTMA!'; this.spn.addEventListener('mouseenter', this.thumb.start.bind(this), false); this.spn.addEventListener('mouseleave', this.thumb.stop, false); this.spn.style.backgroundImage = ['url(https://i3.ytimg.com/vi/', this.data.id, '/1.jpg)'].join(''); a.href = a.href.replace('http:', 'https:').replace('youtu.be/', 'youtube.com/watch?v='); }, vimeo: function () { this.spn.title = 'Vimeo Me Too!'; }, vine: function () { this.spn.title = 'Vine Me!'; }, soundcloud: function () { this.spn.title = 'Sound Off!'; }, html5: function () { this.spn.title = 'HTML5 Me!'; }, gfycat: function () { this.spn.style.backgroundImage = ['url(https://thumbs.gfycat.com/', this.data.id, '-poster.jpg)'].join(''); this.spn.title = 'Gfycat Meow!'; } }, ui: function () { var f = document.createDocumentFragment(); $$.a(f, this.dom.list.call(this, 'ytm_ratios', [ {type: 'ratio', text: '4:3', value: YTMA.DB.player.ratio.SD, title: 'SD'}, {type: 'ratio', text: '16:9', value: YTMA.DB.player.ratio.HD, title: 'Landscape'}, {type: 'ratio', text: '9:16', value: YTMA.DB.player.ratio.PORTRAIT, title: 'Portrait'}]), this.dom.list.call(this, 'ytm_sizes', [ {type: 'size', text: '\u00D8', value: YTMA.DB.player.size.HIDDEN, title: 'Hide the video.'}, {type: 'size', text: 'S', value: YTMA.DB.player.size.S, title: '240p'}, {type: 'size', text: 'M', value: YTMA.DB.player.size.M, title: '360p'}, {type: 'size', text: 'L', value: YTMA.DB.player.size.L, title: '480p'}, {type: 'size', text: 'X', value: YTMA.DB.player.size.X, title: '720p'}]), this.dom.list.call(this, 'ytm_options', [ strg.on ? {type: 'settings', text: '!', title: 'YTMA Settings'} : false, {type: 'close', text: '\u00D7', title: 'Close the video.'}]) ); this.ul.appendChild(f); this.ul.addEventListener('click', this.events.videoBar.bind(this), false); this.wrp.appendChild(this.ul); this.spn.parentNode.insertBefore(this.wrp, this.spn.nextSibling); }, span: function () { var f = document.createDocumentFragment(); $$.e('span', {className: 'ytm_init arialsans', textContent: this.spn.title}, this.spn); this.spn.title = 'Watch now!'; f.appendChild(this.spn); if (!YTMA.DB.dataless[this.data.site]) { f.appendChild(this.dom.preview.call(this)); } if (YTMA.DB.slim[this.data.site]) { this.wrs.classList.add('ytm_site_slim'); } if (YTMA.DB.scroll[this.data.site]) { this.a.classList.add('ytm_scroll'); } if (YTMA.user.preferences.desc === 2) { YTMA.ajaxQueue.add(this.data.site, this.data.id, this.data.uri); } this.wrs.appendChild(f); }, preview: function () { var a, s; s = $$.e('span', {className: 'ytm_title ytm_manual _' + this.data.sid}); a = $$.e('a', { textContent: YTMA.user.preferences.desc === 2 ? 'Loading data . . .' : 'Load description.', href: '#', title: 'Load this video\'s description.', '$data-id': this.data.id, '$data-site': this.data.site, '$data-uri': this.data.uri }); a.addEventListener('click', this.events.manualLoad.bind(this), false); return $$.a(s, a); } }, createPlayer: function () { this.player = new YTMA.Player(this); this.dom.ui.call(this); }, show: function () { if (!this.player) { this.createPlayer(); } this.toggle(true); if (YTMA.user.preferences.focus) { document.location.hash = '#' + this.wrs.id; } }, toggle: function (show, placeholder) { // the object is removed from or reattached to the DOM // if (this.data.open === !!show) { return; } this.data.open = !!show; if (show) { this.spn.classList.add('ytm_none'); this.wrp.classList.remove('ytm_none'); if (!this.player.$player.parentNode) { this.wrp.appendChild(this.player.$player); } this.player.switchToMedia(); } else { if (placeholder) { this.player.switchToPlaceholder(); } else { if (this.player) { this.player.removeMedia(); } this.spn.classList.remove('ytm_none'); this.wrp.classList.add('ytm_none'); } } }, 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(this.thumb.start.bind(this, e), 800); }, stop: function (e) { window.clearTimeout(e.target.dataset.timeout); } } }; /** S C R O L L CLASS * Window-Scroll Event Helper */ YTMA.Scroll = (function () { function Scroll(selector, cb, delay) { this.selector = selector; this.cb = cb; // console.log('YTMA.Scroll Monitor: ', selector); this.bound = Scroll.debounce(this.monitor.bind(this), delay || 500); this.bound(); window.addEventListener('scroll', this.bound, false); } Scroll.debounce = function (fn, delay) { var timeout; delay = delay || 250; return function () { var self = this, args = arguments, timed; timed = function () { timeout = null; fn.apply(self, args); }; window.clearTimeout(timeout); timeout = window.setTimeout(timed, delay); }; }; Scroll.visible = function (el) { var bound = el.getBoundingClientRect(); return (bound.top >= 0 && bound.top <= document.documentElement.clientHeight); }; Scroll.visibleAll = function (el, offset) { var bound = el.getBoundingClientRect(), height = document.documentElement.clientHeight; offset = isNumber(offset) ? +offset : 0; return ((bound.bottom + offset >= 0) && (bound.top <= height + offset || bound.bottom <= height - offset)); }; Scroll.prototype = { stop: function () { // console.log('clear scroll: ', this.selector); window.removeEventListener('scroll', this.bound); }, monitor: function () { $$.s(this.selector, this.cb); } }; return Scroll; }()); YTMA.main(); window.YTMA = YTMA; }());