YouTube Me Again!

YouTube Me Again! automatically converts YouTube and Vimeo links into real embedded videos. Allowing you to hide, rescale, and change any video's aspect ratio.

当前为 2014-05-16 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @id youtube-me-again
  3. // @name YouTube Me Again!
  4. // @namespace hateradio)))
  5. // @author hateradio
  6. // @version 4.1
  7. // @description YouTube Me Again! automatically converts YouTube and Vimeo links into real embedded videos. Allowing you to hide, rescale, and change any video's aspect ratio.
  8. // @homepage https://userscripts.org/scripts/show/60843
  9. // @icon https://dl.dropboxusercontent.com/u/14626536/userscripts/i/ytma/ytma32.png
  10. // @icon64 https://dl.dropboxusercontent.com/u/14626536/userscripts/i/ytma/ytma64.png
  11. // @screenshot http://i.min.us/ic9lvy.png http://i.min.us/kc9lvy.jpg
  12.  
  13. // @include http://*.neogaf.com/forum/showthread.php*
  14. // @include http://*.neogaf.com/forum/showpost.php?p*
  15. // @include http://*.neogaf.com/forum/newreply.php*
  16. // @include http://*.neogaf.com/forum/editpost.php*
  17. // @include http://*.neogaf.com/forum/private.php*
  18.  
  19. // @include http://*.neogaf.net/forum/showthread.php*
  20. // @include http://*.neogaf.net/forum/showpost.php?p*
  21. // @include http://*.neogaf.net/forum/newreply.php*
  22. // @include http://*.neogaf.net/forum/editpost.php*
  23. // @include http://*.neogaf.net/forum/private.php*
  24.  
  25. // @match http://*.neogaf.com/forum/showthread.php*
  26. // @match http://*.neogaf.com/forum/showpost.php?p*
  27. // @match http://*.neogaf.com/forum/newreply.php*
  28. // @match http://*.neogaf.com/forum/editpost.php*
  29. // @match http://*.neogaf.com/forum/private.php*
  30.  
  31. // @match http://*.neogaf.net/forum/showthread.php*
  32. // @match http://*.neogaf.net/forum/showpost.php?p*
  33. // @match http://*.neogaf.net/forum/newreply.php*
  34. // @match http://*.neogaf.net/forum/editpost.php*
  35. // @match http://*.neogaf.net/forum/private.php*
  36.  
  37. // @include http*://*what.cd/forums.php?*viewthread*
  38. // @include http*://*what.cd/torrents.php?*
  39. // @include http*://*what.cd/user.php?*
  40.  
  41. // @match *://*.what.cd/forums.php?*viewthread*
  42. // @match *://*.what.cd/torrents.php?*
  43. // @match *://*.what.cd/user.php?*
  44.  
  45. // @updated 24 Aug 2013 | 17,400
  46. // -updated 04 June 2013 | 13,586
  47.  
  48. // @grant GM_xmlhttpRequest
  49. // ==/UserScript==
  50.  
  51. // Do not modify and re-release this script. If you would like to add support for another site, tell me and I'll put it in the includes.
  52.  
  53. // Whitelist these sites on NoScript/NotScript/etc.
  54. // neogaf.com or neogaf.net, youtube.com, youtube-nocookie.com, vimeo.com, vimeocdn.com, dropboxusercontent.com
  55.  
  56. /*jslint indent: 4, maxerr: 50, browser: true, devel: true, nomen: true, plusplus: true, regexp: true, newcap: true */
  57.  
  58. (function () {
  59. 'use strict';
  60.  
  61. var $$, strg, update;
  62.  
  63. if (!Function.prototype.bind) {
  64. Function.prototype.bind = function (self) {
  65. var args = [].slice.call(arguments, 1), fn = this;
  66. return function () {
  67. return fn.apply(self, args.concat([].slice.call(arguments)));
  68. };
  69. };
  70. }
  71.  
  72. // DOM Handle
  73. $$ = {
  74. s : function (selector, cb) { var s = document.querySelectorAll(selector), i = -1; while (++i < s.length) { if (cb(s[i], i, s) === false) { break; } } },
  75. o : function (object, cb) { var i; for (i in object) { if (object.hasOwnProperty(i)) { if (cb(i, object[i], object) === false) { break; } } } },
  76. 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; },
  77. 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; },
  78. p : function (el, search) { // search is a regexp
  79. if (search.test(el.tagName)) {
  80. return el;
  81. }
  82. if (el.parentElement) {
  83. return this.p(el.parentElement, search);
  84. }
  85. return false;
  86. }
  87. };
  88.  
  89. // S T O R A G E HANDLE
  90. strg = {
  91. 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; } }()),
  92. read: function (key) { return this.on ? JSON.parse(localStorage.getItem(key)) : false; },
  93. save: function (key, dat) { return this.on ? !localStorage.setItem(key, JSON.stringify(dat)) : false; },
  94. wipe: function (key) { return this.on ? !localStorage.removeItem(key) : false; },
  95. zero: function (o) { var k; for (k in o) { if (o.hasOwnProperty(k)) { return false; } } return true; },
  96. grab: function (key, def) { var s = strg.read(key); return strg.zero(s) ? def : s; }
  97. };
  98.  
  99. // U P D A T E HANDLE
  100. update = {
  101. name : 'YouTube Me Again!',
  102. version : 4100,
  103. key : 'ujs_YTMA_UPDT_HR',
  104. callback : 'ytmaupdater',
  105. page : 'https://userscripts.org/scripts/show/60843',
  106. urij : 'https://dl.dropboxusercontent.com/u/14626536/userscripts/updt/ytma/ytma.json',
  107. 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.
  108. checkchrome: false,
  109. interval: 5,
  110. day: (new Date()).getTime(),
  111. time: function () { return new Date(this.day + (1000 * 60 * 60 * 24 * this.interval)).getTime(); },
  112. top: document.head || document.body,
  113. css: function (t) {
  114. if (!this.style) {
  115. this.style = document.createElement('style');
  116. this.style.type = 'text/css';
  117. this.top.appendChild(this.style);
  118. }
  119. this.style.appendChild(document.createTextNode(t + '\n'));
  120. },
  121. js: function (t) {
  122. var j = document.createElement('script');
  123. j.type = 'text/javascript';
  124. j[/^https?\:\/\//i.test(t) ? 'src' : 'textContent'] = t;
  125. this.top.appendChild(j);
  126. },
  127. notification: function (j) {
  128. 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; } }
  129. var a = document.createElement('a'), b = JSON.parse(window.localStorage.getItem(this.key));
  130. a.href = b.page || '#';
  131. a.id = 'userscriptupdater';
  132. a.title = 'Update now.';
  133. a.textContent = 'An update for ' + this.name + ' is available.';
  134. document.body.appendChild(a);
  135. return true;
  136. },
  137. check: function (opt) {
  138. if (typeof (GM_updatingEnabled) === 'boolean' || !strg.on) { return; }
  139. var stored = strg.read(this.key), J, page;
  140. this.csstxt();
  141. if (opt || !stored || stored.date < this.day) {
  142. page = stored && stored.page ? stored.page : '#';
  143. strg.save(this.key, {date: this.time(), version: this.version, page: page});
  144. if (!opt && typeof (GM_xmlhttpRequest) === 'function' && !this.chrome()) {
  145. GM_xmlhttpRequest({method: 'GET', url: update.urij, onload: function (r) { update.notification(JSON.parse(r.responseText)); }, onerror: function () { update.check(1); } });
  146. } else {
  147. 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', 'j.name');
  148. this.js(J);
  149. this.js(this.uric);
  150. }
  151. } else if (this.version < stored.version) { this.notification(); }
  152. },
  153. chrome: function () {
  154. if (this.checkchrome === true && typeof (chrome) === 'object') { return true; }
  155. },
  156. csstxt: function () {
  157. 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}'); }
  158. }
  159. };
  160. update.check();
  161.  
  162. // Y T M A CLASS
  163. /**
  164. @param id Unique ID
  165. @param site Website eg: youtube, vimeo
  166. @param a The link
  167. */
  168. function YTMA(id, site, a) {
  169. if (!YTMA.sites[site]) {
  170. return;
  171. }
  172.  
  173. this.data = {
  174. id : id,
  175. uid : id + (YTMA.num += 1),
  176. site : site,
  177. uri : a.href,
  178. thumb : 1
  179. };
  180.  
  181. this.spn = $$.e('span', {title: 'YouTube Me!', className : 'ylinks _' + this.data.id});
  182. this.spn.addEventListener('click', this.show.bind(this), false);
  183. this.wrp = $$.e('div', {className : 'ytmwrap'});
  184. this.wrs = $$.e('div', {id : 'w' + this.data.uid, className : 'yclear y_' + this.data.site});
  185. this.ul = $$.e('ul', {className : 'ytmbar arialsans'});
  186.  
  187. this.setup(a);
  188. }
  189.  
  190. YTMA.num = 0;
  191. YTMA.sites = {
  192. youtube : 'https://www.youtube-nocookie.com/',
  193. vimeo : 'http://vimeo.com/'
  194. // soundcloud : 'http://soundcloud.com',
  195. // vine : 'https://vine.co/'
  196. };
  197. YTMA.siteByTest = {
  198. youtu : 'youtube',
  199. vimeo : 'vimeo'
  200. // soundcloud : 'soundcloud',
  201. // vine : 'vine'
  202. };
  203. YTMA.reg = {
  204. not : /(?:\b(?:smallfont|user_title|spoiler)\b)/, // Class attributes to ignore
  205. id : /(?:(?:youtu)(?:\.be\/|.*?(?:v\=|#p\/u\/\d*?\/)|.*?(?:v\=|#p\/c\/[a-zA-Z0-9]+\/\d*?\/))([A-Za-z0-9-_]{11}))|(?:vimeo\.com\/(\d+))/i, //|(?:vine\.co\/v\/([A-Za-z0-9-_]{11}))|(?:soundcloud\.com\/(.+?\/.+))
  206. site : /(youtu)|(vimeo)|(vine)/,
  207. time : /(?:t\=(?:(\d+)m)?(\d+)?s?)/,
  208. ios : /(?:\b(?:ipod|iphone|ipad))\b/i
  209. };
  210. YTMA.img = {
  211. play : {
  212. youtube : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAXCAYAAACMLIalAAAACXBIWXMAAAsSAAALEgHS3X78AAADJElEQVRIx81WTWsbVxQ9782bL5kWSgUuuDbdhPyBrmqQCBSs4kXwpjQmm/yALpyf0IVJtsnWKAVBjbKSITWi4NLYqJumcYvpRrjpxhiDbIITyaN5H/d2YTu17AGP/BF64THDMPe88869794rmBnH9tXUbWjTj5Lk7UMhcI+ZP8A1mhCCmfkX34++jaMP/2r+tAQAUCd/0rov+2mv6py9AwEIiOvkBAYLMG4RJ00p/DKAV2dIeX5wu/+mc0dKD+BDt/dhbPWnVunvANw9Q+rtm71vwAxy7jzZYa1FmqaQUiIMQ0gpAeYLHyNNDyrH7wOkkqT3mRDiXIWstRgbG8NUpYJ2u41fWy30ej3EcYxD/+GNKP04kxQRyTwA3W4XU5UK5ubmwADWnj9HrVZDq9WCMQZRFF2YXBapXOo75xBF0WEoAZTKZZTKZayuruL7J0+wtrYGIrowuQFSjiiXkyOCO8q746eUEqVSCZOTk2g2m1hYWMD6+jo8KRGE4VCk5CmlhloAwMxgZjjnYK2FEALT09NYXFzE/Pw8xicm0O12c+OdIeWcG2pl+RhjkKYplFKYnZ1FvV7HzMwMkiTJhXcmfJwzfEwEcjQQvtNl0TkHz5MYHR3FxPg4rDHwlbrmnCJ3tLn9jwoDQgBBEEAphY2NDTx69BjLy8vwgyA3vjodvry3z1oDYwy01u++B0GAIPDRbrdRrVbRaCxhf38fIyMjYOaBvBmmJOQsdHSUPymM0VBKIYoibG7+jVqthkZjCZ3OLgqFGHEc58a9lFJEBK01hJBQSmF7exv1+lPU60+xs7ODOI5RKMRDYV5aqcD3sbLyM27evIGXL//As2c/YmtrC2EYolAoDIWV2VtPzlPFYvE3AJ/nmINgjAERwVr7LrEva7u7uyJLqddSnt/+mBlKKTAzgiC4qtmqn1k8i8VPVojy58Blmu7pQ4Z+9Gcmqb29TlVK+Q/eswkhcHDQe5BJyvNkh4i/ZuZNIcSVKXGO0n2t9f2knzQyb58QEkT0QgjxhbX2LhF9qZT6yPO8qx1/Dxu4cc698DzvB6317ycFGLh9/xf7F99PHfxrdBcwAAAAAElFTkSuQmCC',
  213. vimeo : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACUAAAAXCAYAAACMLIalAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAalJREFUeNrMl79PwkAUx6/XH1SUCAmLCaCTMammYdKB0bnp3r+AkT+AjakbIwNbNwdgYMDJGCbDbEhHFhckBaECLa3vQps46GChHt/kc/On7727vDJom0vgDuAAH9HJG/AM2AwcV4ABZAAP0QtxeQB0Upl7IA2sEN0IwC1wg+FgKVcojB94JDDFGfpVDu/4ZbEkqpQvSVJCFEUmDrmoUp6maaeDweCiXC6nOY5jDkEKQZUQVEus1+tnRA4kU8lkktlHayNLed72wvI8z8iyLBqGkev3++eqqp5ks1k2EPP/VeqnFIvFo1arlQdyiqKkCoUCjzGmKxWmVCoddzqdfKVSyQiC8Od54+KQWiwWG2jntN1uzx3HQdSloHWzRqNh9Xq9eTBTmJqUaZqrWq027na788lk4gYykZ6KnaWWy6Wn6/q42WxOR6ORs49Z3UkKZmZWrVbHw+Fw5bquH7Uy+5JioVXvtm176/X6+z6EaEohy7JiW3fCfepQQqrNEqlPslgdwF6Fg859kOMJ0ACJ4kpMhMgz8gi8hsN5DcjBz8OGUttM4AWYfQkwAOU+isXJ6aEzAAAAAElFTkSuQmCC'
  214. },
  215. fav : {
  216. youtube : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAAsSAAALEgHS3X78AAABUUlEQVQ4y8WTP0sDQRDFf3e3iQlBIQeCYAgaEVGMTRr9AKnERtTCwg9hYWkRBBEFEf+g4OcwgWgTRSy0EhTBKmAnsYiex2Yva2GUZCMRKxceu8O893YGZuC/j3XlxqLAMTACpIHwL5pbQAJ3k5W3JaE0q8DiHz5NN+7MRTz2ZCt0VqFpRhAOMbR3SCiVwswZyNo1SNaAZgSRCO7cAhOnJeKz85j5JiRtqXGlhma818H3faRtM7i9y8DWDqorgsmTGldIcNrb1Hie9x11T8+QCAIeV5ZNoiNqWrfL660GL+UypYN9Ej9whYQAowqNxvd9AO4Lec7X1xiVPtKyTH0gpKYC9LYYqDpetcrZ5gbP+RPGhY2DhWwvoGId9USvgUyLLXApFcPCoc+2Os3EjVDoomkAMBX+7EqhOxkUhdLkgH5g7GvCOggegNfGuwDk/n0Z+QAjkqDhSKnyRwAAAABJRU5ErkJggg==',
  217. vimeo : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAMAAAC67D+PAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAABhQTFRFutjhDKrTKqzN+Pz9H5CxT7nVis7g////lqc5nAAAAAh0Uk5T/////////wDeg71ZAAAAP0lEQVR42iTMyREAMAgCQASP/jsOGj7s8AATPxzwUDai0AG1SQhsYdeEolVLt8c8llZHYuXyTeb9YYo/8wQYAC81AOQXjj+CAAAAAElFTkSuQmCC'
  218. },
  219. css : {
  220. bar : 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAAuCAIAAABmjeQ9AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAFBJREFUeNp0jNENgEAIQ6EuwSre/vOcC1jwegkfJkryQqEUO8fANSeyCiTBm6hKZL6p5ZvZJ/KavhURcWh2941K/e9PA90os3RnW2uf5CPAAIQ5NuW1miKmAAAAAElFTkSuQmCC',
  221. load : 'data:image/gif;base64,R0lGODlhDgAKAJEAAP///+BKV////wAAACH/C05FVFNDQVBFMi4wAwEAAAAh+QQFCgACACwAAAAADgAKAAACHFSOeQYI71p6MtAJz41162yBH+do5Ih1kKG0QgEAIfkEBQoAAgAsAAABAA0ACAAAAhSUYGEoerkgdIzKGlu2ET/9ceJmFAAh+QQFCgACACwAAAEADQAIAAACFJRhcbmiglx78SXKYK6za+NxHyYVACH5BAUKAAIALAAAAQANAAgAAAIWVCSAl+hqEGRTLhtbdvTqnlUf9nhTAQAh+QQFCgACACwAAAEADQAIAAACFZRiYCh6uaCRzNXYsKVT+5eBW3gJBQAh+QQJCgACACwAAAAADgAKAAACGpSPaWGwfZhwQtIK8VTUvuxpm9Yp4XlmpiIUADs='
  222. }
  223. };
  224.  
  225. YTMA.selector = 'a[href*="youtube."], a[href*="youtu.be"], a[href*="vimeo.com"]'; //, a[href*="vine.co"]
  226. YTMA.pod = YTMA.reg.ios.test(navigator.userAgent);
  227. YTMA.ie = document.documentMode; // IE, basically | window.navigator.cpuClass
  228.  
  229. /**
  230. 0 "Frame", 1 Flash // 3 Hidden, 4 Small (240p), 5 Medium (360p), 6 Large (480p), 7 (720p) // 1 4:3, 2 16:9, 3 10:16 // Description // URL Anchor
  231. // 4 240, 5 360, 6 480, 7 720, 8 1080
  232. */
  233. YTMA.user = {
  234. init : function () {
  235. this.load();
  236. if (strg.on) {
  237. this.form();
  238. this.mark();
  239. }
  240. },
  241. defaults : function () {
  242. return {
  243. focus : 0,
  244. desc : 1, // Autoload descriptions. 1 = Yes, 0 = No
  245. flash : YTMA.pod || YTMA.ie ? 0 : 1, // if iOS or IE9+, use "html5" player
  246. ratio : 2,
  247. size : 360,
  248. quality : 360
  249. };
  250. },
  251. load : function () {
  252. var s = strg.grab('ytmasetts', {}), d = this.defaults();// if(s){console.log(s);}
  253. YTMA.user.opt = {
  254. flash : isNaN(s.flash) ? d.flash : +s.flash,
  255. size : isNaN(s.size) || s.size < 240 ? d.size : +s.size,
  256. ratio : isNaN(s.ratio) ? d.ratio : +s.ratio,
  257. desc : isNaN(s.desc) ? d.desc : +s.desc,
  258. focus : isNaN(s.focus) ? d.focus : +s.focus,
  259. quality : isNaN(s.quality) ? d.quality : +s.quality
  260. };
  261. // console.log(YTMA.user.opt.toSource());
  262. // console.log(YTMA.user.opt);
  263. },
  264. save : function (evt) {
  265. var e = evt.target;
  266. if (e.tagName.toLowerCase() === 'input') {
  267. switch (e.name) {
  268. case 'ytmaframe':
  269. YTMA.user.opt.flash = +e.checked;
  270. break;
  271. case 'ytmasize':
  272. YTMA.user.opt.size = e.value;
  273. break;
  274. case 'ytmaratio':
  275. YTMA.user.opt.ratio = +e.value;
  276. break;
  277. case 'ytmainfo':
  278. YTMA.user.opt.desc = +e.checked;
  279. break;
  280. case 'ytmafocus':
  281. YTMA.user.opt.focus = +e.checked;
  282. break;
  283. case 'ytmaiq':
  284. YTMA.user.opt.quality = +e.value;
  285. break;
  286. default:
  287. return;
  288. }
  289. YTMA.user.error.className = strg.save('ytmasetts', YTMA.user.opt) ? 'ytnone' : '';
  290. YTMA.user.load(); // console.log('n'+YTMA.user.opt.toSource()); console.log('n'+YTMA.user.opt);
  291. }
  292. },
  293. mark : function () {
  294. var a = {};
  295. a.ytmaframe = !!YTMA.user.opt.flash;
  296. a.ytmainfo = !!YTMA.user.opt.desc;
  297. a.ytmafocus = !!YTMA.user.opt.focus;
  298. a['ytmaratio' + YTMA.user.opt.ratio] = true;
  299. a['ytmasize' + YTMA.user.opt.size] = true;
  300. a['ytmaiq' + YTMA.user.opt.quality] = !!YTMA.user.opt.quality;
  301. $$.o(a, function (idx, bool) {
  302. try {
  303. document.getElementById(idx).checked = bool;
  304. } catch (e) {}
  305. });
  306. },
  307. reset : function () {
  308. YTMA.user.opt = YTMA.user.defaults();
  309. YTMA.user.mark();
  310. strg.wipe('ytmasetts');
  311. },
  312. form : function () {
  313. var f = [
  314. '<form action=""><div id="ytmasettingst">YouTube Me Again! Persistent Site Settings</div><p><small>Change video defaults.</small></p><div id="ytmaclears"><fieldset><legend>Information</legend><p><input name="ytmainfo" type="checkbox" id="ytmainfo" value="info" /><label for="ytmainfo">Load titles and descriptions automatically.</label></p></fieldset><fieldset><legend>Flash Support</legend><p><input name="ytmaframe" type="checkbox" id="ytmaframe" value="f" /><label for="ytmaframe">Use Flash.*</label></p></fieldset>',
  315. '<fieldset id="ytmasizefield"><legend>Player Size</legend><p><span class="ytmahalf"><input type="radio" name="ytmasize" value="240" id="ytmasize240" /><label for="ytmasize240">S <small>240p</small></label></span><span class="ytmahalf"><input name="ytmasize" type="radio" id="ytmasize360" value="360" /><label for="ytmasize360">M <small>360p</small></label></span><span class="ytmahalf"><input type="radio" name="ytmasize" value="480" id="ytmasize480" /><label for="ytmasize480">L <small>480p</small></label></span><span class="ytmahalf"><input type="radio" name="ytmasize" value="720" id="ytmasize720" /><label for="ytmasize720">X <small>720p</small></label></span></p></fieldset>',
  316. '<fieldset><legend>Quality</legend><p><span class="ytmahalf"><input name="ytmaiq" value="240" id="ytmaiq240" type="radio"><label for="ytmaiq240">240p</label></span><span class="ytmahalf"><input name="ytmaiq" id="ytmaiq360" value="360" type="radio"><label for="ytmaiq360">360p</label></span><span class="ytmahalf"><input name="ytmaiq" value="480" id="ytmaiq480" type="radio"><label for="ytmaiq480">480p</label></span><span class="ytmahalf"><input name="ytmaiq" value="720" id="ytmaiq720" type="radio"><label for="ytmaiq720">720p</label></span><span class="ytmahalf"><input name="ytmaiq" value="1080" id="ytmaiq1080" type="radio"><label for="ytmaiq1080">1080p</label></span></p></fieldset>',
  317. '<fieldset><legend>Window Focus</legend><p><input name="ytmafocus" type="checkbox" id="ytmafocus" value="focus" /><label for="ytmafocus">After clicking the thumbnail, set the video at the top of the window.</label></p></fieldset>',
  318. '<fieldset><legend>Aspect Ratio</legend><p><span class="ytmahalf"><input name="ytmaratio" type="radio" id="ytmaratio2" value="2" /><label for="ytmaratio2">16:9</label></span><span class="ytmahalf"><input type="radio" name="ytmaratio" value="1" id="ytmaratio1" /><label for="ytmaratio1">4:3</label></span><span class="ytmahalf"><input type="radio" name="ytmaratio" value="3" id="ytmaratio1" /><label for="ytmaratio1">6:19</label></span></p></fieldset>',
  319. '</div><p><small id="ytmasettingserror" class="ytnone">Error! Your settings could not be saved.</small></p><p id="ytmaopts"><small id="ytmaclose">Close</small> <small id="ytmareset">Reset</small> <small>*Disable this option for iOS and other devices.</small></p></form>'
  320. ].join('');
  321.  
  322. YTMA.form = $$.e('div', {id : 'ytmasettings', className : 'ytnone', innerHTML : f}, document.body);
  323. YTMA.user.error = document.getElementById('ytmasettingserror');
  324.  
  325. YTMA.form.addEventListener('click', YTMA.user.save, false);
  326. document.getElementById('ytmaclose').addEventListener('click', YTMA.user.toggle, false);
  327. document.getElementById('ytmareset').addEventListener('click', YTMA.user.reset, false);
  328. },
  329. toggle : function (force) {
  330. YTMA.form.className = (force === true || /(?:ytnone)/.test(YTMA.form.className)) ? '' : 'ytnone';
  331. }
  332. };
  333. YTMA.css = function () {
  334. update.css(['\n/* youtube me again! */\n.yclear,.ytmwrap,object{clear:both;text-align:left}.yclear{overflow:auto;margin:0 0 6px}#ytmasettings,.arialsans{font-family:Arial,Helvetica,sans-serif!important}.ylinks{display:block;width:118px;height:68px;overflow:hidden;font-style:normal;background-color:#111!important;background-repeat:no-repeat!important;background-position:center -11px!important;cursor:pointer;-moz-border-radius:2px;border-radius:1px;position:relative;float:left;-moz-box-shadow:0 0 2px #222;box-shadow:0 0 2px #222;margin:4px}.ylinks img{border:0;opacity:1;top:28px;left:42px;z-index:9;position:absolute}.ylinks:hover img{opacity:.9}.ytmainit{display:block;background:#111;color:#fff;text-shadow:#333 0 0 2px;opacity:1.0;text-align:left;font-size:11px;margin:0;padding:3px;-moz-border-radius:2px 2px 0 0;border-radius:2px 2px 0 0;height:12px}.ytmainit:after{content:" "; display:block; width:104%; height:52px; background: url(', YTMA.img.play.youtube, ') no-repeat center center;}.ytmainit:hover:after{opacity:.9}.y_vimeo .ytmainit:after{background-image: url(', YTMA.img.play.vimeo, ');}.ytmwrap{overflow:hidden;font-style:normal;margin:3px 0 0;padding:1px 2px} ul.ytmbar{overflow:hidden;margin:0;padding:3px 0 4px;list-style-position:outside !important}.ytmbar 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 #222;border-bottom:1px solid #000;box-shadow:0 0 1px #333;height:14px;font-size:12px!important;line-height:12px!important;background:#161616 url(', YTMA.img.css.bar, ');margin:0 !important;padding:5px 9px 3px !important}.yliop{-moz-border-radius:2px 0 0 2px;border-radius:2px 0 0 2px}.ylimi{border-left:0!important}li.ylicl{border-left:0!important;-moz-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0;margin:0 2px 0 0 !important}.ylicr{-moz-border-radius:2px;border-radius:2px}.ytmbar li:hover{color:#ccc;text-shadow:1px 1px 0 #333;background:#222 url(', YTMA.img.css.bar, ') 0 -23px} .ytmbar li[id]{color:#ddd;text-shadow:0 0 2px #444} span.yloading{font-style:italic;background:url(', YTMA.img.css.load, ') 0 3px no-repeat;text-indent:17px}.ypg,.ypgv{background:url(', YTMA.img.fav.youtube, ') 2px -1px no-repeat !important;-moz-border-radius:1px;border-radius:1px;padding:0 3px 0 21px !important}.ypgv{background:url(', YTMA.img.fav.vimeo, ') 3px 2px no-repeat !important;padding:0 3px 0 16px !important}.ypg b,.ypg strong{font-weight:400!important}.ypg u{text-decoration:none}.ypg i,.ypg em{font-style:normal}.ypg:hover{background-color:#fff}.ytitled{float:left;max-width:500px;font-style:normal;font-weight:700;margin:5px 0 0 3px}.yterror{color:#CC2F24;font-style:italic} q[ondblclick]{cursor:pointer}.ydescr{display:block;word-wrap:break-word;font-weight:400;max-height:48px;overflow:auto;padding-right:20px}.ydescropen{resize:both;white-space:pre-line;}.ydescropen[style]{max-height:none}#ytmasettings{font-size:12px;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:1px 0 5px;padding:4px 8px 0}#ytmasettings *{font-weight:400}#ytmasettings p{font-size:12px;clear:both;margin:5px 0;padding:0}#ytmaclears{overflow:hidden}#ytmasettings fieldset{border-radius:3px;border:1px solid #ccc;display:inline-block;width:180px;margin:0 2px;padding:4px 7px 9px}#ytmasettings p>input{margin:3px 3px 0 4px !important}#ytmasettings p>span>input[type=radio]{margin:3px 5px!important}#ytmasettingst{font-size:14px;border-bottom:1px dashed #D00;margin-bottom:6px;padding:0 3px 3px}#ytmasettings .ytmahalf{width:80px;display:inline-block}#ytmasettings .ytmahalf label{width:50px;display:inline-block;cursor:pointer}#ytmasettingserror{font-weight:700;color:#d00}#ytmaopts small{cursor:pointer;display:inline-block;margin-right:20px}#ytmaopts small:hover{color:#222}.ytnone,.ypg br{display:none}'].join(''));
  335. };
  336. YTMA.jid = {
  337. sites: {},
  338. init: function () {
  339. $$.o(YTMA.sites, function (site) {
  340. YTMA.jid.sites[site] = {
  341. set: {},
  342. current: 0,
  343. length: 0,
  344. throttle: null
  345. };
  346. });
  347. },
  348. add: function (id, site) {
  349. if (!this.sites[site].set[id]) {
  350. this.sites[site].set[id] = true;
  351. this.sites[site].length += 1;
  352. }
  353. }
  354. };
  355. YTMA.json = {
  356. maxBatch : 50,
  357. intervals : [250, 10000],
  358. start: function () {
  359. var time = 0;
  360. if (YTMA.jid.sites.youtube.length > 100) {
  361. time = 2500;
  362. YTMA.json.intervals[1] = 15000;
  363. }
  364. $$.o(YTMA.sites, function (site) {
  365. return new YTMA.json.Batch(site, time);
  366. });
  367. },
  368. contentScope : function () {
  369. var $Y_T_M_A = {
  370. version: 'ytma.4.1.dat',
  371. cb: function (json) {
  372. var o, site;
  373. if (json.provider_name) {
  374. site = 'soundcloud';
  375. o = $Y_T_M_A.fn.soundcloud(json);
  376. } else if (json.entry) {
  377. site = 'youtube';
  378. o = $Y_T_M_A.fn.youtube(json.entry);
  379. } else { // Object.prototype.toString.call(json) === '[object Array]'
  380. site = 'vimeo';
  381. o = $Y_T_M_A.fn.vimeo(json[0]);
  382. }
  383. if (o.desc && o.desc.length > 140) {
  384. o.full = o.desc;
  385. o.desc = o.desc.substr(0, 130) + ' . . .';
  386. }
  387. $Y_T_M_A.set(site, o);
  388. $Y_T_M_A.proc(o);
  389. },
  390. fn: {
  391. soundcloud: function (j) {
  392. return {
  393. id: unescape(j.html).match(/tracks\/(\d+)/)[1],
  394. title: j.title,
  395. desc: j.description,
  396. th: j.thumbnail_url
  397. };
  398. },
  399. vimeo: function (j) {
  400. return {
  401. id: j.id,
  402. title: j.title + ' ' + $Y_T_M_A.secs(j.duration),
  403. desc: j.description.replace(/<br.?.?>/g, ''),
  404. th: unescape(j.thumbnail_medium)
  405. };
  406. },
  407. youtube: function (j) {
  408. var o = { id: j.media$group.yt$videoid.$t };
  409. if (!j.media$group.yt$duration) {
  410. o.error = true;
  411. } else {
  412. o.title = j.title.$t + ' ' + $Y_T_M_A.secs(j.media$group.yt$duration.seconds);
  413. o.desc = j.media$group.media$description.$t;
  414. }
  415. return o;
  416. }
  417. },
  418. data: {},
  419. set: function (site, obj) {
  420. if (!this.data[site]) {
  421. this.data[site] = {};
  422. }
  423. this.data[site][obj.id] = obj;
  424. this.save();
  425. },
  426. read: function (d) {
  427. try {
  428. d = JSON.parse(localStorage.getItem(this.version));
  429. if (d instanceof Object) {
  430. this.data = d;
  431. }
  432. } catch (e) { console.error(e); }
  433. // alert(this.data);
  434. },
  435. save: function () {
  436. try {
  437. // count this.data props < 1300
  438. localStorage.setItem(this.version, JSON.stringify(this.data));
  439. } catch (e) {}
  440. },
  441. secs: function (secs) {
  442. var p, H, M, S;
  443. try {
  444. H = Math.floor(secs / 3600) % 60;
  445. M = H ? ('0' + Math.floor(secs / 60) % 60).slice(-2) : Math.floor(secs / 60) % 60;
  446. S = ('0' + secs % 60).slice(-2);
  447. p = [' (', H ? H + ':' : '', M, ':', S, ')'].join('');
  448. } catch (e) {}
  449. return p;
  450. },
  451. proc: function (data) {
  452. if (data.error) {
  453. return $Y_T_M_A.select('.ytitled._' + data.id, function (el) {
  454. el.textContent = 'Error, unable to load data.';
  455. el.className = 'yterror ytitled';
  456. });
  457. }
  458.  
  459. if (data.th) { // for Vimeo thumbs
  460. $Y_T_M_A.select('.ylinks', function (el) {
  461. el.setAttribute('style', 'background: url(' + data.th + ')');
  462. });
  463. }
  464.  
  465. $Y_T_M_A.select('.ytitled._' + data.id, function (el) {
  466. var q;
  467. el.textContent = data.title;
  468. el.className = 'ytitled _' + data.id;
  469. if (data.desc) {
  470. q = document.createElement('q');
  471. q.className = 'ydescr';
  472. q.textContent = data.desc;
  473. if (data.full) {
  474. q.setAttribute('data-full', data.full);
  475. q.title = 'Click to toggle the length of the description.';
  476. q.ondblclick = $Y_T_M_A.titleToggle;
  477. }
  478. el.appendChild(q);
  479. }
  480. });
  481. },
  482. select: function (selector, cb) {
  483. var s = document.querySelectorAll(selector), i = -1;
  484. while (++i < s.length) {
  485. cb(s[i]);
  486. }
  487. },
  488. titleToggle: function () {
  489. this.className = this.className === 'ydescr' ? 'ydescr ydescropen' : 'ydescr';
  490. this.textContent = this.textContent.length < 140 ? this.getAttribute('data-full') : this.getAttribute('data-full').substr(0, 130) + ' . . .';
  491. }
  492. };
  493. return $Y_T_M_A;
  494. },
  495. runner : function () { // content-scrope runner
  496. update.js('var $Y_T_M_A = (' + this.contentScope + ')(); $Y_T_M_A.read();');
  497. },
  498. script : function (id, site) {
  499. var s = $$.e('script', { id : id, src : YTMA.DB.json[site].replace('%id', id) });
  500. s.addEventListener('error', YTMA.json.errors, false);
  501. s.addEventListener('load', YTMA.json.loads, false);
  502. document.body.appendChild(s);
  503. },
  504. loads : function () { // console.log('loads');
  505. document.body.removeChild(this);
  506. },
  507. errors : function () {
  508. $$.s('.ytitled._' + this.id, function (el) {
  509. el.textContent = 'Error, unable to load video data.';
  510. el.className = 'yterror ytitled';
  511. });
  512. document.body.removeChild(this);
  513. }
  514. };
  515.  
  516. YTMA.$ = YTMA.json.contentScope();
  517. YTMA.$.data = strg.grab(YTMA.$.version, {});
  518.  
  519. YTMA.json.Batch = function (site, time) {
  520. this.site = site;
  521. this.ref = YTMA.jid.sites[site];
  522. this.fromStorage();
  523. this.timeouts(time);
  524. };
  525. YTMA.json.Batch.prototype = {
  526. constructor: YTMA.json.Batch,
  527. fromStorage: function () {
  528. $$.o(this.ref.set, function (id) { // console.log('current:', id, this.ref.current);
  529. if (strg.on && YTMA.$.data[this.site] && YTMA.$.data[this.site][id]) {
  530. console.log('from strg', id);
  531. delete this.ref.set[id];
  532. this.ref.length -= 1;
  533. YTMA.$.proc(YTMA.$.data[this.site][id]);
  534. return;
  535. }
  536. }.bind(this));
  537. },
  538. timeouts : function (ms) {
  539. if (this.ref.throttle) { // console.log('clear YTMA.json.throttle');
  540. window.clearInterval(this.ref.throttle);
  541. }
  542. if (this.ref.length > 0) {
  543. console.log(YTMA.json.intervals[1]);
  544. window.setTimeout(this.setInterval.bind(this), ms);
  545. }
  546. },
  547. setInterval: function () {
  548. this.ref.throttle = window.setInterval(this.loader.bind(this), YTMA.json.intervals[0]);
  549. },
  550. loader : function () {
  551. console.log(this.ref.length);
  552. if (this.ref.length > 0) {
  553. $$.o(this.ref.set, function (id) { // console.log('current:', id, this.ref.current);
  554.  
  555. delete this.ref.set[id];
  556. this.ref.length -= 1;
  557. this.ref.current += 1;
  558. YTMA.json.script(id, this.site);
  559.  
  560. if (this.ref.current > 0 && this.ref.current % YTMA.json.maxBatch === 0) {
  561. this.timeouts(YTMA.json.intervals[1]); // console.log('000');
  562. return false;
  563. }
  564. }.bind(this));
  565. } else {
  566. window.clearInterval(this.ref.throttle); // console.log('cleared: loader');
  567. }
  568. }
  569. };
  570. YTMA.getIdAndSite = function (uri) {
  571. var id, site;
  572. try {
  573. site = YTMA.siteByTest[YTMA.reg.site.test(uri) ? RegExp.lastMatch : ''];
  574. id = uri.href.match(YTMA.reg.id).filter(function (i) { return i; })[1];
  575. if (id && site) {
  576. // console.log(id, site);
  577. return [id, site];
  578. }
  579. throw TypeError('invalid id/site: ' + uri);
  580. } catch (e) {
  581. console.log(e);
  582. return false;
  583. }
  584. };
  585. YTMA.factory = function () {
  586. $$.s(this.selector, function (el, i) {
  587. var p = el.parentNode,
  588. idSite = YTMA.getIdAndSite(el);
  589. if (p && !YTMA.reg.not.test(p.className) && idSite) {
  590. YTMA.set[idSite[0] + '_' + i] = new YTMA(idSite[0], idSite[1], el);
  591. }
  592. });
  593. // console.log(YTMA.set);
  594. if (YTMA.user.opt.desc) {
  595. YTMA.json.start();
  596. }
  597. };
  598. YTMA.set = [];
  599. YTMA.init = function () {
  600. if (!this.initializer) {
  601. this.initializer = true;
  602. YTMA.css();
  603. YTMA.jid.init();
  604. YTMA.user.init();
  605. YTMA.json.runner();
  606. YTMA.factory();
  607. }
  608. };
  609. YTMA.DB = {
  610. ratios : {
  611. 1 : 3 / 4,
  612. 2 : 9 / 16,
  613. 3 : 16 / 10
  614. },
  615. sizes : {
  616. 0 : 0,
  617. 240 : 360,
  618. 360 : 640,
  619. 480 : 853,
  620. 720 : 1280
  621. },
  622. qualities : {
  623. 240 : 'small',
  624. 360 : 'medium',
  625. 480 : 'large',
  626. 720 : 'hd720',
  627. 1080 : 'hd1080'
  628. },
  629. json : {
  630. youtube : 'https://gdata.youtube.com/feeds/api/videos/%id?v=2&alt=json-in-script&callback=$Y_T_M_A.cb',
  631. vimeo : 'http://vimeo.com/api/v2/video/%id.json?callback=$Y_T_M_A.cb',
  632. soundcloud : 'http://soundcloud.com/oembed?format=json&callback=$Y_T_M_A.cb&iframe=' + true + '&url=' // (!!YTMA.user.opt.flash) http://soundcloud.com/matas/hobnotropic
  633. },
  634. sources : {
  635. youtube : function () {
  636. return [['text/html', YTMA.sites[this.parent.data.site] + 'embed/' + this.parent.data.id + '?theme=dark&color=white&showinfo=1&vq=' + this.$quality + '#at=' + this.$start],
  637. ['application/x-shockwave-flash', YTMA.sites[this.parent.data.site] + 'v/' + this.parent.data.id + '?version=3&theme=dark&color=white&showinfo=1&vq=' + this.$quality + '&start=' + this.$start]];
  638. },
  639. vimeo : function () {
  640. return [['text/html', 'http://player.vimeo.com/video/' + this.parent.data.id + '?badge=0'], false];
  641. },
  642. vine : function () {
  643. return [['text/html', 'https://vine.co/v/' + this.parent.data.id + '/embed#/simple', 'vine-embed'], false];
  644. },
  645. soundcloud : function () {
  646. return [['text/html', 'https://w.soundcloud.com/player/?url=http://api.soundcloud.com/tracks/' + this.parent.data.id], false];
  647. }
  648. }
  649. };
  650. /**
  651. @param parent YTMA object
  652. */
  653. YTMA.Player = function (parent) {
  654. this.parent = parent;
  655. this.$obj = this.$quality = this.$size = this.$ratio = this.$source = null;
  656. this.init_start();
  657. this.$quality = YTMA.DB.qualities[YTMA.user.opt.quality] || YTMA.DB.qualities[360];
  658. this.$source = YTMA.DB.sources[this.parent.data.site].call(this)[YTMA.user.opt.flash] || YTMA.DB.sources[this.parent.data.site].call(this)[(YTMA.user.opt.flash + 1) % 2];
  659. this.init_frame();
  660. this.size();
  661. };
  662. YTMA.Player.prototype = {
  663. constructor : YTMA.Player,
  664. dimmensions : function (n) {
  665. // var bar = (this.parent.data.site === 'youtube' && this.$size > 0) ? 30 : 0; // +30 pixels for the youtube bar
  666. this.$ratio = n === null || isNaN(n) ? YTMA.user.opt.ratio : n;
  667. console.log(n, this.$ratio, YTMA.user.opt.ratio);
  668. this.$obj.height = Math.round(this.$obj.width * YTMA.DB.ratios[this.$ratio]); // + bar;
  669. },
  670. size : function (n) {
  671. this.$size = isNaN(n) ? YTMA.user.opt.size : n;
  672. this.$obj.width = YTMA.DB.sizes[this.$size] > -1 ? YTMA.DB.sizes[this.$size] : YTMA.DB.sizes[360];
  673. this.dimmensions(this.$ratio);
  674. },
  675. reset : function () {
  676. this.size();
  677. this.parent.selected.item.call(this.parent, this.parent.ul.querySelector('li[n="' + this.$size + '"]'), 'size');
  678. },
  679. init_start : function () {
  680. try {
  681. var m = this.parent.data.uri.match(YTMA.reg.time);
  682. m = [m[1] * 60, +m[2]];
  683. this.$start = m[1] ? m[0] + m[1] : m[0];
  684. } catch (e) { this.$start = 0; }
  685. },
  686. init_frame : function () {
  687. // console.log(this.$source);
  688. if (YTMA.user.opt.flash && this.$source[0] === 'application/x-shockwave-flash') {
  689. this.$obj = $$.e('object', {type : 'application/x-shockwave-flash', data : this.$source[1]});
  690. $$.a(this.$obj, $$.e('param', { name : 'movie', value : this.$obj.data }), $$.e('param', {name : 'AllowScriptAccess', value : 'always'}), $$.e('param', {name : 'allowFullScreen', value : 'true'}));
  691. } else {
  692. this.$obj = $$.e('iframe', {$frameborder : 0, $allowfullscreen : 'always', type : 'text/html', src : this.$source[1], className: this.$source[2] || ''});
  693. }
  694. }
  695. };
  696. YTMA.prototype = {
  697. // constructor : YTMA,
  698. settings : function (evt) {
  699. var e = evt.target,
  700. n = +e.getAttribute('n'),
  701. t = e.getAttribute('data-type'),
  702. b = false;
  703. if (e.tagName.toLowerCase() === 'li') {// switch or this.settings.fire[t].call(this, e, n)
  704. if (t === 'settings') {
  705. if (YTMA.form.parentNode != this.wrp) {
  706. b = !!this.wrp.insertBefore(YTMA.form, this.ul.nextSibling);
  707. }
  708. YTMA.user.toggle(b);
  709. } else if (t === 'close') {
  710. this.toggle();
  711. } else if (t === 'ratio') {
  712. this.player.dimmensions(n);
  713. this.selected.item.call(this, e, 'ratio');
  714. } else if (t === 'size') {
  715. this.player.size(n);
  716. this.selected.item.call(this, e, 'size');
  717. }
  718. }
  719. },
  720. selected : {
  721. size : null,
  722. ratio: null,
  723. item : function (e, type) {
  724. e.id = type + this.data.uid;
  725. try {
  726. this.selected[type].removeAttribute('id');
  727. } catch (er) {}
  728. this.selected[type] = e;
  729. }
  730. },
  731. manual : function (e) {
  732. e.preventDefault();
  733. var p = e.target.parentNode;
  734. p.className += ' yloading';
  735. p.textContent = 'Loading data . . .';
  736. YTMA.json.script(this.data.id, this.data.site);
  737. },
  738. setup : function (link) {
  739. var className = this.dom.mod[this.data.site].call(this, link);
  740. this.dom.link.call(this, link, className);
  741. this.dom.span.call(this);
  742. },
  743. dom : {
  744. li : function (type, txt, n, t, c) {
  745. var l = $$.e('li', {'$data-type' : type, textContent : txt, $n : n, title : t, className : c});
  746. if ((type === 'size' && this.player.$size === n) || (type === 'ratio' && this.player.$ratio === n)) {
  747. this.selected.item.call(this, l, type);
  748. }
  749. return l;
  750. },
  751. link : function (link, css) {
  752. if (link.getElementsByTagName('img').length === 0 && css) {
  753. link.className += ' ' + css;
  754. }
  755. link.title = 'Visit the video page.';
  756. link.parentNode.insertBefore(this.wrs, link.nextSibling);
  757. },
  758. mod : { // modifies the link or other site-specific items; return css class for the link
  759. youtube : function (a) {
  760. this.spn.addEventListener('mouseover', this.thumb.start.bind(this), false);
  761. this.spn.addEventListener('mouseout', this.thumb.stop.bind(this), false);
  762. this.spn.style.backgroundImage = ['url(https://i3.ytimg.com/vi/', this.data.id, '/', this.data.thumb, '.jpg)'].join('');
  763. a.href = a.href.replace('http:', 'https:').replace('youtu.be/', 'youtube.com/watch?v=');
  764. return 'ypg';
  765. },
  766. vimeo : function () {
  767. this.spn.title = 'Vimeo Me Too!';
  768. return 'ypgv';
  769. },
  770. vine : function () {
  771. this.spn.title = 'Vine Me!';
  772. return 'ypgvine';
  773. },
  774. soundcloud: function () {
  775. this.spn.title = 'Sound Off!';
  776. return 'ypgsc';
  777. }
  778. },
  779. ui : function () {
  780. var close = 'ylicr', f = document.createDocumentFragment();
  781.  
  782. // todo, YTMA.db.SIZE.PORTRAIT, etc
  783. $$.a(f,
  784. this.dom.li.call(this, 'ratio', '4:3', 1, 'SD', 'yliop'),
  785. this.dom.li.call(this, 'ratio', '16:9', 2, 'Widescreen', 'ylimi'),
  786. this.dom.li.call(this, 'ratio', '10:16', 3, 'Portrait', 'ylicl'),
  787. this.dom.li.call(this, 'size', '\u00D8', 0, 'Hide the video.', 'yliop'),
  788. this.dom.li.call(this, 'size', 'S', 240, '240p', 'ylimi'),
  789. this.dom.li.call(this, 'size', 'M', 360, '360p', 'ylimi'),
  790. this.dom.li.call(this, 'size', 'L', 480, '480p', 'ylimi'),
  791. this.dom.li.call(this, 'size', 'X', 720, '720p', 'ylicl'));
  792.  
  793. if (strg.on) {
  794. f.appendChild(this.dom.li.call(this, 'settings', '!', null, 'Edit YTMA\'s settings.', 'yliop'));
  795. close = 'ylicl';
  796. }
  797.  
  798. f.appendChild(this.dom.li.call(this, 'close', '\u00D7', null, 'Close the video.', close));
  799.  
  800. this.ul.appendChild(f);
  801. this.ul.addEventListener('click', this.settings.bind(this), false);
  802. this.wrp.appendChild(this.ul);
  803. this.spn.parentNode.insertBefore(this.wrp, this.spn.nextSibling);
  804. },
  805. span : function () {
  806. var a, f = document.createDocumentFragment();
  807.  
  808. $$.e('span', {className : 'ytmainit arialsans', textContent : this.spn.title}, this.spn);
  809. f.appendChild(this.spn);
  810. if (YTMA.user.opt.desc) {
  811. YTMA.jid.add(this.data.id, this.data.site);
  812. f.appendChild($$.e('span', {className : 'ytitled yloading _' + this.data.id, textContent : 'Loading data . . .' }));
  813. } else {
  814. a = $$.e('a', { textContent: 'Load description.', href: '#', title: 'Load this video\'s description.' });
  815. a.addEventListener('click', this.manual.bind(this), false);
  816. f.appendChild($$.a($$.e('span', {className : 'ytitled ymanual _' + this.data.id}), a));
  817. }
  818. this.wrs.appendChild(f);
  819. }
  820. },
  821. createPlayer : function () {
  822. this.player = new YTMA.Player(this);
  823. this.dom.ui.call(this);
  824. },
  825. show : function () {
  826. if (!this.player) {
  827. this.createPlayer();
  828. }
  829. this.toggle(true);
  830. if (YTMA.user.opt.focus) {
  831. document.location.set = '#' + this.wrs.id;
  832. }
  833. },
  834. toggle : function (show) {// the object is removed from or reattached to the DOM
  835. if (show) {
  836. if (this.player.$size === 0) {
  837. this.player.reset();
  838. }
  839. this.spn.className += ' ytnone';
  840. this.wrp.className = this.wrp.className.replace(' ytnone', '');
  841. this.wrp.appendChild(this.player.$obj);
  842. } else {
  843. this.spn.className = this.spn.className.replace(' ytnone', '');
  844. this.wrp.className += ' ytnone';
  845. this.wrp.removeChild(this.player.$obj);
  846. }
  847. },
  848. thumb : {
  849. start : function () {
  850. this.data.thumb = this.data.thumb < 3 ? this.data.thumb + 1 : 1;
  851. this.spn.style.backgroundImage = ['url(https://i3.ytimg.com/vi/', this.data.id, '/', this.data.thumb, '.jpg)'].join('');
  852. this.data.timeout = window.setTimeout(this.thumb.start.bind(this), 1000);
  853. },
  854. stop : function () {
  855. window.clearTimeout(this.data.timeout);
  856. }
  857. }
  858. };
  859. YTMA.init();
  860.  
  861. }());