Tobias.Kelmandia / Tsumino Enhanced

"use strict";

// ==UserScript==
// @name				Tsumino Enhanced
// @namespace			http://codingtoby.com
// @version				2.0.3.11
// @description			Adds a collection of customizable tweaks, enhancements, and new features to Tsumino.com.
// @author				Toby
// @include				/((http)(s)?(\:\/\/)(www\.)?(tsumino\.com)(\/)?([\s\S]*))/
// @exclude				/((http)(s)?(\:\/\/)(www\.)?(tsumino\.com)(\/)?(Read\/AuthProcess)/
// @exclude				http://www.tsumino.com/bhome/*
// @require				https://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js
// @require				http://js.codingtoby.com/semantic.min.js
// @require				https://cdnjs.cloudflare.com/ajax/libs/bean/1.0.15/bean.min.js
// @require				https://cdnjs.cloudflare.com/ajax/libs/velocity/1.2.3/velocity.min.js
// @grant				GM_setValue
// @grant				GM_getValue
// @grant				GM_deleteValue
// @grant				unsafeWindow
// @grant				GM_openInTab
// @grant				GM_xmlhttpRequest
// @run-at				document-start
// ==/UserScript==


/*************************************************************************************
 * Open source libraries.
 *************************************************************************************/

/*************************************************************************************
 * This one adds arrayBuffer support to jQuery's ajax method.
 * -------------------------
 * jquery.binarytransport.js
 * @description. jQuery ajax transport for making binary data type requests.
 * @version 1.0
 * @author Henry Algus <henryalgus@gmail.com>
 *************************************************************************************/

// use this transport for "binary" data type
$.ajaxTransport( "+binary", function (options, originalOptions, jqXHR)
{
	if ( window.FormData &&
		 (options.dataType && options.dataType == "binary"
		  || options.data && (window.ArrayBuffer && options.data instanceof ArrayBuffer
							  || window.Blob && options.data instanceof Blob)) )
	{
		return {
			send  : function (headers, callback)
			{
				var xhr                                             = new XMLHttpRequest,
					url                                             = options.url,
					type                                            = options.type,
					async                                           = options.async || true,
					dataType = options.responseType || "blob", data = options.data || null,
					username                                        = options.username || null,
					password                                        = options.password || null;
				xhr.addEventListener( "load", function ()
				{
					var data                 = {};
					data[ options.dataType ] = xhr.response;
					callback( xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders() )
				} );
				xhr.open( type, url, async, username, password );
				for (var i in headers)
				{
					xhr.setRequestHeader( i, headers[ i ] );
				}
				xhr.responseType = dataType;
				xhr.send( data )
			},
			abort : function () {jqXHR.abort()}
		}
	}
} );


/*************************************************************************************
 * Tsumino Enhanced
 *************************************************************************************/

