Friday, May 10, 2013

Youtube Center Aligned


// ==UserScript==
// @name         Youtube Center Aligned
// @namespace    http://userscripts.org/users/332207
// @description  Center aligns the Youtube page
// @include      *.youtube.com/*
// @grant        none
// @run-at       document-start
// @version      2.3.3
// ==/UserScript==

var YC = new Object();

// Delay between player width checks.  Higher value = checks less frequently.  Increase if you have a slow computer.
YC.monitordelay = 20;

// Watch page center style {1, 2, 3, 4, 5}
YC.watchstyle = 1;

// Centering style for large video player {1, 2}
YC.largestyle = 1;

// Player width used for monitoring player size changes
YC.playerwidth = 0;

// Parameters for monitoring content width change after page load for flex-width pages
// Checks once every YC.monitordelay, YC.cmonitor_max times.  Unlimited if YC.cmonitor_max < 0.
YC.cmonitor_max = -1;
YC.cmonitor_count = 0;

// Initialize
YC.init = function() {
	// Make sure we're not embedded
	if (window.top !== window.self) {
		return false;
	}
	// Determine page type
	if (window.location.pathname == '/watch') {
		this.pagetype = 'video';
	}
	else if (document.getElementsByClassName('branded-page-v2-container').length) {
		this.pagetype = 'page-v2';
	}
	else if (document.body.className.indexOf('flex-width-enabled') > -1) {
		this.pagetype = 'flex-width';
	}
	else if (window.location.pathname == '/results') {
		this.pagetype = 'search';
	}
	else {
		this.pagetype = 'default';
	}
	return true;
}

// Center the page
YC.centerPage = function() {
	// Center body
	document.body.classList.remove('site-left-aligned');
	document.body.classList.add('site-center-aligned');
	
	// Page type specific elements
	switch (this.pagetype) {
		case 'video':			
			// Masthead fix
			document.getElementById('yt-masthead').style.width = '1123px';
			document.getElementById('yt-masthead-content').style.maxWidth = '750px';

			// Position top search bar and page content based on watchstyle
			if (this.watchstyle == 1) {
				document.getElementById('yt-masthead').style.position = 'relative';
				document.getElementById('yt-masthead').style.left = '-60px';
			}
			else if (this.watchstyle == 2) {
				document.getElementById('yt-masthead').style.position = 'relative';
				document.getElementById('yt-masthead').style.left = '-20px';
				document.getElementById('page').style.left = '40px';
				document.getElementById('page-container').style.overflow = 'hidden';
			}
			else if (this.watchstyle == 3) {
				document.getElementById('yt-masthead').style.position = 'relative';
				document.getElementById('yt-masthead').style.left = '20px';
				document.getElementById('page').style.left = '80px';
				document.getElementById('page-container').style.overflow = 'hidden';
			}
			else if (this.watchstyle == 4) {
				document.getElementById('yt-masthead').style.position = 'relative';
				document.getElementById('yt-masthead').style.left = '60px';
				document.getElementById('page').style.left = '120px';
				document.getElementById('page-container').style.overflow = 'hidden';
			}
			else if (this.watchstyle == 5) {
				// Do nothing
			}
			
			// Navigation bar when viewing your own videos
			if (document.getElementById('masthead-subnav')) {
				document.getElementById('masthead-subnav').setAttribute('style', 'margin:0 auto !important;position:relative;left:30px;');
				document.getElementById('guide-container') ? document.getElementById('guide-container').style.top = '40px' : '';
			}
			
			// New watch page
			if (document.getElementById('watch7-main')) {
				// watch7-video is deprecated in the latest Youtube code, so width hardcoded to 955px here
				var watch7_main_width = 955;
				document.getElementById('watch7-main').style.width = watch7_main_width + 'px';

				// Newer watch page
				if (document.getElementById('player')) {
					document.getElementById('player').style.width = watch7_main_width + 'px';
					document.getElementById('player').style.position = 'relative';
					document.getElementById('player').style.left = '30px';
					document.getElementById('player').style.marginLeft = 'auto';
					document.getElementById('player').style.marginRight = 'auto';
				}
	
				// Fix for watch-7-main-container as of 2013.04.17 (replaces watch7-main fixes above?)
				if (document.getElementById('watch7-main-container')) {
					document.getElementById('watch7-main-container').style.width = watch7_main_width + 'px';
					document.getElementById('watch7-main-container').style.position = 'relative';
					document.getElementById('watch7-main-container').style.left = '30px';
					document.getElementById('watch7-main-container').style.marginLeft = 'auto';
					document.getElementById('watch7-main-container').style.marginRight = 'auto';
				}
				
				// Playlist fix
				if (document.getElementById('watch7-playlist-data')) {
					document.getElementById('watch7-playlist-data').style.marginLeft = 'auto';
					document.getElementById('watch7-playlist-data').style.marginRight = 'auto';
				}
			}
			break;
			
		case 'page-v2':
			// Get current element widths
			// New classes: branded-page-v2-container, branded-page-v2-flex-width
			var content_page = parseInt(window.getComputedStyle(document.getElementsByClassName('branded-page-v2-container')[0]).getPropertyValue('width'));
			var content_guide = parseInt(window.getComputedStyle(document.getElementById('guide')).getPropertyValue('width'));
			var masthead_logo = parseInt(window.getComputedStyle(document.getElementById('logo-container')).getPropertyValue('width'));
			var masthead_user = parseInt(window.getComputedStyle(document.getElementById('yt-masthead-user')).getPropertyValue('width'));

			// Masthead fix
			document.getElementById('yt-masthead').style.width = (content_page + content_guide) + 'px';
			document.getElementById('yt-masthead-content').style.maxWidth = (content_page + content_guide - masthead_logo - masthead_user) + 'px';
			// Content fix
			document.getElementById('page').style.width = (content_page + content_guide) + 'px';
			break;
			
		case 'flex-width':
			// Get element widths
			var content_width = parseInt(window.getComputedStyle(document.getElementById('content')).getPropertyValue('width'));
			var masthead_logo = parseInt(window.getComputedStyle(document.getElementById('logo-container')).getPropertyValue('width'));
			var masthead_user = parseInt(window.getComputedStyle(document.getElementById('yt-masthead-user')).getPropertyValue('width'));
			
			// Masthead fix
			document.getElementById('yt-masthead').style.width = content_width + 'px';
			document.getElementById('yt-masthead-content').style.maxWidth = (content_width - masthead_logo - masthead_user) + 'px';
			// Content fix
			document.getElementById('page').style.width = content_width + 'px';
			break;
			
		case 'search':
			// Masthead fix
			document.getElementById('yt-masthead').style.width = '1003px';
			document.getElementById('yt-masthead-content').style.maxWidth = '640px';
			// Content fix
			document.getElementById('page') ? document.getElementById('page').style.width = '1003px' : '';
			break;
			
		case 'default':
			// Masthead fix
			var masthead_width = document.getElementById('page') ? Math.min(parseInt(window.getComputedStyle(document.getElementById('page')).getPropertyValue('width')), 1003) : 1003;
			var masthead_content_width = masthead_width - 360;
			document.getElementById('yt-masthead').style.width = masthead_width + 'px';
			document.getElementById('yt-masthead-content').style.maxWidth = masthead_content_width + 'px';
			break;
	}
}

