Greasy Fork is available in English.

Hide Threads and Replies by Poster

Hides threads based on the player(s) that posted the thread or replied. Applies to all sub-forums, your Clan forum and your Mail. Also applies to individual threads.

您查看的为 2018-04-17 提交的版本。查看 最新版本

// ==UserScript==
// @author https://greasyfork.org/en/users/85040-dan-wl-danwl
// @name Hide Threads and Replies by Poster
// @namespace daniel.church@btinternet.com
// @grant none
// @match https://www.warzone.com/*
// @description Hides threads based on the player(s) that posted the thread or replied. Applies to all sub-forums, your Clan forum and your Mail. Also applies to individual threads.
// @version 2.3.0.9
// @require	  https://greasyfork.org/scripts/35370-add-css/code/Add_CSS.js?version=260201
// @require https://greasyfork.org/scripts/39784-easy-dom/code/Easy%20DOM.js?version=265196
// @require https://greasyfork.org/scripts/39985-prank-lib/code/Prank%20Lib.js?version=261562
// ==/UserScript==
var v = '2.3.0.9';

console.log("Dan's userscript version: " + v);

/*
First released on 8/12/2016 see https://www.warzone.com/Forum/222938-dans-userscript-hide-threads-replies-poster for evidence.

localStorage.DanHTRBP_version_changes = "";

minor done features that could be improved:
made prompts auto-focus (mouse has to be over popup)

To do:
fix conflicts with muli's userscript - threadExceptionsHiddenThreadsContainer display inline

make arrow keys and tab select buttons
make it possible to add players by profile numbers?
make threads use ids instead of names?
*/

try{
if (!localStorage)
{
	throw "Your browser doesn't support localStorage. Upgrade to modern browser such as Firefox or Chrome.";
}
}catch(err){console.log(err);}

RemoveLocalStorageItem = function(key)
{
	//localStorage.removeItem doesn't work in Chrome - https://stackoverflow.com/questions/46131249/localstorage-cannot-be-removed-in-chrome
	if (typeof key !== 'string')
	{
		return;
	}
	if (!localStorage.getItem(key))
	{
		return;
	}

	localStorage.setItem(key, '');
	localStorage.removeItem(key);
};

var userscripts =
{
	mulis: function()
	{
		return window.MULIS_USERSCRIPT;
	}
};

function IsUser(player_numbers)
{
	var ret = false;
	var AccountDropDown = document.getElementById('AccountDropDown');

	if (AccountDropDown)
	{
		var AccountDropDownPlayerNumber = parseInt(AccountDropDown.nextElementSibling.firstElementChild.href.match(/\d/g).toString().replace(/[^\d]/g, ''));

		if (typeof player_numbers === 'number')
		{
			ret = player_numbers === AccountDropDownPlayerNumber;
		}
		else
		{
			for (var p_num_counter = 0; p_num_counter < player_numbers.length; p_num_counter++)
			{
				if (AccountDropDownPlayerNumber === player_numbers[p_num_counter])
				{
					ret = true;
					break;
				}
			}
		}
	}

	return ret;
}

function Mail(msg, subject, create_new_pm)
{
	if (!subject)
	{
		subject = 'Hide Threads and Replies by Poster Errors';
	}

	var player_to_send_msg_to = 222685;

	if (IsUser(9522268564))
	{
		player_to_send_msg_to = 278245;
	}

	if (!localStorage.DanHTRBP_MailId || create_new_pm)
	{
		var MailPage = open('https://www.warzone.com/Discussion/SendMail?PlayerID=' + player_to_send_msg_to);

		MailPage.onload = function()
		{
			MailPage.document.getElementById('SubjectBox').value = subject;
			MailPage.document.getElementById('TextArea_0').innerHTML = msg;
			window.old_location = MailPage.location.href;
			var check_if_pm_loaded = setInterval(function(){GetPmId()}, 1000);//page.onload isn't triggered when mail is sent
			var GetPmId = function()
			{
				window.new_location = MailPage.location.href;

				if (window.old_location !== window.new_location)
				{
					clearInterval(check_if_pm_loaded);
					if (!create_new_pm)
					{
						localStorage.DanHTRBP_MailId = window.new_location.replace(/[^\d]/g, '');
					}
					window.old_location = undefined;
					window.new_location = undefined;
					MailPage.close();
				}
			};

			MailPage.document.getElementById('SubmitPostBtn_0').click();
		};

		return;
	}

	var MailPage = open('https://www.warzone.com/Discussion/?ID=' + localStorage.DanHTRBP_MailId);

	MailPage.onload = function()
	{
		MailPage.document.getElementById('TextArea_-1').value = msg;
		MailPage.document.getElementById('SubmitPostBtn_-1').click();
		MailPage.close();
	};
}

