FeeneyDanielson / Numeric Grades

// ==UserScript==
// @name        Numeric Grades
// @namespace   popmundo
// @include     http://*.popmundo.com/*
// @grant       GM_log
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM_openInTab
// @grant       GM_xmlhttpRequest
// @version     4.9
// ==/UserScript==

/*
x = name && name[1]

	TO DO LIST

*/

var multiline = function (fn) {
	var reCommentContents = /\/\*!?(?:\@preserve)?[ \t]*(?:\r\n|\n)([\s\S]*?)(?:\r\n|\n)\s*\*\//;
	var match = reCommentContents.exec(fn.toString());
	return match[1];
};

var NG = {
	utils: {
		toArray: function (t) {
			var arr = []; for (var i = 0; i < t.length; i++) arr.push(t[i]); return arr;
		},
		injectCSS: function (css) {
			if (css.length < 1) return;
			var heads = document.getElementsByTagName("head");
			if (heads.length > 0) {
				var node = document.createElement("style");
				node.type = "text/css";
				node.appendChild(document.createTextNode(css));
				heads[0].appendChild(node);
			}
		}
	},
	features: {
	/*	name: {
			init: function => main function
			exec: function => function to be called upon DOM change
			options: {
				enabled => on/off. generates checkbox on UI
				text => UI menu item text
				tab => UI menu tab
				selected => selected from optionList. generatex select on UI
				path => REGEX match for document.location.pathname
				help => help url
				listen => call exec() on DOM change
			},
			optionList: {
				item: { name: "dropdown name", ... }
				item:
			}
		}*/
		progressBars: {
			init: function () {
				NG.utils.injectCSS('.PPM2_Numeric_Grades_Bar { color: #000; line-height: 8px; font-size: 9px; font-weight: normal; font-family: "Tahome, Geneva, sans-serif", display: inline; width: 0px; }');
				this.exec(document.getElementById('wrapper'));
			},
			exec: function (c) {
				if (!c || !c.tagName || c.tagName == 'BODY') {
					return
				}
				var	a, b, d, e, i;
				if (c.classList && c.classList.contains('progressBar')) {
					b = NG.utils.toArray([c]);
				}
				else {
					b = c.querySelectorAll(".blueProgressBar, .greenProgressBar, .progressBar");
				}
				for (i = b.length; i-- ;) {
					a = b[i],
					d = a.firstChild;
					e=!0==/(%{0,1}[\d]+%{0,1})/i.test(a.title) ? a.title.match(/(%{0,1}[\d]+%{0,1})/i)[1] : a.title,
					(d && d.style) ? (
						d.textContent=e+"\u00a0", //nbsp
						d.align="right",
						d.style.lineHeight="9px",
						d.style.fontSize="10px",
						d.style.color= "#000"
						):(
						a.textContent=e,
						a.style.color="#000"
					);
				}
				b = c.getElementsByClassName("plusMinusBar");
				for (i = b.length; i-- ;) {
					a=b[i];
					if (1>a.getElementsByClassName("PPM2_Numeric_Grades_Bar").length) {
						e = document.createElement("div");
						e.textContent = a.title.match(/(-*[\d]+%)/i)[1];
						e.className = "PPM2_Numeric_Grades_Bar";
						if (0<a.getElementsByClassName("neg").length) {
							a.childNodes[0].firstChild.appendChild(e);
							a.getElementsByClassName('posholder')[0].style.cssFloat = 'none';
						}
						else if (0<a.getElementsByClassName("pos").length) {
							a.childNodes[1].firstChild.appendChild(e);
						}
						else {
							a.childNodes[1].firstChild.appendChild(e);
							a.childNodes[1].firstChild.style.width = "0%";
						}
					}
				}
				return!0
			},
			options: {
				enabled: true,
				text: "Numeric Progress Bars",
				tab: "main",
				help: 'http://s3.amazonaws.com/uso_ss/20748/large.png?1363553739',
				listen: true
			}
		},
		numericGrades: {
			init: function () {
				NG.utils.injectCSS('a.PPM2_Numeric_Grades + span { display: inline-block; margin-left: 5px; padding: 0 5px; border: 5px; font-weight: bold; border-radius: 10px; text-shadow: none; }');
				this.exec();
			},
			exec: function (c) {
				c||(c=document);
				var b = c.href ? Array(c) : c.querySelectorAll('a[href*="Help/Scoring/"]');
				for (var i=b.length;i--;) {
					var a = b[i];
					if (!a.classList.contains("PPM2_Numeric_Grades") && a.href.indexOf('Help/Scoring/')>-1) {
						var e = a.href.match(/\/Help\/Scoring\/(\d+)/i)[1]-1,
						h = NG.features.numericGrades.optionList[NG.features.numericGrades.options.selected][e],
						j = document.createElement("span");
						j.style.color = h[1];
						j.style.backgroundColor = h[0];
						j.textContent = " "+e;
						a.className = "PPM2_Numeric_Grades";
						a.parentNode.insertBefore(j, a.nextSibling)
					}
				}
			},
			options: {
				enabled: true,
				text: "Numeric Grades",
				selected: "rain",
				tab: "main",
				help: "http://s3.amazonaws.com/uso_ss/20751/large.png?1363553875",
				listen: true
			},
			optionList: {
				grad: {
					name: "Gradient",
					0: ["rgb(245,245,245)", "rgb(0,0,0)"],
					1: ["rgb(236,236,236)", "rgb(0,0,0)"],
					2: ["rgb(226,226,226)", "rgb(0,0,0)"],
					3: ["rgb(217,217,217)", "rgb(0,0,0)"],
					4: ["rgb(207,207,207)", "rgb(0,0,0)"],
					5: ["rgb(198,198,198)", "rgb(0,0,0)"],
					6: ["rgb(188,188,188)", "rgb(0,0,0)"],
					7: ["rgb(179,179,179)", "rgb(0,0,0)"],
					8: ["rgb(170,170,170)", "rgb(0,0,0)"],
					9: ["rgb(160,160,160)", "rgb(0,0,0)"],
					10: ["rgb(151,151,151)", "rgb(0,0,0)"],
					11: ["rgb(141,141,141)", "rgb(255,255,255)"],
					12: ["rgb(132,132,132)", "rgb(255,255,255)"],
					13: ["rgb(122,122,122)", "rgb(255,255,255)"],
					14: ["rgb(113,113,113)", "rgb(255,255,255)"],
					15: ["rgb(103,103,103)", "rgb(255,255,255)"],
					16: ["rgb(94,94,94)", "rgb(255,255,255)"],
					17: ["rgb(85,85,85)", "rgb(255,255,255)"],
					18: ["rgb(75,75,75)", "rgb(255,255,255)"],
					19: ["rgb(66,66,66)", "rgb(255,255,255)"],
					20: ["rgb(56,56,56)", "rgb(255,255,255)"],
					21: ["rgb(47,47,47)", "rgb(255,255,255)"],
					22: ["rgb(37,37,37)", "rgb(255,255,255)"],
					23: ["rgb(28,28,28)", "rgb(255,255,255)"],
					24: ["rgb(18,18,18)", "rgb(255,255,255)"],
					25: ["rgb(9,9,9)", "rgb(255,255,255)"],

					26: ["rgb(0,0,0)", "rgb(255,255,255)"]
				},
				rain: {
					name: "Rainbow",
					0: ["#ff0000", "rgb(255,255,255)"],
					1: ["#ff0036", "rgb(255,255,255)"],
					2: ["#ff006c", "rgb(255,255,255)"],
					3: ["#ff00a2", "rgb(255,255,255)"],
					4: ["#ff00d8", "rgb(255,255,255)"],
					5: ["#f000ff", "rgb(255,255,255)"],
					6: ["#ba00ff", "rgb(255,255,255)"],
					7: ["#8400ff", "rgb(255,255,255)"],
					8: ["#4e00ff", "rgb(255,255,255)"],
					9: ["#1900ff", "rgb(255,255,255)"],
					10: ["#001dff", "rgb(255,255,255)"],
					11: ["#0053ff", "rgb(255,255,255)"],
					12: ["#0089ff", "rgb(255,255,255)"],
					13: ["#00bfff", "rgb(255,255,255)"],
					14: ["#00f5ff", "rgb(0,0,0)"],
					15: ["#00ffd3", "rgb(0,0,0)"],
					16: ["#00ff9d", "rgb(0,0,0)"],
					17: ["#00ff67", "rgb(0,0,0)"],
					18: ["#00ff31", "rgb(0,0,0)"],
					19: ["#05ff00", "rgb(0,0,0)"],
					20: ["#3bff00", "rgb(0,0,0)"],
					21: ["#71ff00", "rgb(0,0,0)"],
					22: ["#a7ff00", "rgb(0,0,0)"],
					23: ["#ddff00", "rgb(0,0,0)"],
					24: ["#ffeb00", "rgb(0,0,0)"],
					25: ["#ffb500", "rgb(0,0,0)"],
					26: ["#ff8000", "rgb(0,0,0)"]
				}
			}
		},
		tabs: {
			init: function () {
				if (document.location.hash) {
					var notes = document.querySelectorAll("div#top-menu-notifications-list div.notification-item > a:nth-of-type(2)");
					for (var hash = document.location.hash.replace("#",""), i=0; i < notes.length; i++) {
						if ((notes[i].onclick) && (-1<String(notes[i].onclick).indexOf(hash))) {
							notes[i].click();
							break;
						}
					}
				}
				this.exec(document);
			},
			exec: function (e) {
				var notes;
				if (!e || !(notes = e.querySelectorAll('.notification-item > a:nth-of-type(2)'))) {
					return;
				}
				for (var i = 0; i < notes.length; i++) {
					if (!/["'](.*)["']/gi.test(notes[i].onclick)) {
						continue;
					}
					notes[i].addEventListener("mousedown",this.clickHandler,!0);
					notes[i].addEventListener("click",this.clickHandler,!0);
					notes[i].href = "#"+String(notes[i].onclick).match(/["'](.*)["']/gi)[0].replace(/["']/g,"");
				}
			},
			clickHandler: function (c) {
				if (1==c.which&&(c.ctrlKey||c.shiftKey)||2==c.which) {
					c.stopPropagation();
					c.preventDefault();
					c.cancelBubble=!1;
					this.removeEventListener("mousedown",NG.features.tabs.clickHandler,!0);
					this.removeEventListener("click",NG.features.tabs.clickHandler,!0);
					this.focus();
					var c = JSON.stringify({
						ts: new Date().getTime(),
						arg: String(this.onclick).match(/\(this, (.*)\)/i)[1].replace(/[\'"]/g,"")
					},null),
					b = document.location.protocol+"//"+document.location.hostname+"/WebServices/A/Open.asmx/ClickNotification",
					d = new XMLHttpRequest;
					this.parentNode.parentNode.removeChild(this.parentNode);
					1>document.querySelectorAll("#notifications ul li").length&&(document.getElementById("notifications").className="hidden");
					d.onreadystatechange = function() {
						if (4==d.readyState && 200==d.status){
							var a=document.createElement("div");
							a.innerHTML = d.responseText.replace(/<script(.|\s)*?\/script>/ig,"");
							ret = document.location.protocol+"//"+document.location.hostname+"/"+a.innerHTML.match(/\/(.*)\\"/)[1];
							GM_openInTab?GM_openInTab(ret):window.open(ret)
						}
					};
					d.open("POST",b,!0);
					d.setRequestHeader("Content-type","application/json;charset=utf-8");
					d.setRequestHeader("Content-length",c.length);
					d.send(c);
					this.parentNode.parentNode.removeChild(this.parentNode);
					return!1
				}
			},
			options: {
				enabled: true,
				text: "Notifications in seperate tabs",
				tab: "main",
				help: "http://s3.amazonaws.com/uso_ss/20753/large.png?1363554044",
				listen: true
			}
		},
		/*active: {
			fn: function () {
				var c=document.getElementById("sidemenu").getElementsByTagName("a"),b=document.location.href;
				if(b.match(/\w+(?:$|\/\d+)/i)==(c[0]?c[0].href.match(/(\w+)(?:$|\/\d+)/i)[1]:!1))return c[0].parentNode.style.backgroundColor="#FFF",!0;
				for(i=c.length;	i--;)
					if (b == c[i].href)
						return c[i].parentNode.style.backgroundColor="#FFF",!0
			},
			options: {
				enabled: true,
				text: "Highlight active page on side menu",
				tab: "extras"
			}
		},*/
		hideText: {
			init: function () {
				if(!(0<document.location.pathname.indexOf("/Thread/"))){
					var b;
					b=-1<navigator.userAgent.toLowerCase().indexOf("firefox")?"-moz":"-webkit";
					var d=document.getElementById("content").getElementsByTagName("p");
					for (var i=d.length-1;0<=i;i--)
						!(1<d[i].childNodes.length)&&"ctl00_cphLeftColumn_ctl00_divNoteFromManagement"!=d[i].parentNode.id&&"ctl00_cphLeftColumn_ctl00_divBlog"!=d[i].parentNode.id&&(6>d[i].parentNode.childNodes.length?0===d[i].parentNode.childNodes[1].tagName.indexOf("H")&& 2>d[i].offsetHeight/parseInt(window.getComputedStyle(d[i],"").lineHeight):2>=d[i].offsetHeight/parseInt(window.getComputedStyle(d[i],"").lineHeight,10)||(d[i].setAttribute("style",b+"-transition: max-height 0.5s;"),d[i].style.maxHeight="20px",d[i].style.overflow="hidden",d[i].style.cursor="pointer",d[i].style.marginBottom="2px",d[i].style.borderBottom="dotted 1px",d[i].addEventListener("click",NG.features.hideText.clickHandler,!0)));
				}
			},
			clickHandler: function (a) {
					a = a.target;
					"P"==a.tagName?0<window.getSelection().toString().length&&a==window.getSelection().getRangeAt(0).startContainer.parentNode||("20px"==a.style.maxHeight?(a.style.maxHeight="999px",a.style.borderBottom="none",a.style.marginBottom="15px"):(a.style.maxHeight="20px",a.style.borderBottom="dotted 1px",a.style.marginBottom="2px")):0==a.tagName.indexOf("H")&&(a=a.parentNode.getElementsByTagName("P"),1>a.length||(a=a[0],"7px"==a.style.maxHeight?(a.style.maxHeight="999px",a.style.borderBottom="none"): (a.style.maxHeight="7px",a.style.borderBottom="dotted 1px")))
			},
			options: {
				enabled: false,
				text: "Collapse long text",
				tab: 'extras'
			}
		},
		update: {
			init: function () {
				// disabled
				return;
				if (NG.features.update.options.updateAvailable) {
					NG.features.update.notify();
				}
				else if (parseInt(+new Date().valueOf()-NG.features.update.options.lastCheck) > 604800000) { // 1 week
					GM_xmlhttpRequest({
						method: 'GET',
						url: NG.features.update.options.updateUrl,
						onload: function (res) {
							NG.options.set('update','lastCheck',new Date().valueOf());
							var remoteVersion = res.responseText.match(/\/\/\s+@version\s+([\d\.]+)$/mi);
							if (!remoteVersion) {
								GM_log('Error parsing remote file!');
								return;
							}
							if (remoteVersion[1] > NG.version) {
								NG.options.set('update','updateAvailable',true);
								NG.features.update.notify();
							}
						}
					});
				}
			},
			notify: function () {
				var aClose = document.createElement('div');
				aClose.textContent = 'Numeric Grades Update Available';
				aClose.classList.add('notification-success');
				aClose.onclick = function (t) {
					NG.options.set('update','updateAvailable',false);
					GM_openInTab(NG.features.update.options.url);
					t.target.parentNode.removeChild(t.target);
					if (document.querySelectorAll('#notifications > div').length < 1) {
						document.getElementById('notifications').classList.add('hidden');
						document.getElementById('notifications').style.display = 'none';
					}
				};
				var nots = document.getElementById('notifications');
				nots.appendChild(aClose);
				nots.classList.remove('hidden');
				nots.style.display = 'block';
			},
			options: {
				enabled: true,
				text: "Auto update",
				tab: "extras",
				url: "http://userscripts.org/scripts/source/135906.user.js",
				updateUrl: "http://userscripts.org/scripts/source/135906.meta.js",
				site: 'http://userscripts.org/scripts/show/135906',
				lastCheck: 0,
				updateAvailable: false
			}
		},
		seconds: {
			init: function () {
				unsafeWindow._ptrn = NG.features.seconds.optionList[NG.features.seconds.options.selected].set;
				if (unsafeWindow.updateGameClock) setTimeout( function () { unsafeWindow.updateGameClock(); }, 0);
			},
			options: {
				enabled: true,
				text: "Show seconds in game clock",
				tab: "extras",
				selected: "AMPM"
			},
			optionList: {
				AMPM: {
					name: "AM-PM",
					set: "h:mm:ss tt"
				},
				24: {
					name: "24 Hour Clock",
					set: "HH:mm:ss"
				}
			}
		}
	},
	options: {
		set: function (module, option, value) {
			if (!module || !option || value == null) return false;
			var data = NG.options.load(); // because I don't want to save default values
			NG.features[module].options[option] = value;
			if (!data[module]) data[module] = {};
			data[module][option] = value;
			NG.options.save(data);
			return true;
		},
		get: function (module, option) {
		},
		save: function (data) {
			if (!data) return undefined;
			GM_setValue('numeric_grades_options', JSON.stringify(data));
			return true;
			/*for (i in data) {
				for (j in data[i])
					alert(i+'.options.'+j+' = '+data[i][j])
			}*/
		},
		load: function () {
			var data = GM_getValue('numeric_grades_options','{}');
			if (data.length < 1) data = '{}';
			data = JSON.parse(data);
			for (i in data) {
				for (j in data[i]) {
					if (NG.features[i]) NG.features[i].options[j] = data[i][j];
					//alert(i+'.options.'+ j + ' = ' + data[i][j])
				}
			}
			return data;
		}
	},
	UI: {
		beaker: function () {
			var c = document.createElement("A");
			c.className = "icon";
			c.title = "Numeric Grades";
			c.id = "ppm_numeric_grades";
			c.style.cursor = "pointer";
			var b = document.createElement("img");
			b.src = "/Static/Icons/beaker.png";
			b.id = "ppm_numeric_grades_menu";
			c.appendChild(b);
			// try 'more shortcuts' first and if it fails switch to regular shortcuts
			b = document.getElementById('ctl00_ctl05_ucCharacterBar_divMoreShortcuts');
			if (!b) {
				b = document.getElementById('character-tools-shortcuts');
			}
			if (!b) return; // we must be logged out from the game
			b.appendChild(c);
			document.getElementById("ppm_numeric_grades_menu").addEventListener("click", NG.UI.userInterface,!0);
		},
		userInterface: function () {
			if (document.getElementById("ppm_numeric_grades_options")) return;
			document.querySelector('body').classList.remove('ng_options_recover');
			document.querySelector('body').classList.add('ng_options_disabled');
			NG.utils.injectCSS(multiline(function(){/*
#ppm_numeric_grades_options {
  cursor: auto;
  position: fixed;
  color: #FFF;
  font-family: Tahoma !important;
  font-size: 11px !important;
  width: 100%;
  height: 100%;
  top: 0;
  left: 0;
  background: rgba(0, 0, 0, 0.3);
}
#ppm_numeric_grades_options_container {
  z-index:2;
  position: fixed;
  left: 50%;
  margin-left: -250px;
  width: 500px;
  height: 440px;
  background: none repeat scroll 0% 0% #7F8c8d;
  border: 1px solid #000;
  box-shadow: 2px 4px 2px rgba(0, 0, 0, 0.65);
  padding: 10px;
}
#ppm_numeric_grades_options_titlebar {
  background-color: #2C3E50;
  color: #ECf0f1;
  margin: -10px -10px 10px -10px;
  padding: 0 10px;
  border-bottom: 1px solid #000;
  cursor: default;
}
#ppm_numeric_grades_options_close {
  font-size: 12px;
  position: absolute;
  right: 10px;
  bottom: 8px;
  cursor: pointer;
  margin: 0 0 0 0;
  color: #222;
  background-color: #c0392b;
  padding: 6px 40px;
  font-weight: bold;
  border: 1px solid #000;
  border-radius: 2px;
  -webkit-transition: background-color 0.3s;
  -moz-transition: background-color 0.3s;
  transition: background-color 0.3s;
}
#ppm_numeric_grades_options_close:hover {
  background-color: #e74c3c;
  color: #222;
  border: 1px solid #33647D;
}

.ppm_numeric_grades_tab {
  float: left;
  background-color: #2C3E50;
  padding: 2px;
  height: 26px;
  border-radius: 4px 0 0 4px;
}
.ppm_numeric_grades_tab:last-of-type {
  padding: 2px 4px;
  border-radius: 0 4px 4px 0;
}
.ppm_numeric_grades_tab:last-of-type:after {
  display: block;
  content: '';
  background-color: #2C3E50;
  position: absolute;
  height: 30px;
  width: 90%;
  right: 10px;
  top: 26px;
  border-radius: 4px 4px;
  z-index: -1;
}

.ppm_numeric_grades_tab > label {
  color: #FFF;
  font-weight: normal;
  padding: 5px 10px;
  cursor: pointer;
  display: block;
  width: 60px;
  height: 15px;
  text-transform: capitalize;
  text-align: center;
  letter-spacing: 0.1em;
}
.ppm_numeric_grades_tab > label:hover {
  text-decoration: underline;
}
#ppm_numeric_grades_options_container [type=radio]:checked ~ label {
  color: #FFF;
  background: #16a085;
  z-index: 4;
  border-radius: 2px;
}

.ppm_numeric_grades_tab [type=radio] {
  display: none;
}
.ppm_numeric_grades_content {
  position: absolute;
  top: 70px;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0 10px 50px;
  padding: 5px;
  overflow: hidden;
  background: #2C3E50;
  text-align: left;
  border-radius: 4px;
}
#ng_about ~ .ppm_numeric_grades_content {
  text-align: center;
  color: #FFF;
}
.ppm_numeric_grades_content > * {
  -wekbit-transition: opacity 1.0s;
  -moz-transition: opacity 1.0s;
  transition: opacity 1.0s;
  opacity: 0;
}
.ppm_numeric_grades_content a {
  font-weight: bold;
  text-decoration: none;
  color: #16a085;
  float: none !important;
  letter-spacing: 0.1em;
}
.ppm_numeric_grades_content a:hover {
  text-decoration: underline;
}
.ppm_numeric_grades_content select {
  border: 1px solid #000;
  font-size: 14px !important;
  height: 25px;
  width: 90% !important;
  border-radius: 5px;
  margin: 10px 0px 0px 25px !important;
  background: -moz-linear-gradient(center top, #FFFFFF, #EFEFEF) repeat scroll 0 0 transparent;
  background: -webkit-linear-gradient(center top, #FFFFFF, #EFEFEF) repeat scroll 0 0 transparent;
}
.ppm_numeric_grades_content > div {
  margin-bottom: 5px;
  padding: 10px;
  background: #34495E;
  position: relative;
}
#ppm_numeric_grades_options_container [type=radio]:checked ~ label ~ .ppm_numeric_grades_content {
  z-index: 3;
}
#ppm_numeric_grades_options_container [type=radio]:checked ~ label ~ .ppm_numeric_grades_content > * {
  opacity: 3;
}
.ppm_numeric_grades_content > label {
  float: left;
}
#ppm_numeric_grades_options_container input[type='checkbox'] {
  opacity: 0;
  float: none;
  display: none;
  width: 18px;
}
#ppm_numeric_grades_options_container input[type='checkbox'] + label {
  cursor: pointer;
  color: #FFF;
}
#ppm_numeric_grades_options_container input[type='checkbox'] + label:before {
  content: '✔';
  display: inline-block;
  width: 20px;
  height: 20px;
  text-align: center;
  font-size: 16px;
  color: #95a5a6;
  background-color: #95a5a6;
  border-radius: 2px;
  margin-right: 5px;
  position: relative;
  top: 3px;
  padding-bottom: 2px;
}
#ppm_numeric_grades_options_container input[type='checkbox']:checked + label:before {
  color: #FFF;
}

.ng_help {
  background-color: #FFFFFF;
  border-radius: 100%;
  padding: 0 4px;
  position: absolute;
  right: 5px;
  top: 50%;
  margin-top: -10px;
  border: 1px solid #000000;
  font-size: 12px;
  text-decoration: none !important;
}

body.ng_options_disabled {
  perspective: 800px;
  perspective-origin: 50% 50%;
  overflow: hidden;
}
body.ng_options_disabled form#aspnetForm {
  animation: andrew 0.5s 1 forwards;
  transform-origin: 0 50%;
  transition: all 0.5s ease;
  pointer-events: none;
}
body.ng_options_recover form#aspnetForm {
  animation: recover 0.5s 1 forwards;
}
#ppm_numeric_grades_options_container {
  animation: main 0.5s ease 0s 1 forwards;
  transform-origin: 0 50%;
  transition: all 0.5s ease;
}
@keyframes main {
  0% { opacity: 0.3; transform: rotateX(90deg); }
  50% { opacity: 0.3; transform: rotateX(45deg); }
  100% { }
}
@keyframes andrew {
  0% { transform: translateY(-15%) rotateX(0deg); }
  50% {  transform: translateY(-15%) rotateX(15deg); }
  100% { opacity: 0.2; transform: translate(5%, -15%) rotateX(15deg) scale(0.9); }
}
@keyframes recover {
  100% { }
  99% { opacity: 0.2; transform: translate(0%) rotateX(0deg); transform-origin: 0 50%; transition: all 0.3s ease; pointer-events: none; }
  0% { opacity: 0.2; transform: translate(5%, -15%) rotateX(15deg) scale(0.9); transform-origin: 0 50%; transition: all 0.3s ease; pointer-events: none; }
}
			*/}));
			var main = document.createElement('DIV'),
			titlebar = document.createElement('DIV'),
			container = document.createElement('DIV'),
			close = document.createElement('DIV');

			main.id = 'ppm_numeric_grades_options';
			container.id = 'ppm_numeric_grades_options_container';
			titlebar.id = 'ppm_numeric_grades_options_titlebar';
			titlebar.textContent = 'Numeric Grades';
			close.id = 'ppm_numeric_grades_options_close';
			close.textContent = 'Close';
			container.appendChild(titlebar);
			container.appendChild(close);

			// for generating checkboxes and selects for features
			for (i in NG.features) {
				if (!NG.features[i].options || !NG.features[i].options.tab) {
					continue;
				}
				var tab, contenter, c = document.createElement('div');
				if (container.querySelector('#ng_tab_'+NG.features[i].options.tab) == null) {
					// create new tab
					tab = document.createElement('DIV'),
					contenter = document.createElement('DIV');
					var tabControl = document.createElement('input'),
					label = document.createElement('label');
					tabControl.type = "radio";
					tabControl.id = 'ng_tab_'+NG.features[i].options.tab;
					tabControl.name = 'ng_tab';
					tab.appendChild(tabControl);
					label.textContent = NG.features[i].options.tab;
					label.setAttribute("for",'ng_tab_'+NG.features[i].options.tab);
					tab.appendChild(label);
					tab.className = 'ppm_numeric_grades_tab';
					contenter.className = 'ppm_numeric_grades_content';
					tab.appendChild(contenter);
					container.appendChild(tab);
				}
				else {
					// find existing tab
					contenter = container.querySelector('#ng_tab_'+NG.features[i].options.tab+' ~ .ppm_numeric_grades_content')
				}
				if (NG.features[i].options.enabled != undefined && NG.features[i].options.text) {
					// create a checkbox
					var ck = document.createElement('input'),
					label = document.createElement("label");
					ck.type = 'checkbox';
					ck.id = "ng_"+i;
					NG.features[i].options.enabled && (ck.checked = "checked");
					c.appendChild(ck);
					label.setAttribute("for","ng_"+i);
					label.textContent = NG.features[i].options.text;
					c.appendChild(label);
				}
				if (NG.features[i].options.selected != undefined && NG.features[i].optionList) {
					// create a dropdown
					var sel = document.createElement('select');
					sel.id = "ng_"+i+"_sel";
					for (j in NG.features[i].optionList) {
						var op = document.createElement('option');
						op.value = j;
						op.textContent = NG.features[i].optionList[j].name;
						(NG.features[i].options.selected == j) && (op.selected = true);
						sel.appendChild(op);
					}
					c.appendChild(sel);
				}
				if (c.childNodes.length > 0) {
					// help link if only module has an UI item
					if (NG.features[i].options.help) {
						// create help link
						var h = document.createElement('a');
						h.href = NG.features[i].options.help; // add url check here
						h.className = 'ng_help';
						h.target = "_blank";
						h.textContent = '?';
						c.appendChild(h);
					}
					contenter.appendChild(c);
				}
			}
			// inserting about tab
			var aboutTab = document.createElement('div'),
			about = document.createElement('div'),
			radio = document.createElement('input'),
			radioLabel = document.createElement('label');
			radio.type = 'radio';
			radio.id = 'ng_about';
			radio.name = 'ng_tab';
			radioLabel.setAttribute('for','ng_about');
			radioLabel.textContent = 'about';
			aboutTab.className = 'ppm_numeric_grades_tab';
			about.className = 'ppm_numeric_grades_content';
			about.innerHTML = '<br/><br/><br/>Popmundo Numeric Grades '+NG.version+'<br/><br/>by<br/><br/><a href="/World/Popmundo.aspx/Character/206394">Feeney Danielson</a><br/><br/><br/><br/><a href="'+NG.features.update.options.site+'" target="_blank">Visit Script\'s Website</a>';
			aboutTab.appendChild(radio);
			aboutTab.appendChild(radioLabel);
			aboutTab.appendChild(about);
			container.appendChild(aboutTab);
			// about tab complete
			// select the active tab aka version control
			container.querySelector('.ppm_numeric_grades_tab').firstChild.checked = true;
			main.appendChild(container);
			document.querySelector('body').appendChild(main);
			main.addEventListener('click',NG.UI.UIClickHandler,true);
			main.addEventListener('change',NG.UI.UIClickHandler,true);
		},
		UIClickHandler: function (e) {
			if ((e.type == 'click') && (e.target.id == 'ppm_numeric_grades_options_close')) {
				document.querySelector('body').removeChild(document.getElementById("ppm_numeric_grades_options"));
				document.querySelector('body').classList.remove('ng_options_disabled');
				document.querySelector('body').classList.add('ng_options_recover');
				setTimeout(function () { document.querySelector('body').classList.remove('ng_options_recover') }, 500);
			}
			if ((e.type == 'click') && (e.target.tagName == 'INPUT') && (e.target.type == "checkbox")) {
				var l = e.target.id.match(/ng_(\w+)/)[1];
				NG.options.set(l, 'enabled', e.target.checked);
			}
			else if ((e.type == 'change') && (e.target.tagName == 'SELECT')) {
				var l = e.target.id.match(/ng_(\w+)_sel/)[1];
				NG.options.set(l, 'selected', e.target[e.target.selectedIndex].value);
			}
		}
	},
	init: function () {
		NG.options.load(); // load preferences
		NG.UI.beaker(); // insert menu button to statusbar
		var active = [];
		for (i in NG.features) {
			if ((NG.features[i].options.enabled) && (typeof(NG.features[i].init) === "function")) {
				if (NG.features[i].options.path != undefined) {
					if (document.location.pathname.match(NG.features[i].options.path) != null) {
						NG.features[i].init();
						if (NG.features[i].options.listen && (typeof NG.features[i].exec) === "function") {
							active.push(NG.features[i]);
						}
					}
				}
				else {
					NG.features[i].init();
					if (NG.features[i].options.listen && (typeof NG.features[i].exec) === "function") {
						active.push(NG.features[i]);
					}
				}
			}
		} // launch .features

		if (active.length < 1) {
			return
		}
		// bind DOM mutation listeners
		var Observer = window.MutationObserver || window.WebKitMutationObserver;
		var observer = new Observer(function (records) {
			NG.utils.toArray(records).forEach(function (record) {
				if (record.addedNodes) {
					NG.utils.toArray(record.addedNodes).forEach(function (node) {
						if (!node.tagName) {
							return
						}
						for (var i = active.length; i--;) {
							active[i].exec(node)
						}
						return;
					})
				}
			});
		});
		observer.observe(document.body,{ childList: true, subtree: true });
	},
	version: "4.9"
}
NG.init();
/*
	progCall = 0;
	progTime = 0;

	var timing = new Date().getTime();
	timing = (new Date().getTime() - timing);
	progTime += timing;
	progCall++;
	if (timing > -1) {
		//GM_log(c.tagName);
		//GM_log(c.outerHTML || c.innerHTML);
		GM_log('progressBars('+progCall+'): '+timing+'/'+progTime+' ms');
	}
*/