// Establish Tsumino Enhanced
(function (w, $)
{
	// Main object - Metadata
	var TE                = {
		name           : GM_info[ "script" ][ "name" ],
		version        : GM_info[ "script" ][ "version" ],
		status         : {},
		updateLocation : "https://openuserjs.org/scripts/Tobias.Kelmandia/Tsumino_Enhanced",
		installLocation: "https://openuserjs.org/install/Tobias.Kelmandia/Tsumino_Enhanced.user.js"
	};
	TE.status.pagesLoaded = {};

	// Tsumino Enhanced Configuration
	TE.config = {
		debug        : true,
		verboseDebug : true,
		pfRange      : 5,
		preload      : true
	};

	// User's current location.
	TE.myLocation = w.location.href;


	/*************************************************************************************
	 * User Configuration
	 *************************************************************************************/
	TE.User = {};
	(function ()
	{
		if ( GM_getValue( "TE_settings" ) )
		{
			var TE_settings = GM_getValue( "TE_settings" );
			TE.User         = JSON.parse( TE_settings );
		}
	})();

	/*************************************************************************************
	 * Detect which features the user's browser has.
	 *************************************************************************************/
	TE.ft = {};
	TE.ft.logGroups = typeof w.console.group === 'function';


	/*************************************************************************************
	 * Tsumino Site Configuration.
	 *************************************************************************************/

		// Define prefixes for all major site pages.
	TE.site = {
		account    : {
			prefix : "/Account/Home",
			regex  : "(\/Account\/Home*)"
		},
		auth       : {
			prefix : "/Read/Auth/",
			regex  : "(\/Read\/Auth\/[\\s\\S]*)"
		},
		baseURL    : {root : TE.myLocation.split( ".com" )[ 0 ] + ".com"},
		book       : {
			prefix : "/Book/Info/",
			regex  : "(\/Book\/Info\/[\\s\\S]*)"
		},
		browse     : {
			prefix : "/Browse/Index/",
			regex  : "(\/Browse\/[\\s\\S]*)||(\/*)"
		},
		error      : {
			prefix : "/Error/Index/",
			regex  : "(\/Error\/Index\/[\\s\\S]*)"
		},
		image      : {
			prefix : "/Image/Object/?data=",
			regex  : "(\/Image\/Object\/\\?data=[\\s\\S]*)"
		},
		login      : {
			prefix : "/Account/Login",
			regex  : "(\/Account\/Login[\\s\\S]*)"
		},
		manageTags : {
			prefix : "/Account/ManageTags",
			regex  : "(\/Account\/ManageTags[\\s\\S]*)"
		},
		reader     : {
			prefix : "/Read/View/",
			regex  : "(\/Read\/View\/[\\s\\S]*)"
		},
		search     : {
			prefix : "/Search",
			regex  : "(\/Search[\\s\\S]*)"
		},
		forum      : {
			prefix : "/Forum",
			regex  : "(\/Forum[\\s\\S]*)"
		}
	};

	var temp              = TE.site.baseURL.root;
	TE.site.baseURL.regex = temp.replace( /([.*+?\^=!:${}()\|\[\]\/\\])/g, "\\$1" );

	// Location Checking object.
	TE.on = {};

	// Create full URLs and do location checking.
	for (var key in TE.site)
	{
		if ( TE.site.hasOwnProperty( key ) )
		{
			var obj = TE.site[ key ];
			if ( obj.hasOwnProperty( "prefix" ) )
			{
				// Create Full URLs.
				obj[ "url" ] = TE.site.baseURL.root + obj[ "prefix" ];

				// Perform location checking.
				if ( obj[ "prefix" ] )
				{
					TE.on[ key ] = !!RegExp( "^(" + TE.site.baseURL.regex + ")" + obj[ "regex" ] + "$" ).test( TE.myLocation );
				}
			}
		}
	}

	TE.on[ "tsumino" ] = !!RegExp( "^(" + TE.site.baseURL.regex + ")([\\s\\S]*)$" ).test( TE.myLocation );

	// Prepare prefetch.
	TE.status.prefetch = {};

	TE.status.numRandStrings = 0;

	/*************************************************************************************
	 * Utility Functions
	 *************************************************************************************/
	TE.fn = TE.prototype = {
		// Logging to console with Timestamps.
		randomString : function()
		{
			TE.status.numRandStrings++;
			var text = TE.status.numRandStrings + "_";
			var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-";

			var baseline = 9;
			var ceiling = (Math.floor(Math.random() * 10));
			var numChars = baseline + ceiling;

			for( var i=0; i < numChars; i++ )
			{
				text += possible.charAt(Math.floor(Math.random() * possible.length));
			}
			return text;
		},
		log             : function ()
		{
			if ( (arguments.length > 0) && (TE.config.debug) )
			{
				var date  = new Date(), hr, min, sec, mil, timeStamp;
				hr        = date.getHours();
				min       = date.getMinutes();
				sec       = date.getSeconds();
				mil       = date.getMilliseconds();
				timeStamp = hr + ":" + min + ":" + sec + ":" + mil;
				if ( TE.ft.logGroups )
				{
					if ( arguments[ 0 ] == "gname" )
					{
						console.group( arguments[ 1 ] + " - [" + timeStamp + "]" );
						for (var i = 2 ; i < arguments.length ; ++i)
						{
							console.log( arguments[ i ] );
						}
					}
					else
					{
						console.group( timeStamp );
						for (var i = 0 ; i < arguments.length ; ++i)
						{
							console.log( arguments[ i ] );
						}
					}
					console.groupEnd();
				}
				else
				{
					if ( arguments[ 0 ] == "gname" )
					{
						console.log( "----- " + arguments[ 1 ] + " -----" );
						for (var i = 0 ; i < arguments.length ; ++i)
						{
							console.log( arguments[ i ] );
						}
					}
					else
					{
						console.log( "[" + timeStamp + "]" );
						for (var i = 0 ; i < arguments.length ; ++i)
						{
							console.log( arguments[ i ] );
						}
					}
					console.log();
				}
			}
		},
		vbLog           : function ()
		{
			if ( TE.config.verboseDebug )
			{
				if ( arguments.length > 0 )
				{
					this.log.apply( this.log, arguments );
				}
			}
		},
		errorMsg        : function (code, situation, error)
		{
			this.log( "gname", TE.name, "An error was detected while:", situation, "Error Code: " + code, error );
		},
		replaceAll      : function (str, find, replace)
		{
			// Escape regex.
			find = find.replace( /([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1" );
			return str.replace( new RegExp( find, 'g' ), replace );
		},
		load            : function (pageNumber, imageUrl)
		{
			var dfd = jQuery.Deferred(), authUrl = TE.site.baseURL.root + TE.site.auth.prefix + TE.book.id + "/" + pageNumber;

			if ( (TE.status.pagesLoaded[ pageNumber ] != "working") && (TE.status.pagesLoaded[ pageNumber ] != "done") )
			{
				TE.status.pagesLoaded[ pageNumber ] = "working";
				$( "#te_readerMessageDisplay" ).append( `
				<div id="te_loading_message" class="ui segment"><br />
				<div class="ui active dimmer"><div class="ui text loader">Loading...</div></div><br /></div>
				` );

				this.vbLog( "gname", "TE.load", "Loading Image: " + pageNumber + "...", TE.site.baseURL.root + imageUrl );
				var downloadStart = new Date();
				// Make an ajax request expecting a binary (arraybuffer) datatype.
				var loadImage = $.ajax( {
					method           : "GET",
					url              : imageUrl,
					dataType         : "binary",
					processData      : false,
					responseType     : 'arraybuffer',
					success          : $.proxy( function (data, textStatus, request)
					{
						// Put the response headers into an array.
						var rh = loadImage.getAllResponseHeaders(), rha = rh.split( "\r\n" );

						// Create a proper object from the response header array.
						var responseHeader = {};
						for (var i = 0 ; i < rha.length ; i++)
						{
							var thisRH = rha[ i ];
							thisRH     = thisRH.split( ": " );
							if ( thisRH[ 0 ] != "" )
							{
								responseHeader[ thisRH[ 0 ] ] = thisRH[ 1 ];
							}
						}

						// Local logging to examine response headers.
						TE.vbLog("gname","TE.fn.load","Response Headers",responseHeader);

						// Content-Type is undefined if Tsumino requires us to solve a captcha.
						if ( typeof responseHeader[ "Content-Type" ] === "undefined" )
						{
							// Redirect to the auth page.
							w.location.href = authUrl;
						}
						else
						{
							var downloadComplete = new Date();
							TE.vbLog( "gname", "TE.load", "Content Type: " + responseHeader[ "Content-Type" ] );

							// If we're dealing with a JPEG image.
							// (Why is it 'images/jpeg' instead of 'image/jpeg'? Typo by Tsumino devs?)
							if ( responseHeader[ "Content-Type" ] == "images/jpeg" )
							{
								TE.vbLog( "gname", "TE.load", "Image data loaded.", "Running conversions..." );
								var startTime = new Date();

								// Use Uint8Array to view the arrayBuffer response data.
								var typedArray = new Uint8Array( data );

								// Determine number of bytes for the assembly loop.
								var numBytes     = typedArray.length;
								var binaryString = "";

								// Convert it into a useable binary string.
								for (i = 0 ; i < numBytes ; i++)
								{
									binaryString = binaryString + String.fromCharCode( typedArray[ i ] );
								}

								// And finally encode the binary string as base64.
								var encodedBS = btoa( binaryString );

								var endTime     = new Date();
								var dlTime      = downloadComplete - downloadStart;
								var runTime     = endTime - startTime;
								var dlTimeDISP  = dlTime + "ms";
								var runTimeDISP = runTime + "ms";
								if ( dlTime >= 1000 )
								{ dlTimeDISP = (dlTime / 1000) + "s"; }
								if ( runTime >= 1000 )
								{ runTimeDISP = (runTime / 1000) + "s"; }
								TE.vbLog( "gname", "TE.load", "Conversions completed.",
									"Image downloaded in: " + dlTimeDISP + ".", "Total time spent on conversion: " + runTimeDISP + "." );

								// Take the base64 string and prepend it so it can be used as a dataURI.
								var dataURI = "data:image/jpeg;base64," + encodedBS;

								// Add a hidden image to the page so the dataURI can be harvested from its source later.
								$( "body" ).append( "<img id='te_loadImage_" + pageNumber + "' src='" + dataURI + "' style='display:none;'>" );

								// And we're done.
								this.vbLog( "gname", "TE.load", "Image " + pageNumber + " loaded." );
								$( "#te_loading_message" ).remove();
								TE.status.pagesLoaded[ pageNumber ] = "done";
								dfd.resolve();
							}
						}
					}, this ), error : $.proxy( function (request, status, error)
					{
						this.log( "gname", "TE.load", "Error retrieving image.", request, status, error );
					}, this )
				} );
			}
			else if ( TE.status.pagesLoaded[ pageNumber ] == "working" )
			{
				var checkAgain = function ()
				{
					setTimeout( function ()
					{
						if ( TE.status.pagesLoaded[ pageNumber ] == "done" )
						{
							dfd.resolve();
						}
						else
						{
							checkAgain();
						}
					}, 500 );
				};

				checkAgain();
			}
			else if ( TE.status.pagesLoaded[ pageNumber ] == "done" )
			{
				dfd.resolve();
			}
			return dfd.promise();
		},
		prefetch        : {
			init : function (pageNumber)
			{
				var dfd = jQuery.Deferred();
				TE.vbLog( "gname", "Prefetch Init", "Initializing..." );
				var pfRange = TE.config.pfRange, pfStart = (pageNumber - pfRange), pfEnd = (pageNumber + pfRange);
				if ( pfStart < 1 )
				{
					pfStart = 1;
				}
				if ( pfEnd > TE.book.totalPages )
				{
					pfEnd = TE.book.totalPages;
				}
				var thisRange = pfEnd - pfStart;
				if ( thisRange == 1 )
				{
					thisRange++;
				}

				var timestamp                   = new Date().getTime();
				TE.status.prefetch[ timestamp ] = 0;

				TE.vbLog( "gname", "Prefetch Init", "Base: " + pageNumber, "Start: " + pfStart, "End: " + pfEnd );
				for (var i = pfStart ; i <= pfEnd ; i++)
				{
					if ( TE.status.prefetch[ TE.book.id ][ i ] == "" )
					{
						$.when( this.get( i ) ).then( function ()
						{
							TE.status.prefetch[ timestamp ]++;
							if ( TE.status.prefetch[ timestamp ] == thisRange )
							{
								dfd.resolve();
							}
						} );
					}
				}
				return dfd.promise();
			},
			get  : function (pageNumber)
			{
				TE.status.prefetch[ TE.book.id ][ pageNumber ] = "working";
				var dfd                                        = jQuery.Deferred();
				var url                                        = TE.site.baseURL.root + "/Image/Image/" + TE.book.id + "/" + pageNumber;
				TE.status.prefetch[ TE.book.id ][ pageNumber ] = url;
				if ( TE.config.preload )
				{
					$.when( TE.fn.load( pageNumber, url ) ).then( function ()
					{
						setTimeout(function()
						{
							dfd.resolve();
						},500);
					} );
					//TE.fn.load(pageNumber, pfImgSrc);
				}
				else
				{
					dfd.resolve();
				}

				//TE.vbLog( "gname", "Prefetch", url );

				/*
				 $.get( url ).done( function (data)
				 {
				 data                                           = TE.fn.scrubAjaxData( data );
				 var pfImg                                      = $( data ).find( "img.reader-img" );
				 var pfImgSrc                                   = $( pfImg ).attr( "data-content" );
				 TE.status.prefetch[ TE.book.id ][ pageNumber ] = pfImgSrc;
				 TE.vbLog( "gname", "Prefetch", "Prefetched image src for page " + pageNumber, TE.site.baseURL.root + pfImgSrc );
				 if ( TE.config.preload )
				 {
				 $.when( TE.fn.load( pageNumber, pfImgSrc ) ).then( function ()
				 {
				 dfd.resolve();
				 } );
				 //TE.fn.load(pageNumber, pfImgSrc);
				 }
				 else
				 {
				 dfd.resolve();
				 }
				 } );
				 */
				return dfd.promise();
			}
		},
		camelize        : function (str)
		{
			return str.replace( /(?:^\w|[A-Z]|\b\w|\s+)/g, function (match, index)
			{
				if ( +match === 0 )
				{
					return "";
				}
				return index == 0 ? match.toLowerCase() : match.toUpperCase();
			} );
		},
		updateSettings  : function ()
		{
			GM_setValue( "TE_settings", JSON.stringify( TE.User ) );
		},
		scrubAjaxData   : function (data)
		{
			data = TE.fn.replaceAll( data, "src=", "data-content=" );
			data = TE.fn.replaceAll( data, "script", "div" );
			data = TE.fn.replaceAll( data, "type=", "data-notype=" );
			data = TE.fn.replaceAll( data, "link", "div" );
			return data;
		},
		checkForUpdates : function ()
		{
			var dfd = jQuery.Deferred();

			if ( typeof TE.User.tsuminoEnhanced === "undefined" )
			{
				TE.User.tsuminoEnhanced                 = {};
				TE.User.tsuminoEnhanced.lastUpdateCheck = parseInt( new Date().getTime() );
				TE.User.tsuminoEnhanced.upToDate        = true;
				this.updateSettings();
			}

			if ( TE.User.tsuminoEnhanced.latestVersion != TE.version )
			{
				TE.User.tsuminoEnhanced.upToDate = false;
				this.updateSettings();
			}
			else
			{
				TE.User.tsuminoEnhanced.upToDate = true;
				this.updateSettings();
			}

			var now       = parseInt( new Date().getTime() );
			var oneMinute = 60000;
			var oneHour   = oneMinute * 60;
			var oneDay    = oneHour * 24;


			if ( now >= (parseInt( TE.User.tsuminoEnhanced.lastUpdateCheck ) + oneMinute) )
			{
				GM_xmlhttpRequest({
					method: "GET",
					url: TE.updateLocation,
					onload: $.proxy(function(response) {
						var scrubbed = this.scrubAjaxData(response.responseText);
						TE.log( "gname", TE.name, "Checking for updates..." );
						TE.User.tsuminoEnhanced.lastUpdateCheck = parseInt( new Date().getTime() );
						var latestVersion                       = $(scrubbed).find( "code" )[ 0 ];
						latestVersion                           = $( latestVersion ).text();
						TE.User.tsuminoEnhanced.latestVersion   = latestVersion;
						if ( TE.User.tsuminoEnhanced.latestVersion != TE.version )
						{
							TE.log( "gname", TE.name, "An update is available!" );
							TE.User.tsuminoEnhanced.upToDate = false;
							this.updateSettings();
							dfd.resolve();
						}
						else
						{
							TE.log( "gname", TE.name, TE.name + " is up to date!" );
							TE.User.tsuminoEnhanced.upToDate = true;
							this.updateSettings();
							dfd.resolve();
						}
					},this)
				});
			}
			else
			{
				dfd.resolve();
			}

			return dfd.promise();
		}
	};

	// Alias specific commonly used utility functions to the main namespace.
	TE.log            = TE.fn.log;
	TE.vbLog          = TE.fn.vbLog;
	TE.errorMsg       = TE.fn.errorMsg;
	TE.replaceAll     = TE.fn.replaceAll;
	TE.prefetch       = TE.fn.prefetch;
	TE.load           = TE.fn.load;
	TE.updateSettings = TE.fn.updateSettings;
	TE.randomString   = TE.fn.randomString;


	TE.config.internalIDs = {};
	TE.config.internalIDs.teConfigLink = TE.randomString();
	TE.status.idPrefix = TE.randomString() + "_";

	/*************************************************************************************
	 * Tsumino Enhanced User Interface settings.
	 * Stylesheets, data URI, etc.
	 *************************************************************************************/
		// User Interface object.
	TE.ui = {};

	/* Tsumino Enhanced CSS.
	 ** Minified so it's easier to include in the script.
	 **
	 ** Beautify here:	http://www.cleancss.com/css-beautify/
	 ** Minify here:		http://cssminifier.com/
	 */
	TE.ui.css        = {};
	TE.ui.css.master = `
	.te_mainColor { color:#22a7f0; }
	.te_en_incompatible{background-color:rgba(255,0,0,.1);border:2px solid rgba(255,0,0,0);border-radius:5px;padding:.5em}
	@font-face { font-family: "Icons";
	src: url("https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/themes/default/assets/fonts/icons.eot");
	src: url("https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/themes/default/assets/fonts/icons.eot?#iefix")
	format("embedded-opentype"),
	url("https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/themes/default/assets/fonts/icons.woff2") format("woff2"),
	url("https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/themes/default/assets/fonts/icons.woff") format("woff"),
	url("https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/themes/default/assets/fonts/icons.ttf") format("truetype"),
	url("https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.1.8/themes/default/assets/fonts/icons.svg#icons") format("svg");
	font-style: normal; font-weight: normal; font-variant: normal; text-decoration: inherit; text-transform: none; }


	#te_readerCurrentImage { margin: 0 auto; cursor: pointer; }
	`;


	// Browsing Tweaks CSS.
	TE.ui.css.browsingTweaks = {};

	// Browsing tweaks - Master CSS.
	TE.ui.css.browsingTweaks.master = `
	.te_browsetweak_infobutton,.te_browsetweak_readbutton {
		position:absolute;border:3px solid #fff;bottom:10px;
		padding:10px;margin-left:5%;margin-right:5%;
		font-size:17px;color:#fff;width:42.5%;display:inline-block;
		text-decoration:none;box-sizing:border-box }
	.te_browsetweak_readbutton{right:0;box-sizing:border-box}
	.te_browsetweak_infobutton:focus,.te_browsetweak_readbutton:focus{text-decoration:none}
	.te_browsetweak_infobutton:hover,.te_browsetweak_infobutton:visited,
	.te_browsetweak_readbutton:hover,.te_browsetweak_readbutton:visited
		{background-color:#22a7f0;color:#fff;text-decoration:none}
	.te_browsetweak_infobutton{left:0}
		`;

	// More Books CSS.
	TE.ui.css.browsingTweaks.moreBooks =
		`
		@media(min-width:768px) { .overlay-title { font-size:.8em; } .col-sm-4 { width: 25% } }
		@media(min-width:992px) { .col-md-3 { width: 20% } }
		`;

	// Record Keeper CSS.
	TE.ui.css.recordKeeper = `
		.te_recordKeeper_finished:hover { border: 3px solid rgba(0,125,0,.8) !important; }
		.te_recordKeeper_started:hover { border: 3px solid rgba(190,190,90,.8) !important; }
	`;

	// Tsumino Enhanced Favicon Data URI
	TE.ui.favicon
		= `data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRFGhoaIqfwHD1QHmGFIIS7H3KgGyw1GyMnIY3JHU9rIZbWHlh4Ip/jHDVCIHuuH2qTHUZdxJ5l4gAAAcBJREFUeNrsmdFygyAQRbcCAiqY///apm2qqIBkdDFN73lkBA4O7K5IBAAAAADwssiPMxEQgAAEIHBEQDUB85h90KqmVhM+bM4RWHSeBZqgVUytsmAMCEDgz50CBCIIQAACFwkAAMDL0kSqwqoRDwL/RsDJBCYr0KW62QMLTRIROK8ggAAEIHC5wOWBCLkAAkS6idJnBVS8U3twqYePoYAABCDwpgKaV6AVUYLru8hfDBnv1JwYocdpsoEuSUYy8nemnkDb2GFOPBUF7hMLJbvlzuorCNyzr/DriX9x5ZvwwVMLHuXOdfW8B0uq4uWx2Zm+bDTPJlB4U2/5BGzJYIPmE9BDwWCK+ARIFQzWcgq4517A+QJkNn2NFCb1AhgE7GLm/ruuX2zNkXgF9FdQ84+ZfxDhSJ1OCJwWit3ayMdroVrJ6DZkCxxuASczJ4BfwK2jgqGKAtpuEoPR1QRa67dHSW7nZxHQVpndCMj6BuJlUE/VBGLfJV2ivufZA9uyxGuqKbCuzLpb8lGmUzAuo5+m2gJhYaSy91xccWBKgN7lH2SLhF3B6lkFbvfiVxRcMh68kcztQ0sAAAAAeHc+BRgAUX8aiFKipZUAAAAASUVORK5CYII=`;

	TE.ui.mainColor = "#22a7f0";

	/*************************************************************************************
	 * Classes
	 *************************************************************************************/


	/*************************************************************************************
	 * Class: Enhancement
	 *************************************************************************************/
	TE.Enhancement = {
		/*************************************************************************************
		 * Class:     Enhancement
		 * Subclass: main
		 *
		 * Master Enhancement class.
		 *
		 * name:          Name of the Enhancement. String only.
		 * description:     Description of the Enhancement.
		 *                    Can be a string or boolean false.
		 *                    False will indicate no description.
		 * options:          Should be an object collection of option subclasses, or boolean false.
		 *                    False will indicate no options.
		 *                    If no options are provided:
		 *                         - The Enhancement will not appear on the configuration page.
		 *                         - The Enhancement will be activated automatically.
		 *                    If options is not false, one option must use the "enable" key.
		 * section:          The section of the config page the Enhancement will appear in.
		 * incompatible: Array of Enhancements that this one is incompatible with.
		 * fn:               Object containing all actual Enhancement functionality.
		 *                    "init" key should be used for activation.
		 *                    "upgradeHandling" key should be used for upgrade handling.
		 *
		 * TE.Enhancement.main(name,displayName,description,options,section,incompatible,fn)
		 *************************************************************************************/
		main   : function (name, description, options, section, incompatible, fn)
		{
			try
			{
				if ( typeof name !== "string" )
				{
					throw new Error( "Enhancement name must be defined as a string." );
				}
				if ( (typeof description !== "string") && (description != false) )
				{
					throw new Error( "Enhancement description must be defined as a string." );
				}
				if ( (typeof options !== "object") && (options != false) )
				{
					throw new Error( "Enhancement options must be defined as an object." );
				}
				if ( (options != false) || (section != false) )
				{
					if ( typeof section !== "string" )
					{
						throw new Error( "Enhancement section must be defined as a string." );
					}
				}
				if ( (typeof incompatible !== "object") && (incompatible != false) )
				{
					throw new Error( "Enhancement incompatibilities must be defined as 'false', or an array." );
				}

				if ( typeof fn !== "object" )
				{
					throw new Error( "Enhancement functionality must be defined as an object." );
				}

				this.name         = name;
				this.shortName    = TE.fn.camelize( name );
				this.description  = description;
				this.options      = options;
				this.section      = section;
				this.incompatible = incompatible;
				this.fn           = fn;
			}
			catch (error)
			{
				TE.errorMsg( "CD01", "Creating an Enhancement class object.", error );
			}
		}, /*************************************************************************************
		 * Class:     Enhancment
		 * Subclass: option
		 *************************************************************************************/
		option : {
			/*************************************************************************************
			 * Master Class:     Enhancment
			 * Parent Class:     option
			 * Subclass:          main
			 *
			 * Primary Option class.
			 *
			 * type:               The type of the Option.
			 *                    Must be a string of one of the following:
			 *                    "enable" - Switch that enables the Enhancement.
			 *                         Options of this type require no further parameters.
			 *                    "toggle" - Renders a checkbox.
			 *                    "radio" - Radio buttons. Requires arguments.
			 *                    "dropdown" - Dropdown menu. Requires arguments.
			 * name:          Name of the option.
			 * description:     Description of the Option.
			 *                    Can be a string or boolean false.
			 *                    False will indicate no description.
			 * defaultValue: The default value of the option.
			 * params:     Must be an object of the "params" subclass, or boolean false.
			 *                    False indicates no params.
			 *
			 * TE.Enhancement.option.main(type,name,description,defaultValue,arguments)
			 *************************************************************************************/
			main   : function (type, name, description, defaultValue, params)
			{
				try
				{
					if ( typeof type !== "string" )
					{
						throw new Error( "Option type must be defined as a string." );
					}
					if ( type != "enable" )
					{
						if ( typeof name !== "string" )
						{
							throw new Error( "Option name must be defined as a string." );
						}
						if ( typeof description === "undefined" )
						{
							description = false;
						}

						if ( type == "toggle" )
						{
						}
						if ( (type == "dropdown") && (typeof v !== "object") )
						{
							throw new Error( "You must define params for option type dropdown." );
						}
						if ( (type == "radio") && (typeof params !== "object") )
						{
							if ( typeof params === "undefined" )
							{
								throw new Error( "You must define params for option type radio." );
							}
						}
						if ( type == "dropdown" )
						{
							if ( typeof params === "undefined" )
							{
								throw new Error( "Option params must be defined with type dropdown." );
							}
						}

						this.type         = type;
						this.name         = name;
						this.shortName    = TE.fn.camelize( name );
						this.description  = description;
						this.defaultValue = defaultValue;
						this.params       = params;
					}
					else
					{
						this.type         = type;
						this.name         = "enable";
						this.shortName    = "enable";
						this.description  = false;
						this.defaultValue = false;
						this.params       = false;
					}
				}
				catch (error)
				{
					TE.errorMsg( "CD02", "Creating an Enhancement.option.main class object.", error );
				}
			}, /*************************************************************************************
			 * Master Class:     Enhancment
			 * Parent Class:     option
			 * Subclass:          params
			 *
			 * params for radio and dropdown type options.
			 *
			 * type:               The type of the param.
			 *                    Must be a string of one of the following:
			 *                         "range" - For generating a
			 *************************************************************************************/
			params : function (type, options)
			{
				try
				{
					if ( typeof type !== "string" )
					{
						throw new Error( "Type must be defined as a string." );
					}
					if ( type == "range" )
					{
						if ( typeof options !== "object" )
						{
							throw new Error( "options must be defined as an object." );
						}
						else
						{
							if ( typeof options.rangeStart !== "number" )
							{
								throw new Error( "Range start must be defined as a number." );
							}
							if ( typeof options.rangeEnd !== "number" )
							{
								throw new Error( "Range end must be defined as a number." );
							}
						}
					}
					else
					{
						throw new Error( "Range is the only acceptable type right now." );
					}

					this.type   = type;
					this.params = params;
				}
				catch (error)
				{
					TE.log( "gname", "ERROR", "Error defining params class:", error );
					TE.errorMsg( "CD03", "Creating an Enhancement.option.params class object.", error );
				}
			}
		}
	};


	//Fix the navbar.
	TE.fixNavbar = function ()
	{
		$( "nav .tsumino-nav-items li" ).click( function ()
		{
			var thisLink = $( this ).find( "a:first" )[ 0 ];

			if ( $( thisLink ).text() == "Browse " )
			{
				$( "#te_navMenu" ).toggleClass( "tsumino-nav-visible" );
			}
			else if ( $( thisLink ).prop( "id" ) == TE.config.internalIDs.teConfigLink )
			{
				$( "#te_config_modal" )
					.modal( "show" )
					.modal( "refresh" );
			}
			else
			{
				window.location.href = $( thisLink ).prop( "href" );
			}
		} );
	};

	/*************************************************************************************
	 * Enhance Page - Core Functionality
	 *  + Creates IDs for important elements.
	 *  + Gathers data for storage in the TE object.
	 *************************************************************************************/
	TE.enhancePage = function ()
	{
		var dfd = jQuery.Deferred();
		TE.vbLog( "gname", "TE.enhancePage", "Started working..." );
		$( document ).ready( function ()
		{
			/*************************************************************************************
			 * All pages.
			 *************************************************************************************/

			if ( !TE.on.forum )
			{
				// Prepare config modal
				$( "body" ).append( `<div id="te_config_modal" class="ui fullscreen basic modal"></div>` );
				TE.settings.render();

				// The navigation bar at the top.
				$( "nav" ).attr( "id", "te_siteNavbar" );

				// Replace favicon.
				$( "link[rel='icon']" ).attr( "href", TE.ui.favicon );


				// Add Tsumino Enhanced config link to navbar.
				var navbar = $( ".tsumino-nav-left" )[ 0 ];
				$( navbar ).attr( "id", "te_navbarMain" );

				// Add ID to browse button link and swap href from # to javascript:;.
				var browseButton = $( "#te_navbarMain" ).find( "a[href=#]" )[ 0 ];
				$( browseButton ).prop( "id", "te_navBrowse" );
				$( "#te_navBrowse" ).prop( "href", "javascript:;" );

				// Add ID to nav menu.
				var navMenu = $( "#te_navBrowse" ).siblings()[ 0 ];
				$( navMenu ).prop( "id", "te_navMenu" );
				TE.fixNavbar();

				if ( !TE.User.tsuminoEnhanced.upToDate )
				{
					$( w ).load( function ()
					{
						$( "#"+TE.config.internalIDs.teConfigLink ).append( "&nbsp;&nbsp;<i class='ui red icon upload'></i>" );
						$(".search-wrapper input").css("margin-left","8em");
						$( "#"+TE.config.internalIDs.teConfigLink ).parent().popup( {
							title : 'An update is available!'
						} );
						$( "#"+TE.config.internalIDs.teConfigLink ).parent().css( "background-color", "#333333" );
						setTimeout( function ()
						{
							$( "#"+TE.config.internalIDs.teConfigLink ).parent()
																	   .velocity( {backgroundColor : "#2D5467"} )
																	   .velocity( {backgroundColor : "#333333"} )
																	   .velocity( {backgroundColor : "#2D5467"} )
																	   .velocity( {backgroundColor : "#333333"} );
						}, 1 );
					} );
				}

				// ID the primary content area.
				var pageContent = $( "div.container-fluid" )[ 0 ];
				$( pageContent ).attr( "id", "te_pageContent" );

				var footer = $( "div.nav-footer" )[ 0 ];
				$( footer ).attr( "id", "te_page_footer" );


				var teNLC_className = TE.fn.randomString();
				var teNLC_height = $("nav.tsumino-nav").height();
				var teNLC_left = $("#te_navbarMain").offset().left;
				teNLC_left += $("#te_navbarMain").width();
				var teNLC_top = 0;

				TE.ui.css.master = TE.ui.css.master + `
					.a`+teNLC_className+`
					{
						float: left;
						position: absolute;
						top:`+teNLC_top+`px;
						left:`+teNLC_left+`px;
						height: `+teNLC_height+`px;
						z-index:999;
						border-left: 1px solid #282828;
					}
					.a`+TE.config.internalIDs.teConfigLink+`
					{
						margin:10px 5px;
					}
				`;

				$( "body" ).append( `
				<div class="a`+teNLC_className+`">
					<div id="`+TE.config.internalIDs.teConfigLink+`" class="a`+TE.config.internalIDs.teConfigLink+`">
						<a href='javascript:;' style='color:` + TE.ui.mainColor + ` !important;'>ENHANCED</a>
					</div>
				</div>
					` );
				$( "#"+TE.config.internalIDs.teConfigLink ).click( function ()
				{
					$( "#te_config_modal" ).modal( "show" );
					$( "#te_config_modal" ).modal( "refresh" );
				} );

				$(".search-wrapper input").css("margin-left","6.5em");


				$( "head" )
				// Include Semantic CSS
					.prepend( "<link rel='stylesheet' href='http://js.codingtoby.com/semantic.min.css' />" )
					// Apply Tsumino Enhanced CSS.
					.append( "<style>" + TE.ui.css.master + "</style>" );
			}

			/*************************************************************************************
			 * Book & Reader
			 *************************************************************************************/
			if ( TE.on.reader || TE.on.book )
			{
				// Create the book object.
				TE.book = {};

				// Reader only.
				if ( TE.on.reader && false )
				{
					// Create IDs.
					$( ".reader-page" ).attr( "id", "te_readerPageMain" );
					var imageBlock = $( "#te_readerPageMain" ).children()[ 0 ];
					$( imageBlock ).attr( "id", "te_imageBlock" );
					$( ".reader-btn" ).attr( "id", "te_readerButtonContainer" );
					//$( "img.reader-img" ).attr( "id", "te_readerCurrentImage" );

					var readInfo = TE.myLocation;
					readInfo     = readInfo.replace( TE.site.reader.url, "" );
					readInfo     = readInfo.split( "/" );

					// Book ID.
					TE.book.id = parseInt( readInfo[ 0 ] );
					TE.log(readInfo[ 1 ]);

					// Book title.
					var bookTitle = $( "title" ).text();
					TE.book.title = bookTitle.replace( "Tsumino - Free Premium Doujinshi and Hentai Manga: Read ", "" );

					// Pagination setup.
					var pagination = $( "#te_readerButtonContainer" ).find( "h1" )[ 0 ];
					$( pagination ).attr( "id", "te_readerPagination" );
					var pagesInfo = $( "#te_readerPagination" ).text();
					pagesInfo     = pagesInfo.split( " Page " )[ 1 ];
					pagesInfo     = pagesInfo.split( " of " );

					// Current Page.
					if(readInfo.length > 1)
					{
						TE.book.currentPage    = parseInt( readInfo[ 1 ] );
					}
					else
					{
						TE.book.currentPage    = 1;
					}
					TE.book.currentPageURL = TE.site.reader.prefix + TE.book.id + "/" + TE.book.currentPage;

					$( "title" ).text( "Tsumino - " + TE.book.title + " - Page " + TE.book.currentPage );

					// Origin page.
					TE.book.originPage = TE.book.currentPage;

					// Total Pages.
					TE.book.totalPages = parseInt( pagesInfo[ 1 ] );

					// Next page.
					TE.book.nextPage = TE.book.currentPage + 1;
					if ( TE.book.nextPage > TE.book.totalPages )
					{
						TE.book.nextPage = false;
					}
					else
					{
						TE.book.nextPageURL = TE.site.reader.prefix + TE.book.id + "/" + TE.book.nextPage;
					}

					// Previous page.
					TE.book.prevPage = TE.book.currentPage - 1;
					if ( TE.book.prevPage == 0 )
					{
						TE.book.prevPage = false;
					}
					else
					{
						TE.book.prevPageURL = TE.site.reader.prefix + TE.book.id + "/" + TE.book.prevPage;
					}

					// Rewrite pagination section.
					$( "#te_readerPagination" ).before( `<div id="te_readerMessageDisplay" style="margin-bottom: 25px;"></div>` );
					$( "#te_readerPagination" ).html( "Page <span id='te_currentPage'></span> of <span id='te_totalPages'></span>" );
					$( "#te_currentPage" ).html( TE.book.currentPage );
					$( "#te_totalPages" ).html( TE.book.totalPages );

					// Rename Return button to 'book info' and give it an ID.
					var bookInfoButton = $( "a[href*='" + TE.site.book.prefix + "']:contains('RETURN')" );
					$( bookInfoButton ).attr( "id", "te_bookInfoButton" );
					$( "#te_bookInfoButton" )
						.attr("href",TE.site.book.prefix + TE.book.id)
						.text( "BOOK INFO" );

					// Add a return button that takes you to the index.
					$( "#te_bookInfoButton" ).after( `
						<a class='book-read-button button-stack' id='te_returnToIndexButton'><i class='fa fa-home'></i> BACK TO INDEX</a>
						` );
					var returnToIndexLink = sessionStorage.getItem( "te_returnLink" );
					if ( typeof returnToIndexLink === "object" )
					{
						$( "#te_returnToIndexButton" ).attr( "href", TE.site.baseURL.root );
					}
					else
					{
						$( "#te_returnToIndexButton" ).attr( "href", returnToIndexLink );
					}


					// Enhance Previous Page button.
					if ( $( "a:contains(' PREV')" ).length )
					{
						$( "a:contains(' PREV')" ).attr( "id", "te_prevButton" );
					}
					else
					{
						$( "#jump-page" ).before( `
							<a id="te_prevButton" class="book-read-button button-stack" style="margin-right: 10px;"><i class="fa fa-arrow-left"></i> PREV</a>
							` );
						$( "#te_prevButton" ).css( "display", "none" );
					}
					$( "#te_prevButton" ).attr( "href", TE.book.prevPageURL );
					if ( TE.book.currentPage > 1 )
					{
						$( "#te_prevButton" ).css( "display", "inline" );
					}
					else
					{
						$( "#te_prevButton" ).css( "display", "none" );
					}

					// Enhance Next Page Button
					if ( $( "a:contains('NEXT ')" ).length )
					{
						$( "a:contains('NEXT ')" ).attr( "id", "te_nextButton" );
					}
					else
					{
						$( "#jump-page" ).after( `
							<a id="te_nextButton" class="book-read-button button-stack">NEXT <i class="fa fa-arrow-right"></i></a>
							` );
						$( "#te_nextButton" ).css( "display", "none" );
					}
					$( "#te_nextButton" ).attr( "href", TE.book.nextPageURL );
					if ( TE.book.currentPage < TE.book.totalPages )
					{
						$( "#te_nextButton" ).css( "display", "inline" );
					}
					else
					{
						$( "#te_nextButton" ).css( "display", "none" );
					}


					$("#image-container")
						.after(`
						<div id="te_imageContainer">
							<img class="img-responsive" src="/Image/Image/`+TE.book.id+`/`+TE.book.currentPage+`" id="te_readerCurrentImage">
						</div>
						`)
						.remove();



					// Enhance Image link.
					/*
					 var imageLink = $( "#te_readerCurrentImage" ).parent();
					 $( imageLink ).attr( "id", "te_imageLink" );
					 $( "#te_imageLink" ).attr( "href", TE.book.nextPageURL );
					 */

					TE.vbLog( "gname", "TE.book", TE.book );
				}
				else if ( TE.on.book )
				{
					var readInfo = TE.myLocation;
					readInfo     = readInfo.replace( TE.site.book.url, "" );
					readInfo     = readInfo.split( "/" );

					// Book ID.
					TE.book.id = parseInt( readInfo[ 0 ] );

					// Fix tag display bug causing unwanted line breaks.
					$( ".book-tag:contains(' ')" ).css( "white-space", "nowrap" );
					$( ".book-tag:contains('-')" ).css( "white-space", "nowrap" );

					// Read Online button.
					$( "a.book-read-button:contains(' READ ONLINE')" ).attr( "id", "te_readOnlineButton" );

					var indexButton = $( "a:contains(' BACK TO INDEX')" );
					$( indexButton ).attr( "id", "te_backToIndexButton" );
					var returnToIndexLink = sessionStorage.getItem( "te_returnLink" );
					if ( typeof returnToIndexLink !== "object" )
					{
						$( "#te_backToIndexButton" ).attr( "href", returnToIndexLink );
					}
				}
			}
			if ( TE.on.browse )
			{
				sessionStorage.setItem( "te_returnLink", TE.myLocation );

				var browsePage         = $( "div.browse-page" );
				var ctProper           = $( "div.row.push-in" );
				var bookshelfContainer = $( ctProper ).children()[ 0 ];
				$( bookshelfContainer ).attr( "id", "te_bookshelfContainer" );
				var sidebarContainer = $( ctProper ).children()[ 1 ];
				$( sidebarContainer ).attr( "id", "te_sidebarContainer" );

				var bookshelf = $( browsePage ).find( "div.row.row-no-padding" );
				$( bookshelf ).attr( "id", "te_bookshelf" );
				$( bookshelf ).children().each( function ()
				{
					var thisLinkUrl = $( this ).find( "a.overlay-button" ).attr( "href" );
					var temp        = thisLinkUrl.replace( TE.site.book.prefix, "" );
					temp            = temp.split( "/" );
					var thisBookID  = temp[ 0 ];
					$( this ).attr( "id", "te_book_" + thisBookID + "_masterContainer" );

					$( this ).find( "div.book-grid-item" ).attr( "id", "te_book_" + thisBookID + "_container" );

					var thisOverlay = $( "#te_book_" + thisBookID + "_container" ).find( "div.overlay" );
					$( thisOverlay ).attr( "id", "te_book_" + thisBookID + "_overlay" );

					var thisData = $( "#te_book_" + thisBookID + "_overlay" ).find( "div.overlay-data" );
					$( thisData ).attr( "id", "te_book_" + thisBookID + "_data" );

					var thisPages = $( "#te_book_" + thisBookID + "_data" ).find( "div.overlay-sub" );
					$( thisPages ).attr( "id", "te_book_" + thisBookID + "_pagesContainer" );

					var bottomTitle = $( this ).find( "a.title" );
					$( bottomTitle ).attr( "id", "te_book_" + thisBookID + "_bottomTitle" );
					$( "#te_book_" + thisBookID + "_bottomTitle" ).attr( "href", "javascript:;" );
				} );
				//TE.vbLog( "gname", "TE.enhancePage", bookshelf );
			}
			TE.vbLog( "gname", "TE.enhancePage", "Finished working." );
			dfd.resolve();
		} );

		return dfd.promise();
	};


	/*************************************************************************************
	 * Enhancement Code
	 * Create all Enhancements within anonymous functions.
	 *************************************************************************************/
		// Object for storing all Enhancements
	TE.Enhancements = {};

	/*******************************************************
	 * Hidden Enhancements
	 * Important functionality.
	 * Customization either not yet written or not required.
	 *******************************************************/


	/*******************************************************
	 * General Enhancements
	 *******************************************************/
	(function ()
	{
		/*******************************************************
		 * Unstickied Header - General Enhancement
		 *******************************************************/
		var name, shortName, description, options, section, incompatible, main;
		name         = "Unstickied Header";
		shortName    = TE.fn.camelize( name );
		description  = "The Tsumino navigation bar will no longer follow you as you scroll down.";
		options      = [];
		section      = "General";
		incompatible = false;
		main         = {
			init : function ()
			{
				this.run();
			},
			run  : function ()
			{
				$( "#te_siteNavbar" ).css( "position", "absolute" );
			}
		};
		//TE.Enhancement.option.main(type,name,description,defaultValue,arguments)
		var opt1 = {
			type         : "enable",
			name         : false,
			description  : false,
			defaultValue : false,
			arguments    : false
		};
		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );
		TE.Enhancements[ shortName ] = new TE.Enhancement.main( name, description, options, section, incompatible, main );
	})();


	(function ()
	{
		/*******************************************************
		 * Record Keeper - General Enhancement
		 *******************************************************/
		var name, shortName, description, options, section, incompatible, main;
		name         = "Record Keeper";
		shortName    = TE.fn.camelize( name );
		description  = `
		The aptly named Record Keeper Enhancement keeps a record of what Doujin you've read.<br />
		This record includes Doujin IDs, the last page you read, and whether or not you finished reading a Doujin.<br />
		While browsing, unread Doujin will retain the normal blue border.<br />
		Doujin you have started but haven't finished will have a yellow border.<br />
		Doujin you've finished reading will have a green border.<br />
		Additionally, the information overlay will now contain this information.<br />
		There will also be a 'Continue Reading' button on the book info page if you have previously read a Doujin past the first page.
		`;
		options      = [];
		section      = "General";
		incompatible = false;
		main         = {};


		main = {
			init : function ()
			{
				if ( typeof TE.User.recordKeeper.data !== "object" )
				{
					TE.User.recordKeeper.data = {};
					TE.updateSettings();
				}
				if ( TE.on.browse )
				{
					$.when( TE.status.enhancePage ).done( function ()
					{
						$( "style" ).append( TE.ui.css.recordKeeper );
						TE.log( "gname", name, "Initializining..." );
						for (var key in TE.User.recordKeeper.data)
						{
							if ( TE.User.recordKeeper.data.hasOwnProperty( key ) )
							{
								var obj = TE.User.recordKeeper.data[ key ];
								if ( obj[ "finished" ] )
								{
									$( "#te_book_" + key + "_pagesContainer" ).append( "<br />Finished!" );
									$( "#te_book_" + key + "_container" ).addClass( "te_recordKeeper_finished" );
									$( "#te_book_" + key + "_bottomTitle" ).css( "border-top", "3px solid rgba(0,125,0,.8)" );
								}
								if ( (obj[ "lastSeen" ] > 1) && (!obj[ "finished" ]) )
								{
									$( "#te_book_" + key + "_pagesContainer" ).text( "Read " + obj[ "lastSeen" ] + " / " + obj[ "totalPages" ]
																					 + " pages." );
									$( "#te_book_" + key + "_container" ).addClass( "te_recordKeeper_started" );
									$( "#te_book_" + key + "_bottomTitle" ).css( "border-top", "3px solid rgba(190,190,90,.8)" );
								}
							}
						}
					} );
				}
				if ( TE.on.book )
				{
					$.when( TE.status.enhancePage ).done( $.proxy( function ()
					{
						TE.log( "gname", name, "Initializining..." );
						if ( typeof TE.User.recordKeeper.data[ TE.book.id ] === "object" )
						{
							if ( TE.User.recordKeeper.data[ TE.book.id ][ "lastSeen" ] > 1 )
							{
								//TE.User.recordKeeper.data[ TE.book.id ][ "lastSeen" ];
								var oldButton       = $( "#te_readOnlineButton" ).html();
								var starOver        = oldButton.replace( " READ ONLINE", " START OVER" );
								var continueReading = oldButton.replace( " READ ONLINE", " CONTINUE READING" );
								$( "#te_readOnlineButton" ).html( starOver );
								var resumeUrl = TE.site.reader.url + TE.book.id + "/" + TE.User.recordKeeper.data[ TE.book.id ][ "lastSeen" ];
								$( "#te_readOnlineButton" ).before( `
									<a id='te_resumeButton' class='book-read-button button-stack' href='` + resumeUrl + `'></a>
								` );
								$( "#te_resumeButton" ).html( continueReading );
							}
						}
					}, this ) );
				}
				if ( TE.on.reader && false )
				{
					$.when( TE.status.enhancePage ).done( $.proxy( function ()
					{
						TE.log( "gname", name, "Initializining..." );
						if ( typeof TE.User[ shortName ].data !== "object" )
						{
							TE.User[ shortName ].data = {};
						}
						if ( typeof TE.User[ shortName ].data[ TE.book.id ] !== "object" )
						{
							TE.User[ shortName ].data[ TE.book.id ] = {
								totalPages : TE.book.totalPages, lastSeen : TE.book.currentPage, finished : false
							};
						}
						this.update();
					}, this ) );
				}
			},

			update : function ()
			{
				TE.User[ shortName ].data[ TE.book.id ].lastSeen = TE.book.currentPage;
				if ( !TE.User[ shortName ].data[ TE.book.id ][ "finished" ] )
				{
					if ( TE.book.totalPages == TE.book.currentPage )
					{
						TE.User[ shortName ].data[ TE.book.id ][ "finished" ] = true;
					}
				}
				TE.updateSettings();
			}
		};

		//TE.Enhancement.option.main(type,name,description,defaultValue,arguments)
		var opt1 = {
			type         : "enable",
			name         : false,
			description  : false,
			defaultValue : false,
			arguments    : false
		};
		var opt2 = {
			type         : "toggle",
			name         : "Show Messages",
			description  : "Displays loading messages while preparing images for display.",
			defaultValue : true,
			arguments    : false
		};
		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );
		//options.push(new TE.Enhancement.option.main(opt2.type,opt2.name,opt2.description,opt2.defaultValue,opt2.arguments));

		TE.Enhancements[ shortName ] = new TE.Enhancement.main( name, description, options, section, incompatible, main );
	})();


	(function ()
	{
		/*******************************************************
		 * Browse Tags Lite - Browsing Enhancement
		 *******************************************************/
		var name, shortName, description, options, section, incompatible, main;
		name         = "Browse Tags Lite";
		shortName    = TE.fn.camelize( name );
		description  = `Adds a new link to Tsumino's browse menu. "ALL TAGS (LITE)"<br />
						Clicking it launches the Browse Tags Lite modal window.<br />
						Tags are sorted alphabetically and categorized by the first letter.<br />
						Click a letter at the top to view tags that start with that letter.<br />
						The tag list is downloaded automatically the first time you open BTL.`;
		options      = [];
		section      = "Browsing";
		incompatible = false;
		main         = {
			init             : function ()
			{
				var firstLoad = true;
				$.when( TE.status.enhancePage ).then( $.proxy( function ()
				{
					$( "ul#te_navMenu" ).append( `<li id="te_browseTagsLite_menuLink"><a>All Tags (Lite)</a></li>` );

					var alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
					alphabet     = alphabet.split( "" );

					$( "body" ).append( `
					<div id="te_browseTagsLite_modal" class="ui fullscreen long basic modal">
						<button id="te_btl_closeModal" class="ui icon button right floated"><i class="remove icon"></i></button>
						<div class="header"><h1><span class="te_mainColor">Browse Tags Lite</span></h1></div>
						<div id="te_browseTagsLite_modalBody" class="content" style="font-size: 1.4em;">
							<div id="te_btl_mainDisplay">

							</div>
						</div>
					</div>
					` );

					$( "#te_browseTagsLite_modalBody" ).prepend( `<div id="te_browseTagsLite_tabs" class="ui top attached inverted large tabular menu"></div>` );


					/*
					 $( "#te_browseTagsLite_tabs" ).prepend( `<a class="item te_btl_tabButton" data-tab="te_btl_tab_all">*</a>` );
					 $( "#te_btl_mainDisplay" ).append( `
					 <div id="te_btl_tab_all" class="ui bottom attached inverted tab segment" data-tab="te_btl_tab_all">
					 <h1>ALL</h1>
					 Tags go here
					 </div>
					 ` );
					 */


					// Populate button list
					for (var i = 0 ; i < alphabet.length ; i++)
					{
						$( "#te_browseTagsLite_tabs" ).append(
							`<a id="te_btl_btn_` + alphabet[ i ] + `" class="item te_btl_tabButton" data-tab="te_btl_tab_` + alphabet[ i ] + `">`
							+ alphabet[ i ] + `</a>` );
						$( "#te_btl_mainDisplay" ).append( `
							<div id="te_btl_tab_` + alphabet[ i ] + `" class="ui bottom attached inverted tab segment" data-tab="te_btl_tab_`
														   + alphabet[ i ] + `">
							</div>
							` );
					}
					$( "#te_browseTagsLite_tabs" ).append( `
						<a id="te_btl_btn_reload" class="icon item"><i class="icon refresh" style="color:` + TE.ui.mainColor + `"></i></a>
						` );

					// Check to see if the user has a copy of the tag list.
					if ( TE.User.tsuminoEnhanced.tagList )
					{
						this.renderTagList();
						$( "#te_btl_btn_B" ).addClass( "active" );
						$( "#te_btl_tab_B" ).addClass( "active" );
					}

					$( "#te_btl_btn_reload" ).click( $.proxy( function ()
					{
						$( "#te_btl_btn_reload" ).addClass( "disabled" );
						$( "#te_browseTagsLite_modal" ).append( `
							<div id="te_btl_downloadingTagListLoader">
								<div class="ui active dimmer">
									<div class="ui text loader">Downloading Tag List...</div>
								</div>
							</div>
						` );
						$.when( this.updateTagList() ).then( $.proxy( function ()
						{
							$( "#te_btl_downloadingTagListLoader" ).remove();
							$( "#te_btl_btn_reload" ).removeClass( "disabled" );
							this.renderTagList();
							$( "#te_btl_btn_A" ).addClass( "active" );
							$( "#te_btl_tab_A" ).addClass( "active" );
						}, this ) );
					}, this ) );


					// Initialize tabs.
					$( ".tabular.menu .item" ).tab();

					// Initialize modal.
					$( "#te_browseTagsLite_modal" ).modal(
						{
							onVisible      : function ()
							{
								if ( !TE.User.tsuminoEnhanced.tagList )
								{
									$( "#te_btl_btn_reload" ).click();
								}

								if ( firstLoad )
								{
									$( "#te_browseTagsLite_modal" ).modal( "refresh" );
									$( "#te_btl_btn_A" ).click();
									firstLoad = false;
								}
							},
							observeChanges : true
						} );

					$( "#te_browseTagsLite_menuLink" ).click( function ()
					{
						$( "#te_browseTagsLite_modal" ).modal( "show" );
					} );

					$( ".te_btl_tabButton" ).click( function ()
					{
						$( "#te_browseTagsLite_modal" ).modal( "refresh" );
					} );

					// Close button
					$( "#te_btl_closeModal" ).click( function ()
					{
						$( "#te_browseTagsLite_modal" ).modal( "hide" );
					} );


					$( "#te_btl_btn_reload" ).popup( {
						title : 'Reload the Tag List from the Server'
					} );


				}, this ) );
			}, updateTagList : function ()
			{
				var dfd                     = jQuery.Deferred();
				TE.status.tagListDownloaded = false;
				TE.status.tagListPage       = 1;
				TE.status.tagList           = [];

				bean.on( TE.status.tagList, "completed", function ()
				{
					TE.log( "gname", "Browse Tags Lite", "Tag list downloaded." );
					TE.status.tagListDownloaded     = true;
					TE.User.tsuminoEnhanced.tagList = TE.status.tagList;
					TE.updateSettings();
					dfd.resolve();
				} );

				this.loadTagPages( TE.status.tagListPage );

				TE.log( "gname", "Browse Tags Lite", "Retrieving tags..." );
				return dfd.promise();
			},
			loadTagPages     : function (pageNum)
			{
				if ( !TE.status.tagListDownloaded )
				{
					$.ajax( {
						method  : "GET",
						url     : TE.site.baseURL.root + TE.site.browseTags.prefix,
						data    : {infpage : pageNum},
						success : $.proxy( function (data)
						{
							if ( data.trim() != "" )
							{
								data = TE.fn.scrubAjaxData( data );
								$( data ).find( "a" ).each( function ()
								{
									TE.status.tagList.push( $( this ).text() );
								} );
								TE.status.tagListPage++;
								this.loadTagPages( TE.status.tagListPage );
							}
							else
							{
								bean.fire( TE.status.tagList, "completed" );
							}
						}, this ),
						error   : function () {}
					} );
				}
			},
			renderTagList    : function ()
			{
				var numTags         = 0;
				var tagCounter      = [];
				var thisTag         = "";
				var urlFormattedTag = "";
				var thisTagUrl      = "";
				var idFormattedTag  = "";
				var thisTagFL       = "";
				var alphabet        = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
				alphabet            = alphabet.split( "" );

				for (var i = 0 ; i < alphabet.length ; i++)
				{
					tagCounter[ alphabet[ i ] ] = 0;
					$( "#te_btl_tab_" + alphabet[ i ] ).html( `
						<h1>` + alphabet[ i ] + `</h1>
						<hr />` );

					$( "#te_btl_tab_" + alphabet[ i ] ).removeClass( "active" );
					$( "#te_btl_btn_" + alphabet[ i ] ).removeClass( "active" );
				}

				for (var i = 0 ; i < TE.User.tsuminoEnhanced.tagList.length ; i++)
				{
					numTags++;
					thisTag = TE.User.tsuminoEnhanced.tagList[ i ];
					thisTag = thisTag.trim();
					thisTag = thisTag.replace( /\w\S*/g, function (txt)
					{
						return txt.charAt( 0 ).toUpperCase() + txt.substr( 1 ).toLowerCase();
					} );

					urlFormattedTag = TE.fn.replaceAll( thisTag, " ", "+" );
					thisTagUrl      = TE.site.baseURL.root + "/Browse/Tag?name=" + urlFormattedTag;
					idFormattedTag  = TE.fn.replaceAll( thisTag, " ", "_" );
					thisTagFL       = thisTag.charAt( 0 );
					tagCounter[ thisTagFL ]++;
					$( "#te_btl_tab_" + thisTagFL ).append( `
						<a class="book-tag" id="te_btl_tagLink_"` + idFormattedTag + `" href="` + thisTagUrl + `">` + thisTag + `</a>
						<br />
						` );
				}

				// Remove links from empty sections and add tag counters to populated sections.
				for (i = 0 ; i < alphabet.length ; i++)
				{
					if ( tagCounter[ alphabet[ i ] ] == 0 )
					{
						$( "#te_btl_tab_" + alphabet[ i ] ).append( "<br />No tags that start with '" + alphabet[ i ] + "'.<br />" );
					}
				}
			}

		};

		//TE.Enhancement.option.main(type,name,description,defaultValue,arguments)
		var opt1 = {
			type         : "enable",
			name         : false,
			description  : false,
			defaultValue : false,
			arguments    : false
		};
		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );
		TE.Enhancements[ shortName ] = new TE.Enhancement.main( name, description, options, section, incompatible, main );
	})();

	(function ()
	{
		/*******************************************************
		 * Browsing Tweaks - Browsing Enhancement
		 *******************************************************/
		var name, shortName, description, options, section, incompatible, main;
		name         = 'Browsing Tweaks';
		shortName    = TE.fn.camelize( name );
		description  = "A collection of customizations to browsing.";
		options      = [];
		section      = "Browsing";
		incompatible = false;
		main         = {};

		main = {
			init : function ()
			{
				if ( TE.on.browse )
				{
					$.when( TE.status.enhancePage ).done( function ()
					{
						if ( typeof TE.User[ shortName ] !== "undefined" )
						{
							if ( TE.User[ shortName ].removeSidebar )
							{
								$( "#te_sidebarContainer" ).remove();
								$( "#te_bookshelfContainer" ).css( "width", "100%" );
							}

							if ( TE.User[ shortName ].moreBooks )
							{
								$( "style" ).append( "@media(min-width:768px) { .overlay-title { font-size:.8em; } .col-sm-4 { width: 25% } }" );
								$( "style" ).append( "@media(min-width:992px) { .col-md-3 { width: 20% } }" );
							}
							if ( TE.User[ shortName ].skipInfo )
							{
								// Apply new CSS.
								$( "style" ).append( TE.ui.css.browsingTweaks.master );
								$( "div.overlay" ).each( function ()
								{
									// Get Book ID
									var bookID = $( this ).attr( "id" );
									bookID     = bookID.replace( "te_book_", "" );
									bookID     = bookID.replace( "_overlay", "" );
									bookID     = parseInt( bookID );

									// Replace old class on view button.
									var viewInfoButton = $( this ).find( "a.overlay-button" );
									var linkURL = TE.site.reader.prefix + bookID + "/1";
									$( viewInfoButton ).after(`<a href="`+linkURL+`" class="te_browsetweak_readbutton">READ</a>`);
									var readButton = $( this ).next();
									$( viewInfoButton ).text( "INFO" );
									$( viewInfoButton ).removeClass( "overlay-button" );
									$( viewInfoButton ).addClass( "te_browsetweak_infobutton" );
									// Add new read button.


									if ( TE.User.recordKeeper )
									{
										if ( TE.User.recordKeeper.data[ bookID ] )
										{
											linkURL = TE.site.reader.prefix + bookID + "/" + TE.User.recordKeeper.data[ bookID ][ 'lastSeen' ];
											$( readButton ).attr( "href", linkURL );
										}
									}
								} );
							}
							if ( TE.User[ shortName ].fitTitles )
							{
								$( "div.overlay" ).each( function ()
								{
									var thisTitle   = $( this ).find( ".overlay-title" ).text();
									var titleLength = thisTitle.split( "" );
									titleLength     = titleLength.length;
									if ( (titleLength > 40) && (titleLength < 50) )
									{
										$( this ).find( ".overlay-title" ).css( "font-size", ".75em" );
									}
									else if ( (titleLength > 50) )
									{
										$( this ).find( ".overlay-title" ).css( "font-size", ".65em" );
									}
								} );
							}
							if ( TE.User[ shortName ].thumbnailLinks )
							{
								$( "div.overlay" ).each( function ()
								{
									$( this ).on( "mousedown", $.proxy( function (e)
									{
										// Only fire if the div itself is clicked, ignoring children.
										if ( e.target == this )
										{
											// Left Mouse
											if ( (e.which == 1) )
											{
												TE.vbLog( "Left mouse button clicked." );
												if ( TE.User[ shortName ].skipInfo )
												{
													var thisLink = $( this ).find( "a.te_browsetweak_readbutton" ).attr( "href" );
												}
												else
												{
													var thisLink = $( this ).find( "a.overlay-button" ).attr( "href" );
												}
												thisLink = TE.site.baseURL.root + thisLink;
												if ( e.ctrlKey )
												{
													w.open( thisLink );
												}
												else
												{
													w.location.href = thisLink;
												}

											}

											// Middle Mouse
											if ( (e.which == 2) )
											{
												TE.vbLog( "Middle mouse button clicked." );
												if ( TE.User[ shortName ].skipInfo )
												{
													var thisLink = $( this ).find( "a.te_browsetweak_readbutton" ).attr( "href" );
												}
												else
												{
													var thisLink = $( this ).find( "a.overlay-button" ).attr( "href" );
												}
												thisLink = TE.site.baseURL.root + thisLink;
												w.open( thisLink );
											}
										}
										e.preventDefault();
									}, this ) );
								} );
							}
						}
					} );
				}
			}
		};

		//TE.Enhancement.option.main(type,name,description,defaultValue,arguments)
		var opt1 = {
			type         : "toggle",
			name         : "Remove Sidebar",
			description  : "Removes the &quot;random picks&quot; sidebar.",
			defaultValue : false,
			arguments    : false
		};
		var opt2 = {
			type         : "toggle",
			name         : "More Books",
			description  : "Displays one extra book per row.",
			defaultValue : false,
			arguments    : false
		};
		var opt3 = {
			type         : "toggle",
			name         : "Thumbnail Links",
			description  : "Clicking anywhere on the thumbnail image will load the Doujin.",
			defaultValue : false,
			arguments    : false
		};
		var opt4 = {
			type         : "toggle",
			name         : "Skip Info",
			description  : "Skips the book info page and takes you directly to the reader.",
			defaultValue : false,
			arguments    : false
		};
		var opt5 = {
			type         : "toggle",
			name         : "Fit Titles",
			description  : "Makes sure doujin titles fit appropriately.",
			defaultValue : false,
			arguments    : false
		};

		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );
		options.push( new TE.Enhancement.option.main( opt2.type, opt2.name, opt2.description, opt2.defaultValue, opt2.arguments ) );
		options.push( new TE.Enhancement.option.main( opt3.type, opt3.name, opt3.description, opt3.defaultValue, opt3.arguments ) );
		options.push( new TE.Enhancement.option.main( opt4.type, opt4.name, opt4.description, opt4.defaultValue, opt4.arguments ) );
		options.push( new TE.Enhancement.option.main( opt5.type, opt5.name, opt5.description, opt5.defaultValue, opt5.arguments ) );
		TE.Enhancements[ shortName ] = new TE.Enhancement.main( name, description, options, section, incompatible, main );
	})();


	/*******************************************************
	 * Reader Enhancements
	 *******************************************************/
	(function ()
	{
		/*******************************************************
		 * Automatic Repositioning - Reader Enhancement
		 *******************************************************/
		var name, shortName, description, options, section, incompatible, main;
		name         = "Automatic Repositioning";
		shortName    = TE.fn.camelize( name );
		description  = "Automatically scrolls you to the top of the image.";
		options      = [];
		section      = "Reader";
		incompatible = false;
		main         = {
			init   : function ()
			{
				if ( TE.on.reader )
				{
					$.when( TE.status.enhancePage ).done( $.proxy( function ()
					{
						TE.Enhancements.unstickiedHeader.fn.run();
						this.run();
					}, this ) );
				}
			}, run : function ()
			{
				var imgPos = $( "#te_imageBlock" ).offset().top;
				$( "html, body" ).animate( {scrollTop : imgPos}, 300 );
			}
		};

		var opt1 = {
			type         : "enable",
			name         : false,
			description  : false,
			defaultValue : false,
			arguments    : false
		};
		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );
		TE.Enhancements[ shortName ] = new TE.Enhancement.main( name, description, options, section, incompatible, main );
	})();


	(function ()
	{
		/*******************************************************
		 * Seamless Viewing - Reader Enhancement
		 *******************************************************/
		var name, shortName, description, options, section, incompatible, main;
		name         = "Seamless Viewing";
		shortName    = TE.fn.camelize( name );
		description  = `Negates the need to load the entire Tsumino webpage again every time you flip through a Doujin.<br />
			This means faster load times, and not losing sight of the previous page until the instant the new page is loaded.<br />
			Seamless Viewing leaves the previous image in place until the new one is ready.<br />
			Once the new image is ready, you are automatically scrolled up to the top of the image.`;
		options      = [];
		section      = "Reader";
		incompatible = [ "Infinity Scrolling" ];
		main         = {};

		main = {
			replaceKeybinds : function ()
			{
				// Disable default Tsumino Reader Keybinds.
				unsafeWindow.$( document ).off( "keydown" );

				// Use Classic Seamless Viewing keybinds instead.
				$( document ).keydown( $.proxy( function (e)
				{
					var bk  = $.proxy( function ()
					{
						this.changePage( TE.book.prevPage );
					}, this );
					var fwd = $.proxy( function ()
					{
						this.changePage( TE.book.nextPage );
					}, this );
					if ( (!e.ctrlKey) && (!e.altKey) )
					{
						switch (e.which)
						{
							case 87: // w
								w.scrollBy( 0, -100 );
								break;
							case 83: // s
								w.scrollBy( 0, 100 );
								break;
							case 8: //back
							case 37: //left
							case 65: //a
								bk();
								break;
							case 32: //space
							case 13: //enter
							case 39: //right
							case 68: //d
								fwd();
								break;
							default:
								return;
						}
						e.preventDefault();
					}
				}, this ) );
			}, changePage   : function (pageNumber)
			{
				var dfd = jQuery.Deferred();

				function changePageCommon(pageNumber)
				{
					pageNumber = parseInt( pageNumber );
					// Update page and location variables.
					TE.book.currentPage = pageNumber;
					TE.book.prevPage    = pageNumber - 1;
					TE.book.nextPage    = pageNumber + 1;
					if ( TE.book.nextPage > TE.book.totalPages )
					{
						TE.book.nextPage = false;
					}
					if ( TE.book.prevPage <= 0 )
					{
						TE.book.prevPage = false;
					}
					TE.book.currentPageURL = TE.site.reader.prefix + TE.book.id + "/" + TE.book.currentPage;

					// Get the dataURI from the source of loader's hidden image.
					var newImageSrc = $( "#te_loadImage_" + pageNumber ).attr( "src" );
					//var newImageSrc = TE.site.image.prefix + TE.book.id + "/" + TE.book.currentPage;

					// Remove the loader's hidden image.
					$( "#te_readerCurrentImage" ).attr( "src", newImageSrc );

					// Reposition.
					TE.Enhancements.automaticRepositioning.fn.run();

					// If Record Keeper is Enabled.
					if ( TE.User.recordKeeper.enable )
					{
						TE.Enhancements.recordKeeper.fn.update();
					}

					// If Page Jumper is Enabled.
					if ( TE.User.pageJumper.enable )
					{
						$( "#te_pageJumper" ).val( pageNumber );
						$( "#te_pageJumper" ).dropdown( "set selected", pageNumber );
					}

					// Prefetch new pages.
					// TE.fn.prefetch.init( TE.book.currentPage );

					// Update title.
					$( "title" ).text( "Tsumino - " + TE.book.title + " - Page " + TE.book.currentPage );

					// Update links.
					this.updateLinks();

					// Update history and window location.
					if ( (!history.state) || (history.state && history.state.pageNumber != TE.book.currentPage) )
					{
						w.history.pushState( {pageNumber : TE.book.currentPage}, $( "title" ).text(), TE.book.currentPageURL );
					}
					TE.log( "gname", name, "Image " + pageNumber + " has been placed in the reader." );
					unsafeWindow.ga('send', 'pageview', TE.site.reader.prefix + TE.book.id + '/' + TE.book.currentPage);
					dfd.resolve();
				}

				var cpc = changePageCommon.bind( this );
				// Make sure the page is in range first.
				if ( (pageNumber <= TE.book.totalPages) && (pageNumber > 0) )
				{
					if ( TE.status.pagesLoaded[ pageNumber ] == "done" )
					{
						cpc( pageNumber );
					}
					else
					{
						if ( (TE.status.prefetch[ TE.book.id ][ pageNumber ] != "") && (TE.status.prefetch[ TE.book.id ][ pageNumber ] != "working") )
						{
							//TE.status.load = TE.load( pageNumber, TE.status.prefetch[ TE.book.id ][ pageNumber ] );
							// Once the requested page is loaded, continue.
							/*
							$.when( TE.status.load ).then( $.proxy( function ()
							{
								if ( TE.status.pagesLoaded[ pageNumber ] == "done" )
								{
									TE.log( "CPC going" );
									cpc( pageNumber );
								}
								else
								{
									TE.log( "CPC ERROR" );
								}
							}, this ) );
							*/
							$( "body" ).append( `
								<img id="te_loadImage_"` + pageNumber + `" src="/Image/Image/"` + TE.book.id + `/` + pageNumber + `" style="display:none;">
							` );
							$("#te_loadImage_" + pageNumber).load(function ()
							{
								cpc ( pageNumber );
							});
							if ($("#te_loadImage_" + pageNumber).complete)
							{
								$(this).load();
							}
						}
						else
						{
							TE.log( "gname", name, "Prefetch is still initializing..." )
						}
					}
				}
				// If the user requested a page that was less than 1 or greater than the total number of pages, stop.
				else
				{
					if ( pageNumber == false )
					{
						w.location.href = TE.site.book.url + TE.book.id;
					}
					TE.log( "gname", "Seamless Viewing", "Image " + pageNumber + " is out of range and will not be loaded." );
					dfd.resolve();
				}
				return dfd.promise();
			}, updateLinks  : function ()
			{
				TE.vbLog( "gname", name, "Updating links... " );
				// Remove old click binds from links.
				$( "#te_prevButton" ).off( "click" );
				$( "#te_nextButton" ).off( "click" );
				$( "#te_readerCurrentImage" ).off( "click" );

				// Establish updated click binds.
				if ( TE.book.currentPage <= TE.book.totalPages )
				{
					$( "#te_nextButton" ).css( "display", "inline" );
					$( "#te_nextButton" ).click( $.proxy( function ()
					{
						this.changePage( TE.book.nextPage );
					}, this ) );
					$( "#te_readerCurrentImage" ).click( $.proxy( function ()
					{
						this.changePage( TE.book.nextPage );
					}, this ) );
				}
				if ( TE.book.currentPage == TE.book.totalPages )
				{
					$( "#te_nextButton" ).css( "display", "none" );
					$( "#te_readerCurrentImage" ).click( $.proxy( function ()
					{
						this.changePage( TE.book.nextPage );
					}, this ) );
				}

				if ( TE.book.currentPage > 1 )
				{
					$( "#te_prevButton" ).css( "display", "inline" );
					$( "#te_prevButton" ).click( $.proxy( function ()
					{
						this.changePage( TE.book.prevPage );
					}, this ) );

				}
				else
				{
					$( "#te_prevButton" ).css( "display", "none" );
				}

				$( "#te_currentPage" ).html( "<a href='" + TE.book.currentPageURL + "'>" + TE.book.currentPage + "</a>" );
			}, init         : function ()
			{
				if ( TE.on.reader )
				{
					$.when( TE.status.enhancePage ).done( $.proxy( function ()
					{
						w.history.replaceState( {pageNumber : TE.book.currentPage}, $( "title" ).text(), TE.book.currentPageURL );

						// Allow history navigation to work with Seamless Viewing.
						$( w ).on( "popstate", $.proxy( function ()
						{
							if ( history.state )
							{
								this.changePage( history.state.pageNumber );
							}
						}, this ) );

						TE.log( "gname", name, "Initializining..." );

						// Replace default Tsumino reader keybinds with Enhanced Seamless Viewing keybinds.
						this.replaceKeybinds();

						// Automatic Repositioning.
						TE.Enhancements.automaticRepositioning.fn.run();

						// Unstickied Header.
						TE.Enhancements.unstickiedHeader.fn.run();

						// Remove default Tsumino doujin navigation links.
						$( "#te_prevButton" ).attr( "href", "javascript:;" );
						$( "#te_nextButton" ).attr( "href", "javascript:;" );
						$( "#te_imageLink" ).attr( "href", "javascript:;" );

						// Prepare Prefetch
						TE.status.prefetch[ TE.book.id ] = {};
						for (var i = 1 ; i <= TE.book.totalPages ; i++)
						{
							TE.status.prefetch[ TE.book.id ][ i ] = "";
						}
						TE.fn.prefetch.init( TE.book.currentPage );

						// Update doujin navigation links.
						this.updateLinks();
						$( "body" ).append( "<img id='te_loadImage_" + TE.book.currentPage + "' style='display:none;'>" );

						// "Cache" the first image that loads for later.
						var originImage    = new Image();
						originImage.onload = function ()
						{
							var canvas    = document.createElement( "canvas" );
							canvas.width  = this.naturalWidth;
							canvas.height = this.naturalHeight;
							canvas.getContext( "2d" ).drawImage( this, 0, 0 );
							var newSrc = canvas.toDataURL( "image/jpeg" );
							$( "#te_loadImage_" + TE.book.currentPage ).attr( "src", newSrc );
						};
						originImage.src    = $( "#te_readerCurrentImage" ).attr( "src" );

					}, this ) );
				}
				else if ( TE.on.auth )
				{
					// Reserved
				}
			}
		};

		//TE.Enhancement.option.main(type,name,description,defaultValue,arguments)
		var opt1 = {
			type         : "enable",
			name         : false,
			description  : false,
			defaultValue : false,
			arguments    : false
		};
		var opt2 = {
			type         : "toggle",
			name         : "Show Messages",
			description  : "Displays loading messages while preparing images for display.",
			defaultValue : true,
			arguments    : false
		};

		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );
		//options.push(new TE.Enhancement.option.main(opt2.type,opt2.name,opt2.description,opt2.defaultValue,opt2.arguments));

		TE.Enhancements[ shortName ] = new TE.Enhancement.main( name, description, options, section, incompatible, main );
	})();


	(function ()
	{
		/*******************************************************
		 * Page Jumper - Reader Enhancement
		 *******************************************************/
		var name, shortName, description, options, section, incompatible, main;
		name         = "Page Jumper";
		shortName    = TE.fn.camelize( name );
		description  = "Adds a dropdown box to the Reader that lets you skip directly to a page.";
		options      = [];
		section      = "Reader";
		incompatible = false;
		main         = {};

		main = {
			init : function ()
			{
				if ( TE.on.reader )
				{
					$.when( TE.status.enhancePage ).done( $.proxy( function ()
					{
						$( "#te_readerPagination" ).after( `
							<h1 style='display:inline;'>Jump to page: </h1>
							<select class='ui compact search dropdown' id='te_pageJumper'></select><br />
							` );
						for (var i = 1 ; i <= TE.book.totalPages ; i++)
						{
							$( "#te_pageJumper" ).append( "<option value='" + i + "'>" + i + "</option>" );
						}
						$( "#te_pageJumper" ).val( TE.book.currentPage );

						$( "#te_pageJumper" ).change( $.proxy( function ()
						{
							// Seamless Viewing Compatibility
							if ( TE.User.seamlessViewing.enable )
							{
								var pageNumber = parseInt( $( "#te_pageJumper" ).val() );

								$.when( TE.fn.prefetch.init( pageNumber ) ).then( function ()
								{
									TE.Enhancements.seamlessViewing.fn.changePage( pageNumber );
								} );

							}
							// Vanilla Tsumino
							else
							{
								w.location.href = TE.site.reader.url + TE.book.id + "/" + pageNumber;
							}
						}, this ) );
						$( "#te_pageJumper" ).dropdown();
					}, this ) );
				}
			}
		};

		//TE.Enhancement.option.main(type,name,description,defaultValue,arguments)
		var opt1 = {
			type         : "enable",
			name         : false,
			description  : false,
			defaultValue : false,
			arguments    : false
		};
		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );

		TE.Enhancements[ shortName ] = new TE.Enhancement.main( name, description, options, section, incompatible, main );
	})();


	(function ()
	{
		/*******************************************************
		 * Infinity Scrolling - Reader Enhancement
		 *******************************************************/
		var name                  = "Infinity Scrolling",
			shortName             = TE.fn.camelize( name ),
			description           = "Scroll down to load images.",
			options = [], section = "Reader",
			incompatible          = [ "Seamless Viewing" ],
			main                  = {};

		main = {
			init : function ()
			{
				if ( TE.on.reader )
				{
					$.when( TE.status.enhancePage ).done( function ()
					{

					} );
				}
			}

		};

		//TE.Enhancement.option.main(type,name,description,defaultValue,arguments)
		var opt1 = {
			type         : "enable",
			name         : false,
			description  : false,
			defaultValue : false,
			arguments    : false
		};
		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );

		//TE.Enhancements[shortName] = new TE.Enhancement.main(name,description,options,section,incompatible,main);
	})();

	(function ()
	{
		/*******************************************************
		 * Automatic Repositioning - Reader Enhancement
		 *******************************************************/
		var name, shortName, description, options, section, incompatible, main;
		name         = "Automatic Update Installation";
		shortName    = TE.fn.camelize( name );
		description  = `If your version of Tsumino Enhanced is out of date, it will automatically attempt to update.<br />
						You must still accept your browser's prompt to install the update.`;
		options      = [];
		section      = "TsuminoEnhanced";
		incompatible = false;
		main         = {
			init   : function ()
			{
				// No INIT.
			}
		};

		var opt1 = {
			type         : "enable",
			name         : false,
			description  : false,
			defaultValue : false,
			arguments    : false
		};
		options.push( new TE.Enhancement.option.main( opt1.type, opt1.name, opt1.description, opt1.defaultValue, opt1.arguments ) );
		TE.Enhancements[ shortName ] = new TE.Enhancement.main( name, description, options, section, incompatible, main );
	})();



	/*************************************************************************************
	 * Tsumino Enhanced Settings Page
	 *************************************************************************************/
	TE.settings = {
		render    : function ()
		{
			if ( !TE.User.readNews )
			{
				TE.User.readNews = {};
			}

			$( "#te_config_modal" ).html( "<div id='te_settings' style='font-size: 1.4em;'></div>" );
			$( "#te_config_modal" ).prepend( `
				<div class="header"><h1><span class="te_mainColor">Tsumino Enhanced</span>
				<span id="te_version" class="small">` + TE.version + `</span></h1></div>
				` );
			if ( !TE.User.tsuminoEnhanced.upToDate )
			{
				var installLocation = TE.updateLocation;
				installLocation     = installLocation.replace( "/scripts/", "/install/" );
				installLocation     = installLocation + ".user.js";
				//$("#te_version").append("&nbsp;&nbsp;-&nbsp;&nbsp;<a style='color:#ff0000; text-decoration:none;' href='" + installLocation + "'>Update!</a>");
				$( "#te_version" ).after( `&nbsp;&nbsp;
					<div id="te_updateButton" class="ui big labeled button" tabindex="0">
						<div class="ui red button"><i class="upload icon"></i>Update!</div><a class="ui basic red left pointing label">`
										  + TE.User.tsuminoEnhanced.latestVersion + `</a></div>` );
				//$("#te_config_modal").append("<a id='te_secretUpdateLink' style='display:none;' href='" + installLocation + "'>Update!</a>")
				$( "#te_updateButton" ).click( function ()
				{
					$( "body" ).append( `
					<div id="te_refresh_modal" class="ui basic modal">
					<div class="header" style="font-size: 3em;"><i class="upload icon"></i> Updating Tsumino Enhanced...</div>
					<div class="image content"><div class="image"><i class="refresh icon"></i></div>
					<div class="description" style="font-size: 1.5em;">
						<p>You will be prompted to install the update in just a moment.</p>
						<p>In order for the update to take effect, you must refresh this page after it has finished installing.</p>
						<p>Do you wish to refresh the page now?</p>
						</div></div>
					<div class="actions">
						<button id="te_refreshPageButton" class="massive fluid gray ui button disabled">Refresh</button>
					</div></span>` );
					$( "#te_config_modal" ).modal( "hide" );
					$( "#te_refresh_modal" ).modal();
					$( "#te_refresh_modal" ).modal( "show" );
					$( "#te_refresh_modal" ).modal( "refresh" );
					setTimeout( function ()
					{
						w.location.href = installLocation;
						$("#te_refreshPageButton").removeClass("disabled");
						$("#te_refreshPageButton").removeClass("gray");
						$("#te_refreshPageButton").addClass("green");
					}, 5000 );
					$( "#te_refreshPageButton" ).click( function ()
					{
						if(!$("#te_refreshPageButton").hasClass("disabled"))
						{
							w.location.reload();
						}
					} );
				} );

				$( "#te_updateButton" ).popup( {
					title : 'Click here to begin the update process.'
				} );
			}

			// Settings page navigation structure.
			//$("#te_settings").prepend("<div id='te_tabContainer' class='te_configTab'><nav><ul><li id='tab_generalEnhancements'><a href='javascript:;'>General</a></li><li id='tab_browsingEnhancements'><a href='javascript:;'>Browsing</a></li><li id='tab_readerEnhancements'><a href='javascript:;'>Reader</a></li><li id='tab_teNews'><a href='javascript:;'>TE News</a></li><li id='tab_searchEnhancements'><a href='javascript:;'>Search</a></li></ul></nav></div>");

			$( "#te_settings" ).prepend( `<div id="te_settings_tabs" class="ui top attached inverted large tabular menu"></div>` );
			$( "#te_settings_tabs" ).append( `<a class="item active" data-tab="generalEnhancements">General Enhancements</a>` );
			$( "#te_settings_tabs" ).append( `<a class="item" data-tab="browsingEnhancements">Browsing Enhancements</a>` );
			$( "#te_settings_tabs" ).append( `<a class="item" data-tab="readerEnhancements">Reader Enhancements</a>` );
			$( "#te_settings_tabs" ).append( `<a class="item" data-tab="TE_options">TE Configuration</a>` );
			$( "#te_settings_tabs" ).append( `<a class="item" data-tab="teAbout">About</a>` );

			$( "#te_settings" ).append( `
				<div id="te_settings_tab_generalEnhancements" class="ui bottom attached inverted tab segment active" data-tab="generalEnhancements"></div>
			` );
			$( "#te_settings" ).append( `
				<div id="te_settings_tab_browsingEnhancements" class="ui bottom attached inverted tab segment" data-tab="browsingEnhancements"></div>
			` );
			$( "#te_settings" ).append( `
				<div id="te_settings_tab_readerEnhancements" class="ui bottom attached inverted tab segment" data-tab="readerEnhancements"></div>
			` );
			$( "#te_settings" ).append( `
				<div id="te_settings_tab_TE_options" class="ui bottom attached inverted tab segment" data-tab="TE_options"></div>
			` );
			$( "#te_settings" ).append( `
				<div id="te_settings_tab_teAbout" class="ui bottom attached tab segment inverted" data-tab="teAbout"></div>
			` );

			var tobyAvatar = "data:image/jpeg;base64,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";
			var tobyCard   = `

<div class="ui centered grid">
	<div class="seven wide column">
		<div class="ui fluid blue card">
			<div class="content">
				<h1 class="header">Tsumino Enhanced</h1>
				<div class="description">
					<table class="ui single line definition blue left aligned table">
						<tbody>
						<tr>
							<td class="left aligned">Current Version</td>
							<td>` + TE.version + `</td>
						</tr>
						<tr>
							<td class="left aligned">Latest Version</td>
							<td>` + TE.User.tsuminoEnhanced.latestVersion + `</td>
						</tr>
						<tr>
							<td>Changelog</td>
							<td><button id="te_tobyLinks_teChangelog" data-content="Check out the list of changes."
							class="ui large circular inverted blue icon button teTooltip"><i class="external icon"></i></button></td>
						</tr>
						<tr>
							<td>Requests &amp; Feedback</td>
							<td><button id="te_tobyLinks_teRaF" data-content="Influence TE's development."
							class="ui large circular inverted blue icon button teTooltip"><i class="external icon"></i></button></td>
						</tr>
						<tr class="top aligned">
							<td class="left aligned collapsing">Library Dependencies</td>
							<td>
								<ul class="ui list">
									<li class="teTooltip" data-content="General purpose library.">jQuery 2.1.14</li>
									<li class="teTooltip" data-content="Gives TE a nicer UI.">SemanticUI 2.1.8</li>
									<li class="teTooltip" data-content="Event management library.">Bean 1.0.15</li>
									<li class="teTooltip" data-content="A more versatile animation library.">Velocity 1.2.3</li>
								</ul>
							</td>
						</tr>
						<tr class="top aligned">
							<td class="left aligned">@grant Permissions</td>
							<td>
								<ul class="ui list">
									<li class="teTooltip" data-content="Used for saving your settings.">GM_setValue</li>
									<li class="teTooltip" data-content="Used for reading your settings.">GM_getValue</li>
									<li class="teTooltip" data-content="Used for cleaning up depreciated values.">GM_deleteValue</li>
									<li class="teTooltip" data-content="Used for opening links in new tabs.">GM_openInTab</li>
									<li class="teTooltip" data-content="Used for overriding Tsumino hotkeys.">unsafeWindow</li>
								</ul>
							</td>
						</tr>
						</tbody>
					</table>
				</div>
			</div>
		</div>
	</div>
	<div class="five wide column">
		<div class="ui purple card" style="width:280px;">
			<div class="image">
				<img src="` + tobyAvatar + `" />
			</div>
			<div class="content">
				<div class="header">Toby</div>
				<div class="meta">
					<a>Web Developer</a>
				</div>
				<div class="description">
					<p>I'm the guy that made this.</p>
				</div>
			</div>
			<div class="extra content">
				<button id="te_tobylinks_home" data-content="Visit my project blog!" class="ui large circular inverted violet icon button teTooltip">
					<i class="large home icon"></i>
				</button>
				<button id="te_tobylinks_github" data-content="Take a look at my GitHub profile!" class="ui large circular black icon button teTooltip">
					<i class="large github alternate icon"></i>
				</button>
				<button id="te_tobylinks_openuserjs" data-content="Check out my other userscripts!" class="ui large circular grey icon button teTooltip">
					<i class="large code icon"></i>
				</button>
				<button id="te_tobylinks_skype" data-content="Chat with me on Skype!" class="ui large circular inverted blue icon button teTooltip">
					<i class="large skype icon"></i>
				</button>
				<button id="te_tobylinks_tsuminopm" data-content="Send me a PM on the Tsumino Forums!" class="ui large circular inverted pink icon button teTooltip">
					<i class="large mail outline icon"></i>
				</button>
			</div>
		</div>
	</div>
</div>
			`;

			$( "#te_settings_tab_teAbout" ).append( tobyCard );

			$( "#te_tobyLinks_teChangelog" ).click( function ()
			{
				GM_openInTab( "http://codingtoby.com/category/userscripts/tsumino-enhanced/te-updates/" );
			} );
			$( "#te_tobyLinks_teRaF" ).click( function ()
			{
				GM_openInTab( "http://codingtoby.com/userscripts/tsumino-enhanced/requests-and-feedback/#respond" );
			} );
			$( "#te_tobylinks_home" ).click( function ()
			{
				GM_openInTab( "http://codingtoby.com/" );
			} );
			$( "#te_tobylinks_github" ).click( function ()
			{
				GM_openInTab( "https://github.com/tobiaskelmandia" );
			} );
			$( "#te_tobylinks_openuserjs" ).click( function ()
			{
				GM_openInTab( "https://openuserjs.org/users/Tobias.Kelmandia/scripts" );
			} );
			$( "#te_tobylinks_skype" ).click( function ()
			{
				w.location.href = "skype:tobias_kelmandia?chat";
			} );
			$( "#te_tobylinks_tsuminopm" ).click( function ()
			{
				GM_openInTab( "http://www.tsumino.com/Forum/ucp.php?i=pm&mode=compose&u=191" );
			} );

			// Initialize Tooltips
			$( ".teTooltip" ).popup();

			// Populate Sections.
			for (var key in TE.Enhancements)
			{
				if ( TE.Enhancements.hasOwnProperty( key ) )
				{
					var obj = TE.Enhancements[ key ];

					if ( obj[ "section" ] != false )
					{
						// Determine which section to append to.
						var sectionID = "";
						if ( obj[ "section" ] == "General" )
						{
							sectionID = "#te_settings_tab_generalEnhancements";
						}
						else if ( obj[ "section" ] == "Browsing" )
						{
							sectionID = "#te_settings_tab_browsingEnhancements";
						}
						else if ( obj[ "section" ] == "Reader" )
						{
							sectionID = "#te_settings_tab_readerEnhancements";
						}
						else if ( obj[ "section" ] == "TsuminoEnhanced" )
						{
							sectionID = "#te_settings_tab_TE_options";
						}

						// Append the Enhancement's options group to the section.
						$( sectionID ).append( "<div id='" + obj[ "shortName" ] + "_group' class='te_optionGroup'></div>" );

						// Add the description.
						if ( obj[ "description" ] != false )
						{
							$( "#" + obj[ "shortName" ] + "_group" ).append( "<div class='te_optionDescription'>" + obj[ "description" ] + "</div>" );
						}

						// Add the primary options area.
						$( "#" + obj[ "shortName" ] + "_group" ).append( "<div id='te_options_" + obj[ "shortName" ] + "'></div>" );

						var noEnable = true;
						if ( obj[ "options" ] != false )
						{
							// Display all options.
							for (var oKey in obj[ "options" ])
							{
								if ( obj[ "options" ].hasOwnProperty( oKey ) )
								{
									var option = obj[ "options" ][ oKey ];
									// Write the Enable option.
									if ( option[ "type" ] == "enable" )
									{
										$( "#" + obj[ "shortName" ] + "_group" ).prepend( `
											<div class="ui middle aligned toggle checkbox">
												<input id="tes_` + obj[ "shortName" ] + `_enable" name="tes_` + obj[ "shortName" ] + `_enable"  type="checkbox">
												<label for="tes_` + obj[ "shortName" ] + `_enable">
													<a class="ui huge blue label">` + obj[ "name" ] + `</a>
												</label>
											 </div>` );


										$( "#enhancement_header_" + obj[ "shortName" ] ).click( {obj : obj}, function (event)
										{
											TE.log( $( "#tes_" + event.data.obj[ "shortName" ] + "_enable" ) );
											if ( $( "#tes_" + event.data.obj[ "shortName" ] + "_enable" ).prop( "checked" ) == true )
											{
												$( "#tes_" + event.data.obj[ "shortName" ] + "_enable" ).prop( "checked", false );
											}
											else
											{
												$( "#tes_" + event.data.obj[ "shortName" ] + "_enable" ).prop( "checked", true );
											}
										} );
										noEnable = false;
									}
									// Write Toggle Options.
									if ( option[ "type" ] == "toggle" )
									{
										$( "#te_options_" + obj[ "shortName" ] ).append( `<br />
											<div class="ui middle aligned toggle checkbox">
												<input id="tes_` + obj[ "shortName" ] + `_` + option[ "shortName" ] + `"
												name="tes_` + obj[ "shortName" ] + `_` + option[ "shortName" ] + `" type="checkbox" class="te_subOption" />
												<label for="tes_` + obj[ "shortName" ] + `_` + option[ "shortName" ] + `">
													<a class="ui huge blue label">` + option[ "name" ] + `</a>
												</label>
											</div>` );

										// Write the option's description.
										if ( option[ "description" ] != false )
										{
											$( "#" + obj[ "shortName" ] + "_optionContainer_" + option[ 'shortName' ] ).append( "<br />"
																																+ option[ "description" ] );
										}
									}
								}
							}
						}

						// If there was no "enable" option found:
						if ( noEnable )
						{
							// Display the title without a switch.
							$( "#" + obj[ "shortName" ] + "_group" ).prepend( "<h2 class='te_enhancementName'>" + obj[ "name" ] + "</h2>" );

							// Apply user settings.
							if ( typeof TE.User[ obj[ "shortName" ] ] !== "undefined" )
							{
								for (var oKey in obj[ "options" ])
								{
									var option = obj[ "options" ][ oKey ];
									if ( option[ "type" ] == "toggle" )
									{
										$( "#tes_" + obj[ "shortName" ] + "_" + option[ 'shortName' ] )
											.prop( "checked", TE.User[ obj[ "shortName" ] ][ option[ 'shortName' ] ] );
									}
								}
							}
						}
						else
						{
							// Apply user settings.
							if ( typeof TE.User[ obj[ "shortName" ] ] !== "undefined" )
							{
								for (var oKey in obj[ "options" ])
								{
									var option = obj[ "options" ][ oKey ];
									if ( TE.User[ obj[ "shortName" ] ][ "enable" ] == true )
									{
										if ( option[ "type" ] == "enable" )
										{
											$( "#tes_" + obj[ "shortName" ] + "_" + option[ 'shortName' ] ).prop( "checked", true );
										}
										else
										{
											if ( option[ "type" ] == "toggle" )
											{
												$( "#tes_" + obj[ "shortName" ] + "_" + option[ 'shortName' ] )
													.prop( "checked", TE.User[ obj[ "shortName" ] ][ option[ 'shortName' ] ] );
											}
										}
									}
									else
									{
										if ( option[ "type" ] != "enable" )
										{
											$( "#tes_" + obj[ "shortName" ] + "_" + option[ 'shortName' ] ).prop( "checked", false );
											$( "#tes_" + obj[ "shortName" ] + "_" + option[ 'shortName' ] ).prop( "disabled", "disabled" );
										}
									}
								}
							}
							else
							{
								for (var oKey in obj[ "options" ])
								{
									if ( obj[ "options" ].hasOwnProperty( oKey ) )
									{
										var option = obj[ "options" ][ oKey ];
										if ( option[ "type" ] != "enable" )
										{
											if ( !$( "#tes_" + obj[ "shortName" ] + "_" + option[ 'shortName' ] ).prop( "disabled" ) )
											{
												$( "#tes_" + obj[ "shortName" ] + "_" + option[ 'shortName' ] ).prop( "disabled", "disabled" );
											}
										}
									}
								}
							}

							// Apply default values to options when enabling an Enhancement.
							$( "#tes_" + obj[ "shortName" ] + "_enable" ).change( {obj : obj}, function (event)
							{
								if ( $( "#tes_" + event.data.obj[ "shortName" ] + "_enable" ).prop( "checked" ) == true )
								{
									for (var oKey in event.data.obj[ "options" ])
									{
										if ( event.data.obj[ "options" ].hasOwnProperty( oKey ) )
										{
											var option = event.data.obj[ "options" ][ oKey ];
											if ( option[ "type" ] == "toggle" )
											{
												$( "#tes_" + event.data.obj[ "shortName" ] + "_" + option[ 'shortName' ] ).removeProp( "disabled" );
												$( "#tes_" + event.data.obj[ "shortName" ] + "_"
												   + option[ 'shortName' ] ).prop( "checked", option[ 'defaultValue' ] );
											}
										}
									}
								}
								// Disable Enhancement options unless the enhancement is enabled.
								else
								{
									for (var oKey in event.data.obj[ "options" ])
									{
										if ( event.data.obj[ "options" ].hasOwnProperty( oKey ) )
										{
											var option = event.data.obj[ "options" ][ oKey ];
											if ( option[ "type" ] != "enable" )
											{
												if ( option[ "type" ] == "toggle" )
												{
													$( "#tes_" + event.data.obj[ "shortName" ] + "_"
													   + option[ 'shortName' ] ).prop( "checked", false );
												}
												$( "#tes_" + event.data.obj[ "shortName" ] + "_"
												   + option[ 'shortName' ] ).prop( "disabled", "disabled" );
											}
										}
									}
								}
							} );
						}
						// List any incompatibilities.
						if ( obj[ "incompatible" ] != false )
						{
							$( "#" + obj[ "shortName" ] + "_group" ).append( "<br /><div class='te_en_incompatible' id='" + obj[ "shortName" ]
																			 + "_incompatible'>This Enhancement is incompatible with: </div>" );
							var punct = "";
							for (var i = 0 ; i < obj[ "incompatible" ].length ; i++)
							{
								$( "#" + obj[ "shortName" ] + "_incompatible" ).append( "<span class='te_enhancementColor'>"
																						+ obj[ "incompatible" ][ i ] + "</span>" );
								if ( i + 1 == obj[ "incompatible" ].length )
								{
									punct = ".";
								}
								else
								{
									punct = ", ";
								}
								$( "#" + obj[ "shortName" ] + "_incompatible" ).append( punct );
								$( "#" + obj[ "shortName" ] + "_group" ).append( "<br /><br />" );
							}
						}
						else
						{
							$( "#" + obj[ "shortName" ] + "_group" ).append( "<br /><br />" );
						}
					}
				}
			}


			//$("#te_settingsBody").append("<div id='searchEnhancements' class='te_options'></div>");
			//$("#te_settings").append("<div id='forumEnhancements' class='te_options'></div>");

			// Create Buttons
			$( "#te_settings" ).append( "<br /><br /><div id='te_buttonContainer'></div><br /><br />" );
			$( "#te_buttonContainer" ).append( "<a id='te_saveAndCloseButton' class='book-read-button'>Save &amp; Reload</a>&nbsp;&nbsp;" );
			$( "#te_saveAndCloseButton" ).click( $.proxy( function ()
			{
				this.save();
				location.reload();
			}, this ) );
			$( "#te_buttonContainer" ).append( "<a id='te_applySettingsButton' class='book-read-button'>Apply</a>&nbsp;&nbsp;" );
			$( "#te_applySettingsButton" ).click( $.proxy( function ()
			{
				this.save();
			}, this ) );
			$( "#te_buttonContainer" ).append( "<a id='te_cancelSettingsButton' class='book-read-button'>Cancel</a>" );
			$( "#te_cancelSettingsButton" ).click( $.proxy( function ()
			{
				this.remove();
			}, this ) );


			$( ".menu .item" ).tab();
			$( "#te_config_modal" ).modal(
				{
					onVisible      : function ()
					{
						$( "#te_config_modal" ).modal( "refresh" );
					},
					observeChanges : true
				} );

			$( ".menu .item" ).click( function ()
			{
				$( "#te_config_modal" ).modal( "refresh" );
			} );
		}, remove : function ()
		{
			$( "#te_config_modal" ).modal( "hide" );
		}, save   : function ()
		{
			// Find all enhancement groups within the main settings area.
			var enhancementGroups = $( "#te_settings" ).find( "div[id*='_group']" ), enhancementSettings = {};

			// Loop through the groups to get all the individual settings.
			for (var i = 0 ; i < enhancementGroups.length ; i++)
			{
				var thisEnhancement                = enhancementGroups[ i ];
				var thisEnhName                    = $( thisEnhancement ).attr( "id" );
				thisEnhName                        = thisEnhName.replace( "_group", "" );
				var thisEnhSettings                = $( thisEnhancement ).find( "*[id*='tes_" + thisEnhName + "_']" );
				enhancementSettings[ thisEnhName ] = {};
				for (var es = 0 ; es < thisEnhSettings.length ; es++)
				{
					var thisEnSetting = $( thisEnhSettings )[ es ], thisEnSettingName = $( thisEnSetting ).attr( "id" );
					thisEnSettingName = thisEnSettingName.replace( "tes_" + thisEnhName + "_", "" );
					if ( $( thisEnSetting ).prop( "tagName" ) == "INPUT" )
					{
						if ( $( thisEnSetting ).prop( "type" ) == "checkbox" )
						{
							enhancementSettings[ thisEnhName ][ thisEnSettingName ] = $( thisEnSetting ).prop( "checked" );
						}
					}
				}
			}
			$.extend( true, TE.User, enhancementSettings );
			TE.updateSettings();
		}
	};

	/*************************************************************************************
	 * Tsumino Enhanced Initialization Code
	 *************************************************************************************/
		// Initialization.
	TE.init = function ()
	{
		TE.User.seamlessViewing.enable = false;
		TE.User.automaticRepositioning.enable = false;
		TE.User.pageJumper.enable = false;
		TE.User.unstickiedHeader.enable = false;

		$.when(TE.fn.checkForUpdates()).then(function()
		{
			if(!TE.User.tsuminoEnhanced.upToDate)
			{
				if(TE.User.automaticUpdateInstallation)
				{
					if(TE.User.automaticUpdateInstallation.enable)
					{
						GM_openInTab(TE.installLocation);
					}
				}
			}
		});

		// Output initializating messages to the console.
		var debugState = "Disabled";
		if ( TE.config.debug )
		{
			if ( TE.config.verboseDebug )
			{
				debugState = "Verbose";
			}
			else
			{
				debugState = "Standard";
			}
		}

		// Check which Enhancements the user has enabled.
		var enabledEnhancements = [], eeLongNames = "", autoOn = [];
		for (var key in TE.User)
		{
			if ( TE.User.hasOwnProperty( key ) )
			{
				var obj = TE.User[ key ];
				for (var prop in obj)
				{
					if ( obj.hasOwnProperty( prop ) )
					{
						if ( (prop == "enable") && (obj[ prop ] == true) )
						{
							// Add enabled Enhancements to the appropriate array.
							if ( typeof TE.Enhancements[ key ] !== "undefined" )
							{
								enabledEnhancements.push( key );
								eeLongNames = eeLongNames + "[X] " + TE.Enhancements[ key ].name + "\r\n";
							}
						}
						else if ( (prop == "enable") && (obj[ prop ] == false) )
						{
							eeLongNames = eeLongNames + "[ ] " + TE.Enhancements[ key ].name + "\r\n";
						}
					}
				}
			}
		}
		// Check for automatic enhancements.
		for (var key in TE.Enhancements)
		{
			if ( TE.Enhancements.hasOwnProperty( key ) )
			{
				var obj = TE.Enhancements[ key ];
				autoOn.push( obj[ 'shortName' ] );
				for (var prop in obj)
				{
					if ( obj.hasOwnProperty( prop ) )
					{
						if ( prop == "options" )
						{
							for (var optNum in obj[ 'options' ])
							{
								for (var opt in obj[ 'options' ][ optNum ])
								{
									if ( (opt == "type") && (obj[ 'options' ][ optNum ][ opt ] == "enable") )
									{
										var thisIndex = autoOn.indexOf( obj[ 'shortName' ] );
										if ( thisIndex > -1 )
										{
											autoOn.splice( thisIndex, 1 );
										}
									}
								}
							}
						}
					}
				}
			}
		}
		// Enable automatic enhancements.
		for (i = 0 ; i < autoOn.length ; i++)
		{
			enabledEnhancements.push( autoOn[ i ] );
			eeLongNames = eeLongNames + "[X] " + TE.Enhancements[ autoOn[ i ] ].name + "\r\n";
		}



		// Output initialization messages.
		TE.log( "gname", TE.name,
			"Version:	" + TE.version,
			"Latest:		" + TE.User.tsuminoEnhanced.latestVersion,
			"Up2Date:	" + TE.User.tsuminoEnhanced.upToDate,
			"Debugging:	" + debugState,
			"Enhancements:", eeLongNames );
		TE.vbLog( "gname", TE.name, "Current Settings:", TE.User );
		//TE.vbLog( "gname", "TE.site", TE.site );
		TE.vbLog( "gname", "TE.on", TE.on );
		TE.vbLog( "gname", "TE.Enhancements", TE.Enhancements );

		// Set up TE.status.enhancePage for Enhancements that require it to run.
		TE.status.enhancePage = TE.enhancePage();

		// Initialize all enabled Enhancements.
		for (var i = 0 ; i < enabledEnhancements.length ; i++)
		{
			if ( typeof TE.Enhancements[ enabledEnhancements[ i ] ] !== "undefined" )
			{
				TE.Enhancements[ enabledEnhancements[ i ] ].fn.init();
			}
		}
	};

	var tempMyLocation = TE.myLocation;
	// Initialize Tsumino Enhanced.
	if ( !TE.on.forum )
	{
		TE.init();
	}
	else if((TE.on.forum) && ( (tempMyLocation.indexOf("#p1472") != -1) || (tempMyLocation.indexOf("p=1472") != -1) ) )
	{
		var messageID = TE.randomString();
		$(document).ready(function()
		{
			$("#p1472").after(`
			<div class="post" id="`+messageID+`">
				<div class="inner">
					<div class="postbody">
						<span style="font-size: 2em">A message from <span style="color:`+TE.ui.mainColor+`">Tsumino Enhanced</span></span>
						<hr />
						<div class="content">
							If you're here, that means that Tsumino has updated their detection script again.<br />
							The good news is that you don't appear to be banned yet.<br />
							If you wish to continue using Tsumino Enhanced, make sure you're using the latest version.<br />
							You can still manually update over on
							<a href="https://openuserjs.org/scripts/Tobias.Kelmandia/Tsumino_Enhanced">OpenUserJS</a>
							by clicking the install button on that page.<br />
							If you're using the latest version and still get taken here, you can disable TE until the new
							detection method has been defeated.<br />
							You can find the latest news for Tsumino Enhanced over on the
							<a href="http://codingtoby.com/" target="_blank">development blog</a>.<br />
							If you're interested, you can also read
							<a href="http://codingtoby.com/userscripts/tsumino-enhanced/regarding-tsuminos-stance-on-userscripts/"
								target="_blank">my response to Tweety's post</a>.<br />
						</div>
					</div>
				</div>
			</div>
		`);
		});
		$(w).load(function()
		{
			var scrollTo = $( "#" + messageID ).offset().top;
			scrollTo -= ($(".nav-tabs").height() + 10);
			$( "html, body" ).animate( {scrollTop : scrollTo}, 300 );
		});
	}

})( typeof window === "undefined" ? this : window, this.jQuery );