/*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
// ==/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 = [
'<div id="ytm_settings" class="ytm_sans ytm_block ytm_normalize"><form action="" title="Double click to close"><div id="ytm_settingst">ytma! Site Settings</div><div class="ytm_field_container">',
'<fieldset><legend title="Load descriptions from the content sever.">Load Descriptions</legend><p><span><input id="ytma__desc0" type="radio" data-num="0" name="ytma__desc" data-key="desc"><label for="ytma__desc0" title="Load descriptions on demand">Manually</label></span><span><input id="ytma__desc1" type="radio" data-num="1" name="ytma__desc" data-key="desc"><label for="ytma__desc1" title="Load descriptions as they become visible on the screen.">Automatically, on scrolling</label></span></p></fieldset>',
'<fieldset><legend>HTML5 Players</legend><p><input name="ytma__autoShow" data-key="autoShow" id="ytma__autoShow" type="checkbox"><label for="ytma__autoShow">Automatically show WebM, MP4 and Soundcloud players</label></p></fieldset>',
'<fieldset><legend>Player Size</legend><p><span><input type="radio" name="ytma__size" data-key="size" data-num="240" id="ytma__size240" /><label for="ytma__size240">S <small>240p</small></label></span><span><input name="ytma__size" data-key="size" type="radio" id="ytma__size360" data-num="360" /><label for="ytma__size360">M <small>360p</small></label></span><span><input type="radio" name="ytma__size" data-key="size" data-num="480" id="ytma__size480" /><label for="ytma__size480">L <small>480p</small></label></span><span><input type="radio" name="ytma__size" data-key="size" data-num="720" id="ytma__size720" /><label for="ytma__size720">X <small>720p</small></label></span></p></fieldset>',
'<fieldset><legend>Quality</legend><p><span><input name="ytma__quality" data-key="quality" data-num="240" id="ytma__quality240" type="radio"><label for="ytma__quality240">240p</label></span><span><input name="ytma__quality" data-key="quality" id="ytma__quality360" data-num="360" type="radio"><label for="ytma__quality360">360p</label></span><span><input name="ytma__quality" data-key="quality" data-num="480" id="ytma__quality480" type="radio"><label for="ytma__quality480">480p</label></span><span><input name="ytma__quality" data-key="quality" data-num="720" id="ytma__quality720" type="radio"><label for="ytma__quality720">720p</label></span><span><input name="ytma__quality" data-key="quality" data-num="1080" id="ytma__quality1080" type="radio"><label for="ytma__quality1080">1080p</label></span></p></fieldset>',
'<fieldset><legend>Aspect Ratio</legend><p><span><input name="ytma__ratio" data-key="ratio" type="radio" id="ytma__ratio2" data-num="2" /><label for="ytma__ratio2">16:9</label></span><span><input type="radio" name="ytma__ratio" data-key="ratio" data-num="1" id="ytma__ratio1" /><label for="ytma__ratio1">4:3</label></span></p></fieldset>',
'<fieldset><legend>YouTube</legend>',
'<p><input name="ytma__yt_annotation" data-key="yt_annotation" type="checkbox" id="ytma__yt_annotation" /><label for="ytma__yt_annotation">Enable video annotations</label></p>',
'<p><input name="ytma__yt_nocookie" data-key="yt_nocookie" type="checkbox" id="ytma__yt_nocookie" /><label for="ytma__yt_nocookie">Use https://youtube-nocookie.com to load videos</label></p>',
'<p><input name="ytma__yt_volume" data-key="yt_volume" type="number" style="width:4em" min=0 max=100 id="ytma__yt_volume" /><label for="ytma__yt_volume">Video volume (Experimental)</label></p>',
'</fieldset>',
'<fieldset><legend>Window Focus</legend><p><input name="ytma__focus" data-key="focus" type="checkbox" id="ytma__focus" value="focus" /><label for="ytma__focus">After clicking the thumbnail, set the video at the top of the window.</label></p></fieldset>',
'</div><p><small id="ytm_settings_error" class="ytm_error ytm_none ytm_title">Error! Your settings could not be saved.</small></p><p id="ytm_opts"><button type="button" id="ytmaclose">Close</button> <button type="button" id="ytmareset">Reset</button></p></form></div>'
].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(/<br.?.?>/g, ''),
th: decodeURI(j.thumbnail_medium)
};
},
youtube: function (j, id) {
if (j.pageInfo.totalResults < 1) {
return { id: id, error: true };
}
j = j.items[0];
var o = {
site: 'youtube',
id: id,
title: j.snippet.title + ' ' + YTMA.external.helper.time(j.contentDetails.duration),
desc: j.snippet.description
// aspectRatio: j.contentDetails.aspectRatio
};
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;
},
gfycat: function (j, id) {
j = j.gfyItem;
if (j) {
return {
site: 'gfycat',
id: id || j.gfyName,
title: j.title || j.gfyName
};
}
}
},
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, db) {
// limits an object's items by half of the max
// removes the older items at the start of the object
var keys = Object.keys(db),
half = Math.floor(max / 2),
start,
ndb,
i;
if (keys.length > max) {
ndb = {};
start = keys.length - half;
for (i = start; i < keys.length; i++) {
ndb[keys[i]] = db[keys[i]];
}
}
return ndb || db;
},
save: function () {
this.db = this.limitDB(1000, this.db);
return strg.save(this.version, this.db);
},
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 (iso8601) {
var p = '', a, i;
// P#DT#H#M#S || PT#H#M#S
try {
a = iso8601.replace(/(?:PT?)/, '').split(/(?:D|H|M|S)/g).slice(0, -1);
for (i = (a.length - 1); i > 0; i--) {
if ((a[i - 1] >= 0) && a[i] > 0) {
a[i] = ('00' + a[i]).slice(-2);
}
}
p = '(' + a.join(':') + ')';
} catch (e) {
}
return p;
},
thumbnail: function (data) {
$$.s('[data-ytmid="%id"].ytm_trigger'.replace('%id', data.id), function (el) {
el.setAttribute('style', 'background: url(' + data.th + ')');
});
},
titleToggle: function () {
this.classList.toggle('ytm_descr_open');
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_bd._' + YTMA.escapeId(data.id), function (el) {
var q;
el.innerHTML = '<span class="ytm_title">' + data.title + '</span>';
if (data.desc) {
q = $$.e('q', { className: 'ytm_descr ytm_block', textContent: data.desc }, el);
if (data.full) {
q.dataset.full = data.full;
q.title = 'Click to toggle the length of the description.';
q.addEventListener('dblclick', YTMA.external.helper.titleToggle, false);
}
}
});
},
dataFromStorage: function (site, id) {
if (this.db && this.db[site]) {
return this.db[site][id];
}
},
events: {
manualLoad: function (e) {
// console.log(this);
e.preventDefault();
YTMA.ajax.loadFromDataset(e.target.dataset);
}
}
};
YTMA.external.db = strg.grab(YTMA.external.version, {});
/** Database */
YTMA.DB = {
postInit: function () {
if (YTMA.user.preferences.yt_nocookie) {
YTMA.DB.sites.youtube = 'https://www.youtube-nocookie.com/';
} else {
YTMA.DB.sites.youtube = 'https://www.youtube.com/';
}
},
fn: {
hasAjax: function (site) {
return YTMA.DB.ajax[site] || YTMA.DB.ajaxExtension[site];
}
},
extension: window.chrome && window.chrome.extension,
browser: {
pod: YTMA.reg.ios.test(navigator.userAgent),
ie: !!document.documentMode, // IE, basically | window.navigator.cpuClass
safari: Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0
},
sites: {
youtube: 'https://www.youtube.com/',
vimeo: 'http://vimeo.com/',
vine: 'https://vine.co/',
gfycat: 'https://gfycat.com/',
html5: true,
'html5-audio': true,
soundcloud: 'https://soundcloud.com/',
imgur: 'https://i.imgur.com/'
},
customControls: {
$get: function (site) {
var customBar = this[site] || {};
return {
ratio: customBar.ratio === undefined ? true : customBar.ratio,
size: customBar.size === undefined ? true : customBar.size
};
},
vine: {
ratio: false,
size: true
},
soundcloud: {
ratio: false,
size: false
}
},
slim: {
html5: true
},
scroll: {
html5: true,
soundcloud: true,
gfycat: true,
imgur: true
},
playerSize: {
ratios: {
1: 'sd',
2: 'hd',
3: 'pr'
},
sizes: {
0 : 'h',
240 : 's',
360 : 'm',
480 : 'l',
720 : 'xl'
},
aspects: {
1: 4 / 3,
2: 16 / 9,
3: 16 / 9
},
$get: function (ratio, size) {
return 'ytm_panel ytm_block ytm_panel-' + this.ratios[ratio] + ' ytm_panel-' + this.sizes[size];
}
},
qualities: {
240 : 'small',
360 : 'medium',
480 : 'large',
720 : 'hd720',
1080 : 'hd1080',
1081 : 'highres',
$get: function (quality) {
return this[quality] || this[360];
}
},
ajax: {
youtube: 'https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=%key' + window.atob('JmtleT1BSXphU3lEVG5INkxzRERyVElYaFZTZWRQQjlyRHo1czBSczQzZnM='),
vimeo: 'https://vimeo.com/api/v2/video/%key.json',
soundcloud: 'https://soundcloud.com/oembed?format=json&url=%uri',
gfycat: 'http://gfycat.com/cajax/get/%key'
},
ajaxExtension: { // cross-site request with extension/GM support
vine: 'https://vine.co/v/%key'
},
videoTag: { // sites / types that use video tag
html5: true,
imgur: true,
gfycat: true
},
// videoTypes: (function () {
// var v = document.createElement('video');
// return {
// ogg: !!v.canPlayType('video/ogg; codecs="theora, vorbis"'),
// webm: !!v.canPlayType('video/webm'),
// mp4: !!v.canPlayType('video/mp4')
// };
// }()),
sources: {
'html5-audio': function (data) {
return [
{type: 'audio/mp3', src: data.uri}
];
},
html5: function (data) {
// attaching the type as either mp4 or webm
return [
{type: 'video/mp4', src: data.uri},
{type: 'video/webm', src: data.uri}
];
},
imgur: function (data) {
return [
{type: 'video/webm', src: 'https://i.imgur.com/' + data.id + '.webm'},
{type: 'video/mp4', src: 'https://i.imgur.com/' + data.id + '.mp4'}
];
},
$gfycatFrame: function (data) {
return [{type: 'text/html', src: 'https://gfycat.com/iframe/' + data.id }, false];
},
gfycat: function (data) {
return [
{type: 'video/mp4', src: 'http://zippy.gfycat.com/' + data.id + '.mp4'},
{type: 'video/mp4', src: 'http://fat.gfycat.com/' + data.id + '.mp4'},
{type: 'video/mp4', src: 'http://giant.gfycat.com/' + data.id + '.mp4'},
{type: 'video/webm', src: 'http://zippy.gfycat.com/' + data.id + '.webm'},
{type: 'video/webm', src: 'http://fat.gfycat.com/' + data.id + '.webm'},
{type: 'video/webm', src: 'http://giant.gfycat.com/' + data.id + '.webm'}
];
},
youtube: function (data, attrs) {
var params = '?html5=1&version=3&modestbranding=1&theme=dark&color=white&showinfo=1&vq=' + attrs.quality
+ '&iv_load_policy=' + YTMA.user.preferences.yt_annotation
+ '&start=' + attrs.start
+ '&volume=' + YTMA.user.preferences.yt_volume;
return [
{type: 'text/html', src: YTMA.DB.sites[data.site] + 'embed/' + data.id + params}
];
},
vimeo: function (data) {
return [{type: 'text/html', src: 'http://player.vimeo.com/video/' + data.id + '?badge=0'}, null];
},
vine: function (data) {
return [{type: 'text/html', src: 'https://vine.co/v/' + data.id + '/embed/simple?audio=1'}, null]; // card
},
soundcloud: function (data) {
return [
{type: 'text/html', src: 'https://w.soundcloud.com/player/?show_comments=false&url=' + data.uri},
null
];
}
}
};
/** U I CLASS
* Class for the player controls
*/
YTMA.UI = function (ytma) {
this.ytmx = ytma;
this.play = new YTMA.Player(this.ytmx);
this.open = false;
this.selected = { size: null, ratio: null };
this.trigger = ytma.spn;
this.projector = $$.e('div', {className: 'ytm_projector ytm_none ytm_block ytm_normalize ytm_sans'});
this.control = $$.e('ul', {className: 'ytm_control ytm_sans'});
this.customBar = YTMA.DB.customControls.$get(this.ytmx.data.site);
this.controlBar();
};
YTMA.UI.ratios = {
SD: 1,
HD: 2,
PORTRAIT: 3
};
YTMA.UI.sizes = {
HIDDEN: 0,
S: 240,
M: 360,
L: 480,
X: 720
};
/** Trigger is the VAR element */
YTMA.UI.createFromTrigger = function (t) {
console.log('createFromTrigger');
if (t.hasAttribute('data-ytmuid') && !YTMA.set[t.dataset.ytmuid]) {
console.log('createFromTrigger-new');
YTMA.set[t.dataset.ytmuid] = new YTMA()._reactivate(t);
}
console.log('createFromTrigger-ui');
return YTMA.set[t.dataset.ytmuid].getUI();
};
YTMA.UI.events = {
$fire: {
settings: function () {
YTMA.user.events.formToggle();
},
close: function () {
if (YTMA.DB.scroll[this.ytmx.data.site]) {
console.log('events.close-1');
this.hideAllPlayers();
} else {
console.log('events.close-2');
this.ytmx.disableOpenOnScroll();
this.hidePlayer();
}
},
ratio: function (li) {
var n = parseInt(li.dataset.value, 10);
this.play.dimmensions(n);
this.markSelected(li, 'ratio');
},
size: function (li) {
var n = parseInt(li.dataset.value, 10);
this.play.dimmensions(null, n);
this.markSelected(li, 'size');
}
},
videoBar: function (e) {
var el = e.target, t;
if (el.tagName.toLowerCase() === 'li' && el.dataset && el.dataset.type) {
t = el.dataset.type;
if (YTMA.UI.events.$fire[t]) {
YTMA.UI.events.$fire[t].call(this, el);
}
}
}
};
YTMA.UI.prototype = {
constructor: YTMA.UI,
resetViewSize: function () {
this.play.dimmensions();
this.setControlBarSize(this.play.attrs.size);
},
showOnScroll: function (el) {
if (!this.open && this.ytmx.canScroll() && this.ytmx.isBelow(el)) {
this.showPlayer();
}
},
showPlayer: function () {
this.open = true;
this.trigger.classList.add('ytm_none');
this.projector.classList.remove('ytm_none');
this.attachPlayPanel();
this.play.switchOn();
if (YTMA.user.preferences.focus) {
document.location.hash = '#' + this.ytmx.container.id;
}
},
hidePlayer: function () {
this.open = false;
this.play.switchOff();
this.trigger.classList.remove('ytm_none');
this.projector.classList.add('ytm_none');
},
attachPlayPanel: function () {
if (!this.play.panel.parentNode) {
// console.log('attaching display panel');
this.projector.appendChild(this.play.panel);
}
},
hideAllPlayers: function () {
var group = YTMA.collect(this.ytmx.data.id);
console.log('closing all', this.ytmx.data.id, group.length);
group.forEach(function (y) {
y.disableOpenOnScroll();
y.getUI().hidePlayer();
});
},
setControlBarSize: function (size) {
this.markSelected(this.control.querySelector('li[data-value="' + size + '"]'), 'size');
},
controlBar: function () {
var f = document.createDocumentFragment();
$$.a(f,
this.customBar.ratio ? this.buildList('ytm_ratios', [
{type: 'ratio', text: '4:3', value: YTMA.UI.ratios.SD, title: 'SD'},
{type: 'ratio', text: '16:9', value: YTMA.UI.ratios.HD, title: 'Landscape'},
{type: 'ratio', text: '9:16', value: YTMA.UI.ratios.PORTRAIT, title: 'Portrait'}]) : null,
this.customBar.size ? this.buildList('ytm_sizes', [
{type: 'size', text: '\u00D8', value: YTMA.UI.sizes.HIDDEN, title: 'Hide the video.'},
{type: 'size', text: 'S', value: YTMA.UI.sizes.S, title: '240p'},
{type: 'size', text: 'M', value: YTMA.UI.sizes.M, title: '360p'},
{type: 'size', text: 'L', value: YTMA.UI.sizes.L, title: '480p'},
{type: 'size', text: 'X', value: YTMA.UI.sizes.X, title: '720p'}]) : null,
this.buildList('ytm_options', [
strg.on ? {type: 'settings', text: '!', title: 'YTMA Settings'} : null,
{type: 'close', text: '\u00D7', title: 'Close the video.'}])
);
this.control.appendChild(f);
this.control.addEventListener('click', YTMA.UI.events.videoBar.bind(this), false);
this.projector.appendChild(this.control);
this.ytmx.container.insertBefore(this.projector, this.trigger.nextSibling);
},
markSelected: function (el, type) {
el.id = type + this.ytmx.data.uid;
try {
this.selected[type].removeAttribute('id');
} catch (e) {}
this.selected[type] = el;
},
buildList: 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.li(e.type, e.text, e.value, e.title));
}
}
ul.appendChild(f);
return li;
},
li: function (type, txt, value, title) {
var l = $$.e('li', {_type: type, textContent: txt, _value: value, title: title});
if ((type === 'size' && this.play.attrs.size === value) || (type === 'ratio' && this.play.attrs.ratio === value)) {
this.markSelected(l, type);
}
return l;
}
};
/** P L A Y E R CLASS
* @param parent YTMA instance
*/
YTMA.Player = function (parent) {
this.parent = parent;
this.mode = 'off';
this.attrs = {
sources: null,
quality: YTMA.DB.qualities.$get(YTMA.user.preferences.quality),
size: null,
ratio: null,
start: this.time(),
type: null
};
this.attrs.sources = YTMA.DB.sources[parent.data.site](parent.data, this.attrs);
this.attrs.type = this.findType();
this.media = YTMA.Player.makeMedia[this.attrs.type](this);
this.channel = $$.e('div', {className: 'ytm_panel_channel ytm_block'}, this.media, true);
this.switcher = $$.e('div', {className: 'ytm_panel_switcher ytm_panel_size ytm_block ytm_' + this.attrs.type, _ytmuid: this.parent.data.uid, _standby: true});
this.panel = $$.e('div', {className: 'ytm_panel ytm_block'}, this.switcher, true);
if (parent.data.site === 'soundcloud' && YTMA.reg.extra.soundcloud.playlist.test(parent.anchor.href)) {
this.media.classList.add('ytm_soundcloud-playlist');
this.switcher.classList.add('ytm_soundcloud-playlist');
}
this.dimmensions(YTMA.user.preferences.ratio, YTMA.user.preferences.size);
};
YTMA.Player.css = {
item: function (key, value) {
if (isNumber(value)) {
value += 'px';
}
return '\t' + key + ': ' + value + ';\n';
},
iter: function (css, cssEntries) {
$$.o(cssEntries, function (key, value) {
css.push(YTMA.Player.css.item(key, value));
});
css.push('}');
},
generator: function () {
var css = [];
$$.o(this.sizes, function (size, sizes) {
$$.o(sizes, function (dimm, keys) {
css.push('\n.ytm_panel-' + size + '.ytm_panel-' + dimm + ' .ytm_panel_size {\n');
YTMA.Player.css.iter(css, keys);
});
});
// add site overrides
$$.o(this.sites, function (site, data) {
$$.o(data, function (setting, keys) {
if (setting === 'all') {
css.push('\n.ytm_site_' + site + ' .ytm_panel_size {\n');
} else {
css.push('\n.ytm_site_' + site + ' .ytm_panel-' + setting + ' .ytm_panel_size {\n');
}
YTMA.Player.css.iter(css, keys);
});
});
return css.join('');
},
sizes: (function () {
var merge = {};
$$.o(YTMA.DB.playerSize.sizes, function (num, size) {
if (num >= 0) {
merge[size] = {};
$$.o(YTMA.DB.playerSize.ratios, function (k, ratio) {
if (ratio === 'pr') {
var w = Math.floor(num * 0.95); // smaller than the normal sizes
merge[size][ratio] = {
width: w,
height: Math.floor(Math.floor(w * YTMA.DB.playerSize.aspects[k]))
};
} else {
merge[size][ratio] = {
width: Math.floor(num * YTMA.DB.playerSize.aspects[k]),
height: num
};
}
});
}
});
return merge;
}()),
sites: { // custom sizes per site
soundcloud: {
all: {
height: '118px !important'
}
},
vine: {
s: {
width: 240,
height: 240
},
m: {
width: 360,
height: 360
},
l: {
width: 480,
height: 480
},
xl: {
width: 720,
height: 720
}
}
}
};
YTMA.Player.makeMedia = {
$css: function (type) {
return 'ytm_panel_media ytm_panel_size ytm_block ytm_' + type;
},
video: function (player) {
var video = $$.e('video', {
controls: true,
autoplay: false,
loop: true,
className: this.$css('video'),
$allowscriptaccess: true,
preload: 'metadata'
});
player.attrs.sources.forEach(function (source) {
$$.e('source', {src: source.src, $type: source.type}, video);
});
return video;
},
iframe: function (player) {
return $$.e('iframe', {
$allowfullscreen: true,
// $sandbox: 'allow-same-origin allow-scripts allow-popups',
$type: player.attrs.sources[0].type,
src: player.attrs.sources[0].src,
className: this.$css('iframe')
});
},
audio: function (player) {
return $$.e('audio', {
src: player.attrs.sources[0].src,
$type: player.attrs.sources[0].type
});
}
};
YTMA.Player.prototype = {
constructor: YTMA.Player,
dimmensions: function (ratio, size) {
this.attrs.ratio = isNumber(ratio) ? ratio : this.attrs.ratio;
this.attrs.size = isNumber(size) ? size : this.attrs.size;
this.panel.className = YTMA.DB.playerSize.$get(this.attrs.ratio, this.attrs.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; }
},
findType: function () {
if (this.parent.data.site === 'html5-audio') { return 'audio'; }
if (YTMA.DB.videoTag[this.parent.data.site]) { return 'video'; }
return 'iframe';
},
switchOff: function () {
// console.log('removed media');
if (this.media.pause) {
console.log('pausing');
this.media.pause();
}
try {
this.switcher.removeChild(this.channel);
} catch (e) {
// console.error(e);
}
this.mode = 'off';
},
switchOn: function () {
if (this.attrs.size === 0) {
this.attrs.size = YTMA.user.preferences.size;
this.parent.ui.resetViewSize();
}
// console.log('switch to media');
this.switcher.appendChild(this.channel);
this.switcher.dataset.standby = false;
this.mode = 'on';
},
switchStandby: function () {
// console.log('switch to standby');
this.switchOff();
this.switcher.dataset.standby = true;
this.mode = 'standby';
},
isStandby: function () {
return this.mode === 'standby';
}
};
YTMA.prototype = {
constructor: YTMA,
getUI: function () {
if (!this.ui) {
this.ui = new YTMA.UI(this);
}
return this.ui;
},
setup: function () {
try {
this.dom.mod[this.data.site].call(this);
} catch (e) {}
this.dom.link.call(this);
this.dom.span.call(this);
},
disableOpenOnScroll: function () {
this.anchor.dataset.ytmscroll = false;
},
canScroll: function () {
return this.anchor.dataset.ytmscroll === 'true';
},
isBelow: function (link) {
return YTMA.Scroll.compare(this.anchor, link) < 1;
},
dom: {
mod: { // modifies YTMA interface according to site
youtube: function () {
this.spn.title = 'ytma!';
this.spn.addEventListener('mouseenter', YTMA.events.thumb.start, false);
this.spn.addEventListener('mouseleave', YTMA.events.thumb.stop, false);
this.spn.style.backgroundImage = ['url(https://i3.ytimg.com/vi/', this.data.id, '/1.jpg)'].join('');
this.achor.href = this.achor.href.replace('http:', 'https:').replace('youtu.be/', 'youtube.com/watch?v=');
},
vimeo: function () {
this.spn.title = 'vimeo too!';
},
vine: function () {
this.spn.title = 'vine me!';
this.achor.href = this.achor.href.replace('http:', 'https:');
},
soundcloud: function () {
this.spn.title = 'sound off!';
this.achor.href = this.achor.href.replace('http:', 'https:');
},
html5: function () {
this.spn.title = 'html5 go!';
},
gfycat: function () {
this.spn.style.backgroundImage = ['url(https://thumbs.gfycat.com/', this.data.id, '-poster.jpg)'].join('');
this.spn.title = 'gfycat meow!';
this.achor.href = this.achor.href.replace('http:', 'https:');
},
imgur: function () {
this.spn.style.backgroundImage = ['url(https://i.imgur.com/', this.data.id, 'h.jpg)'].join('');
this.spn.title = 'imgur it!';
this.achor.href = this.achor.href.replace('http:', 'https:');
}
},
link: function () {
if (this.anchor.getElementsByTagName('img').length === 0) {
this.anchor.className += ' ytm_link ytm_link_' + this.data.site + ' ';
}
this.anchor.dataset.ytmid = this.data.id;
this.anchor.dataset.ytmuid = this.data.uid;
this.anchor.dataset.ytmsid = this.data.sid;
this.anchor.title = 'Visit the video page.';
this.anchor.parentNode.insertBefore(this.container, this.anchor.nextSibling);
},
span: function () {
var f = document.createDocumentFragment();
$$.e('span', {className: 'ytm_init ytm_label ytm_sans ytm_box', textContent: this.spn.title}, this.spn);
$$.e('var', {className: 'ytm_label ytm_box', _ytmid: this.data.id, _ytmuid: this.data.uid, _ytmsid: this.data.sid, _ytmsite: this.data.site, textContent: '\u25B6'}, this.spn);
this.spn.title = 'Watch now!';
f.appendChild(this.spn);
if (YTMA.DB.fn.hasAjax(this.data.site)) { f.appendChild(this.dom.dataLoadLink.call(this)); }
if (YTMA.DB.slim[this.data.site]) { this.container.classList.add('ytm_site_slim'); }
if (YTMA.DB.scroll[this.data.site]) { this.anchor.classList.add('ytm_scroll'); }
this.container.appendChild(f);
},
dataLoadLink: function () {
var a, s;
s = $$.e('span', {className: 'ytm_bd ytm_normalize ytm_manual _' + this.data.sid});
a = $$.e('a', {
className: 'ytm_title',
textContent: 'Load description.',
href: '#',
title: 'Load this video\'s description.',
_ytmid: this.data.id,
_ytmsite: this.data.site,
_ytmuri: this.data.uri,
_ytmdescription: 'true'
});
return $$.a(s, a);
}
}
};
/**
* Creates a new YTMA from the given attributes
* @String|Number id Unique ID
* @String site Website eg: youtube, vimeo
* @HTMLAnchorElement a Anchor element
*/
YTMA.prototype._new = function (id, site, a) {
var uid = YTMA.escapeId(id + '_' + (YTMA.num += 1));
this.data = {
id: id,
uid: YTMA.escapeId(uid), // unique id
sid: YTMA.escapeId(id), // shared id
site: site,
uri: a.href
};
this.ui = null;
if (!a.hasAttribute('data-ytmscroll')) { a.dataset.ytmscroll = true; }
this.anchor = a;
this.spn = $$.e('span', {className: 'ytm_trigger ytm_block ytm_normalize ytm_sans', _ytmid: this.data.id, _ytmsite: this.data.site});
this.container = $$.e('div', {id: 'w' + this.data.uid, className: 'ytm_spacer ytm_block ytm_site_' + this.data.site});
return this;
};
/**
* Recreates a YTMA object from a trigger element
* @HTMLElement
*/
YTMA.prototype._reactivate = function (trigger) {
var id = trigger.dataset.ytmid,
a = document.querySelector('a[data-ytmuid="' + trigger.dataset.ytmuid + '"]');
this.data = {
id: id,
uid: trigger.dataset.ytmuid,
sid: trigger.dataset.ytmsid,
site: trigger.dataset.ytmsite,
uri: a.href
};
this.ui = null;
this.anchor = a;
this.spn = trigger.parentElement;
this.container = this.spn.parentElement;
return this;
};
/** 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));
};
/** Returns 1, 0, -1 when el1 is above, exactly the same, or below el2 */
Scroll.compare = function (el1, el2) {
var a = el1.getBoundingClientRect().y,
b = el2.getBoundingClientRect().y;
if (a < b) { return 1; }
if (a === b) { return 0; }
return -1;
};
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();
}());