var ui =
{
	CallFocusedUIAction: function()
	{
		var DefaultAction = ui.focusedUiPopup;

		if (DefaultAction)
		{
			DefaultAction = DefaultAction.defaultAction;
		}
		if (typeof DefaultAction === 'function')
		{
			DefaultAction();
		}
	},
	CreateOverlay: function(zIndex)
	{
		var overlay = document.createElement('div');

		overlay.className = 'overlay';

		if (zIndex)
		{
			overlay.style.zIndex = zIndex;
		}

		overlay.onclick = function(){ui.CallFocusedUIAction();};

		document.body.appendChild(overlay);

		return overlay;
	},
	createOverlays: function()
	{
		try{
		//whole UI overlay
		if (document.getElementsByClassName('overlay').length === 0)
		{
			//if an overlay doesn't exist, create one and style it
			this.CreateOverlay();
		}

		document.getElementsByClassName('overlay')[0].id = 'mainOverlay';
		}catch(err){HandelErr(err);}
	},
	disableButtons: function()
	{
		try{
		var btns_that_can_be_disabled = document.getElementsByClassName('CanBeDisabled');
		var btn;
		var condition;

		for (var btns_that_can_be_disabled_counter = 0; btns_that_can_be_disabled_counter < btns_that_can_be_disabled.length; btns_that_can_be_disabled_counter++)
		{
			btn = btns_that_can_be_disabled[btns_that_can_be_disabled_counter];

			if (btns_that_can_be_disabled_counter === 0)
			{
				condition = true;
				//it's impossible to not have any players on the Blocklist
			}
			else if (btns_that_can_be_disabled_counter === 1)
			{
				condition = localStorage.threads.match(/,/);
			}
			else
			{
				condition = localStorage._threads.match(/,/);
			}

			if (condition)
			{
				btn.disabled = false;
				btn.style.cursor = "";
			}
			else
			{
				btn.disabled = true;
				btn.style.cursor = 'not-allowed';
			}
		}
		}catch(err){HandelErr(err);}
	},
	AddLayer: function(layerNo)
	{
		try{
		layerNo = 10001 + layerNo;

		this.CreateOverlay(layerNo);

		var new_layer = document.createElement('div');

		new_layer.className = 'SettingMenu';
		new_layer.style.zIndex = layerNo + 1;
		//ok and close popup this.AddEnterEvent(new_layer, );
		document.body.appendChild(new_layer);
		return new_layer;
		}catch(err){HandelErr(err);}
	},
	focusedUiPopup: undefined,
	canChangeFocusedUiPopup: true,
	popupThatWantsToBeShown: undefined,
	ShowLayer: function(ui_popup)
	{
		this.popupThatWantsToBeShown = ui_popup;//remember which popup to show after detecting a bug

		if (ui.canChangeFocusedUiPopup)
		{
			//in try-catch blocks, the report bug ui is sometimes taken out of focus
			this.focusedUiPopup = ui_popup;
		}

		ui_popup.previousElementSibling.style.display = 'block';
		ui_popup.style.display = 'block';

		if (window.onresize)
		{
			window.onresize();
		}
	},
	HideLayer: function(ui_popup_to_hide, ui_popup_to_show)
	{
		ui_popup_to_hide.style.display = "";
		ui_popup_to_hide.previousElementSibling.style.display = "";

		if (ui_popup_to_show === undefined)
		{
			ui_popup_to_show = document.getElementById('config_dan_userscript');
		}

		this.focusedUiPopup = ui_popup_to_show;
	},
	functions_to_call: false,
	keypressed: false,
	AddEnterEvent: function(element, function_to_call, preventDefault)
	{
		var main = function(e)
		{
			if (ui.keypressed)
			{
				//prevent spam enter
				return;
			}

			ui.keypressed = true;

			var key = e.which || e.keyCode;

			if (key === 13)
			{
				if (preventDefault)
				{
					e.preventDefault();
				}

				function_to_call();
				ui.keypressed = false;
			}
		};

		element.onkeypress = function(e){main(e);};
		element.onkeydown = function(e){main(e);};
	},
	AddFocus: function(input, popup)
	{
		input.focus();
		popup.onmouseenter = function()
		{
			input.focus();
		};
	},
	MsgBox: function(type, msg_txt, title_txt, layerNo, popup_to_focus)
	{
		try{
		var _ui = document.getElementById(type + '_ui');
		var title = document.getElementById(type + '_ui_title');
		var msg = document.getElementById(type + '_ui_msg');

		if (!title_txt)
		{
			title_txt = '';
		}
		if (!layerNo)
		{
			layerNo = 1;
		}

		if (!_ui)
		{
			_ui = this.AddLayer(layerNo);
			_ui.id = type + '_ui';

			title = document.createElement('h2');
			title.id = type + '_ui_title';

			msg = document.createElement('p');
			msg.id = type + '_ui_msg';

			var btn_container = document.createElement('div');

			btn_container.className = 'FlexContainer';

			Append([title, msg, btn_container], _ui);

			var call_function = function(function_no)
			{
				//calls functions after an input for a ui.Confirm or ui.Prompt has been submitted
				var function_array_instance = ui.functions_to_call[function_no];

				if (typeof ui.functions_to_call === 'function' && function_no === 0)
				{
					ui.functions_to_call();
				}
				else if (typeof function_array_instance === 'function')
				{
					function_array_instance();
				}
			};
			var yes_no_close_btns;

			if (type === 'confirm')
			{
				yes_no_close_btns = this.MakeBigBlueBtns(['Yes', 'No'], btn_container); 

				var yes_btn = yes_no_close_btns[0];

				yes_btn.className += ' Darkblue';
				yes_btn.onclick = function()
				{
					ui.HideLayer(_ui, popup_to_focus);
					call_function(0);
				};

				var no_btn = yes_no_close_btns[1];

				no_btn.className += ' Darkblue';
				no_btn.onclick = function()
				{
					ui.HideLayer(_ui, popup_to_focus);
					call_function(1);
				};

				_ui.defaultAction = function(){no_btn.click();};
			}
			else
			{
				var text_input = document.createElement('input');

				if (type === 'prompt')
				{
					text_input.type = 'text';
					btn_container.insertAdjacentElement('beforebegin', text_input);
				}

				yes_no_close_btns = this.MakeBigBlueBtns(['Close'], btn_container)[0];
				yes_no_close_btns.className += ' Darkblue';

				if (type === 'prompt')
				{
					var OkClicked = function()
					{
						_ui.value = text_input.value;
						ui.HideLayer(_ui);
						call_function(0);
					};

					yes_no_close_btns.innerHTML = 'OK';
					yes_no_close_btns.style.width = '100%';
					yes_no_close_btns.onclick = function()
					{
						OkClicked();
					};
					ui.AddEnterEvent(text_input, OkClicked, true);
					ui.AddFocus(text_input, _ui);
					_ui.defaultAction = (function(){text_input.focus();});
				}
				else
				{
					yes_no_close_btns.onclick = function(){ui.HideLayer(_ui);};
					_ui.defaultAction = function(){ui.HideLayer(_ui);};
				}
			}
		}
		else
		{
			if (type === 'prompt')
			{
				//reset the prompt's value;
				_ui.value = '';
				document.getElementById('prompt_ui_msg').nextElementSibling.value = '';
			}
		}
		//bring the ui to the front
		_ui.style.zIndex = 100002 + layerNo;
		_ui.previousElementSibling.style.zIndex = 100001 + layerNo;

		title.innerHTML = capitalise(title_txt);
		msg.innerHTML = msg_txt;

		this.ShowLayer(_ui);
		return _ui;
		}catch(err){HandelErr(err);}
	},
	Alert: function(msg_txt, title_txt, layerNo)
	{
		return this.MsgBox('alert', msg_txt, title_txt, layerNo);
	},
	AlertErr: function(msg_txt, title_txt)
	{
		if (!title_txt)
		{
			title_txt = '';
		}

		return this.Alert(msg_txt, title_txt, 999);
	},
	Confirm: function(msg_txt, functions_to_call, title_txt, layerNo, popup_to_focus)
	{
		ui.functions_to_call = functions_to_call;

		var confirmMsgBox = this.MsgBox('confirm', msg_txt, title_txt, layerNo, popup_to_focus);

		ui.focusedUiPopup = confirmMsgBox;
		ui.popupThatWantsToBeShown = confirmMsgBox;

		return confirmMsgBox;
	},
	Prompt: function(msg_txt, function_to_call, title_txt, layerNo)
	{
		ui.functions_to_call = function_to_call;
		return this.MsgBox('prompt', msg_txt, title_txt, layerNo);
	},
	CreateForm: function(keyName, container, mode)
	{
		var new_form = create('form', 0, 0, container);

		new_form.name = keyName + '_form';

		return new_form;
	},
	CreateCheckboxes: function(form, values, labels)
	{
		if (!labels)
		{
			labels = values;
		}	
		if (typeof values === 'string' && typeof labels === 'string')
		{
			//turn values and values into an array - easier for looping
			values = [values];
			labels = [labels];
		}
		else if (!Array.isArray(values) || !Array.isArray(labels))
		{
			return;
		}
		if (values.length !== labels.length)
		{
			return;
		}

		var all_checkboxes = [];
		var label;
		var input;
		var input_value;

		for (var n = 0; n < values.length; n++)
		{
			label = document.createElement('label');
			input = document.createElement('input');
			input_value = values[n];

			label.htmlFor = input_value;
			label.innerHTML = labels[n] + '&nbsp;';
			input.type = 'checkbox';
			input.value = input_value;
			input.id = input_value;

			Append([label, input, document.createElement('br')], form);

			all_checkboxes.push(input);
		}

		return all_checkboxes;
	},
	CreateInputs: function(keyName, form, mode, what_to_add_remove, players_add_type)
	{
		try{
		var local_storage_items_list = localStorage.getItem(keyName).split(',');
		var local_storage_item;
		var remove = mode === 'remove';
		var label;
		var input;
		var spacer;
		var listing_threads = keyName !== 'Players';

		if (remove)
		{
			for (var i = 0; i < local_storage_items_list.length; i++)
			{
				if (!(listing_threads && i === 0))
				{
					//first item for threads and _threads is an item that shouldn't be removed because if it was removed then all threads would be hidden
					local_storage_item = local_storage_items_list[i];

					label = document.createElement('label');
					label.htmlFor = local_storage_item;

					if (keyName === 'Players')
					{
						//link the player
						label.innerHTML = '<a href = "https://www.warzone.com/profile?p=' + ConvertPlayerIdToPlayerNumber(local_storage_item) + '">' + local_storage_item + ' - ' + ConvertPlayerIdToPlayerName(local_storage_item) + '</a>';
					}
					else
					{
						label.innerHTML = local_storage_item;
					}

					label.innerHTML += '&nbsp;';

					input = document.createElement('input');
					input.type = 'checkbox';
					input.id = local_storage_item;
					input.value = local_storage_item;

					spacer = document.createElement('br');

					Append([label, input, spacer], form);
				}
			}
		}
		else
		{
			input = document.createElement('input');

			var placeholder_value = capitalise(what_to_add_remove);

			placeholder_value = placeholder_value.substring(0, placeholder_value.length - 1) + ' ';

			if (keyName === 'Players')
			{
				placeholder_value += players_add_type;
			}
			else
			{
				placeholder_value += 'subject';
			}

			input.type = 'text';
			input.name = 'add_threads_new_thread_input';
			input.placeholder = placeholder_value + '...';

			var playerDataList;
			var playerData = player_data;

			if (keyName === 'Players')
			{
				//suggests players - can't do player links accurately
				playerDataList = document.createElement('datalist');

				if (players_add_type === 'name')
				{
					playerData = playerData.names;
					input.setAttribute('list', 'playernames');
					playerDataList.id = 'playernames';
				}
				else if (players_add_type === 'id')
				{
					playerData = playerData.ids;
					input.setAttribute('list', 'playerids');
					playerDataList.id = 'playerids';
				}

				playerDataList.style.display = 'none';//some browsers don't support datalist
				playerDataList.innerHTML = TurnPlayerDataToDataListOptions(playerData);
			}

			var add_another_btn = this.CreateOkBtn(form);

			add_another_btn.value = 'Add another';
			add_another_btn.onclick = function()
			{
				ui.ValidateThreadOrPlayerInput(input, keyName, 0, players_add_type);
			};
			ui.AddEnterEvent(input, function()
			{
				ui.ValidateThreadOrPlayerInput(input, keyName, 0, players_add_type);
			}, true);

			form.appendChild(input);

			if (playerDataList)
			{
				form.appendChild(playerDataList);
			}

			Append([document.createElement('br'), add_another_btn, document.createElement('br')], form)
		}

		return input;
		}catch(err){HandelErr(err);}
	},
	GetCheckedItems: function(form)
	{
		try{
		var checked_items = [];
		var form_children = form.children;
		var form_child;

		for (var form_child_counter = 0; form_child_counter < form_children.length; form_child_counter++)
		{
			form_child = form_children[form_child_counter];

			if (form_child.tagName === 'INPUT')
			{
				if (form_child.checked)
				{
					checked_items.push(form_child.value)
				}
			}
		}

		return checked_items;
		}catch(err){HandelErr(err);}
	},
	CreateOkBtn: function(form)
	{
		var btn = create('input', 0, 'OK', form);

		btn.type = 'button';

		return btn;
	},
	old_thread_or_player_input: false,
	ValidateThreadOrPlayerInput: function(input, keyName, done, players_add_type, callback)
	{
		var inputValue = input.value;
		var inputFromForm = false;

		if (inputValue)
		{
			inputFromForm = true;

			if (inputValue === '')
			{
				return;
			}
		}
		else
		{
			inputValue = input;
		}
		if (inputValue === undefined)
		{
			return;
		}
		if (!inputValue.match)
		{
			return;
		}
		if (typeof inputValue !== 'string')
		{
			throw inputValue + ' must be a string';
		}

		var is_multiple = config.isMultiple(localStorage.getItem(keyName), inputValue);

		if ((inputValue === this.old_thread_or_player_input || is_multiple) && done && inputFromForm)
		{
			input.value = '';
			return;
		}
		else if (is_multiple)
		{
			//if the thread or player is already added, prevent it from being added again
			var err_msg_txt = 'You ';

			if (keyName === '_threads')
			{
				err_msg_txt += 'are already hiding this thread';
			}
			else
			{
				var list_txt = 'Thread Exceptions';

				if (keyName === 'Players')
				{
					list_txt = 'Blocklist';
				}

				err_msg_txt += 'already have this ' + keyName.toLowerCase().substring(0, keyName.toLowerCase().length - 1) + ' on your ' + list_txt;
			}

			ui.AlertErr(err_msg_txt + '.');

			if (inputFromForm)
			{
				input.value = '';
			}
		}
		else if (inputValue.match(/,/) && keyName !== 'Players')
		{
			ui.AlertErr('Thread subjects aren\'t allowed to contain commas ",".');
		}
		else if (inputValue.match(/[^\d]/) && keyName === 'Players' && players_add_type === 'id')
		{
			ui.AlertErr('Player ids can only be numbers.');
		}
		else if (player_data.ids.indexOf(inputValue) === -1 && keyName === 'Players' && players_add_type === 'id')
		{
			requestNewPlayerIds([parseInt(inputValue)]);
		}
		else if (player_data.numbers.indexOf(inputValue) === -1 && keyName === 'Players' && players_add_type === 'number')
		{
			ui.AlertErr('Player name not found. Player name = ' + inputValue);
		}
		else if (!inputValue.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Profile?p=') + '\\d+', 'i')) && keyName === 'Players' && players_add_type === 'link')
		{
			ui.AlertErr('Invalid player URL.');
		}
		else
		{
			if (keyName === 'threads' || keyName === '_threads' || players_add_type === 'id')
			{
				addRemoveItemToFromStorage(keyName, inputValue, 'add');
			}
			else
			{
				if (players_add_type === 'link')
				{
					var TurnPlayerUrlToId = function()
					{
						var playerid;

						if (inputValue.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Profile?p=') + '\\d+', 'i')))
						{
							var player_numbers = inputValue.match(/\d/g);

							if (player_numbers)
							{
								playerid = player_numbers.toString().replace(/[^\d]/g, '');
								playerid = playerid.substring(2, playerid.length - 2);
							}
						}

						return playerid;
					};

					blocklist.CheckIfPlayerIdAlreadyEntered(TurnPlayerUrlToId());
				}
				else if (players_add_type === 'name')
				{
					var player_id = ConvertPlayerNameToPlayerId(inputValue);
					var profile_link = 'https://www.warzone.com/profile?p=' + ConvertPlayerIdToPlayerNumber(player_id);
					var check_if_player_id_alerdy_entered = function()
					{
						blocklist.CheckIfPlayerIdAlreadyEntered(player_id);
					};
					var get_other_player = function()
					{
						blocklist.addUsing.links();
					};

					ui.Confirm('Suggested player id is ' + player_id + '. Is this the player you wanted to hide posts from? Link to profile: ' + profile_link + '.', [check_if_player_id_alerdy_entered, get_other_player]);
				}
			}

			ui.old_thread_or_player_input = inputValue;

			if (inputFromForm)
			{
				input.value = '';
			}

			ui.disableButtons();//(un)disable buttons
		}

		if (typeof callback === 'function')
		{
			callback();
		}
	},
	AddRemoveMany: function(local_storage_item, what_to_add_remove, remove, layerNo, players_add_type, list)
	{
		try{
		if (list)
		{
			//predefines the players to add/remove
			if (Array.isArray(list))
			{
				if (remove)
				{
					var thingToRemove;

					for (var i = 0; i < list.length; i++)
					{
						thingToRemove = list[i];

						if (typeof thingToRemove !== 'string')
						{
							throw what_to_add_remove + ' must be a string';
						}

						addRemoveItemToFromStorage(local_storage_item, thingToRemove, 'remove');
					}

					return;
				}

				//can't use a standard loop encase there is an error in the input
				var CheckThreadOrPlayer = function(index)
				{
					var threadOrPlayerToAddRemove = list[index];

					if (index < list.length - 1)
					{
						ui.ValidateThreadOrPlayerInput(threadOrPlayerToAddRemove, local_storage_item, 1, players_add_type, (function(){CheckThreadOrPlayer(index + 1);}))
					}
					else if (index === list.length - 1)
					{
						return ui.ValidateThreadOrPlayerInput(threadOrPlayerToAddRemove, local_storage_item, 1, players_add_type);
					}
				};

				CheckThreadOrPlayer(0);
			}
			else
			{
				throw "list must be an array e.g. ['item1', 'item2', 'etc']";
			}
		}

		var remove_players = local_storage_item === 'Players';
		var remove_thread_exceptions = local_storage_item === 'threads';
		var remove_threads = local_storage_item === '_threads';

		var mode = 'add';
		var heading_lable = 'Enter';

		if (remove)
		{
			mode = 'remove';
			heading_lable = 'Select';
		}

		if (!layerNo)
		{
			layerNo = 1;
		}

		var _ui = document.getElementById(mode + '_' + local_storage_item + '_ui');

		if (_ui)
		{
			_ui.innerHTML = '';//empty the ui
		}
		else
		{
			_ui = this.AddLayer(layerNo);
			_ui.id = mode + '_' + local_storage_item + '_ui';
		}

		if (remove_players)
		{
			//the amount of players on the Blocklist can be too large when removing players so reset the height to allow overflow to be taken care with
			var remove_Players_uiStyle = document.getElementById('remove_Players_uiStyle');

			if (!remove_Players_uiStyle)
			{
				remove_Players_uiStyle = AddCss(['#remove_Players_ui', ['height', 'unset !important']])
				remove_Players_uiStyle[0].id = 'remove_Players_uiStyle';
			}
		}

		var ui_heading = document.createElement('h2');

		ui_heading.innerHTML = heading_lable + ' ' + capitalise(what_to_add_remove) + ' to ' + capitalise(mode);
		_ui.appendChild(ui_heading);

		var add_remove_form = this.CreateForm(local_storage_item, _ui, mode);
		var created_input = this.CreateInputs(local_storage_item, add_remove_form, mode, what_to_add_remove, players_add_type);
		var btn = this.CreateOkBtn(add_remove_form);

		btn.onclick = function()
		{
			if (remove)
			{
				ui.old_thread_or_player_input = false;

				var checked_items = ui.GetCheckedItems(add_remove_form);

				for (var checked_item_counter = 0; checked_item_counter < checked_items.length; checked_item_counter++)
				{
					addRemoveItemToFromStorage(local_storage_item, checked_items[checked_item_counter], 'remove');
				}
			}
			else
			{
				ui.ValidateThreadOrPlayerInput(add_remove_form.add_threads_new_thread_input, local_storage_item, 1, players_add_type);
			}

			ui.disableButtons();
			ui.HideLayer(_ui);
		};

		ui.AddFocus(created_input, _ui);
		_ui.defaultAction = function(){btn.click();};
		this.ShowLayer(_ui);
		return _ui;
		}catch(err){HandelErr(err);}
	},
	MakeBigBlueBtns: function(btn_lables, _ui, btn_ids)
	{
		try{
		var btn;
		var btns = [];

		for (var btn_label_counter = 0; btn_label_counter < btn_lables.length; btn_label_counter++)
		{
			btn = document.createElement('div');
			btn.innerHTML = btn_lables[btn_label_counter];
			btn.className = 'FlexContainer Flex3 Centered SettingsBtn';
			btns.push(btn);
		}

		Append(btns, _ui);
		return btns;
		}catch(err){HandelErr(err);}
	},
	CreateHTMLStringList: function(keyName)
	{
		try{
		var storage_item_split = localStorage.getItem(keyName).split(',');
		var storage_item_counter = 1;
		var item;
		var list_str = '<ul>';
		var getting_players = keyName === 'Players';

		if (getting_players)
		{
			storage_item_counter = 0;
		}

		for (storage_item_counter; storage_item_counter < storage_item_split.length; storage_item_counter++)
		{
			item = storage_item_split[storage_item_counter];
			list_str += '<li>';

			if (getting_players)
			{
				//link the player
				list_str += '<a href = "https://www.warzone.com/profile?p=' + ConvertPlayerIdToPlayerNumber(item) + '">' + item + ' - ' + ConvertPlayerIdToPlayerName(item) + '</a>';
			}
			else
			{
				list_str += item;
			}

			list_str += '</li>';
		}

		return list_str + '</ul>';
		}catch(err){HandelErr(err);}
	},
	show: function()
	{
		try{
		//because the UI is hidden before it's clicked. this renders the settings incorrectly, so open the ui then fix the rendering issue.
		document.getElementById('mainOverlay').style.display = 'block';
		document.getElementById('config_dan_userscript').style.display = 'block';

		if (window.onresize)
		{
			window.onresize();
		}

		this.disableButtons();
		}catch(err){HandelErr(err);}
	},
	hide: function()
	{
		try{
		document.getElementById('config_dan_userscript').removeAttribute('style');
		document.getElementById('mainOverlay').style.display = 'none';
		}catch(err){HandelErr(err);}
	},
	build: function()
	{
		try{
		var uistyle = AddCss(['.FlexContainer', ['display', 'flex', 0], '.FlexWrap', ['flex-wrap', 'wrap', 1], '.Flex3', ['flex', '3', 1], '.Flex4', ['flex', '4', 1], '.Centered', ['justify-content', 'center'], ['align-items', 'center'], ['text-align', 'center'], '.FlexColumn', ['flex-direction', 'column', 1], '.Darkblue', ['background-color', '#000080 !important'], '.SettingMenu', ['position', 'fixed'], ['top', '0'], ['right', '0'], ['bottom', '0'], ['left', '0'], ['margin', 'auto'], ['padding', '10px'], ['color', '#fff'], ['font', '16px sans-serif'], ['background-color', '#f00'], ['border', '2px solid #000'], ['border-radius', '5px'], ['z-index', '10001'], ['width', 'fit-content', 0], ['display', 'none'], ['overflow', 'auto'], '.SettingMenu ul', ['margin', '10px auto !important'], '#main_settings_container', ['overflow', 'auto'], ['margin-top', '5px'], '.SettingsRow', ['margin-top', '5px'], ['min-height', '80px'], '.AutoHeight', ['height', 'auto'], ['min-height', 'auto !important'], '.SettingsBtn', ['border', '2px solid #000'], ['border-radius', '5px'], ['color', '#d5ffd5'], ['background-color', '#00f'], ['cursor', 'pointer'], '.SettingsRow div', ['margin-right', '20px'], ['padding', '0 3px'], '.SettingsRow .SettingsBtn:last-child', ['margin-right', '0'], '.SettingsRow:first-child', ['margin-top', '0'], '.NoMargin', ['margin', '0 !important'], '.OntopOfSettings', ['z-index', '10003'], '[id $= "_ui_title"]', ['text-align', 'center']])[0];

		uistyle.id = 'uistyle';
		uistyle.className = 'Dan_Style';

		var overlayStyle = AddCss(['.overlay', ['display', 'none'], ['background', 'white none repeat scroll 0% 0%'], ['top', '0'], ['right', '0'], ['bottom', '0'], ['left', '0'], ['opacity', '0.5'], ['width', '100%'], ['height', '100%'], ['position', 'fixed'], ['z-index', '10000']])[0];

		overlayStyle.id = 'overlayStyle';
		overlayStyle.className = 'Dan_Style';

		var createdElements = create(['div', 'b', 'div'], 'config_dan_userscript', ['', 'Hide Threads and Replies (v ' + v + ')'], [document.body, 0]);
		var settings_container = createdElements[0];
		var settings_header = createdElements[1];
		var scroller = createdElements[2];
	
		settings_container.className = 'SettingMenu';
		settings_header.className = 'FlexContainer Centered';
		scroller.className = 'FlexContainer';

		var main_settings_container = document.createElement('div');

		main_settings_container.className = 'FlexContainer FlexColumn';
		main_settings_container.id = 'main_settings_container';
		scroller.appendChild(main_settings_container);

		var CreateRowContainer = function(use_auto_height)
		{
			var row_container = document.createElement('div');

			row_container.className = 'FlexContainer FlexWrap SettingsRow';

			if (use_auto_height)
			{
				row_container.className += ' AutoHeight';
				settings_container.appendChild(row_container);
			}
			else
			{
				main_settings_container.appendChild(row_container);
			}

			return row_container;
		};
		var CreateLabel = function(description, row_container)
		{
			var label = document.createElement('div');

			label.className = 'FlexContainer Flex4 Centered';
			label.innerHTML = capitalise(description) + ':';
			row_container.appendChild(label);

			return label;
		};
		var CreateSettingsBtns = function(labels, row_container, can_be_disabled, use_darkblue_background)
		{
			var btn;
			var btns = [];

			for (var btns_to_make_counter = 0; btns_to_make_counter < labels.length; btns_to_make_counter++)
			{
				btn = document.createElement('div');
				btn.className = 'FlexContainer Flex3 Centered SettingsBtn';

				if (btns_to_make_counter === labels.length - 1)
				{
					if (can_be_disabled)
					{
						btn.className += ' CanBeDisabled';
					}
				}
				if (use_darkblue_background)
				{
					btn.className += ' Darkblue';
				}

				btn.innerHTML = capitalise(labels[btns_to_make_counter]);

				if (btn.innerHTML.match(/remove/i))
				{
					btn.className += ' NoMargin';
				}

				btns.push(btn);
				row_container.appendChild(btn);
			}

			return btns;
		};

		//blocklist
		var blocklist_row = CreateRowContainer();

		CreateLabel('blocklist', blocklist_row);

		var blocklist_row_btns = CreateSettingsBtns(['view', 'add players', 'remove players'], blocklist_row, 1);

		blocklist_row_btns[0].onclick = function(){config.players.view();};
		blocklist_row_btns[1].onclick = function(){config.players.add();};
		blocklist_row_btns[2].onclick = function()
		{
			if (blocklist_row_btns[2].disabled)
			{
				return;
			}

			config.players.remove();
		};

		//thread exceptions
		var thread_exceptions_row = CreateRowContainer();

		CreateLabel('thread exceptions', thread_exceptions_row);

		var thread_exceptions_row_btns = CreateSettingsBtns(['view', 'add threads', 'remove threads'], thread_exceptions_row, 1);

		thread_exceptions_row_btns[0].onclick = function(){config.threads.view();};
		thread_exceptions_row_btns[1].onclick = function(){config.threads.add();};
		thread_exceptions_row_btns[2].onclick = function()
		{
			if (thread_exceptions_row_btns[2].disabled)
			{
				return;
			}

			config.threads.remove();
		};

		//hide threads
		var hide_threads_row = CreateRowContainer();

		CreateLabel('hidden threads', hide_threads_row);

		var hide_threads_row_btns = CreateSettingsBtns(['view', 'add threads', 'remove threads'], hide_threads_row, 1);

		hide_threads_row_btns[0].onclick = function(){config._threads.view();};
		hide_threads_row_btns[1].onclick = function(){config._threads.add();};
		hide_threads_row_btns[2].onclick = function()
		{
			if (hide_threads_row_btns[2].disabled)
			{
				return;
			}

			config._threads.remove();
		};

		//motw and ot
		var hide_other_threads_row = CreateRowContainer();

		CreateLabel('hide mOTW threads', hide_other_threads_row);

		var hide_motw_btn = CreateSettingsBtns([localStorage.MOTW.replace('0', 'no').replace('1', 'yes')], hide_other_threads_row)[0];

		hide_motw_btn.id = 'hide_motw_btn';
		hide_motw_btn.onclick = function(){config.ChangeMOTW();};

		var hide_ot_label = CreateLabel('hide OT threads', hide_other_threads_row);

		hide_ot_label.className = hide_ot_label.className.replace('4', '3');

		var hide_ot_btn = CreateSettingsBtns([localStorage.DanHTRBP_hidingOT.replace('0', 'no').replace('1', 'yes')], hide_other_threads_row)[0];

		hide_ot_btn.id = 'hide_ot_btn';
		hide_ot_btn.onclick = function(){config.ChangeHidingOT();};

		//[blank name] and ui
		var hide_blankname_ui_row = CreateRowContainer();
		var blankname_label = CreateLabel('hide [blank name] posts', hide_blankname_ui_row)

		blankname_label.innerHTML = blankname_label.innerHTML.replace('N', 'n');

		var hide_blankname_btn = CreateSettingsBtns([localStorage.DanHTRBP_hide_blank_name.replace('0', 'no').replace('1', 'yes')], hide_blankname_ui_row)[0];

		hide_blankname_btn.id = 'hide_blankname_btn';
		hide_blankname_btn.onclick = function(){config.ChangeHideBlankName();};

		var hide_ui_label = CreateLabel('hide uI', hide_blankname_ui_row);

		hide_ui_label.className = hide_ui_label.className.replace('4', '3');

		var hide_ui_btn = CreateSettingsBtns([localStorage.DanHTRBP_hidingUI.replace('0', 'no').replace('1', 'yes')], hide_blankname_ui_row)[0];

		hide_ui_btn.id = 'hide_ui_btn';
		hide_ui_btn.onclick = function(){config.ChangeHidingUI();};

		//hide/show threads and hide/show replies
		var hide_show_threads_replies_row = CreateRowContainer();
		var threads_label = CreateLabel('hide threads', hide_show_threads_replies_row);
		var threads_btn = CreateSettingsBtns([localStorage.DanHTRBP_hide_threads.replace('0', 'no').replace('1', 'yes')], hide_show_threads_replies_row)[0];

		threads_btn.id = 'threads_btn';
		threads_btn.onclick = function(){config.ChangeHideThreads();};

		var replies_label = CreateLabel('hide replies', hide_show_threads_replies_row);

		replies_label.className = replies_label.className.replace('4', '3');

		var replies_btn = CreateSettingsBtns([localStorage.DanHTRBP_hide_replies.replace('0', 'no').replace('1', 'yes')], hide_show_threads_replies_row)[0];

		replies_btn.id = 'replies_btn';
		replies_btn.onclick = function(){config.ChangeHideReplies();};

		//settings
		var settings_row = CreateRowContainer();
		var settings_row_btns = CreateSettingsBtns(['import settings', 'export settings', 'reset', 'update player data'], settings_row);

		settings_row_btns[0].onclick = function(){config.settings.Import();};
		settings_row_btns[1].onclick = function(){config.settings.Export();};
		settings_row_btns[2].onclick = function(){config.settings.Reset();};
		updatePlayerDataBtn = settings_row_btns[3];
		updatePlayerDataBtn.id = 'updatePlayerDataBtn';
		updatePlayerDataBtn.onclick = function(){blocklist.updatePlayerData()};
		

		//close and report bug
		var bottom_row = CreateRowContainer(1);
		var bottom_row_btns = CreateSettingsBtns(['report bug', 'close'], bottom_row, 0, 1);

		bottom_row.id = 'bottom_row';
		bottom_row_btns[0].onclick = function(){ReportBug();};
		bottom_row_btns[1].onclick = function(){ui.hide();};
		settings_container.defaultAction = function(){ui.hide();};

		var ResizeSettingsToFit = function()
		{
			scroller.style.height = 'unset';
			settings_container.style.height = 'unset';

			//settings_container.clientHeight creates extra whitespace when debugger isn't open and settings_container.clientHeight is correct when the debugger is open

			var settings_container_clientHeight = 2 + settings_container.clientHeight + 2;
			var height = 2 + 10 + settings_header.clientHeight + 5 + blocklist_row.clientHeight + 5 + thread_exceptions_row.clientHeight + 5 + hide_threads_row.clientHeight + 5 + hide_other_threads_row.clientHeight + 5 + hide_blankname_ui_row.clientHeight + 5 + settings_row.clientHeight + 5 + bottom_row.clientHeight + 10 + 2;

			//console.log('height = ' + height + '\nsettings_container_clientHeight = ' + settings_container_clientHeight + '\nwindow.innerHeight = ' + window.innerHeight);

			if (height > window.innerHeight)
			{
				height = settings_container_clientHeight;
			}

			var bottom_row_height = bottom_row.scrollHeight + 5;

			scroller.style.height = height - settings_header.scrollHeight - bottom_row_height - 20 + 'px';
			settings_container.style.height = height + 'px';

			//resize all other SettingsMenus
			var SettingMenus = document.getElementsByClassName('SettingMenu');
			var setting_menu;
			var setting_menu_height;
			var settings_menu_children;
			var settings_menu_child;
			var settings_menu_child_counter;

			for (var setting_menu_counter = 1; setting_menu_counter < SettingMenus.length; setting_menu_counter++)
			{
				setting_menu = SettingMenus[setting_menu_counter];
				setting_menu_height = 2 + 10 + 10 + 2;
				settings_menu_children = setting_menu.children;

				setting_menu.style.height = 'unset';

				for (settings_menu_child_counter = 0; settings_menu_child_counter < settings_menu_children.length; settings_menu_child_counter++)
				{
					settings_menu_child = settings_menu_children[settings_menu_child_counter];

					if (settings_menu_child.tagName === 'H2' || (settings_menu_child.tagName === 'DIV' && settings_menu_child_counter > 0) || settings_menu_child.tagName === 'P')
					{
						setting_menu_height += 10;
						//h2 and p has style of 10px bottom margin
						//all divs have 10 margin-top except for the first one
					}
					if (settings_menu_child.className.match(/SettingsBtn/))
					{
						setting_menu_height += 2 + 2;
						//SettingsBtn has a border of 2px in all directions
					}
					if (settings_menu_child.tagName === 'UL')
					{
						setting_menu_height += 10 + 10;
						//ul has margin of 10px top and bottom
					}

					setting_menu_height += settings_menu_child.clientHeight;
				}

				if (setting_menu_height < window.innerHeight)//if setting_menu_height too big, allow the overflow to become scrollable instead on not allowing the setting menu to not be scrollable
				{
					setting_menu.style.height = setting_menu_height + 'px';
				}
			}
		};

		window.onresize = function(){ResizeSettingsToFit();};
		}catch(err){HandelErr(err);}
	}
};

try{
document.body.onkeyup = function(e)
{
	var key = e.keyCode || e.which;

	if (key === 13 || key === 27)
	{
		//if enter or esc do default action
		ui.CallFocusedUIAction();
	}
};
}catch(err){HandelErr(err);}

function HandelErr(err, is_user_spotted_error)
{
	try{
	var errorTime = new Date().toGMTString();

	ui.canChangeFocusedUiPopup = false;
	console.log(err);

	var change_focus = function()
	{
		ui.canChangeFocusedUiPopup = true;
		ui.focusedUiPopup = ui.popupThatWantsToBeShown;
	};
	var report_bug = function()
	{
		var details = 'Page = ' + location.href + '.\nUser agent = ' + navigator.userAgent + '.\nScript version = ' + v + '.\nError = ' + err + '.\nStack trace:\n[code]' + err.stack + '[/code]\nwindow.player_data_time = ' + window.player_data_time + '.\nTime ran into error = ' + errorTime + '.';

		Mail(details);
		change_focus();
	};

	if (is_user_spotted_error)
	{
		report_bug();//no need to confirm to send a bug report if user spotted a bug
	}
	else
	{
		ui.Confirm('An error has occured on Hide Threads and Replies by Poster. Report the bug?', [report_bug, change_focus], '', 1001, ui.focusedUiPopup);
	}
	}catch(err2){console.log(err2);}
}

function ReportBug(msg)
{
	var err_msg;
	var cause_error = function()
	{
		try
		{
			if (err_msg.value)
			{
				msg = err_msg.value;
			}
			if (msg !== '')
			{
				throw msg;
			}
		}catch(err){HandelErr(err, 1);}
	};

	if (typeof msg === 'string')
	{
		cause_error();
	}
	else
	{
		err_msg = ui.Prompt('Enter the error you encountered below.', cause_error, '', 999);
	}
}

window.ReportBug = ReportBug;

var player_data;
window.updating_player_data = false;//have to use window prefix as XMLHttpRequest thinks that updating_player_data is a local variable instead of global

function player_dataAddIds()
{
	//in 2.3.0.5 no longer storing player ids by default - saving storage space
	if (!player_data.ids)
	{
		player_data.ids = [];
		player_data.numbers.forEach(function(number)
		{
			player_data.ids.push(number.substring(2, number.length - 2));
		});
	}
}

function GetSavedPlayerData(forceUpdate)
{
	try{
	var date = new Date();
	var month = date.getUTCMonth();
	var year = date.getUTCFullYear();
	var updatePlayerDataBtn = document.getElementById('updatePlayerDataBtn');
	var canUpdateVisual = forceUpdate && updatePlayerDataBtn;

	if (canUpdateVisual)
	{
		updatePlayerDataBtn.innerHTML = 'Updating...';
	}

	if (localStorage.DanHTRBP_player_data && !forceUpdate)
	{
		//if the date is over a month old, request the up to date player data
		var parsed_player_data = JSON.parse(localStorage.DanHTRBP_player_data);
		var parsed_player_data_date = parsed_player_data.date;

		if (month > parsed_player_data_date[0] || year > parsed_player_data_date[1])
		{
			window.updating_player_data = true;
		}
		else
		{
			player_data = parsed_player_data;
			player_dataAddIds();
		}
	}
	else
	{
		window.updating_player_data = true;//get the player data - same procedure as updating player data
	}

	console.log('window.updating_player_data = ' + JSON.stringify(window.updating_player_data));

	if (!window.updating_player_data)
	{
		window.player_data = player_data;
		window.player_data_time = date.toGMTString();
		return;
	}

	var xhttp = new XMLHttpRequest();

	if (xhttp)
	{
		xhttp.onreadystatechange = function()
		{
			if (this.readyState === 4 && this.status === 200)
			{
				window.xhttp = this;
				console.log(this);
				player_data = JSON.parse(this.responseText.split('StartPlayerData')[1].split('EndPlayerData')[0].replace(new RegExp(EscapeRegExpChars('\\&quot;'), 'g'), '"').replace(new RegExp(EscapeRegExpChars('&quot;'), 'g'), '"'));
				//wiki renders " as &quote;, not using own site because of cross-origin limitations
				
				player_data.date = [month, year];
				localStorage.DanHTRBP_player_data = JSON.stringify(player_data);
				player_dataAddIds();
				window.player_data = player_data;
				window.player_data_time = date.toGMTString();
				window.updating_player_data = false;
				console.log('updated player data');

				if (canUpdateVisual)
				{
					updatePlayerDataBtn.innerHTML = 'Updated';
				}

				localStorageChecks();

				//build settings ui - only isn't present when updating/getting player data 
				elementExists('config_dan_userscript', function()
				{
					ui.build();
					ui.createOverlays();
				});

				if (forceUpdate)
				{
					//update players
					PlayersToP();
					hideThreads();
					hideReplies();

					if (updatePlayerDataBtn)
					{
						updatePlayerDataBtn.innerHTML = capitalise('update player data');
					}
				}
			}
		};
		xhttp.open("GET", "https://www.warzone.com/wiki/User:DanWL60/playerdata", true);
		xhttp.send();
	}
	}catch(err){HandelErr(err);}
}

GetSavedPlayerData();

function ConvertPlayerData(data, return_player_name, ignore_errors)
{
	try{
	var modes = ['id to player name', 'name to player id'];
	var mode = modes[1];

	console.log('ignore_errors = ' + JSON.stringify(ignore_errors));

	if (!player_data)
	{
		if (!ignore_errors)
		{
			throw 'Trying to convert a player ' + mode + ' before player_data is defined - a refresh will fix this';
		}

		return 'unknown';
	}

	var array_to_find_data_index = player_data.names;
	var array_to_get_data_from = player_data.ids;

	if (return_player_name)
	{
		mode = modes[0];
		array_to_find_data_index = player_data.ids;
		array_to_get_data_from = player_data.names;
	}

	var index = array_to_find_data_index.indexOf(data);

	if (index === - 1)
	{
		if (!ignore_errors)
		{
			console.log("Data for converting this player's id or name to a player name or id is not currently available. Player details: " + data);
			requestNewPlayerIds([parseInt(data)]);
		}

		return 'unknown';
	}

	return array_to_get_data_from[index];
	}catch(err){HandelErr(err);}
}

function ConvertPlayerIdToPlayerNumber(playerid)
{
	return player_data.numbers[player_data.ids.indexOf(playerid)];
}

function ConvertPlayerIdToPlayerName(playerid, ignore_errors)
{
	return ConvertPlayerData(playerid, true, ignore_errors);
}

function ConvertPlayerNameToPlayerId(playername, ignore_errors)
{
	return ConvertPlayerData(playername, false, ignore_errors);
}

function TurnPlayerDataToDataListOptions(playerDataItem)
{
	try{
	if (!playerDataItem)
	{
		return;
	}

	var dataListOptionsHTML = '';

	for (var i = 0; i < playerDataItem.length; i++)
	{
		dataListOptionsHTML += '<option value = "' + playerDataItem[i] + '">';
	}

	return dataListOptionsHTML;
	}catch(err){HandelErr(err);}
}

function requestNewPlayerIds(requestedPlayerIds)
{
	try{
	var logError = function(){console.log('requestedPlayerIds must be an array of player ids in an number format.');};

	if (!Array.isArray(requestedPlayerIds))
	{
		return logError();		
	}

	requestedPlayerIds.forEach(function(playerId)
	{
		if (typeof playerId !== 'number' || isNaN(playerId))
		{
			return logError();
		}
	});

	var messagePlayerIds = function()
	{
		Mail('Support these ids:\n[code][ids]' + JSON.stringify(requestedPlayerIds) + '[\\ids][/code]');
	};

	ui.Confirm('Unsupported player ids detected. Do you want these ids to be supported?', messagePlayerIds);
	}catch(err){HandelErr(err);}
}

function fixBlank(object, newText, useLoop, object_start_num, updatePlayers)
{
	try{
	//makes blanked-out things visible globally by replacing the things' innerHTML with new text
	var ObjectHasBlankChar = function(object)
	{
		return object.innerHTML.match(/\uA0/gi) || object.innerHTML.match(/\uAD/gi) || object.innerHTML.match(/\u2DE/gi) || object.innerHTML.match(/\u00AD/gi) || object.innerHTML.match(/\u02DE/gi) || object.innerHTML.match(/\u1361/gi) || object.innerHTML.match(/\u1680/gi) || object.innerHTML.match(/\u180E/gi) || object.innerHTML.match(/\u2000/gi) || object.innerHTML.match(/\u2001/gi) || object.innerHTML.match(/\u2002/gi) || object.innerHTML.match(/\u2003/gi) || object.innerHTML.match(/\u2004/gi) || object.innerHTML.match(/\u2005/gi) || object.innerHTML.match(/\u2006/gi) || object.innerHTML.match(/\u2007/gi) || object.innerHTML.match(/\u2008/gi) || object.innerHTML.match(/\u2009/gi) || object.innerHTML.match(/\u200A/gi) || object.innerHTML.match(/\u200B/gi) || object.innerHTML.match(/\u202F/gi) || object.innerHTML.match(/\u205F/gi) || object.innerHTML.match(/\u2800/gi) || object.innerHTML.match(/\u3000/gi) || object.innerHTML.match(/\u3164/gi) || object.innerHTML.match(/\uFEFF/gi);
	};

	var FixBlankMain = function(object)
	{
		if (ObjectHasBlankChar(object))
		{
			if (object === document.getElementsByTagName('font'))
			{
				if (object.parentNode === "[object HTMLTableCellElement]" && object.innerHTML !== "WarLight Creator" && object.innerHTML !== "Script Creator")
				{
					object.innerHTML = newText;
				}
			}
			else
			{
				object.innerHTML = newText;
			}
			if (updatePlayers)
			{
				localStorageChecks();
				PlayersToP();
			}
		}
	};

	if (useLoop)
	{
		if (!object_start_num)
		{
			object_start_num = 0;
		}

		while (object_start_num < object.length)
		{
			FixBlankMain(object[object_start_num]);
			object_start_num++;
		}
	}
	else
	{
		FixBlankMain(object);
	}
	}catch(err){HandelErr(err);}
}

//required global vars
var	Players,
	threads,
	_threads;

function localStorageRemoveDublicates(key)
{
	//removes duplicates from localStorage
	try{
	var localStorageItem = localStorage.getItem(key);
	var localStorageItemValues = localStorageItem.split(',');
	var itemValue;
	var allReadItemValues = [];

	for (var valueNo = 0; valueNo < localStorageItemValues.length; valueNo++)
	{
		itemValue = localStorageItemValues[valueNo];

		if (allReadItemValues.indexOf(itemValue) === -1)
		{
			allReadItemValues.push(itemValue);
		}
	}

	localStorage.setItem(key, allReadItemValues.toString());
	}catch(err){HandelErr(err);}
}

var updating_settings_to_work_with_2point3 = false;
var blocklist =
{
	CheckIfPlayerIdAlreadyEntered: function(playerid)
	{
		if (!playerid)
		{
			return;
		}

		var all_player_ids = localStorage.Players.split(',');
		
		if (all_player_ids.indexOf(playerid) === -1)
		{
			addRemoveItemToFromStorage('Players', playerid, 'add');
		}
	},
	updatePlayerData: function()
	{
		GetSavedPlayerData(true);
	},
	addUsing:
	{
		links: function(links)
		{
			try{
			return ui.AddRemoveMany('Players', 'players', 0, 3, 'link', links);
			}catch(err){HandelErr(err);}
		},
		names: function(names)
		{
			try{
			return ui.AddRemoveMany('Players', 'players', 0, 3, 'name', names);
			}catch(err){HandelErr(err);}
		},
		ids: function(ids)
		{
			try{
			return ui.AddRemoveMany('Players', 'players', 0, 3, 'id', ids);
			}catch(err){HandelErr(err);}
		},
		BulkConvert: function(convert_from, convert_to)
		{
			try{
			var convert_txt = [];

			if (!convert_from)
			{
				convert_from = 0;
				convert_txt.push('Names');
			}
			else
			{
				convert_txt.push('Ids');
			}
			if (convert_to)
			{
				convert_txt.push('Names');
			}
			else
			{
				convert_to = 1;
				convert_txt.push('Ids');
			}

			var current_players_list = localStorage.Players.split(',');
			var current_player;
			var converted_player;
			var all_converted_players = [];
			var convert_names_to_ids = !convert_from && convert_to;
			var convert_ids_to_names = convert_from && !convert_to;

			console.log('convert_names_to_ids = ' + JSON.stringify(convert_names_to_ids));
			console.log('convert_ids_to_names = ' + JSON.stringify(convert_ids_to_names));

			for (var i = 0; i < current_players_list.length; i++)
			{
				current_player = current_players_list[i];

				if (!current_player)
				{
					//pre 2.3 had an extra comma at the end for players
					break;
				}

				if (convert_names_to_ids)
				{
					updating_settings_to_work_with_2point3 = true;

					if (current_player === '[blank name]')
					{
						localStorage.DanHTRBP_hide_blank_name = '1';
					}
					else
					{
						converted_player = ConvertPlayerNameToPlayerId(current_player, true);
					}
				}
				else if (convert_ids_to_names)
				{
					converted_player = ConvertPlayerIdToPlayerName(current_player, true);
				}

				all_converted_players.push(converted_player);//don't need to check that the converted player is there as this can be corrected later
			}

			var players_conversion_ui = document.getElementById('PlayersConversionUI');

			if (!players_conversion_ui)
			{
				players_conversion_ui = ui.AddLayer(1);
				players_conversion_ui.id = 'PlayersConversionUI';
				AddCss(['#PlayersConversionUI', ['height', 'unset !important']]);//makes the height overflow get detected correctly
			}

			var players_coversion_form = ui.CreateForm('players_conversion', players_conversion_ui);

			players_coversion_form.innerHTML = '<p>Tick which items have been INCORRECTLY converted.</p>';

			var players_container = document.createElement('div');

			players_container.style.display = 'flex';
			players_coversion_form.appendChild(players_container);

			var original_players_div = document.createElement('div');
			var original_players_list = current_players_list;

			if (localStorage.DanHTRBP_hide_blank_name && convert_names_to_ids)
			{
				var blank_name_index = current_players_list.indexOf('[blank name]');

				if (blank_name_index !== -1)
				{
					original_players_list.splice(blank_name_index, 1);
				}
			}

			original_players_div.style.marginRight = '1em';
			original_players_list_html = '<p>' + original_players_list.join('</p><p>') + '</p>';
			original_players_div.innerHTML = '<h2 class = "ui_title">' + convert_txt[0] + '</h2>' + original_players_list_html;
			players_container.appendChild(original_players_div);

			var converted_players_div = document.createElement('div');

			converted_players_div.id = 'converted_players_div';
			converted_players_div.innerHTML = '<h2 class = "ui_title">' + convert_txt[1] + '</h2>';
			players_container.appendChild(converted_players_div);

			AddCss(['#converted_players_div label', ['margin-bottom', '10px']]);//makes the text appear inline - uneven spacing from labels

			var converted_players_checkboxes = ui.CreateCheckboxes(converted_players_div, all_converted_players);
			var converted_players_checkboxes_length = converted_players_checkboxes.length;

			//automatically check the unknown player ids
			var current_checkbox;

			for (var i = 0; i < converted_players_checkboxes_length; i++)
			{
				current_checkbox = converted_players_checkboxes[i];

				if (current_checkbox.value === 'unknown')
				{
					current_checkbox.checked = true;
				}
			}

			var ok_btn = ui.CreateOkBtn(players_coversion_form);
			var UpdatePlayersAndHidePosts = function()
			{
				localStorage.Players = all_converted_players.toString();//remember the conversion
				updating_settings_to_work_with_2point3 = false;
				ui.HideLayer(players_conversion_ui);
				document.getElementById('mainOverlay').style.zIndex = '1000';//conversion ui changed mainOverlay to have z-index of 10002 - needs to be reduced to allow the main settings ui to become clickable

				//hide posts
				localStorageChecks();

				//build settings ui - only isn't present when updating/getting player data
				elementExists('config_dan_userscript', function()
				{
					ui.build();
					ui.createOverlays();
				});

				PlayersToP();
				hideThreads();
				hideReplies();
				CreateUIForSubForumsAllForumsMailAndClanForum();
				CreateAddToBlocklistBtnOnProfile();
				CreateAddToThreadExceptionsHiddenThreadsOnThread();
			};
			var ModifyConversion = function(suggested_player, original_player, counter)
			{
				var enter_correct_ui;
				var main = function()
				{
					var correct_conversion = enter_correct_ui.value;

					//checking for errors is too complex given the way that I reinvented prompts - let's assume that the input was correct
					all_converted_players.splice(all_converted_players.indexOf(suggested_player), 1, correct_conversion);//replace suggested with user inputted

					var correct_conversion = enter_correct_ui.value;
					var cur_checkbox = converted_players_checkboxes[counter];

					cur_checkbox.id = correct_conversion;
					cur_checkbox.value = correct_conversion;
					cur_checkbox.checked = false;
					cur_checkbox.previousElementSibling.htmlFor = correct_conversion;
					cur_checkbox.previousElementSibling.innerHTML = correct_conversion + '&nbsp;';

					if (counter === converted_players_checkboxes_length - 1)
					{
						return UpdatePlayersAndHidePosts();//wait until all names have been converted before updating players then hide posts
					}

					EvaluateCheckbox(counter + 1);
				};

				enter_correct_ui = ui.Prompt('The original player was ' + original_player + '. The suggested conversion was ' + suggested_player + '. Enter the correct conversion.', main, '', 3);
			};
			var EvaluateCheckbox = function(counter)
			{
				//using a standard loop doesn't easily allow conversions to be done then go to the next checkbox
				counter = parseInt(counter);

				var current_checkbox = converted_players_checkboxes[counter];

				if (current_checkbox.checked)
				{
					ModifyConversion(current_checkbox.value, original_players_list[counter], counter);
				}
				else if (counter < converted_players_checkboxes_length - 1)
				{
					EvaluateCheckbox(counter + 1);
				}
				else if (counter === converted_players_checkboxes_length - 1)
				{
					UpdatePlayersAndHidePosts();//wait until all names have been converted before updating players then hide posts
				}
			};

			ok_btn.onclick = function()
			{
				EvaluateCheckbox(0);//go though all the checkboxes, if checked prompt user and let them enter the player id
			};

			players_conversion_ui.defaultAction = function(){ok_btn.click();};
			ui.ShowLayer(players_conversion_ui);
			}catch(err){HandelErr(err);}
		},
		blacklist: function()
		{
			try{
			var blacklistPage = open('https://www.warzone.com/ManageBlackList');

			blacklistPage.onload = function()
			{
				var bl$ = blacklistPage.$;
				var blacklistedPlayerIds = [];
				var blacklistedPlayerId;
				var unsupportedIds = [];

				//get all lis with id beginning with ListItem_ and push the player id
				bl$('li').filter("[id ^= 'ListItem_']").each(function()
				{
					blacklistedPlayerId = bl$(this.id).selector.replace(/[^\d]/g, '');
					
					if (player_data.ids.indexOf(blacklistedPlayerId) > -1)
					{
						if (p.indexOf(blacklistedPlayerId) === -1)
						{
							//prevent adding player ids that aren't there and prevent re-adding player that are already added
							blacklistedPlayerIds.push(blacklistedPlayerId);
						}
					}
					else
					{
						unsupportedIds.push(parseInt(blacklistedPlayerId));
					}
				});
				ui.AddRemoveMany('Players', 'players', 0, 3, 'id', blacklistedPlayerIds);

				if (Array.isArray(unsupportedIds))
				{
					requestNewPlayerIds(unsupportedIds);
				}

				blacklistPage.close();
			}
			}catch(err){HandelErr(err);}
		}
	},
	remove: function(playersToRemove)
	{
		try{
		ui.AddRemoveMany('Players', 'players', 1, 1, undefined, playersToRemove);
		}catch(err){HandelErr(err);}
	}
};

//check localStorage for players and threads
function localStorageChecks()
{
	try{
	//many use of checking the type due to using binary values as strings. '0' is the same as false... yes and no values in settings were replaced with 1 and 0 in 2.3.0.0 to make checking if settings are enabled easier.
	//localStorage.DanHTRBP_hide_blank_name became an independent setting in 2.3.0.0 - before it was stored in players. Players on the Blocklist have to be numbers only.

	if (['0', '1'].indexOf(localStorage.DanHTRBP_hide_blank_name) === -1)
	{
		localStorage.DanHTRBP_hide_blank_name = '0';
	}
	
	if (typeof localStorage.Players !== 'string' || localStorage.Players === '')
	{
		localStorage.Players = '143539,717609';
		localStorage.DanHTRBP_hide_blank_name = '1';
	}
	else
	{
		//if [blank name] is being used, prevent loads of random [blank name]s from appearing
		if (localStorage.Players.match(/\[blank name\]/))
		{
			localStorage.Players = localStorage.Players.replace(localStorage.Players.match(/\[blank name\],/), '').replace(localStorage.Players.match(/\[blank name\]/g), '');
			localStorage.DanHTRBP_hide_blank_name = '1';
		}

		if (localStorage.Players.substring(localStorage.Players.length - 1, localStorage.Players.length) === ',' && !window.updating_player_data)
		{
			//2.3.0.0 changed the last character to not be a comma - before a comma had to be added at the end
			console.log('using pre 2.3 settings and not getting/updating player_data');
			localStorage.Players = localStorage.Players.substring(0, localStorage.Players.length - 1);
			blocklist.addUsing.BulkConvert(0);//turns the stored player names to player ids then remembers the correctly converted values
		}
		localStorageRemoveDublicates('Players');
	}

	Players = localStorage.Players.split(',');

	console.log('Currently hiding threads and replies by ' + Players);

	//thread exceptions
	if (typeof localStorage.threads !== 'string')
	{
		localStorage.threads = 'localStorage.threads_first-item(do_not_remove_this)';//prevents visual UI bugs
	}
	else
	{
		localStorageRemoveDublicates('threads');

		if (!localStorage.threads.match('localStorage.threads_first-item(do_not_remove_this)'))
		{
			localStorage.threads = 'localStorage.threads_first-item(do_not_remove_this),' + localStorage.threads;
		}
	}

	threads = localStorage.threads.split(',');

	//hidden threads
	if (typeof localStorage._threads !== 'string')
	{
		localStorage._threads = 'localStorage._threads_first-item(do_not_remove_this)';
	}
	else
	{
		localStorageRemoveDublicates('_threads');

		if (!localStorage._threads.match('localStorage._threads_first-item(do_not_remove_this)'))
		{
			localStorage._threads = 'localStorage._threads_first-item(do_not_remove_this),' + localStorage._threads;
		}
	}

	_threads = localStorage.getItem('_threads').split(',');

	//show/hide OT threads
	if (localStorage.DanHTRBP_hidingOT === 'no')
	{
		localStorage.DanHTRBP_hidingOT = '0';
	}
	else if (localStorage.DanHTRBP_hidingOT === 'yes')
	{
		localStorage.DanHTRBP_hidingOT = '1';
	}
	else if (['0', '1'].indexOf(localStorage.DanHTRBP_hidingOT) === -1)
	{
		localStorage.DanHTRBP_hidingOT = '0';
	}

	console.log('localStorage.DanHTRBP_hidingOT = ' + localStorage.DanHTRBP_hidingOT);

	//MOTW
	if (localStorage.MOTW === 'no')
	{
		localStorage.MOTW = '0';
	}
	else if (localStorage.MOTW === 'yes')
	{
		localStorage.MOTW = '1';
	}
	else if (['0', '1'].indexOf(localStorage.MOTW) === -1)
	{
		localStorage.MOTW = '0';
	}

	console.log('localStorage.MOTW = ' + localStorage.MOTW);

	if (localStorage.bpDialogue)
	{
		//discontinued blank posts messages
		RemoveLocalStorageItem('bpDialogue');
	}

	//ability to hide UI elements
	if (localStorage.DanHTRBP_hidingUI === 'no')
	{
		localStorage.DanHTRBP_hidingUI = '0';
	}
	else if (localStorage.DanHTRBP_hidingUI === 'yes')
	{
		localStorage.DanHTRBP_hidingUI = '1';
	}
	else if (['0', '1'].indexOf(localStorage.DanHTRBP_hidingUI) === -1)
	{
		localStorage.DanHTRBP_hidingUI = '0';
	}

	console.log('localStorage.DanHTRBP_hidingUI = ' + localStorage.DanHTRBP_hidingUI);

	//ability to hide threads - new in 2.3.0.0
	if (['0', '1'].indexOf(localStorage.DanHTRBP_hide_threads) === -1)
	{
		localStorage.DanHTRBP_hide_threads = '0';
	}

	//ability to hide replies - new in 2.3.0.0
	if (['0', '1'].indexOf(localStorage.DanHTRBP_hide_replies) === -1)
	{
		localStorage.DanHTRBP_hide_replies = '1';
	}

	//create UI display
	var	nextSelector;
	var	newNextSelector = '#HiddenThreadsRow td:nth-last-child(2)';
	var	isAllF = location.pathname.match(/\/forum\/forum/i);

	if (isAllF)
	{
		nextSelector = '#HiddenThreadsRow td:nth-last-child(2)';
		newNextSelector = '#HiddenThreadsRow td:nth-last-child(3)';
	}

	var uiDisplay = AddCss(['.PlayersTD, .ThreadExceptionsTD, .UIElement, #HiddenThreadsRow td:last-child, ' + nextSelector, ['display', 'table-cell'], newNextSelector, ['border-top-right-radius', '0px']])[0];

	if (localStorage.DanHTRBP_hidingUI === '0')
	{
		uiDisplay.innerHTML = uiDisplay.innerHTML.replace(/none/g, 'table-cell').replace('8px', '0px');
	}
	else
	{
		uiDisplay.innerHTML = uiDisplay.innerHTML.replace(/table-cell/g, 'none').replace('0px', '8px');
	}

	uiDisplay.id = 'uiDisplay';
	uiDisplay.className = 'Dan_Style';
	}catch(err){HandelErr(err);}
}

localStorageChecks();//perform the checks
//some required global variables
var h = location.href,
	genF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/f1'), 'i')),
	mapF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/f4'), 'i')),
	ladF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/f5'), 'i')),
	progF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/f6'), 'i')),
	helpF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/f7'), 'i')),
	OTF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/f8'), 'i')),
	clansF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/f9'), 'i')),
	stratF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/f10'), 'i')),
	subForum = genF || mapF || ladF || progF || helpF || OTF || clansF || stratF,
	allF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/forum'), 'i')),
	threadP =  h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Forum/') + '\\d', 'i')),
	discussionP = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Discussion/?ID=') + '\\d', 'i')),
	mail =  h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Discussion/MyMail'), 'i')),
	clanF = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/Clans/Forum'), 'i')),
	onProfile = h.match(new RegExp(EscapeRegExpChars('https://www.warzone.com/profile?p=') + '\\d', 'i'));

if (stratF && genF)
{
	//fixes bug that makes the script think your currently on the general forum when your actually on the strategy forum
	genF = false;
}

//prevents certain people from using all features
function isInvalidUser()
{
	return IsUser([5614353942, 9071760924, 3085172703]);
}
if (isInvalidUser())
{
	throw new Error();
}

var PlayersNo = 0,
	threadsNo = 0,
	_threadsNo = 0;

//Players array to another array where Players[PlayersNo] is a single var
var p;
var pNo = 0;

function PlayersToP()
{
	try{
	p = [];
	Players.forEach(function(player)
	{
		p.push(player);
	});
	}catch(err){HandelErr(err);}
}

PlayersToP();

//thread exceptions
var t;

//thread exceptions array to another array where threads[threadsNo] is a single var
function threadsToT()
{
	try{
	t = [];
	threads.forEach(function(thread)
	{
		t.push(thread);
	});
	}catch(err){HandelErr(err);}
}

threadsToT();

//hidden threads
var _t;

function _threadsTo_t()
{
	try{
	_t = [];
	_threads.forEach(function(thread)
	{
		_t.push(thread);
	});
	}catch(err){HandelErr(err);}
}

_threadsTo_t();

function fixThreadExceptionsBug()
{
	try{
	for (var i=threads.length-1; i>=0; i--)
	{
		t.splice(i, 1);
	}
	}catch(err){HandelErr(err);}
}

function addRemoveItemToFromStorage(keyName, item, mode, addingRemovingUsingPlayerName)
{
	try{
	console.log(mode + 'ing ' + item + ' to/from ' + keyName);
	if (!item)
	{
		return;
	}
	if (addingRemovingUsingPlayerName && keyName === 'Players')
	{
		item = ConvertPlayerNameToPlayerId(item.replace(' by ', ''));

		if (player_data.ids.indexOf(item) === -1 && mode === 'add')
		{
			//prevent adding unsupported player ids - allowing removing
			return requestNewPlayerIds([parseInt(item)]);
		}
	}

	if (mode !== 'add' && mode !== 'remove')
	{
		return;
	}
	if (mode === 'add')
	{
		localStorage.setItem(keyName, localStorage.getItem(keyName) + ',' + item);
	}
	else
	{
		if ((keyName === 'threads' && item === 'localStorage.threads_first-item(do_not_remove_this)') || (keyName === '_threads' && item === 'localStorage._threads_first-item(do_not_remove_this)'))
		{
			return;
		}

		localStorage.setItem(keyName, localStorage.getItem(keyName).replace(',' + item, ''));
	}

	localStorageChecks();

	var btn_class;
	var fullItemHTML = item;

	if (keyName === 'Players')
	{
		PlayersToP();
		btn_class = 'PlayerName';
		fullItemHTML = ' by ' + ConvertPlayerIdToPlayerName(item);
	}
	else if (keyName === 'threads')
	{
		btn_class = 'ThreadLink';
		threadsToT();
	}
	else if (keyName === '_threads')
	{
		_threadsTo_t();
	}

	if ((subForum || allF || clanF || mail) && btn_class)
	{
		//update buttons
		var currentShownBtnClassName = keyName;
		var currentHiddenBtnClassName = keyName;

		if (mode === 'add')
		{
			currentShownBtnClassName += 'H';
			currentHiddenBtnClassName += 'S';
		}
		else
		{
			currentShownBtnClassName += 'S';
			currentHiddenBtnClassName += 'H';
		}

		currentShownBtnClassName += 'Btn';
		currentHiddenBtnClassName += 'Btn';
		
		var btnUsedClassNames = document.getElementsByClassName(currentShownBtnClassName);
		var btnUnusedClassNames = document.getElementsByClassName(currentHiddenBtnClassName);
		var threadNameClass = document.getElementsByClassName(btn_class);
		var threadNameClassItem;

		for (var i = 0; i < threadNameClass.length; i++)
		{
			threadNameClassItem = threadNameClass[i];

			if (threadNameClassItem.innerHTML === fullItemHTML)
			{
				if (keyName === 'Players')
				{
					//make the thread visible
					threadNameClassItem.parentNode.parentNode.className = '';
					threadNameClassItem.parentNode.parentNode.removeAttribute('style');
				}

				//update the buttons
				btnUsedClassNames[i].style.display = 'none';
				btnUnusedClassNames[i].removeAttribute('style');
			}
		}
	}

	hideThreads();
	hideReplies();
	CreateAddToBlocklistBtnOnProfile();
	CreateAddToThreadExceptionsHiddenThreadsOnThread();
	console.log(mode + 'ed ' + item + ' to/from ' + keyName);
	}catch(err){HandelErr(err);}
}

var config =
{
	update: function()
	{
		try{
		localStorageChecks();

		if (allF && localStorage.DanHTRBP_hidingOT === '0')
		{
			//show OT threads and hide the downvoted OT threads
			OT.removeClassNames();
		}

		hideThreads();//if on forum, hide threads
		hideReplies();//if on forum post, hide replies
		}catch(err){HandelErr(err);}
	},
	ChangeBinValue: function(keyName, btnId)
	{
		try{
		var value = '1';
		var old_value = '0';
		var new_label = 'Yes';

		if (parseInt(localStorage.getItem(keyName)))
		{
			value = '0';
			old_value = '1';
			new_label = 'No';
		}

		localStorage.setItem(keyName, value);
		document.getElementById(btnId).innerHTML = new_label;
		console.log('changed ' + keyName + ' from ' + old_value + ' to ' + localStorage.getItem(keyName));
		config.update();
		}catch(err){HandelErr(err);}
	},
	ChangeHideBlankName: function()
	{
		config.ChangeBinValue('DanHTRBP_hide_blank_name', 'hide_blankname_btn');
	},
	ChangeMOTW: function()
	{
		config.ChangeBinValue('MOTW', 'hide_motw_btn');
	},
	ChangeHidingOT: function()
	{
		config.ChangeBinValue('DanHTRBP_hidingOT', 'hide_ot_btn');
	},
	ChangeHidingUI: function()
	{
		config.ChangeBinValue('DanHTRBP_hidingUI', 'hide_ui_btn');
	},
	ChangeHideThreads: function()
	{
		config.ChangeBinValue('DanHTRBP_hide_threads', 'threads_btn');
	},
	ChangeHideReplies: function()
	{
		config.ChangeBinValue('DanHTRBP_hide_replies', 'replies_btn');
	},
	settings:
	{
		Import: function(exported_settings)
		{
			try{
			var ImportSettings = function()
			{				
				var exported_settings_val = exported_settings.value;

				if (!exported_settings_val)
				{
					exported_settings_val = exported_settings;
				}

				var parsed_settings = JSON.parse(exported_settings_val);

				var setting_MOTW = parsed_settings[3];
				var setting_hidingUI = parsed_settings[4];
				var setting_hidingOT = parsed_settings[5];
				var setting_hideBlankName = parsed_settings[6];
				var setting_hideThreads = parsed_player_data_date[7];
				var setting_hideReplies = parsed_player_data_date[8];

				if (setting_MOTW !== '1' && setting_MOTW !== '0')
				{
					throw 'Error while importing settings: Invalid MOTW setting value - exported_settings = ' + _exported_settings;
				}
				else if (setting_hidingUI !== '1' && setting_hidingUI !== '0')
				{
					throw 'Error while importing settings: Invalid hiding UI setting value - exported_settings = '  + _exported_settings;
				}
				else if (setting_hidingOT !== '1' && setting_hidingOT !== '0')
				{
					throw 'Error while importing settings: Invalid hiding OT setting value - exported_settings = ' + _exported_settings;
				}
				if (typeof setting_hideBlankName === 'string')
				{
					if (setting_hideBlankName !== '1' && setting_hideBlankName !== '0')
					{
						throw 'Error while importing settings: Invalid hide blank name value - exported_settings = ' + _exported_settings;
					}
				}
				if (typeof setting_hideThreads === 'string')
				{
					if (setting_hideThreads !== '1' && setting_hideThreads !== '0')
					{
						throw 'Error while importing settings: Invalid hide threads value - exported_settings = ' + _exported_settings;
					}
				}
				if (typeof setting_hideReplies === 'string')
				{
					if (setting_hideReplies !== '1' && setting_hideReplies !== '0')
					{
						throw 'Error while importing settings: Invalid hide replies value - exported_settings = ' + _exported_settings;
					}
				}

				localStorage.Players = parsed_settings[0];
				localStorage.threads = parsed_settings[1];
				localStorage._threads = parsed_settings[2];
				localStorage.MOTW = setting_MOTW;
				localStorage.DanHTRBP_hidingUI = setting_hidingUI;
				localStorage.DanHTRBP_hidingOT = setting_hidingOT;
				localStorage.DanHTRBP_hide_blank_name = setting_hideBlankName;
				localStorage.DanHTRBP_hide_threads = setting_hideThreads;
				localStorage.DanHTRBP_hide_replies = setting_hideReplies;

				ui.Alert('Imported settings.');

				//update everything
				localStorageChecks();
				PlayersToP();
				threadsToT();
				_threadsTo_t();
				hideThreads();
				hideReplies();
			};

			if (exported_settings)
			{
				ImportSettings();
			}
			else
			{
				exported_settings = ui.Prompt('Paste exported settings here.', ImportSettings);
			}
			}catch(err){HandelErr(err);}
		},
		Export: function()
		{
			try{
			var exported_settings = [];

			exported_settings.push(localStorage.Players);
			exported_settings.push(localStorage.threads);
			exported_settings.push(localStorage._threads);
			exported_settings.push(localStorage.MOTW);
			exported_settings.push(localStorage.DanHTRBP_hidingUI);
			exported_settings.push(localStorage.DanHTRBP_hidingOT);
			exported_settings.push(localStorage.DanHTRBP_hide_blank_name);
			exported_settings.push(localStorage.DanHTRBP_hide_threads);
			exported_settings.push(localStorage.DanHTRBP_hide_replies);

			var exported_settings_txt = JSON.stringify(exported_settings);

			ui.Alert(exported_settings_txt, 'Current settings');
			console.log('Current settings:\n' + exported_settings_txt);
			}catch(err){HandelErr(err);}
		},
		Reset: function()
		{
			try{
			var reset_ui = document.getElementById('reset_ui');

			if (!reset_ui)
			{
				reset_ui = ui.AddLayer(1);
				reset_ui.id = 'reset_ui';

				var heading = document.createElement('h2');

				heading.id = 'reset_ui_title';
				heading.innerHTML = capitalise('reset');
				reset_ui.appendChild(heading);

				var description = document.createElement('p');

				description.innerHTML = 'Select items to reset.';
				reset_ui.appendChild(description);

				var reset_form = ui.CreateForm('reset', reset_ui);
				var checkboxes = ui.CreateCheckboxes(reset_form, ['Blocklist', 'Thread Exceptions', 'Hidden threads', 'Off-topic threads', 'Map of the Week threads', 'Hiding blank name posts', 'Hiding UI', 'Hide Threads', 'Hide Replies']);
				var reset_btn = ui.CreateOkBtn(reset_form);

				reset_btn.value = 'Reset & close';
				reset_btn.onclick = function()
				{
					//reset all the checked items then close
					if (checkboxes[0].checked)
					{
						RemoveLocalStorageItem('Players');
					}
					if (checkboxes[1].checked)
					{
						RemoveLocalStorageItem('threads');
					}
					if (checkboxes[2].checked)
					{
						RemoveLocalStorageItem('_threads');
					}
					if (checkboxes[3].checked)
					{
						RemoveLocalStorageItem('DanHTRBP_hidingOT');
					}
					if (checkboxes[4].checked)
					{
						RemoveLocalStorageItem('MOTW');
					}
					if (checkboxes[5].checked)
					{
						RemoveLocalStorageItem('DanHTRBP_hidingUI');
					}
					if (checkboxes[6].checked)
					{
						RemoveLocalStorageItem('localStorage.DanHTRBP_hide_blank_name');
					}
					if (checkboxes[7].checked)
					{
						RemoveLocalStorageItem('localStorage.DanHTRBP_hide_threads');
					}
					if (checkboxes[8].checked)
					{
						RemoveLocalStorageItem('localStorage.DanHTRBP_hide_replies');
					}

					//update everything
					localStorageChecks();
					PlayersToP();
					threadsToT();
					_threadsTo_t();

					if (allF && checkboxes[3].checked && localStorage.DanHTRBP_hidingOT === '0')
					{
						//show OT threads and hide the downvoted OT threads
						OT.removeClassNames();
					}

					hideThreads();//if on forum, hide threads
					hideReplies();//if on a thread, hide replies
					ui.disableButtons();//(un)disable buttons
					ui.HideLayer(reset_ui);
				};
				reset_ui.defaultAction = function(){reset_btn.click();};
			}

			ui.ShowLayer(reset_ui);
			}catch(err){HandelErr(err);}
		}
	},
	isMultiple: function(LSITEM, TEXT)
	{
		try{
		var	ObjectLS = LSITEM.split(',');

		for (var ObjectLSNo = 0; ObjectLSNo < ObjectLS.length; ObjectLSNo++)
		{
			if (TEXT === ObjectLS[ObjectLSNo])
			{
				return true;//prevent returning false if duplicate found
			}
		}

		return false;
		}catch(err){HandelErr(err);}
	},
	view: function(keyName)
	{
		var stored_item = localStorage.getItem(keyName);
		var msg_txt;

		if (stored_item.match(/,/) && keyName !== 'Players' || keyName === 'Players')
		{
			msg_txt = 'Currently ';

			if (keyName === 'threads')
			{
				msg_txt += 'not ';
			}

			msg_txt += 'hiding ';

			if (keyName === 'Players')
			{
				msg_txt += 'posts by ';
			}

			msg_txt += 'these ' + keyName.toLowerCase().replace('_', '') + ':' + ui.CreateHTMLStringList(keyName);
		}
		else
		{
			msg_txt = 'You ';

			if (keyName === '_threads')
			{
				msg_txt += 'are';
			}
			else
			{
				msg_txt += 'do';
			}

			msg_txt += "n't ";

			if (keyName === '_threads')
			{
				msg_txt += 'hiding any individual threads';
			}
			else
			{
				msg_txt += 'have any ' + keyName.toLowerCase() + ' on your ';

				if (keyName === 'Players')
				{
					msg_txt += 'Blocklist';
				}
				else
				{
					msg_txt += 'Thread Exceptions';
				}

			}

			msg_txt += '.';
		}

		ui.Alert(msg_txt);
	},
	players:
	{
		view: function()
		{
			try{
			config.view('Players');
			}catch(err){HandelErr(err);}
		},
		add: function()
		{
			try{
			var add_players_ui = document.getElementById('add_players_ui');

			if (!add_players_ui)
			{
				add_players_ui = ui.AddLayer(1);
				add_players_ui.id = 'add_players_ui';

				var btns = ui.MakeBigBlueBtns(['Add players via profile link', 'Add players via username', 'Add players via player id', 'Add players via Blacklist', 'Close'], add_players_ui);

				btns[0].onclick = function(){blocklist.addUsing.links();};
				btns[1].onclick = function(){blocklist.addUsing.names();};
				btns[2].onclick = function(){blocklist.addUsing.ids();};
				btns[3].onclick = function(){blocklist.addUsing.blacklist();};

				var close_btn = btns[4];

				close_btn.onclick = function(){ui.HideLayer(add_players_ui);};
				close_btn.className += ' Darkblue';

				AddCss(['#add_players_ui div', ['height', '30px'], ['margin-top', '10px'], ['padding', '0 3px'], '#add_players_ui div:first-child', ['margin-top', '0']]);
				add_players_ui.defaultAction = function(){close_btn.click();};
			}

			ui.ShowLayer(add_players_ui);
			}catch(err){HandelErr(err);}
		},
		remove: function()
		{
			blocklist.remove();
		}
	},
	threads:
	{
		view: function()
		{
			try{
			config.view('threads');
			}catch(err){HandelErr(err);}
		},
		add: function(threads)
		{
			try{
			ui.AddRemoveMany('threads', 'threads', 0, 1, undefined, threads);
			}catch(err){HandelErr(err);}
		},
		remove: function(threads)
		{
			try{
			ui.AddRemoveMany('threads', 'threads', 1, 1, undefined, threads);
			}catch(err){HandelErr(err);}
		}
	},
	_threads:
	{
		update: function()
		{
			try{
			localStorageChecks();//updates definition of _threads
			_threadsTo_t();//updates _t
			hideThreads();//refreshes threads
			CreateAddToThreadExceptionsHiddenThreadsOnThread();
			}catch(err){HandelErr(err);}
		},
		view: function()
		{
			try{
			config.view('_threads');
			}catch(err){HandelErr(err);}
		},
		add: function(threads)
		{
			try{
			ui.AddRemoveMany('_threads', 'threads', 0, 1, undefined, threads);
			}catch(err){HandelErr(err);}
		},
		remove: function(threads)
		{
			try{
			ui.AddRemoveMany('_threads', 'threads', 1, 1, undefined, threads);
			}catch(err){HandelErr(err);}
		},
		removeThread: function(thread)
		{
			try{
			localStorage.setItem('_threads', localStorage._threads.replace(',' + thread, ''));
			this.update();
			}catch(err){HandelErr(err);}
		}
	}
};

if (!window.updating_player_data)
{
	ui.build();
	ui.createOverlays();
}

//config script without using ui
window.configDan =
{
	blocklist:
	{
		addUsing:
		{
			links: blocklist.addUsing.links,
			names: blocklist.addUsing.names,
			ids: blocklist.addUsing.ids,
			blacklist: blocklist.addUsing.blacklist
		},
		remove: blocklist.remove,
		view: config.players.view,
		updatePlayerData: blocklist.updatePlayerData
	},
	threads:
	{
		exceptions:
		{
			add: config.threads.add,
			remove: config.threads.remove,
			view: config.threads.view
		},
		hidden:
		{
			add: config._threads.add,
			remove: config._threads.remove,
			view: config._threads.view
		}
	},
	change:
	{
		hideBlankName: config.ChangeHideBlankName,
		motw: config.ChangeMOTW,
		hidingOT: config.ChangeHidingOT,
		hidingUI: config.ChangeHidingUI,
		hideThreads: config.ChangeHideThreads,
		hideReplies: config.ChangeHideReplies
	},
	exportSettings: config.settings.Export,
	importSettings: config.settings.Import,
	resetSettings: config.settings.Reset,
	version: v
};

//main
var	sHT = document.createElement("button"),
	hT = document.createElement("button"),
	td1 = document.createElement("td"),
	settings_btn = document.createElement("a"),
	a = document.getElementsByTagName("a"),
	aNo = 0,
	f = document.getElementsByTagName("font"),
	fNo = 0,
	dhCN = document.getElementsByClassName('detail_hidden'),
	dsCN = document.getElementsByClassName('detail_shown'),
	dbCN = document.getElementsByClassName('detail_blank');

window.a = a;
window.dhCN = dhCN;
window.dsCN = dsCN;
window.dbCN = dbCN;

var ddM = document.getElementById('AccountDropDown');

if (ddM)
{
	ddM = ddM.nextElementSibling;
}

if (ddM)
{
	try{
	//create a settings button
	settings_btn.id = 'DansUserscriptBtn';
	settings_btn.innerHTML = "Dan's Userscript";
	settings_btn.className = 'dropdown-item';
	settings_btn.href = '#';
	settings_btn.onclick = function()
	{
		ui.show();
	};

	var settings_btn_divider = document.createElement('div');

	settings_btn_divider.className = 'dropdown-divider';

	//find the drop down divider an insert the settings btn before it
	TurnDOMArrayToNormalArray(ddM.children).forEach(function(ddM_child)
	{
		if (ddM_child.className === 'dropdown-divider')
		{
			return Append([settings_btn_divider, settings_btn], [ddM_child.nextElementSibling, settings_btn_divider], 'afterend');
		}
	});
	}catch(err){HandelErr(err);}
}

function setTheadClassNames()
{
	try{
	//this allows the jump to last page functionality to stay
	var aNo = 0;
	var curr_a;
	var curr_a_href;

	while (aNo < a.length)
	{
		curr_a = a[aNo];
		curr_a_href = curr_a.href;

		if (curr_a_href.match(/\/\Discussion\/\?ID=/i) || curr_a_href.match(/\/\Forum\/\d/i))
		{
			if (!curr_a_href.match(/\?Offset=\d/i) && !curr_a_href.match(/\&Offset=\d/i))
			{
				curr_a.className = 'ThreadLink';
			}
		}

		aNo++;
	}
	}catch(err){HandelErr(err);}
}

var ThreadLink = document.getElementsByClassName("ThreadLink");
window.ThreadLink = ThreadLink;

var TBL;

//styling info for hidden and unhidden threads
var detailShownRules = '';

if (allF || subForum || clanF || mail)
{
	detailShownRules = '-row';
}

var Hide_Show_Threads = AddCss(['.detail_hidden, .detail_blank, .OT_hidden', ['display', 'none !important'], '.detail_shown', ['display', 'table' + detailShownRules + ' !important'], '.OT_shown', ['display', 'table-row !important'], '.detail_shown .sub-forum, .detail_shown td[valign="middle"], .OT_shown .sub-forum, .OT_shown td[valign="middle"]', ['text-decoration', 'line-through'], '.detail_good', ['display', 'table-row !important'], ['text-decoration', 'none !important']])[0];

Hide_Show_Threads.id = 'Hide_Show_Threads';
Hide_Show_Threads.className = 'Dan_Style';

AddCss(['.round_btn', ['border-radius', '13px']])[0].className = 'Dan_Style';

//hides all-caps subjects
function hideAllCaps(ThreadLinkNo)
{
	try{
	var curr_thread_link = ThreadLink[ThreadLinkNo];

	curr_thread_link.parentElement.parentElement.className += 'detail_hidden';
	curr_thread_link.title = 'This thread has an all-caps subject';
	console.log('ThreadLink[' + ThreadLinkNo + '].innerHTML = ' + curr_thread_link.innerHTML);
	}catch(err){HandelErr(err);}
}

//vars required for UI and hide/show replies
var psttbls = [],
	psttbl = "",
	psttblNo = 0,
	cIds = [],
	cId = "",
	cIdsNo = 0;

//makes it possible to hide and show OT threads
var OT =
{
	buttonTd: document.createElement('td'),
	buttons:
	{
		hide: document.createElement('button'),
		show: document.createElement('button')
	},
	hidden: document.getElementsByClassName('OT_hidden'),
	shown: document.getElementsByClassName('OT_shown'),
	no: (function(){return OT.hidden.length-1;}),
	show: function()
	{
		try{
		OT.buttons.hide.style.display = 'none';

		console.log('OT.no() = ' + OT.no());
		while (OT.no() < OT.hidden.length && OT.no() >= 0)
		{
			OT.hidden[OT.no()].className = OT.hidden[OT.no()].className.replace('OT_hidden', 'OT_shown');
			console.log('unhid OT thread');
			OT.no = (function(){return OT.hidden.length-1;});
		}

		OT.buttons.show.style.display = 'block';
		if (OT.shown.length > 0)
		{
			if (OT.shown.length > 1)
			{
				OT.buttons.show.innerHTML = 'Hide ' + OT.shown.length + ' off-topic threads';
			}
			else
			{
				OT.buttons.show.innerHTML = 'Hide 1 off-topic thread';
			}
		}
		}catch(err){HandelErr(err);}
	},
	hide: function()
	{
		try{
		OT.buttons.show.style.display = 'none';

		var	subForumCN = document.getElementsByClassName('sub-forum'),
			subForumCNNo = 0,
			curr_subforum;

		//search through all threads
		while (subForumCNNo < subForumCN.length)
		{
			curr_subforum = subForumCN[subForumCNNo];

			if (curr_subforum.innerHTML.includes('Off-topic'))
			{
				//if the thread is in OT, hide it
				if (curr_subforum.parentNode.className.match(/OT_shown/g))
				{
					curr_subforum.parentNode.className = curr_subforum.parentNode.className.replace('OT_shown', 'OT_hidden');
				}
				else if (!curr_subforum.parentNode.className.match(/OT_hidden/g))
				{
					curr_subforum.parentNode.className += 'OT_hidden';
				}
				console.log('hid OT thread');
			}
			subForumCNNo++;
		}

		if (OT.hidden.length > 0)
		{
			if (OT.hidden.length > 1)
			{
				OT.buttons.hide.innerHTML = 'Show ' + OT.hidden.length + ' off-topic threads';
			}
			else
			{
				OT.buttons.hide.innerHTML = 'Show 1 off-topic thread';
			}
		}
		OT.buttons.hide.style.display = 'block';
		}catch(err){HandelErr(err);}
	},
	removeClassNames: function()
	{
		try{
		if (!allF)
		{
			return;
		}

		var ThreadLinkNo = 0;
		var thread_row;

		while (ThreadLinkNo < ThreadLink.length)
		{
			thread_row = ThreadLink[ThreadLinkNo].parentElement.parentElement;

			thread_row.className = thread_row.className.replace('OT_hidden', '').replace('OT_shown', '');
			console.log('removed OT thread class name');
			ThreadLinkNo++;
		}
		}catch(err){HandelErr(err);}
	}
};
OT.buttonTd.className = 'UIElement';
OT.buttons.hide.className = 'round_btn';
OT.buttons.hide.style.cursor = 'pointer';
OT.buttons.hide.onclick = function()
{
	OT.show();
	//to do: keep downvoted threads hidden
};

OT.buttons.show.className = 'round_btn';
OT.buttons.show.style.cursor = 'pointer';
OT.buttons.show.onclick = function()
{
	OT.hide();
};

//makes it possible to hide threads
function hideThreads()
{
	try{
	if (!(subForum || allF || clanF || mail))
	{
		return;
	}

	//sets thread class so that Jump to Last Page links aren't counted as threads
	setTheadClassNames();
	console.log('hiding threads');

	if (allF)
	{
		var	td = document.getElementsByTagName('td');
		var	tdNo = 0;
		var curr_td;

		while (tdNo < td.length)
		{
			curr_td = td[tdNo];
			//decide which tds are subforums
			if (curr_td.parentElement.parentElement.parentElement.className === 'table' && curr_td.children.length === 0 && !curr_td.innerHTML.match(/\d/) && curr_td.innerText !== '')
			{
				curr_td.className = 'sub-forum';
				//console.log('td[' + tdNo + '] is a sub-forum');
			}
			tdNo++;
		}	
	}

	//allows hiding threads from sub-forums
	if (allF)
	{
		if (localStorage.DanHTRBP_hidingOT === '1')
		{
				OT.hide();//hide the OT posts
				OT.buttonTd.removeAttribute('style');//show the show/hide buttons if not hiding OT posts
		}
		else
		{
			OT.buttonTd.style.display = 'none';//hide the show/hide buttons if not hiding OT posts
		}
	}
	else
	{
		OT.buttonTd.style.display = 'none';//hide the show/hide buttons if not hiding OT posts
	}

	var ThreadLinkNo = 0;
	var curr_ThreadLink;

	//hide all-caps
	var match_punctuation = function(curr_ThreadLink)
	{
		return curr_ThreadLink.innerText.match(/[\u2000-\u206F\u2E00-\u2E7F\\'!"#$%&()*+,\-.\/:;<=>?@\[\]^_`{|}~]/g);
	};
	var match_main = function(curr_ThreadLink)
	{
		var num_whitespace_matches = 0;

		if (curr_ThreadLink.innerText.match(/\s/))
		{
			num_whitespace_matches = curr_ThreadLink.innerText.match(/\s/g).length;
		}

		return curr_ThreadLink.innerText.match(/[A-Z]/g).length + num_whitespace_matches;
	};

	var current_ThreadLink_matches;
	var current_ThreadLink_matches_punctuation;

	while (ThreadLinkNo < ThreadLink.length)
	{
		curr_ThreadLink = ThreadLink[ThreadLinkNo];

		if (curr_ThreadLink.innerText.match(/[A-Z]/))
		{
			//console.log('found A-Z');
			current_ThreadLink_matches = match_main(curr_ThreadLink);
			current_ThreadLink_matches_punctuation = match_punctuation(curr_ThreadLink);

			if (curr_ThreadLink.innerText.length - 1 === current_ThreadLink_matches)
			{
				console.log('found all-caps thread');
				hideAllCaps(ThreadLinkNo);
			}
			else if (current_ThreadLink_matches_punctuation)
			{
				if (curr_ThreadLink.innerText.length - 1 === current_ThreadLink_matches + current_ThreadLink_matches_punctuation.length)
				{
					console.log('found all-caps thread');
					hideAllCaps(ThreadLinkNo);
				}
			}
		}

		fixBlank(curr_ThreadLink, '[blank subject]');

		ThreadLinkNo++;
	}

	var ThreadLinkNo = 0;
	var curr_f;
	var curr_p;
	var curr_d;

	while (ThreadLinkNo < ThreadLink.length)
	{
		//console.log('going through threads');
		curr_ThreadLink = ThreadLink[ThreadLinkNo];
		curr_f = curr_ThreadLink.nextElementSibling.nextElementSibling;
		curr_d = curr_ThreadLink.parentElement.parentElement;

		fixBlank(curr_f, ' by [blank name]', false, 0, true);

		pNo = 0;

		if (localStorage.DanHTRBP_hide_threads === '1')
		{
			while (pNo < p.length)
			{
				curr_p = ConvertPlayerIdToPlayerName(p[pNo]);

				//console.log(curr_f.innerHTML + " ===  by  + " + curr_p  + " = " + (curr_f.innerHTML === ' by ' + curr_p).toString());

				if (curr_f.innerHTML === ' by ' + curr_p || localStorage.DanHTRBP_hide_blank_name === '1' && curr_f.innerHTML === ' by [blank name]')
				{
					//hide threads by certain posters
					//console.log('curr_d.className = ' + curr_d.className);

					if (curr_d.className.match(/ detail_shown/))
					{
						console.log('matched " detail_shown"');
						curr_d.className = curr_d.className.replace(' detail_shown', ' detail_hidden');
					}
					else
					{
						//console.log('init');
						curr_d.className += ' detail_hidden';
					}

					if (curr_d.style.display === 'table-row')
					{
						curr_d.removeAttribute('style');
					}
					console.log('hid thread by ' + curr_p);
				}
				pNo++;
			}
		}

		if (localStorage.MOTW === '1')
		{
			//hide motw
			if (curr_ThreadLink.innerText.includes("Map of the week discussion: Week "))
			{
				if (curr_d.className.includes(' detail_shown'))
				{
					curr_d.className = curr_d.className.replace(' detail_shown', ' detail_hidden');
				}
				else
				{
					curr_d.className += ' detail_hidden';
				}
				curr_ThreadLink.title = 'Map of the Week is being hidden';
			}
		}
		else
		{
			if (curr_ThreadLink.innerText.includes('Map of the week discussion: Week '))
			{
				curr_d.className = curr_d.className.replace(' detail_hidden', '');
			}
		}
		ThreadLinkNo++;
	}

	var HideUnhideThreads = function(array)
	{
		var ThreadLinkNo = 0;
		var index;

		var dont_hide_thread = array === t;

		if (array.length > 1)
		{
			while (ThreadLinkNo < ThreadLink.length)
			{
				curr_ThreadLink = ThreadLink[ThreadLinkNo];
				curr_d = curr_ThreadLink.parentElement.parentElement;
				index = 0;

				while (index < array.length)
				{
					if (curr_ThreadLink.innerText.includes(array[index]))
					{
						if (dont_hide_thread)
						{
							if (!curr_d.className.includes(' detail_good'))
							{
								curr_d.className += ' detail_good';
								curr_ThreadLink.title = 'This thread is NOT being hidden';
							}
						}
						else
						{
							if (curr_d.className.includes(' detail_shown'))
							{
								curr_d.className = curr_d.className.replace(' detail_shown', ' detail_hidden');
							}
							else
							{
								curr_d.className += 'detail_shown';
							}
							curr_ThreadLink.title = 'This thread is being hidden';
						}
					}
					index++;
				}
				ThreadLinkNo++;
			}
		}
	};

	HideUnhideThreads(t);//thread exceptions
	HideUnhideThreads(_t);//hides individual threads

	hT.style.display = 'none';

	if (dhCN.length > 0)
	{
		if (dhCN.length > 1)
		{
			sHT.innerHTML = 'Show ' + dhCN.length + ' hidden threads';
		}
		else
		{
			sHT.innerHTML = 'Show 1 hidden thread';
		}
		sHT.style.display = 'block';
	}
	else
	{
		sHT.style.display = 'none';
	}
	console.log('hid threads');
	}catch(err){HandelErr(err);}
}

function showHiddenThreads()
{
	//makes it possible to show hidden threads
	try{
	console.log('showing hidden threads');

	var	dhNo = 0;
	var curr_dh;

	while (dhNo < dhCN.length)
	{
		curr_dh = dhCN[dhNo];

		if (curr_dh.className.includes('OT_hidden'))
		{
			curr_dh.style.display = 'table-row';
		}

		curr_dh.className = curr_dh.className.replace(' detail_hidden', ' detail_shown').replace('detail_hidden', 'detail_shown');
		dhNo = dhNo;
	}

	sHT.style.display = 'none';

	if (dsCN.length > 0)
	{
		if (dsCN.length > 1)
		{
			hT.innerHTML = 'Hide ' + dsCN.length + ' threads';
		}
		else
		{
			hT.innerHTML = 'Hide 1 thread';
		}
		hT.style.display = 'block';
	}
	else
	{
		hT.style.display = 'none';
	}
	console.log('shown hidden threads');
	}catch(err){HandelErr(err);}
}

function hideReplies()
{
	try{
	if (!(threadP || discussionP))
	{
		return;
	}
	if (localStorage.DanHTRBP_hide_replies === '0')
	{
		return;
	}

	var table_left_col;
	var table_left_col_child;
	var table_left_col_child_counter;
	var players = [];
	var player_account_num;
	var playerNo = 0;

	var aNo = 0;
	var curr_a;

	var tables = document.getElementsByTagName('table');
	var table_counter = 0;
	var table;

	while (table_counter < tables.length)
	{
		//get the post tables
		table = tables[table_counter];

		if (table.id.match(/PostTbl_/) && table.className.match(/region/))
		{
			psttbls.push(table);

			//get the player that posted the comment
			table_left_col = table.firstElementChild.children[1].firstElementChild.children;
			table_left_col_child_counter = 0;

			while (table_left_col_child_counter < table_left_col.length)
			{
				table_left_col_child = table_left_col[table_left_col_child_counter];

				if (table_left_col_child.tagName.toLowerCase() === 'a')
				{
					if (table_left_col_child.href.match(/\/Profile\?p=\d/))
					{
						if (localStorage.DanHTRBP_hide_blank_name == '1' && table_left_col_child.innerText === '[blank name]')
						{
							players.push('[blank name]');
						}
						else
						{
							player_account_num = table_left_col_child.href.split(/\/Profile\?p=/)[1];
							players.push(player_account_num.substring(2, player_account_num.length - 2));
						}
					}
				}
				table_left_col_child_counter++;
			}
		}
		table_counter++;
	}

	//hide main
	playerNo = 0;
	psttblNo = 0;

	var curr_psttbl;
	var player;

	while (playerNo < players.length)
	{
		curr_psttbl = psttbls[psttblNo];
		pNo = 0;

		while (pNo < p.length)
		{
			player = players[playerNo]
			if (player === (p[pNo]) || player === '[blank name]' && localStorage.DanHTRBP_hide_blank_name == '1')
			{
				if (curr_psttbl.className.match(/ detail_shown/))
				{
					curr_psttbl.className = curr_psttbl.className.replace(' detail_shown', ' detail_hidden');
				}
				else
				{
					curr_psttbl.className += ' detail_hidden';
				}
				console.log('hid post by ' + player);
			}
			pNo++;
		}
		playerNo++;
		psttblNo++;
	}
	psttblNo = 0;

	//hides show downvoted/hidden reply link if a player on the hide list has had their comment to be downvoted or hidden
	fNo = 0;
	pNo = 0;
	var curr_f;
	window.f = [];
	
	while (fNo < f.length)
	{
		curr_f = f[fNo];
		pNo = 0;

		while (pNo < p.length)
		{
			if (curr_f.innerHTML.includes('- downvoted') || curr_f.innerHTML.includes('- hidden') && curr_f.nextElementSibling.children[0].children[1].children[0].innerHTML.includes(p[pNo]))
			{
				curr_f.style.display = 'none';
			}
			pNo++;
		}
		fNo++;
	}

	hT.style.display = 'none';

	if (dhCN.length > 0)
	{
		if (dhCN.length > 1)
		{
			sHT.innerHTML = 'Show ' + dhCN.length + ' hidden replies';
		}
		else
		{
			sHT.innerHTML = 'Show 1 hidden reply';
		}
		sHT.style.display = 'block';
	}
	else
	{
		sHT.style.display = 'none';
	}
	}catch(err){HandelErr(err);}
}

function showHiddenReplies()
{
	try{
	var curr_psttbl;

	while (psttblNo < psttbls.length)
	{
		curr_psttbl = psttbls[psttblNo];
		curr_psttbl.setAttribute("class", curr_psttbl.className.replace(' detail_hidden', ' detail_shown'));
		psttblNo++;
	}

	sHT.style.display = 'none';

	if (dsCN.length > 0)
	{
		if (dsCN.length > 1)
		{
			hT.innerHTML = 'Hide ' + dsCN.length + ' replies';
		}
		else
		{
			hT.innerHTML = 'Hide 1 reply';
		}
		hT.style.display = 'block';
	}
	else
	{
		hT.style.display = 'none';
	}
	}catch(err){HandelErr(err);}
}

if (subForum || allF || clanF || mail)
{
	try{
	var _table = document.getElementsByTagName('table')[document.getElementsByTagName('table').length - 1];

	if (_table)
	{
		if (_table.childNodes[1])
		{
			if (_table.childNodes[1].childNodes[0])
			{
				//defines where the X threads/posts hidden should be
				TBL = _table.childNodes[1].childNodes[0];
			}
		}
	}

	//spam
	var spam = [25, 5, 5, 5, 5, 20, 5, 5];

	spam[8] = spam.reduce((function(total, number){return total + number;}));
	//spam order is: general, map development, ladder, programming, help, OT, clans, strategy, all

	/*if (subForum || allF)
	{
		var createdElements = create(['td', 'a'], 'spamTd', ['', 'Jump to non-spam threads'], [TBL, 0]);
		var jumpToNonSpamTd = createdElements[0];
		var jumpToNonSpamLink = createdElements[1];

		Append(jumpToNonSpamTd, jumpToNonSpamTd.previousElementSibling, 'beforebegin');

		var setJumpToEndOfSpamLinksDetails = function(pageCounter)
		{
			var pagesOfSpam = spam[pageCounter];

			if (!pagesOfSpam && pagesOfSpam !== 0)
			{
				return;
			}
		
			jumpToNonSpamLink.href = location.href.replace('#', '').replace(new RegExp(EscapeRegExpChars('?Offset=') + '.')) + '?Offset=' + (pagesOfSpam * 50);

			if (pagesOfSpam < 1)
			{
				jumpToNonSpamTd.style.display = 'none';
			}

			setJumpToEndOfSpamLinksDetails(pageCounter + 1);
		};

		setJumpToEndOfSpamLinksDetails(0);
	}*/

	//make reset and restore buttons
	if (TBL)
	{
		td1.id = 'btnTd';
		td1.className = 'UIElement';
		TBL.appendChild(td1);

		td1.parentNode.insertBefore(td1, td1.parentNode.childNodes[0]);

		sHT.className = 'round_btn';
		sHT.onclick = function()
		{
			showHiddenThreads();
		};
		sHT.style.cursor = 'pointer';
		td1.appendChild(sHT);

		hT.className = 'round_btn';
		hT.style.cursor = 'pointer';
		hT.onclick = function()
		{
			hideThreads();
		};

		td1.appendChild(hT);

		TBL.appendChild(OT.buttonTd);
		OT.buttonTd.parentNode.insertBefore(OT.buttonTd, OT.buttonTd.parentNode.children[1]);
		OT.buttonTd.appendChild(OT.buttons.hide);
		OT.buttonTd.appendChild(OT.buttons.show);
	}

	//makes blanked-out last post by players visible by changing the text to "by [blank name]"

	fixBlank(document.getElementsByTagName('span'), 'by [blank name]', true, 2);

	if (!updating_settings_to_work_with_2point3 && !window.updating_player_data)//don't hide threads while trying to correct invalid settings!
	{
		hideThreads();//hide threads straight away
	}
	}catch(err){HandelErr(err);}
}
else if (threadP || discussionP)
{
	try{
	var _table = document.getElementsByTagName("table")[document.getElementsByTagName("table").length - 2];

	if (_table)
	{
		if (_table.childNodes[1])
		{
			if (_table.childNodes[1].childNodes[0])
			{
				TBL = _table.childNodes[1].childNodes[0];
			}
		}
	}

	//turns blanked-out subjects to [blank subject] so that subject becomes visible
	fixBlank(f, '[blank subject]', true);
	fNo = 0;

	//makes reset and restore buttons
	if (TBL)
	{
		td1.id = 'btnTd';
		td1.className = 'UIElement';
		TBL.appendChild(td1);

		var btnTd = document.getElementById('btnTd');

		btnTd.parentNode.insertBefore(btnTd, btnTd.parentNode.childNodes[0]);

		sHT.className = 'round_btn';
		sHT.style.cursor = 'pointer';
		sHT.onclick = function()
		{
			showHiddenReplies();
		};
		td1.appendChild(sHT);

		hT.className = 'round_btn';
		hT.style.cursor = 'pointer';
		hT.onclick = function()
		{
			hideReplies();
		};
		td1.appendChild(hT);
	}

	//hide blank posts
	var pfds = [],
		pfd = '',
		pfdNo = 0,
		divNo = 0,
		div = document.getElementsByTagName('div'),
		curr_div;

	if (!document.getElementById('SubjectBox') && !location.pathname.includes('/Discussion/Notes'))
	{
		while (divNo < div.length)
		{
			curr_div = div[divNo];

			if (curr_div.id.includes('PostForDisplay') && curr_div.id != 'PostForDisplay_-1')
			{
				pfd = curr_div.id;
				pfds.push(pfd);
			}
			divNo++;
		}
		window.pfds = pfds;
	
		var curr_post_for_display;
		var edited_post_match;
		var tbl;
		var curr_post_for_displayMatchSpaces;
		var curr_post_for_displayIsOnlySpaces;

		while (pfdNo < pfds.length)
		{
			curr_post_for_display = document.getElementById(pfds[pfdNo]);
			edited_post_match = curr_post_for_display.innerHTML.match(/\s+<br><br><font class=\"text-muted\">Edited \d+\/\d+\/\d+ \d+:\d+:\d+.*\s+/);
			//"Edited 12/2/2017 18:13:45"
			curr_post_for_displayMatchSpaces = curr_post_for_display.innerHTML.match(/\s/g);

			if (curr_post_for_displayMatchSpaces)
			{
				curr_post_for_displayIsOnlySpaces = curr_post_for_display.innerHTML.length === curr_post_for_display.innerHTML.match(/\s/g).length;
			}

			if (curr_post_for_displayIsOnlySpaces || edited_post_match)
			{
				tbl = curr_post_for_display.parentNode.parentNode.parentNode.parentNode;

				if (edited_post_match)
				{
					if (curr_post_for_display.innerHTML.length === edited_post_match[0].length)
					{
						tbl.className = 'detail_blank';
					}
				}
				else
				{
					tbl.className = 'detail_blank';
				}
			}

			pfdNo++;
		}
		if (dbCN.length > 0)
		{
			if (dbCN.length === 1)
			{
				console.log('1 blank post was hidden.');
			}
			else if (dbCN.length > 1)
			{
				console.log(dbCN.length + ' blank posts were hidden.');
			}
		}
	}

	hideReplies();//hide replies straight away
	}catch(err){HandelErr(err);}
}
//remove extra Muli's Userscript menu - a script causes this bug to happen
setTimeout('try{document.getElementsByClassName("userscript-menu")[1].remove();} catch(err) {}',750);
setTimeout('try{document.getElementsByClassName("userscript-menu")[1].remove();} catch(err) {}',1250);
//UI
//show and hide clicked are for making it possible to show and hide the downvoted threads an unlimited amount of time
function showClicked()
{
	try{
	$('tr[data-hidden]').show();
	var show = document.getElementById("show");
	show.id = "hide";
	var hide = document.getElementById("hide");
	hide.innerHTML = hide.innerHTML.replace("Show", "Hide");
	hide.onclick = function()
	{
		hideClicked();
	};
	}catch(err){HandelErr(err);}
}

function hideClicked()
{
	try{
	$('tr[data-hidden]').hide();
	var hide = document.getElementById("hide");
	hide.id = "show";
	var show = document.getElementById("show");
	show.innerHTML = show.innerHTML.replace("Hide", "Show");
	show.onclick = function()
	{
		showClicked();
	};
	}catch(err){HandelErr(err);}
}

function FixHiddenThreadsRow()
{
	try{
	var htr = document.getElementById('HiddenThreadsRow');
	var show = htr.children[htr.children.length - 1].children[0];

	if (show)
	{
		show.id = 'show';
		show = document.getElementById('show');
		show.innerHTML = 'Show ' + show.innerHTML.replace('hidden', 'downvoted');
	}

	var td2to6 =
	[
		document.createElement('td'),
		document.createElement('td'),
		document.createElement('td'),
		document.createElement('td'),
		document.createElement('td'),
		document.createElement('td'),
		document.createElement('td')
	];
	if (allF)
	{
		if (userscripts.mulis())
		{
			//if Muli's script enabled, hidden threads row looks quite bad, so make it look nicer
			setTimeout('var htr = document.getElementById("HiddenThreadsRow");var td2to6 = [document.createElement("td"),	document.createElement("td"),	document.createElement("td"),	document.createElement("td"),	document.createElement("td"),	document.createElement("td"),	document.createElement("td")];/*end of vars*/htr.appendChild(td2to6[0]);htr.insertBefore(td2to6[0], htr.childNodes[2]);',3000);
		}
		else
		{
			//hidden threads row looks bad, so make it look nicer
			htr.appendChild(td2to6[0]);
			htr.insertBefore(td2to6[0], htr.childNodes[0]);
			htr.appendChild(td2to6[1]);
			htr.insertBefore(td2to6[1], htr.childNodes[2]);
			htr.appendChild(td2to6[2]);
			htr.insertBefore(td2to6[2], htr.children[htr.children.length-1]);
			show.parentElement.removeAttribute('colSpan');
			show.parentElement.style.textAlign = 'left';
		}
	}
	else
	{
		var tds = [document.createElement('td'), document.createElement('td'), document.createElement('td')];

		//console.log('htr.children.length = ' + htr.children.length);
		if (htr.children.length < 4)
		{
			htr.appendChild(tds[0]);
			htr.insertBefore(tds[0], htr.children[0]);
			htr.appendChild(tds[1]);
			htr.insertBefore(tds[1], htr.children[htr.children.length-1]);
			htr.appendChild(tds[2]);
			htr.insertBefore(tds[2], htr.children[htr.children.length-1]);
			show.parentElement.removeAttribute('colSpan');
			show.parentElement.style.textAlign = 'left';
		}
	}

	show.onclick = function()
	{
		showClicked();
	};
	}catch(err){HandelErr(err);}
}

function CreateUIForSubForumsAllForumsMailAndClanForum()
{
	if (subForum || allF || clanF || mail || threadP || discussionP)
	{
		//create UI for sub-forums, all forums, mail and clan forum (i.e. non-thread pages or non-discussion pages)
		try{
		var ActionsTh0 = document.createElement('th'),
			ActionsTh1 = document.createElement('th');

		if (!threadP && !discussionP)
		{
			//prevent the threads table container from overflowing
			var preventOverflowingThreadsTableStyle = document.getElementById('preventOverflowingThreadsTableStyle');

			if (!preventOverflowingThreadsTableStyle)
			{
				preventOverflowingThreadsTableStyle = AddCss(['div.container.p-4.mt-3.mb-5, div.container.p-4.mt-3.mb-5 > table, div.container.p-4.mt-3.mb-5 > table div:first-child', ['max-width', 'unset !important'], ['width', '100% !important'], 'span.text-muted', ['display', 'flex'], ['word-break', 'break-all !important'], ['flex-direction', 'column-reverse']])[0];
				preventOverflowingThreadsTableStyle.id = 'preventOverflowingThreadsTableStyle';
				preventOverflowingThreadsTableStyle.className = 'Dan_Style';
			}

			ActionsTh0.className = 'UIElement';
			ActionsTh0.innerHTML = 'Blocklist';
			ActionsTh0.style.cursor = 'pointer';
			ActionsTh0.onclick = function()
			{
				config.players.view();
			};
			ActionsTh1.className = 'UIElement';
			ActionsTh1.innerHTML = 'Thread Exceptions';
			ActionsTh1.style.cursor = 'pointer';
			ActionsTh1.onclick = function()
			{
				config.threads.view();
			};

			//different forum categories have different em and px sizes
			if (allF)
			{
				ActionsTh0.style.minWidth = '96px';
				ActionsTh0.style.maxWidth = '96px';
				ActionsTh1.style.minWidth = '163px';
				ActionsTh1.style.maxWidth = '163px';
			}
			else
			{
				ActionsTh0.style.minWidth = '3em';
				ActionsTh0.style.maxWidth = '3em';

				if (mail || clanF)
				{
					ActionsTh1.style.minWidth = '5em';
					ActionsTh1.style.maxWidth = '5em';
				}
				else
				{
					ActionsTh1.style.minWidth = '7em';
					ActionsTh1.style.maxWidth = '7em';
				}
			}

			var headings_row = ThreadLink[0].parentElement.parentElement.previousElementSibling;

			if (headings_row.tagName !== 'TR')
			{
				headings_row = headings_row.previousElementSibling;
			}

			headings_row.appendChild(ActionsTh0);
			headings_row.appendChild(ActionsTh1);

			//center the buttons that will be created and vertically align table date to the middle
			AddCss(['.PlayersTD, .ThreadExceptionsTD, .sub-forum', ['text-align', 'center'], '.table td', ['vertical-align', 'middle !important']])[0].className = 'Dan_Style';

			//add the Add and Remove buttons for the Blocklist and Thread Exceptions
			var ThreadLinkNo = 0;
			var curr_ThreadLink;
			var curr_d;
			var curr_f;
			var curr_s;
			var curr_blocklist;
			var curr_thread_exception;
			var PlayersTD;
			var PlayersHBtn;
			var PlayersSBtn;
			var shown_remove_from_blocklist_btn;
			var ThreadExceptionsTD;
			var ThreadExceptionsHBtn;
			var ThreadExceptionsSBtn;

			while (ThreadLinkNo < ThreadLink.length)
			{
				curr_ThreadLink = ThreadLink[ThreadLinkNo];
				curr_f = curr_ThreadLink.nextElementSibling.nextElementSibling;
				curr_d = curr_ThreadLink.parentElement.parentElement;

				if (allF)
				{
					curr_s = curr_d.children[4].children[1];
				}
				else if (mail)
				{
					curr_s = curr_d.children[2].children[1];
				}
				else
				{
					curr_s = curr_d.children[3].children[1];
				}

				PlayersTD = document.createElement('td');
				PlayersHBtn = document.createElement('button');
				PlayersSBtn = document.createElement('button');
				PlayersTD.className = 'PlayersTD';

				curr_d.appendChild(PlayersTD);

				PlayersHBtn.innerHTML = 'Add';
				PlayersHBtn.className = 'PlayersHBtn round_btn';
				PlayersSBtn.innerHTML = 'Remove';
				PlayersSBtn.className = 'PlayersSBtn round_btn';

				//decides if you get to see the hide posts or unhide posts by players button
				pNo = 0;
				shown_remove_from_blocklist_btn = false;

				//console.log('curr_f.innerText = ' + curr_f.innerText);
				while (pNo < p.length)
				{
					if (curr_f.innerText.replace(/ by /, '') === p[pNo])
					{
						PlayersHBtn.style.display = 'none';
						PlayersSBtn.style.display = 'table-row';
						shown_remove_from_blocklist_btn = true;
						
					}
					else if (!shown_remove_from_blocklist_btn)
					{
						PlayersHBtn.style.display = 'table-row';
						PlayersSBtn.style.display = 'none';
					}
					pNo++;
				}

				curr_blocklist = curr_d.children[curr_d.children.length - 1];

				curr_blocklist.appendChild(PlayersHBtn);
				curr_blocklist.appendChild(PlayersSBtn);

				ThreadExceptionsTD = document.createElement('td');
				ThreadExceptionsHBtn = document.createElement('button');
				ThreadExceptionsSBtn = document.createElement('button');

				ThreadExceptionsTD.className = 'ThreadExceptionsTD';

				curr_d.appendChild(ThreadExceptionsTD);

				ThreadExceptionsHBtn.innerHTML = 'Add';
				ThreadExceptionsHBtn.className = 'threadsHBtn round_btn';
				ThreadExceptionsSBtn.innerHTML = 'Remove';
				ThreadExceptionsSBtn.className = 'threadsSBtn round_btn';

				//decides if you get to see the add or remove a thread from thread exceptions
				if (curr_ThreadLink.title === 'This thread is NOT being hidden')
				{
					ThreadExceptionsHBtn.style.display = 'none';
					ThreadExceptionsSBtn.style.display = 'table-row';
				}
				else
				{
					ThreadExceptionsHBtn.style.display = 'table-row';
					ThreadExceptionsSBtn.style.display = 'none';
				}

				curr_thread_exception = curr_blocklist.nextElementSibling;
				curr_thread_exception.appendChild(ThreadExceptionsHBtn);
				curr_thread_exception.appendChild(ThreadExceptionsSBtn);
		
				curr_f.className = 'PlayerName';
				//curr_f.innerHTML = ' by 12345678901234567890123456789012345678901234567890';
				//curr_ThreadLink.innerHTML = '12345678901234567890123456789012345678901234567890';
				//curr_s.innerHTML = 'by 12345678901234567890123456789012345678901234567890';
				if (ActionsTh0.parentNode.childNodes[5].style.minWidth !== '468px')
				{
					if (curr_f.innerHTML.length + curr_s.innerHTML.length > 85)
					{
						//resize thread width to make the table look better
						//if thread poster name last replier length is greater than 85
						ActionsTh0.parentNode.childNodes[5].style.minWidth = '468px';
						ActionsTh0.parentNode.childNodes[5].style.maxWidth = '468px';
					}
				}
				ThreadLinkNo++;
			}
		}

		//assigning onclick using a normal loop doesn't work how it should, so using a function that makes each onclick for each type of button one at a time - this works how it should
		var DecideOnClickForBtn = function(btn_no, btn_for_what, mode, addingUsingPlayerName)
		{
			var btn;
			var btn_type;
			var btnClassName = btn_for_what;

			if (mode === 'add')
			{
				btnClassName += 'H';
			}
			else
			{
				btnClassName += 'S';
			}

			btnClassName += 'Btn';
			btn = document.getElementsByClassName(btnClassName)[btn_no];

			if (btn_for_what === 'Players')
			{
				btn_type = document.getElementsByClassName('PlayerName');
			}
			else
			{
				btn_type = ThreadLink;
			}
	
			if (btn)
			{
				btn.onclick = function()
				{
					addRemoveItemToFromStorage(btn_for_what, btn_type[btn_no].innerHTML, mode, addingUsingPlayerName);
				};
				GiveOnClickToBtn(btn_no + 1, btn_for_what, mode, addingUsingPlayerName);
			}
			else
			{
				if (btn_for_what === 'Players' && mode === 'add')
				{
					GiveOnClickToBtn(0, 'Players', 'remove', true);
				}
				else if (btn_for_what === 'Players' && mode === 'remove')
				{
					GiveOnClickToBtn(0, 'threads', 'remove');
				}
				else if (btn_for_what === 'threads' && mode === 'remove')
				{
					GiveOnClickToBtn(0, 'threads', 'add');
				}
			}
		};

		var GiveOnClickToBtn = function(btn_no, btn_for_what, mode, addingUsingPlayerName)
		{
			DecideOnClickForBtn(btn_no, btn_for_what, mode, addingUsingPlayerName);
		};

		GiveOnClickToBtn(0, 'Players', 'add', true);

		if (document.getElementById('HiddenThreadsRow'))
		{
			FixHiddenThreadsRow();
		}
		}catch(err){HandelErr(err);}
	}
}

function CreateButtons(ids, type)
{
	if (!Array.isArray(ids))
	{
		return;
	}

	var createdBtns = [];
	var btn;
	var btnId;

	for (var btnNo = 0; btnNo < ids.length; btnNo++)
	{
		btnId = ids[btnNo];
		btn = document.createElement('input');
		btn.id = btnId.replace(/\s/g, '') + 'Btn';
		btn.type = type;
		btn.value = btnId.replace('add', '+ ').replace('remove', '- ');
		btn.style.cursor = 'pointer';
		createdBtns.push(btn);
	}

	return createdBtns;
}

function CreateAddToBlocklistBtnOnProfile()
{
	try{
	if (!onProfile)
	{
		return;
	}

	var BlackListImage = document.getElementById('BlackListImage');

	if (BlackListImage)
	{
		var addRemoveBlocklistRow = document.getElementById('addRemoveBlocklistRow');
		var addRemoveBlocklistTd = document.getElementById('addRemoveBlocklistTd');
		var addBlocklistBtn = document.getElementById('addBlocklistBtn');
		var removeBlocklistBtn = document.getElementById('removeBlocklistBtn');
		var playernumber = location.href.match(/\d+/)[0];
		var playerid = playernumber.substring(2, playernumber.length - 2);
		var UpdateVisual = function()
		{
			if (Players.indexOf(playerid) > -1)
			{
				addBlocklistBtn.style.display = 'none';
				removeBlocklistBtn.style.display = 'block';
			}
			else
			{
				addBlocklistBtn.style.display = 'block';
				removeBlocklistBtn.style.display = 'none';
			}
		};

		if (!addRemoveBlocklistRow)
		{
			addRemoveBlocklistRow = document.createElement('tr');
			addRemoveBlocklistTd = document.createElement('td');
			addRemoveBlocklistRow.id = 'addRemoveBlocklistRow';
			addRemoveBlocklistTd.id = 'addRemoveBlocklistTd';
			addRemoveBlocklistTd.colSpan = '2';

			var addRemoveBlocklistBtns = CreateButtons(['addBlocklist', 'removeBlocklist'], 'button');

			addBlocklistBtn = addRemoveBlocklistBtns[0];
			removeBlocklistBtn = addRemoveBlocklistBtns[1];

			addBlocklistBtn.style.width = '100%';
			addBlocklistBtn.onclick = function()
			{
				blocklist.addUsing.ids([playerid]);
				UpdateVisual();
			};
			removeBlocklistBtn.style.width = '100%';
			removeBlocklistBtn.onclick = function()
			{
				blocklist.remove([playerid]);
				UpdateVisual();
			};

			UpdateVisual();
			BlackListImage.parentElement.parentElement.parentElement.parentElement.appendChild(addRemoveBlocklistRow);//is the tbody of the add/remove from blacklist/friends, private notes, mail buttons
			addRemoveBlocklistRow.appendChild(addRemoveBlocklistTd);
			Append([addBlocklistBtn, removeBlocklistBtn], addRemoveBlocklistTd);
		}

		UpdateVisual();
	}
	}catch(err){HandelErr(err);}
}

function CreateAddToThreadExceptionsHiddenThreadsOnThread()
{
	try{
	if (!(threadP || discussionP))
	{
		return;
	}

	var postReplyLink = window.$('a').filter("[href $= '#Reply']")[0];
	var threadExceptionsHiddenThreadsContainer = document.getElementById('threadExceptionsHiddenThreadsContainer');
	var addHiddenThreadsBtn = document.getElementById('addHiddenThreadsBtn');
	var removeHiddenThreadsBtn = document.getElementById('removeHiddenThreadsBtn');
	var addThreadExceptionsBtn = document.getElementById('addThreadExceptionsBtn');
	var removeThreadExceptionsBtn = document.getElementById('removeThreadExceptionsBtn');
	var threadSubject = document.title.replace(' - Play Risk Online Free - Warzone', '');
	var UpdateVisual = function()
	{
		if (_threads.indexOf(threadSubject) > -1)
		{
			addHiddenThreadsBtn.style.display = 'none';
			removeHiddenThreadsBtn.style.display = 'inline-block';
		}
		else
		{
			addHiddenThreadsBtn.style.display = 'inline-block';
			removeHiddenThreadsBtn.style.display = 'none';
		}
		if (threads.indexOf(threadSubject) > -1)
		{
			addThreadExceptionsBtn.style.display = 'none';
			removeThreadExceptionsBtn.style.display = 'inline-block';
		}
		else
		{
			addThreadExceptionsBtn.style.display = 'inline-block';
			removeThreadExceptionsBtn.style.display = 'none';
		}
	};

	if (!threadExceptionsHiddenThreadsContainer)
	{
		threadExceptionsHiddenThreadsContainer = document.createElement('div');
		threadExceptionsHiddenThreadsContainer.id = 'threadExceptionsHiddenThreadsContainer';

		var btns = CreateButtons(['addHidden Threads', 'removeHidden Threads', 'addThread Exceptions', 'removeThread Exceptions'], 'button');

		addHiddenThreadsBtn = btns[0];
		removeHiddenThreadsBtn = btns[1];
		addThreadExceptionsBtn = btns[2];
		removeThreadExceptionsBtn = btns[3];

		addHiddenThreadsBtn.onclick = function()
		{
			config._threads.add([threadSubject]);
			UpdateVisual();
		};
		removeHiddenThreadsBtn.onclick = function()
		{
			config._threads.remove([threadSubject]);
			UpdateVisual();
		};
		addThreadExceptionsBtn.onclick = function()
		{
			config.threads.add([threadSubject]);
			UpdateVisual();
		};
		removeThreadExceptionsBtn.onclick = function()
		{
			config.threads.remove([threadSubject]);
			UpdateVisual();
		};

		Append(threadExceptionsHiddenThreadsContainer, postReplyLink, 'afterend');
		Append(btns, threadExceptionsHiddenThreadsContainer);
		UpdateVisual();
	}

	UpdateVisual();
	}catch(err){HandelErr(err);}
}

if (!updating_settings_to_work_with_2point3 && !window.updating_player_data)
{
	CreateUIForSubForumsAllForumsMailAndClanForum();
	CreateAddToBlocklistBtnOnProfile();
	CreateAddToThreadExceptionsHiddenThreadsOnThread();
}

//makes blanked-out links visible globally by replacing the link's innerHTML with [blank name]
fixBlank(document.getElementsByTagName('a'), '[blank name]', true);

var CanUpdateHTRPThread = true;
//if not signed in as Dan, don't allow updating the thread with the changes if the are changes
if (!IsUser(9522268564) || !localStorage.DanHTRBP_version_changes)
{
	CanUpdateHTRPThread = false;
}

if (CanUpdateHTRPThread)
{
	try{
	var page = window;
	var main = function()
	{
		var changes = localStorage.DanHTRBP_version_changes;
		var changes_split = changes.split('.');
		var changes_formatted_str = '';

		for (var changes_split_counter = 0; changes_split_counter < changes_split.length; changes_split_counter++)
		{
			changes_formatted_str += '[*] ' + changes_split[changes_split_counter] + '.\n';
		}

		page.document.getElementById('TextArea_-1').value = v + ' changes:\n[list]\n' + changes_formatted_str.replace('\n[*] .', '') + '[/list]';
		RemoveLocalStorageItem('DanHTRBP_version_changes');
		page.document.getElementById('SubmitPostBtn_-1').click();
	};
	var thread_page;
	var thread_page_url = 'https://www.warzone.com/Forum/299366-hide-threads-replies-poster-official-3';

	if (location.href.match(new RegExp(EscapeRegExpChars(thread_page_url))))
	{
		main();
	}
	else
	{
		thread_page = open(thread_page_url);
		page = thread_page;
		thread_page.onload = function()
		{
			thread_page.onload = function()
			{
				thread_page.close();
			};
			main();
		};
	}
	}catch(err){HandelErr(err);}
}

var todaysdate = new Date();

if (todaysdate.getMonth() === 3 && todaysdate.getDate() === 1)
{
	//if april fools
	obscurify();

	//allow password to unobscurify to be entered
	(function()
	{
		var id = 'unobscurifyPWSettingBtn';
		var unobscurifyPWSettingBtn = elementExists(id, function()
		{
			return create('div', id, '46 01101001 120 20 01010100 101 78 01110100', document.getElementById('bottom_row'));//Fix Text
		});

		unobscurifyPWSettingBtn.className = 'FlexContainer Flex3 Centered SettingsBtn Darkblue';
		unobscurifyPWSettingBtn.onclick = function()
		{
			var enterPWPrompt;
			var correctPW = "Dan is #1 WarZoner!";
			var checkIfPasswordIsCorrect = function()
			{
				var enteredPW = enterPWPrompt.value;

				if (enteredPW === correctPW)
				{
					ui.AlertErr('Correct password entered');
					password = true;
					obscurify('unobscurify');
				}
				else
				{
					ui.AlertErr('49 01101110 99 6F 01110010 114 65 01100011 116 20 01110000 97 73 01110011 119 6F 01110010 100');//Incorrect password
				}
			};

			enterPWPrompt = ui.Prompt('45 01101110 116 65 01110010 32 50 01100001 115 73 01110111 111 72 01100100', checkIfPasswordIsCorrect);//Enter Password
		};
	})();
}