// Prevent the guide slideout from breaking the page alignment
YC.fixSlideout = function() {	
	// Initial check
	document.body.className.indexOf('sidebar-collapsed') >= 0 ? document.body.classList.remove('sidebar-collapsed') : '';
	document.body.className.indexOf('sidebar-expanded') == -1 ? document.body.classList.add('sidebar-expanded') : '';
	
	// Onclick event
	if (document.getElementById('guide-container')) {
		document.getElementById('guide-container').onclick = function() {
			// Delay the onclick action because Youtube adds the sidebar-collapsed class via onclick as well
			setTimeout(function() {
				document.body.className.indexOf('sidebar-collapsed') >= 0 ? document.body.classList.remove('sidebar-collapsed') : '';
				document.body.className.indexOf('sidebar-expanded') == -1 ? document.body.classList.add('sidebar-expanded') : '';
			}, 0);
		};
	}
}

// Make the dislike bar red like it used to be
YC.showDislikes = function() {
	var els = document.getElementsByClassName('video-extras-sparkbar-dislikes');
	for (var i = 0; i < els.length; i++) {
		els[i].style.backgroundColor = '#bc281c';
	}
}

// Monitor player to detect changes in size to allow proper centering
YC.monitorPlayer = function() {
	// Keep guide-container aligned with video player when resizing window
	document.getElementById('guide-container') ? document.getElementById('guide-container').style.left = document.getElementById('yt-masthead').offsetLeft + 'px' : '';
	
	// Get current player width
 	if (document.getElementById('movie_player')) {
		var currentwidth = parseInt(window.getComputedStyle(document.getElementById('movie_player')).getPropertyValue('width'));
	}
	else if (document.getElementById('player-api')) {
		var currentwidth = parseInt(window.getComputedStyle(document.getElementById('player-api')).getPropertyValue('width'));
	}
	else {
		// Exit gracefully
		return false;
	}
	
	// Check if player width has changed
	if (currentwidth != this.playerwidth) {
		// Set margin based on new width
		if (this.largestyle == 1) {
			if (currentwidth <= 640) {
				//var player_left = parseInt(window.getComputedStyle(document.getElementById('watch7-main')).getPropertyValue('left'));
				var player_left = 30;
				// New player element "player"
				document.getElementById('player') ? document.getElementById('player').style.left = player_left + 'px' : '';
				document.getElementById('guide-container') ? document.getElementById('guide-container').style.marginLeft = '' : '';
			}
			else if (currentwidth <= 945) {
				//var player_left = parseInt(window.getComputedStyle(document.getElementById('watch7-main')).getPropertyValue('left'));
				var player_left = 30;
				// New player element "player"
				document.getElementById('player') ? document.getElementById('player').style.left = player_left + 'px' : '';
				document.getElementById('guide-container') ? document.getElementById('guide-container').style.marginLeft = '' : '';
			}
			else {
				var margin = Math.round((945 - currentwidth) / 2);
				//var player_left = parseInt(window.getComputedStyle(document.getElementById('watch7-main')).getPropertyValue('left'));
				var player_left = 30;
				// New player element "player"
				document.getElementById('player') ? document.getElementById('player').style.left = (margin + player_left) + 'px' : '';
				document.getElementById('guide-container') ? document.getElementById('guide-container').style.marginLeft = (margin) + 'px' : '';
			}
		}
		else if (this.largestyle == 2) {
			if (currentwidth <= 640) {
				document.getElementById('page').style.left = 0;
			}
			else {
				var margin = Math.round((945 - currentwidth) / 2);
				margin > 0 ? document.getElementById('page').style.left = 0 : document.getElementById('page').style.left = margin + 'px';
			}
		}
		
		// Update playerwidth
		this.playerwidth = currentwidth;
		
	}

	// Certain actions (i.e. add to playlist, maybe more?) cause the guide to slideout and break the video alignment
	YC.monitorSidebarClass();

	setTimeout(function() {
		YC.monitorPlayer();
	}, YC.monitordelay);
}

