Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // ==UserScript==
- // @name Yays! (Yet Another Youtube Script)
- // @description Control autoplaying and playback quality on YouTube.
- // @version 1.4.3
- // @author eugenox_gmail_com
- // @license (CC) BY-SA-3.0 http://creativecommons.org/licenses/by-sa/3.0/
- // @namespace youtube
- // @include http://*.youtube.*/*
- // @include http://youtube.*/*
- // ==/UserScript==
- function YAYS(unsafeWindow) {
- /*
- * Meta data
- */
- var Meta = {
- title: 'Yays! (Yet Another Youtube Script)',
- version: '1.4.3',
- releasedate: 'Jul 24, 2010',
- site: 'http://eugenox.appspot.com/script/yays',
- namespace: 'yays'
- };
- /*
- * Script namespace.
- */
- unsafeWindow[Meta.namespace] = {};
- /*
- * Utility functions.
- */
- function each(callback, iterable, scope) {
- if (iterable.length) {
- for (var i = 0; i < iterable.length; i++)
- callback.call(scope, i, iterable[i]);
- }
- else {
- for (var key in iterable)
- if (iterable.hasOwnProperty(key))
- callback.call(scope, key, iterable[key]);
- }
- }
- function map() {
- var args = Array.prototype.constructor.apply([], arguments);
- var callback = args.shift() || createCallback(Array.prototype.constructor, []);
- var buffer = [];
- if (args.length > 1) {
- var len = Math.max.apply(Math, map(function(arg) { return arg.length; }, args));
- var getter = function(arg) { return arg[i]; };
- for (var i = 0; i < len; i++)
- buffer.push(callback.apply(null, map(getter, args)));
- }
- else {
- for (var i = 0, arg = args[0], len = arg.length; i < len; i++)
- buffer.push(callback(arg[i]));
- }
- return buffer;
- }
- function combine(keys, values) {
- var object = {};
- map(function(key, value) { object[key] = value; }, keys, values);
- return object;
- }
- function copyProperties(src, target) {
- for (var key in src) target[key] = src[key];
- return target;
- }
- function createCallback(func, scope) {
- return function() { return func.apply(scope, arguments); };
- }
- var emptyFunction = function() { return; };
- function extendFunction(func, extension) {
- return function() {
- try { func.apply(this, arguments); } catch (ex) { }
- extension.apply(this, arguments);
- };
- }
- /*
- * i18n
- */
- function _(text) {
- return _.dictionary[text] || text;
- }
- _.dictionary = (function() {
- var vocabulary = [
- 'Auto play', 'ON', 'OFF', 'Toggle video autoplay',
- 'Quality', 'AUTO', 'LOW', 'MEDIUM', 'HIGH', 'VERY HIGH', 'Set default video quality',
- 'Settings', 'Player settings'
- ];
- switch ((document.documentElement.lang || 'en').substr(0, 2)) {
- // hungarian - magyar
- case 'hu':
- return combine(vocabulary, [
- 'Automatikus lej\xE1tsz\xE1s', 'BE', 'KI', 'Automatikus lej\xE1tsz\xE1s ki-, bekapcsol\xE1sa',
- 'Min\u0151s\xE9g', 'AUTO', 'ALACSONY', 'K\xD6ZEPES', 'MAGAS', 'NAGYON MAGAS', 'Vide\xF3k alap\xE9rtelmezett felbont\xE1sa',
- 'Be\xE1ll\xEDt\xE1sok', 'Lej\xE1tsz\xF3 be\xE1ll\xEDt\xE1sai'
- ]);
- // dutch - nederlands (Mike-RaWare @userscripts.org)
- case 'nl':
- return combine(vocabulary, [
- 'Auto spelen', 'AAN', 'UIT', 'Stel automatisch afspelen in',
- 'Kwaliteit', 'AUTOMATISCH', 'LAAG', 'GEMIDDELD', 'HOOG', 'ZEER HOOG', 'Stel standaard videokwaliteit in',
- undefined, undefined
- ]);
- // spanish - español (yonane @userscripts.org)
- case 'es':
- return combine(vocabulary, [
- 'Reproducci\xF3n Autom\xE1tica', undefined, undefined, 'Modificar Reproducci\xF3n Autom\xE1tica',
- 'Calidad', 'AUTO', 'BAJA', 'MEDIA', 'ALTA', undefined, 'Usar calidad por defecto',
- undefined, undefined
- ]);
- // german - deutsch (xemino @userscripts.org)
- case 'de':
- return combine(vocabulary, [
- 'Automatische Wiedergabe', 'AN', 'AUS', 'Automatische Wiedergabe umschalten',
- 'Qualit\xE4t', 'AUTO', 'NIEDRIG', 'MITTEL', 'HOCH', undefined, 'Standard Video Qualit\xE4t setzen',
- undefined, undefined
- ]);
- // brazilian portuguese - português brasileiro (Pitukinha @userscripts.org)
- case 'pt':
- return combine(vocabulary, [
- 'Reprodu\xE7\xE3o Autom\xE1tica', 'LIGADO', 'DESLIGADO', 'Modificar Reprodu\xE7\xE3o Autom\xE1tica',
- 'Qualidade', 'AUTOM\xC1TICO', 'MÁ', 'M\xC9DIO', 'BOA', 'MUITO BOA', 'Defini\xE7\xE3o padr\xE3o de v\xEDdeo',
- 'Configura\xE7\xF5es', 'Configura\xE7\xE3o do usu\xE1rio'
- ]);
- }
- return {};
- })();
- /*
- * DOM Helper singleton.
- */
- var DH = {
- build: function(def) {
- switch (Object.prototype.toString.call(def)) {
- case '[object Object]':
- def = copyProperties(def, {tag: 'div', style: {}, attributes: {}, children: []});
- var node = this.createElement(def.tag);
- this.style(node, def.style);
- this.attributes(node, def.attributes);
- this.append(node, def.children);
- return node;
- case '[object String]':
- return this.createTextNode(def);
- default:
- return def;
- }
- },
- getById: createCallback(unsafeWindow.document.getElementById, unsafeWindow.document),
- createElement: createCallback(unsafeWindow.document.createElement, unsafeWindow.document),
- createTextNode: createCallback(unsafeWindow.document.createTextNode, unsafeWindow.document),
- style: function(node, style) {
- copyProperties(style, node.style);
- },
- append: function(node, children) {
- each(function(i, child) { node.appendChild(this.build(child)); }, [].concat(children), this);
- },
- prepend: function(node, children) {
- if (node.hasChildNodes()) {
- var firstChild = node.firstChild;
- each(function(i, child) { node.insertBefore(this.build(child), firstChild); }, [].concat(children), this);
- }
- else {
- this.append(node, children);
- }
- },
- content: function(node, children) {
- if (node.hasChildNodes()) {
- var child;
- while (child = node.firstChild) node.removeChild(child);
- }
- this.append(node, children);
- },
- attributes: function(node, attributes) {
- each(node.setAttribute, attributes, node);
- },
- on: function(node, type, listener) {
- node.addEventListener(type, listener, false);
- }
- };
- /*
- * Configuration handler singleton.
- */
- var Config = (function(namespace) {
- // Greasemonkey compatible
- if (typeof GM_listValues == 'function') {
- // Accessing GM_getValue from unsafeWindow is not allowed.
- var GM_values = combine(GM_listValues(), map(GM_getValue, GM_listValues()));
- return {
- get: function(key) {
- return GM_values[key] || null;
- },
- set: function(key, value) {
- GM_setValue(key, value);
- GM_values[key] = value;
- }
- };
- }
- var prefix = namespace ? namespace + '.' : '';
- // HTML5
- if (typeof unsafeWindow.localStorage == 'object') {
- return {
- get: function(key) { return unsafeWindow.localStorage.getItem(prefix + key); },
- set: function(key, value) { return unsafeWindow.localStorage.setItem(prefix + key, value); }
- };
- }
- // Cookie
- return {
- get: function(key) {
- return (document.cookie.match(new RegExp('(?:^|; *)' + prefix + key + '=(\\w+)(?:$|;)')) || [, null])[1];
- },
- set: function(key, value) {
- key = prefix + key;
- if (new RegExp('(?:^|; *)' + key + '=\\w+(?:$|;)').test(document.cookie)) {
- document.cookie = key + '=' + value;
- }
- else {
- document.cookie = key + '=' + value + '; path=/; expires=' + new Date(new Date().valueOf() + 365 * 24 * 3600 * 1000).toUTCString();
- }
- }
- };
- })(Meta.namespace);
- /*
- * JSONRequest class.
- */
- var JSONRequest = (function(namespace) {
- function buildURL(base, parameters) {
- var queryParams = [];
- each(function(key, value) { queryParams.push(key + '=' + encodeURIComponent(value)); }, parameters);
- return base + '?' + queryParams.join('&');
- }
- var RequestClass;
- // Greasemonkey XHR
- if (typeof GM_xmlhttpRequest == 'function') {
- RequestClass = function(url, parameters, callback) {
- this._callback = callback;
- GM_xmlhttpRequest({
- method: 'GET',
- url: buildURL(url, parameters),
- onload: createCallback(this._onLoad, this)
- });
- };
- RequestClass.prototype = {
- _onLoad: function(response) {
- this._callback(eval('(' + response.responseText + ')'));
- }
- };
- }
- // Script tag
- else {
- unsafeWindow[namespace].JSONRequest = [];
- RequestClass = function(url, parameters, callback) {
- this._callback = callback;
- this._id = unsafeWindow[namespace].JSONRequest.push(createCallback(this._onLoad, this)) - 1;
- parameters.callback = namespace + '.JSONRequest[' + this._id + ']';
- this._scriptTag = document.body.appendChild(DH.build({
- tag: 'script',
- attributes: {
- type: 'text/javascript',
- src: buildURL(url, parameters)
- }
- }));
- };
- RequestClass.prototype = {
- _onLoad: function(response) {
- this._callback(response);
- document.body.removeChild(this._scriptTag);
- delete unsafeWindow[namespace].JSONRequest[this._id];
- }
- };
- }
- return RequestClass;
- })(Meta.namespace);
- /*
- * Check for update.
- */
- (function () {
- if (new Date().valueOf() - new Number(Config.get('update_checked_at')).valueOf() < 24 * 3600 * 1000) return;
- var popup = null;
- new JSONRequest(Meta.site + '/changelog', {version: Meta.version}, function (changelog) {
- Config.set('update_checked_at', new String(new Date().valueOf()).valueOf());
- if (changelog && changelog.length) popup = renderPopup(changelog);
- });
- function renderPopup(changelog) {
- return document.body.appendChild(DH.build({
- style: {
- position: 'fixed', top: '20px', right: '20px', zIndex: 1000, padding: '5px', background: '#f5f5f5', border: '1px solid #c3c3c3',
- color: '#202020', fontSize: '11px', fontFamily: 'Arial,Nimbus Sans L,sans-serif', lineHeight: '11px'
- },
- children: [{
- style: {margin: '2px 0', textAlign: 'center', fontWeight: 'bold'},
- children: Meta.title
- }, {
- style: {marginBottom: '6px', textAlign: 'center'},
- children: 'UserScript update notification.'
- }, {
- children: ['You are using version ', {tag: 'b', children: Meta.version}, {tag: 'i', children: [' (', Meta.releasedate, ')']}, '. Consider updating to the newest version.']
- }, {
- style: {margin: '5px'},
- children: map(function(entry) {
- return {
- children: [
- {tag: 'b', style: {fontSize: '11px'}, children: entry.version},
- {tag: 'i', style: {marginLeft: '5px'}, children: entry.date},
- {style: {padding: '0 0 2px 10px', whiteSpace: 'pre'}, children: [].concat(entry.note).join('\n')}
- ]
- };
- }, [].concat(changelog))
- }, {
- style: {textAlign: 'center', padding: '10px'},
- children: map(function(text, handler) {
- var node = DH.build({
- tag: 'span',
- style: {border: '1px solid #cccccc', padding: '3px 10px', margin: '0 5px', cursor: 'pointer', backgroundColor: '#e5e5e5'},
- children: text
- });
- DH.on(node, 'click', handler);
- return node;
- }, ['Update', 'Later'], [openSite, removePopup])
- }]
- }));
- }
- function removePopup() {
- document.body.removeChild(popup);
- }
- function openSite() {
- removePopup();
- unsafeWindow.open(Meta.site);
- }
- })();
- /*
- * Button class.
- */
- function Button(labelText, tooltipText) {
- var node = DH.build(this._dom.node);
- var label = DH.build(this._dom.label);
- var indicator = DH.build(this._dom.indicator);
- DH.attributes(node, { title: tooltipText });
- DH.append(label, labelText);
- DH.append(node, [label, indicator]);
- DH.on(node, 'click', createCallback(this._onClick, this));
- this._node = node;
- this.indicator = indicator.firstChild;
- }
- Button.prototype = {
- _onClick: function(event) {
- this.handler();
- this.refresh();
- },
- render: function() {
- this.refresh();
- return this._node;
- },
- _dom: {
- node: {
- tag: 'button',
- style: {margin: '0 0 0 5px'},
- attributes: {type: 'button', 'class': 'yt-uix-button yt-uix-tooltip'}
- },
- label: {
- tag: 'span',
- attributes: {'class': 'yt-uix-button-content'}
- },
- indicator: {
- tag: 'span',
- style: {fontWeight: 'bold', marginLeft: '5px'},
- attributes: {'class': 'yt-uix-button-content'},
- children: ''
- }
- },
- handler: emptyFunction,
- refresh: emptyFunction
- };
- /*
- * PLAYERFUNCTION class.
- */
- function PlayerFunction(configKey, overrides) {
- copyProperties(overrides, this);
- this._configKey = configKey;
- PlayerFunction.functions.push(this);
- }
- PlayerFunction.prototype = {
- _player: null,
- get: function() {
- return new Number(Config.get(this._configKey)).valueOf();
- },
- set: function(value) {
- Config.set(this._configKey, value);
- },
- init: emptyFunction,
- apply: emptyFunction
- };
- PlayerFunction.functions = [];
- PlayerFunction.init = function(player) {
- this.prototype._player = player;
- each(function(i, func) { func.init(); }, this.functions);
- };
- /*
- * AUTOPLAY
- */
- var AutoPlay = new PlayerFunction('auto_play', {
- _applied: false,
- init: function() {
- this._applied = this.get() == 0;
- },
- step: function() {
- this.set((this.get() + 1) % 2);
- },
- apply: function() {
- if (! this._applied && this._player.getPlayerState() == 1) {
- this._player.seekTo(0, true);
- this._player.pauseVideo();
- this._applied = true;
- }
- },
- createButton: function() {
- var button = new Button(_('Auto play'), _('Toggle video autoplay'));
- button.handler = createCallback(this.step, this);
- button.refresh = function() {
- this.indicator.data = _(['ON', 'OFF'][AutoPlay.get()]);
- };
- return button;
- }
- });
- /*
- * VIDEO QUALITY
- */
- var VideoQuality = new PlayerFunction('video_quality', {
- step: function() {
- this.set((this.get() + 1) % 5);
- },
- qualities: {hd1080: 4, hd720: 3, large: 2, medium: 1, small: 0},
- apply: function() {
- var qualities = this._player.getAvailableQualityLevels();
- var quality = null;
- switch (this.get()) {
- case 1: // LOW
- quality = qualities.pop(); break;
- case 2: // MEDIUM
- while (this.qualities[quality = qualities.shift()] > this.qualities.large); break;
- case 3: // HIGH
- while (this.qualities[quality = qualities.shift()] > this.qualities.hd720); break;
- case 4: // VERY HIGH
- quality = qualities.shift(); break;
- default:
- return;
- }
- this._player.setPlaybackQuality(quality);
- },
- createButton: function() {
- var button = new Button(_('Quality'), _('Set default video quality'));
- button.handler = createCallback(this.step, this);
- button.refresh = function() {
- this.indicator.data = _(['AUTO', 'LOW', 'MEDIUM', 'HIGH', 'VERY HIGH'][VideoQuality.get()]);
- };
- return button;
- }
- });
- /*
- * PLAYER STATE CHANGE callback
- */
- unsafeWindow[Meta.namespace].onPlayerStateChange = function() {
- AutoPlay.apply();
- };
- /*
- * PLAYER READY callback
- */
- function onPlayerReady() {
- var player = DH.getById('movie_player');
- if (player/* && typeof player.getPlayerState == 'function'*/) {
- PlayerFunction.init(player);
- VideoQuality.apply();
- AutoPlay.apply();
- player.addEventListener('onStateChange', Meta.namespace + '.onPlayerStateChange()');
- return true;
- }
- return false;
- }
- /*
- * PER-SITE
- */
- // WATCH page
- if (DH.getById('watch-actions-right') !== null) {
- var controlButton = DH.build({
- tag: 'button',
- style: {margin: '0 0 0 5px'},
- attributes: {type: 'button', 'class': 'yt-uix-button yt-uix-tooltip', title: _('Player settings')},
- children: {
- tag: 'img',
- attributes: {src: 'data:image/png;base64,\
- iVBORw0KGgoAAAANSUhEUgAAABAAAAARCAQAAAB+puRPAAAAAXNSR0IArs4c6QAAAYxJREFUKM+N\
- 0T9I1HEABfDPzzuMLvFPQ38QOYj+YCClo7T0l/7SEji1VkSu/bGhsRouyS6IlnDpcIksggYnA6Os\
- 5EoIrMBQKIIo9O707vzdt0FBx97y4L03vMeLrMHgoXA1Ft86N7KqJdcGPOteT65balWqg1x/LgwW\
- qYQFZc2BbDEbBgYgIne+9cF20z6hA+/Qqd2Yid4b2SQLiUlJJXusU8EBiyqmvFSpI8Hw+JmF1OGS\
- ed+8MqtBpKpkri+TIXqUr7aFlg5zfno6Ue5plh463pnQ5LlKoToTPQzHTPutwWufdz7+QmZH21Ra\
- UaOtrkjGSpaQsElhZVoQi1UUzIl687/a0i0nlTQam4h6gtrQvs6KWNbfwuJMBHcu775dk1LvO9Ji\
- RfOe9OVukiBzsda/V2yDRi02SiHS6u3B9j+Tb5JU412ajPuq3gmxuyJHbbbFaG2l1IV7PeFUmevl\
- fHgfTpfZX+4K7ffXvHQ2gmtLo+FFOLIEXdGyk1imj2Dbh+H0yEz10uwUP/wn/gGkFpjRuL8SbgAA\
- AABJRU5ErkJggg=='}
- }
- });
- DH.on(controlButton, 'click', function() {
- DH.attributes(DH.getById('watch-actions-area-container'), {
- 'class': '',
- style: 'height: auto'
- });
- DH.content(DH.getById('watch-actions-area'), [{
- attributes: {'class': 'close'},
- children: {
- tag: 'img',
- attributes: {'class': 'master-sprite close-button', src: 'http://s.ytimg.com/yt/img/pixel-vfl73.gif', onclick: 'yt.www.watch.watch5.hide()'}
- }
- }, {
- style: {textAlign: 'center', margin: '5px 0'},
- children: [
- VideoQuality.createButton().render(),
- AutoPlay.createButton().render()
- ]
- }]);
- });
- DH.append(DH.getById('watch-actions-right'), controlButton);
- unsafeWindow.onYouTubePlayerReady = extendFunction(unsafeWindow.onYouTubePlayerReady, onPlayerReady);
- onPlayerReady();
- }
- // CHANNEL page
- else if (DH.getById('playnav-video-details') !== null) {
- var tabLabel = DH.build({
- tag: 'a',
- attributes: {href: 'javascript:', title: _('Player settings')},
- children: _('Settings')
- });
- // "Settings" tab clicked
- DH.on(tabLabel, 'mousedown', function() {
- each(function(index, element) {
- var panelName = (new RegExp('^playnav-panel-tab-(\\w+)').exec(element.getAttribute('id')) || [, null])[1];
- if (panelName) {
- element.setAttribute('class', '');
- DH.getById('playnav-panel-' + panelName).style.display = 'none';
- }
- }, DH.getById('playnav-bottom-links-clip').getElementsByTagName('td'));
- DH.getById('playnav-panel-tab-settings').setAttribute('class', 'panel-tab-selected');
- DH.getById('playnav-panel-settings').style.display = 'block';
- });
- // Create and append tab
- DH.append(DH.getById('playnav-bottom-links-clip').getElementsByTagName('tr')[0], {
- tag: 'td',
- attributes: {id: 'playnav-panel-tab-settings'},
- children: {
- tag: 'table',
- attributes: {'class': 'panel-tabs'},
- children: [{
- tag: 'tr',
- children: {
- tag: 'td',
- attributes: {'class': 'panel-tab-title-cell'},
- children: [{
- attributes: {'class': 'playnav-panel-tab-icon'},
- style: {marginTop: '2px', height: '10px', backgroundImage: 'url(data:image/png;base64,\
- iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAEdJREFUGNON\
- kFEOADAEQ9udyf1P0DvZl0RsRL+kHqJAkSSX5NU/GfgNRc0OyjIzctoYEACwAtGo/sFS+9PbZ54o\
- co7jgi7wC1N5OUtzk3BUAAAAAElFTkSuQmCC)'}
- }, {
- attributes: {'class': 'playnav-bottom-link'},
- children: tabLabel
- }]
- }
- }, {
- tag: 'tr',
- children: {
- tag: 'td',
- attributes: {'class': 'panel-tab-indicator-cell inner-box-opacity'},
- children: {
- attributes: {'class': 'panel-tab-indicator-arrow'}
- }
- }
- }]
- }
- });
- // Other tab clicked
- unsafeWindow.playnav.selectPanel = extendFunction(unsafeWindow.playnav.selectPanel, function () {
- DH.getById('playnav-panel-tab-settings').setAttribute('class', '');
- DH.getById('playnav-panel-settings').style.display = 'none';
- });
- // Create and append panel
- DH.append(DH.getById('playnav-video-panel-inner'), {
- attributes: {id: 'playnav-panel-settings', 'class': 'hid'},
- children: {
- children: [{
- tag: 'b',
- children: _('Player settings')
- }, {
- style: {textAlign: 'center', marginTop: '5px'},
- children: [
- VideoQuality.createButton().render(),
- AutoPlay.createButton().render()
- ]
- }]
- }
- });
- unsafeWindow.onChannelPlayerReady = extendFunction(unsafeWindow.onChannelPlayerReady, onPlayerReady);
- onPlayerReady();
- }
- } // YAYS
- /*
- * DETECT browser, and run YAYS() accordingly.
- */
- // Firefox
- /*if (new RegExp('Firefox/\\d', 'i').test(navigator.userAgent)) {
- YAYS(unsafeWindow);
- }
- // Chrome, Opera, Safari
- else*/ {
- var scriptNode = document.createElement('script');
- scriptNode.setAttribute('type', 'text/javascript');
- scriptNode.text = '(' + YAYS.toString() + ')(window);';
- document.body.appendChild(scriptNode);
- }
Add Comment
Please, Sign In to add comment