// Prevent guide slideout from breaking video alignment
YC.monitorSidebarClass = function() {
	document.body.className.indexOf('sidebar-collapsed') >= 0 ? document.body.classList.remove('sidebar-collapsed') : '';
	document.body.className.indexOf('sidebar-expanded') == -1 ? document.body.classList.add('sidebar-expanded') : '';
}

// Monitor content width for flex-width pages
YC.monitorContentWidth = function() {
	// Check if we need to continue monitoring
	if ( (YC.cmonitor_max >= 0) && (YC.cmonitor_count++ > YC.cmonitor_max) ) {
		return;
	}
	
	// Get element widths
	var content_width = parseInt(window.getComputedStyle(document.getElementById('content')).getPropertyValue('width'));
	var masthead_logo = parseInt(window.getComputedStyle(document.getElementById('logo-container')).getPropertyValue('width'));
	var masthead_user = parseInt(window.getComputedStyle(document.getElementById('yt-masthead-user')).getPropertyValue('width'));

	// Just in case #content does not exist
	content_width = Math.max(content_width, 940);
	
	// Masthead fix
	document.getElementById('yt-masthead').style.width = content_width + 'px';
	document.getElementById('yt-masthead-content').style.maxWidth = (content_width - masthead_logo - masthead_user) + 'px';
	// Content fix
	document.getElementById('page').style.width = content_width + 'px';

	setTimeout(function() {
		YC.monitorContentWidth();
	}, YC.monitordelay);
}

// Main
function main() {
	if (YC.init()) {
		YC.centerPage();
		YC.fixSlideout();
		if (YC.pagetype == 'video') {
			YC.monitorPlayer();
			YC.showDislikes();
		}
		if (YC.pagetype == 'flex-width') {
			YC.monitorContentWidth();
		}
	}
}

/**
 * Opera reads user.js files as greasemonkey notation with the following results:
 *   - "Not permitted to use window.opera.addEventListener."  Alternate addEvenetListener supported, but with wonky syntax
 *   - DOES NOT WORK: addEventListener('DOMContentLoaded', main, false)
 *   - WORKS: addEventListener('DOMContentLoaded', main(), false)
 *   - Always runs after creating the DOM for the page; does not support // @run-at document-start 
 * Opera reads .js files (NOT ending in user.js) as default with the following results:
 *   - Allows use of window.opera.addEventListener
 *   - WORKS: addEventListener('DOMContentLoaded', main, false)
 *   - DOES NOT WORK: addEventListener('DOMContentLoaded', main(), false)
 *   - "It is usually run before the DOM for the page has been completed," so // @run-at document-start is redundant
 *   - Need to attach main() to an event listener, because DOM may not be ready when script is loaded.
 * More info:
 *   - http://www.opera.com/docs/userjs/using/  (Adding User JavaScripts)
 *   - http://www.opera.com/docs/userjs/examples/  (Greasemonkey scripts)
 */
if (window.opera) {
	// Opera's greasemonkey version of addEventListener() breaks try-catch on error, so it must be called first.
	try {
		document.addEventListener('DOMContentLoaded', main(), false)
	}
	catch(err) {
		document.addEventListener('DOMContentLoaded', main, false)
	}
}
else {
	// FF, Chrome
	document.addEventListener('DOMContentLoaded', main, false);
}

0 comments:

Post a Comment