Configuration Dialog

A enhanced configuration dialog for Userscripts.

Dieses Skript sollte nicht direkt installiert werden. Es handelt sich hier um eine Bibliothek für andere Skripte, welche über folgenden Befehl in den Metadaten eines Skriptes eingebunden wird // @require https://update.greasyfork.org/scripts/45343/759338/Configuration%20Dialog.js

/*
/////////////////////////////////////////////////////
#                                                   #
#          Script made by Marius Adam               #
#                ©DevForce 2019                     #
#               Code Version 0.4                    #
#                                                   #
/////////////////////////////////////////////////////
*/

var configurationWindow = {
	maximized: false,
	minimized: false,

	changed: false,

    data: undefined,
	window_id: "window",

	values: {},
	
	get : function(id){
		return this.values[id];
	},
	
	getElseSet : function(id, def, ifNone){
		var val = this.get(id);
		if(val == undefined){
			if(def == undefined){
				val = ifNone;
				this.set(id, ifNone);
			}else{
				val = def;
				this.set(id, def);
			}
		}
		return val;
	},
	
	set : function(id, value){
		this.values[id] = value;
	},
	
	save : function(){
		GM_setValue(this.window_id, JSON.stringify(this.values));
		console.debug("Saved to #" + this.window_id, this.values);
	},
	
	load : function(){
		var loaded = GM_getValue(this.window_id);
		if(loaded == undefined || loaded.length < 2) loaded = "{}";
		this.values = JSON.parse(loaded);
		console.debug("Loaded Values: ", this.values);
	},
	
	updateChanged : function() {
		this.changed = ($('[style*="border: 2px solid rgb(255, 244, 0);"]').length + $('[style*="outline: rgb(255, 244, 0) solid 3px;"]').length + $('[style*="outline: 3px solid rgb(255, 244, 0);"]').length) > 0;
		
		$('#' + this.window_id).find('#saveButton').prop("disabled", ! this.changed);
		$('#' + this.window_id).find('#revertButton').prop("disabled", ! this.changed);
	},
	
	maximize : function() {
		$('#' + this.window_id).find('#content').show();
		$('#' + this.window_id).find('#footer').show();
		$('#' + this.window_id).find('#theme_dropdown').show();
		$("#window_minimize").show();
		$('#' + this.window_id).width("calc(100% - 20px)");
		$('#' + this.window_id).height("calc(100% - 20px)");
		$('#' + this.window_id).css("top", "7px");
		$('#' + this.window_id).css("left", "7px");
		$('#' + this.window_id).css("min-height", "");

		this.maximized = true;
		this.minimized = false;
	},

	minimize : function(){
		$('#' + this.window_id).find('#content').hide();
		$('#' + this.window_id).find('#footer').hide();
		$('#' + this.window_id).find('#theme_dropdown').hide();
		$("#window_minimize").hide();
		$('#' + this.window_id).width("50%");
		$('#' + this.window_id).height("25px");
		$('#' + this.window_id).css("top", "calc(100% - 30px)");
		$('#' + this.window_id).css("left", "25%");
		$('#' + this.window_id).css("min-height", "30px");

		this.minimized = true;
	},

	normalize : function(){
		$('#' + this.window_id).find('#content').show();
		$('#' + this.window_id).find('#footer').show();
		$('#' + this.window_id).find('#theme_dropdown').show();
		$("#window_minimize").show();
		$('#' + this.window_id).width("");
		$('#' + this.window_id).height("");
		$('#' + this.window_id).css("top", "");
		$('#' + this.window_id).css("left", "");
		$('#' + this.window_id).css("min-height", "");

		this.maximized = false;
		this.minimized = false;
	},

	clearSelection : function(){
		if (window.getSelection) {
			if (window.getSelection().empty) {  // Chrome
				window.getSelection().empty();
			} else if (window.getSelection().removeAllRanges) {  // Firefox
				window.getSelection().removeAllRanges();
			}
		} else if (document.selection) {  // IE
			document.selection.empty();
		}
	},

	makeDragable : function(move, dragbox, useBorder) {
		if(dragbox == undefined) dragbox = move;
		if(useBorder == undefined) useBorder = true;

		var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0, dragged = false;

		dragbox.onmousedown = dragMouseDown;

		function dragMouseDown(e) {
			e = e || window.event;
			if(configurationWindow.minimized){
				document.onmouseup = null;
				document.onmousemove = null;
				return;
			}
			// get the mouse cursor position at startup:
			pos3 = e.clientX;
			pos4 = e.clientY;
			document.onmouseup = closeDragElement;
			// call a function whenever the cursor moves:
			document.onmousemove = elementDrag;
		}

		function elementDrag(e) {
			e = e || window.event;
			
			// calculate the new cursor position:
			pos1 = pos3 - e.clientX;
			pos2 = pos4 - e.clientY;
			pos3 = e.clientX;
			pos4 = e.clientY;
			
			// set the element's new position:
			var new_top = move.offsetTop - pos2;
			var new_left = move.offsetLeft - pos1;
			
			if(configurationWindow.maximized){
				configurationWindow.normalize();
				new_top = e.clientY;
				new_left = e.clientX;
			}
			
			if(useBorder){
				var max_width = $(window).width() - $(move).width();
				var max_height = $(window).height() - $(move).height();
				if(new_top < 0) new_top = 0;
				else if(new_top > max_height) new_top = max_height; 
				if(new_left < 0) new_left = 0;
				else if(new_left > max_width) new_left = max_width;
			}
			
			move.style.left = new_left + "px";
			move.style.top = new_top + "px";
			dragged = true;
			
			configurationWindow.clearSelection();
		}

		function closeDragElement() {
			/* stop moving when mouse button is released:*/
			if(useBorder && dragged){
				if(move.style.top.indexOf("%") == -1 && move.style.top.replace("px", "") < 2)
					configurationWindow.maximize();
			}
			document.onmouseup = null;
			document.onmousemove = null;
		}
	},

	isArray : function(what) {
		return Object.prototype.toString.call(what) === '[object Array]';
	},

	isObject : function(what) {
		return Object.prototype.toString.call(what) === '[object Object]';
	},

	join : function(labelFirst, label, element){
		return (labelFirst ? label + " " + element : element + " " + label);
	},

	replaceAll : function(target, search, replacement) {
		return target.replace(new RegExp(search, 'g'), replacement);
	},

	revertChanges : function(){
		$('#' + this.window_id).find("#content").find("input[type=text], input[type=password], input[type=number], input[type=color], textarea").each(function(){
			$(this).val($(this).attr("value"));
			$(this).css("border", "");
		});

		$('#' + this.window_id).find("#content").find("select").each(function(){
			this.value = $(this).find("option[selected]").val();
			$(this).css("border", "");
		});

		$('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').each(function() {
			this.checked = $(this).attr("default") == "true";
			$(this).css("outline", "");
		});

		$($(this)).change();
		this.updateChanged();
	},

	saveChanges : function(){
		$('#' + this.window_id).find("#content").find("input[type=text], input[type=password], input[type=number], input[type=color], textarea").each(function(){
			configurationWindow.set(this.id, this.value);
			$(this).attr("value", this.value);
			$(this).css("border", "");
		});

		$('#' + this.window_id).find("#content").find("select").each(function(){
			configurationWindow.set(this.id, this.value);

			var main_val = this.value;

			$(this).find("option[selected]").removeAttr("selected");
			$(this).find("option").filter(function() {
				return this.innerHTML == main_val;
			}).attr("selected", "selected");

			this.value = main_val;

			$(this).css("border", "");
		});

		$('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').each(function() {
			configurationWindow.set(this.id, this.checked);
			$(this).attr("default", this.checked);
			$(this).css("outline", "");
		});

		this.updateChanged();
		this.save();
	},

    ResetSettings : function(){
        if(this.isArray(this.data.content)){
			for(i = 0; i < this.data.content.length; i++){
				if(this.isObject(this.data.content[i])){
					var object = this.data.content[i];
                    object.default = (object.default == undefined ? "" : object.default);
                    
                    var elem = $('#' + this.window_id).find("#content").find("#" + object.id);
					
					var type = elem.attr("type");
					if(type == undefined && elem.is("select")) type = "select"; 
						
                    switch(type){
						case "text":
						case "number":
						case "password":
						case "select":
						case "textarea":
							$(elem).val(object.default);
							break;
						case "checkbox":
							$(elem).prop("checked", object.default);
							break;
						default: break;
					}
					$(elem).change();
                }
            }
        }
        this.updateChanged();
    },

	close : function(){
		if(this.changed){
			if(!confirm(this.data.confirm_close)){
				return false;
			}
		}
		$('#' + this.window_id).attr("style", "display: none;");
		return true;
	},
	
    open : function(data){
        $('#' + this.window_id).attr("style", "");
    },

	create : function(data){
		//var data = JSON.parse(content);

        this.data = data;
		
        if(this.window_id != undefined)
            $('#' + this.window_id).remove();

		$('#window_style').remove();
		$('#font-awesome').remove();

		if(data.id == undefined) data.id = "window";
		this.window_id = data.id;

		this.load();
	
		$('head').append('<link id="font-awesome" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">');

		if (data.theme == undefined) data.theme = "mac";
		if (!(data.theme == "mac" || data.theme == "win10" || data.theme == "winXP")) data.theme = "mac";
		
		var saved_theme = GM_getValue("config_theme");
		if(data.theme_selector == undefined || data.theme_selector == true || data.theme_selector == "true"){
			data.theme_selector = true;
			if(saved_theme != undefined) data.theme = saved_theme;
		}else{
			data.theme_selector = false;
		}
		
		if(data.width == undefined) data.width = 50;
		if(data.height == undefined) data.height = 50;
		
		var section_color = "#c9c9c9";
		var subsection_color = "#f1f1f1";
		
		var style = "<style id='window_style'>";
		if(data.theme == "mac"){
			style += `
				#` + this.window_id + ` > #top > .btn {
					height: 16px;
					width: 16px;
					background-color: #bbb;
					border-radius: 50%;
					float: right;
					margin-right: 10px;
					display: inline-block;
					font-size: 10px;
					text-align: center;
					color: white;
					cursor: pointer;
					//font-weight: bold;
				}

				#` + this.window_id + ` > #top > .title {
					margin: auto;
					font-size: 16px;
					font-weight: bold;
					cursor: move;
				}

				#` + this.window_id + ` {
					border: 3px solid #f1f1f1;
					border-top-left-radius: 3px;
					border-top-right-radius: 3px;
					height: ` + data.height + `%;
					width: ` + data.width + `%;
					top: ` + ((100 - data.height) / 2) + `%;
					left: ` + ((100 - data.width) / 2) + `%;
					position: fixed;
					z-index: 11000;
					background: white;
					min-width: 250px;
					min-height: 250px;
					resize: both;
					overflow: auto;
					line-height: unset;
					overflow-y: hidden;`
				+ (data.font != undefined ?
					 (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "")  +
					 (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
				   : "") +
				`}

				#` + this.window_id + ` > #top {
					padding: 10px;
					//height: 20px;
					background: #f1f1f1;
					border-top-left-radius: 4px;
					border-top-right-radius: 4px;
					position: absolute;
					width: calc(100% - 20px);
				}
			`;
		}else if(data.theme == "win10"){
			section_color = "#1f9cff";
			subsection_color = "#9dd4ff";
			style += `
				#` + this.window_id + ` > #top > .btn {
					height: 22px;
					width: 30px;
					float: right;
					margin-right: 5px;
					display: inline-block;
					font-size: 16px;
					text-align: center;
					color: white;
					cursor: pointer;
					color: black;
					padding: 2px;
				}
				
				#` + this.window_id + ` > #top > #window_minimize:hover, #` + this.window_id + ` > #top > #window_maximize:hover {
					background-color: #ddd;
				}
				
				#` + this.window_id + ` > #top > #window_close:hover {
					background-color: red;
				}

				#` + this.window_id + ` > #top > .title {
					margin: auto;
					font-size: 16px;
					font-weight: bold;
					cursor: move;
					padding: 10px;
				}

				#` + this.window_id + ` {
					border: 3px solid #1f9cff;
					height: ` + data.height + `%;
					width: ` + data.width + `%;
					top: ` + ((100 - data.height) / 2) + `%;
					left: ` + ((100 - data.width) / 2) + `%;
					position: fixed;
					z-index: 11000;
					background: white;
					min-width: 250px;
					min-height: 250px;
					resize: both;
					overflow: auto;
					line-height: unset;
					overflow-y: hidden;`
				+ (data.font != undefined ?
					 (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "")  +
					 (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
				   : "") +
				`}

				#` + this.window_id + ` > #top {
					//padding: 10px;
					//height: 20px;
					background: #1f9cff;
					position: absolute;
					width: 100%;
				}
			`;
		}else if(data.theme == "winXP"){
			section_color = "#226ce7";
			subsection_color = "#4094ff";
			style += `
				#` + this.window_id + ` > #top > .btn {
					height: 20px;
					width: 20px;
					float: right;
					margin-right: 5px;
					margin-top: 5px;
					display: inline-block;
					font-size: 16px;
					text-align: center;
					color: white;
					cursor: pointer;
					color: white;
					border-radius: 2px;
					padding: 2px;
					border: 1px solid white;
					background: linear-gradient(135deg, #7EAED6 0%, #1B72FF 50%, #1655BE 100%);
				}
				
				#` + this.window_id + ` > #top > #window_minimize:hover, #` + this.window_id + ` > #top > #window_maximize:hover {
					background: linear-gradient(135deg, #6a93b5 0%, #1862da 50%, #124499 100%);
				}
				
				#` + this.window_id + ` > #top > #window_close {
					background: linear-gradient(135deg, #F1A689 0%, #C0442A 50%, #C2311E 100%);
				}
				
				#` + this.window_id + ` > #top > #window_close:hover {
					background: linear-gradient(135deg, #c3846c 0%, #a43923 50%, #982415 100%);
				}

				#` + this.window_id + ` > #top > .title {
					margin: auto;
					font-size: 16px;
					font-weight: bold;
					cursor: move;
					padding: 10px;
					color: white;
				}

				#` + this.window_id + ` {
					border-left: 3px solid #0056e4;
					border-right: 3px solid #0056e4;
					border-bottom: 3px solid #0056e4;
					height: ` + data.height + `%;
					width: ` + data.width + `%;
					top: ` + ((100 - data.height) / 2) + `%;
					left: ` + ((100 - data.width) / 2) + `%;
					position: fixed;
					z-index: 11000;
					background: white;
					min-width: 250px;
					min-height: 250px;
					border-radius: 8px;
					resize: both;
					overflow: auto;
					line-height: unset;
					overflow-y: hidden;`
				+ (data.font != undefined ?
					 (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "")  +
					 (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
				   : "") +
				`}

				#` + this.window_id + ` > #top {
					//padding: 10px;
					//height: 20px;
					border-radius: 5px 5px 0px 0px;
					background: linear-gradient(to bottom, #4094ff 0%, #0056e4 13%, #0056e4 71%, #16428b 100%);
					position: absolute;
					width: 100%;
				}
			`;
		}
		
		style += `
			#` + this.window_id + ` > #footer {
				text-align: right;
				margin: 0px 0px 4px -20px;
				height: 40px;
				border-top-left-radius: 4px;
				border-top-right-radius: 4px;
				position: absolute;
				width: 100%;
				bottom: 0;
				pointer-events: none;
			}

			#` + this.window_id + ` > #footer > button {
				background-color: #f1f1f1;
				border: none;
				color: black;
				padding: 12px 40px;
				font-size: 14px;
				cursor: pointer;
				margin-left: 5px;
				pointer-events: all;
			}

			#` + this.window_id + ` > #footer > button:hover {
				background-color: RoyalBlue;
				color: white;
			}
			
			#` + this.window_id + ` > #footer > button:disabled {
				background-color: darkgrey;
				color: white;
			}
			
			#` + this.window_id + ` > #content {
				padding: 10px;
				margin-top: 40px;
				overflow-y: scroll;
				height: calc(100% - 75px);
				overflow-wrap: break-word;
			}

			#` + this.window_id + ` > #content > input,#` + this.window_id + ` > #content > select {`
				 + (data.font != undefined ?
				 (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "")  +
				 (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
			   : "") +
			`}

			#` + this.window_id + ` > #content > br {
				display: block;
				margin-top: 4px;
				content: " ";
			}

			#` + this.window_id + ` > #theme_dropdown {
				float: left;
				bottom: 5px;
				position: absolute;
				left: 5px;
				border: none;
				-webkit-appearance: none;
				-moz-appearance: none;
				appearance: none;
				color: gray;
				background-color: transparent;
			}
			
			#` + this.window_id + ` > #theme_dropdown > option {
				color: black;
			}
			
			.no-margin {
				margin: 0px;
			}
			
			.wrap-collapsible {
				margin-bottom: 1.2rem 0;
			}

			.toggle {
				display: none;
			}

			.lbl-toggle {
				display: block;
				cursor: pointer;
				
				transition: all 0.25s ease-out;
			}
			
			.lbl-toggle h2, .lbl-toggle h4 {
				display: inline;
			}

			.lbl-toggle:hover {
				color: white;
			}

			.lbl-toggle::before {
				content: ' ';
				display: inline-block;

				border-top: 5px solid transparent;
				border-bottom: 5px solid transparent;
				border-left: 5px solid currentColor;
				vertical-align: middle;
				margin-right: .7rem;
				transform: translateY(-2px);

				transition: transform .2s ease-out;
			}

			.toggle:checked + .lbl-toggle::before {
				transform: rotate(90deg) translateX(-3px);
			}

			.collapsible-content {
				max-height: 0px;
				overflow: hidden;
				transition: max-height .25s ease-in-out;
			}

			.toggle:checked + .lbl-toggle + .collapsible-content {
				max-height: unset;
			}

			.collapsible-content .content-inner {
				//background: rgba(161, 161, 161, 0.2);
				//border: 1px solid black;
			}
		`;
		
		style += "<style>";
		
		$('head').append(style);
		
		if(data.theme_section_color == undefined || data.theme_section_color == false){
			section_color = "#c9c9c9";
			subsection_color = "#f1f1f1";
		}
		
		var content = "";

		if(this.isArray(data.content)){
			var section_collapsible = false;
			var subsection_collapsible = false;
			var collapsible_id = 1;
			
			for(i = 0; i < data.content.length; i++){
				if(this.isObject(data.content[i])){
					var label_first = undefined;
					Object.keys(data.content[i]).forEach(function(key){
						if(label_first != undefined) return;

						if(key == "label") label_first = true;
						else if(key == "type") label_first = false;
					});

					var label = this.replaceAll(data.content[i].label, "  ", "&nbsp;&nbsp;");

					var object = data.content[i];

					if(object.style != undefined) object.style = " style='" + object.style + "'";
					else object.style = "";

					if(object.require != undefined) object.style += " require='" + object.require + "'";
					
					switch(object.type){
						case "p":
							content += "<p class='no-margin'" + object.style + ">" + label  + "</p>";
							break;
						case "h1":
							content += "<h1 class='no-margin'" + object.style + ">" + label + "</h1>";
							break;
						case "h2":
							content += "<h2 class='no-margin'" + object.style + ">" + label + "</h2>";
							break;
						case "h3":
							content += "<h3 class='no-margin'" + object.style + ">" + label + "</h3>";
							break;
						case "h4":
							content += "<h4 class='no-margin'" + object.style + ">" + label + "</h4>";
							break;
						case "section":
							if(object.align == undefined) object.align = "center";
							if(object.background == undefined) object.background = section_color;
							
							if(subsection_collapsible){
								content += "</div></div></div>";
								subsection_collapsible = false;
							}
							
							if(section_collapsible){
								content += "</div></div></div>";
								section_collapsible = false;
							}
							
							if(object.collapsible != undefined && object.collapsible){
								content += "<div class='wrap-collapsible'><input id='collapsible" + collapsible_id + "' class='toggle' type='checkbox' " + (object.collapsed != undefined && object.collapsed == false ? "checked" : "") + "><label style='margin: 5px 0px 0px 0px; background: " + object.background + "; text-align: " + object.align + ";' for='collapsible" + collapsible_id + "' class='lbl-toggle'><h2>" + label + "</h2></label><div class='collapsible-content'><div class='content-inner'>";
								section_collapsible = true;
								collapsible_id++;
							}else{
								content += "<div width='100%' style='margin: 5px 0px; background: " + object.background + "; text-align: " + object.align + ";'><h2 class='no-margin'>" + label + "</h2></div>";
							}
							break;
						case "subsection":
							if(object.align == undefined) object.align = "center";
							if(object.background == undefined) object.background = subsection_color;
							
							if(subsection_collapsible){
								content += "</div></div></div>";
								subsection_collapsible = false;
							}
							
							if(object.collapsible != undefined && object.collapsible){
								content += "<div class='wrap-collapsible'><input id='collapsible" + collapsible_id + "' class='toggle' type='checkbox' " + (object.collapsed != undefined && object.collapsed == false ? "checked" : "") + "><label style='margin: 5px 0px 0px 0px; background: " + object.background + "; text-align: " + object.align + ";' for='collapsible" + collapsible_id + "' class='lbl-toggle'><h4>" + label + "</h4></label><div class='collapsible-content'><div class='content-inner'>";
								subsection_collapsible = true;
								collapsible_id++;
							}else{
								content += "<div width='100%' style='margin: 5px 0px; background: " + object.background + "; text-align: " + object.align + ";'><h4 class='no-margin'>" + label + "</h4></div>";
							}
							break;
						case "text":
							var value = this.getElseSet(object.id, object.default, "");
							
							content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='text' value='" + value + "' />");

							content += "<br>";
							break;
						case "textarea":
							var value = this.getElseSet(object.id, object.default, "");
							
							content += this.join(label_first, label, "<textarea id='" + object.id + "'" + object.style + " value='" + value + "'>" + value + "</textarea>");

							content += "<br>";
							break;
						case "password":
							var value = this.getElseSet(object.id, object.default, "");
							
							content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='password' value='" + value + "' />");

							content += "<br>";
							break;
						case "checkbox":
							var value = this.getElseSet(object.id, object.default, false);
							
							if(value == "true" || value == true) value = true;
							else value = false;

							label = "<label for='" + object.id + "'>" + label + "</label>";
							
							content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " default='" + value + "' type='checkbox' " + (value ? "checked" : "") + "/>");

							content += "<br>";
							break;
						case "select":
							var value = this.getElseSet(object.id, object.default, "");

							var select = " <select" + object.style + " id='" + object.id + "'>";
							object.options.forEach(function(opt){
								if(opt == value){
									select += "<option selected>" + opt + "</option>";
								}else{
									select += "<option>" + opt + "</option>";
								}
							});
							select += "</select> ";

							content += this.join(label_first, label, select);

							content += "<br>";
							break;
						case "numeric":
							var value = this.getElseSet(object.id, object.default, 0);
							
							var element = "<input id='" + object.id + "'" + object.style + " type='number' value='" + value + "'";
							if(object.min != undefined) element += " min='" + object.min + "'";
							if(object.max != undefined) element += " max='" + object.max + "'";
							element += " />";
							
							content += this.join(label_first, label, element);

							content += "<br>";
							break;
						case "color":
							var value = this.getElseSet(object.id, object.default, "#FFFFFF");

							content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='color' value='" + value + "' />");

							content += "<br>";
							break;
						default: break;
					}
				}else{
					content += "<p>" + data.content[i] + "</p>";
				}
			}
			
			if(subsection_collapsible){
				content += "</div></div></div>";
				section_collapsible = false;
			}
			
			if(section_collapsible){
				content += "</div></div></div>";
				section_collapsible = false;
			}
		}else{
			content = data.content;
		}
		//content += "<br style='height: 25px;' />";
		content += "<br><br><br>";
		
		var buttons = "";

        if(data.completeresetbutton == undefined || data.completeresetbutton == true || data.completeresetbutton == "true"){
            buttons += "<button id='completeResetButton'><i class='fa fa-trash'></i></button>";
        }

		if(data.revertbutton == undefined || data.revertbutton == true ||  data.revertbutton == "true"){
			buttons += "<button id='revertButton'><i class='fa fa-undo'></i></button>";
		}

		if(data.savebutton == undefined || data.savebutton == true ||  data.savebutton == "true"){
			buttons += "<button id='saveButton'><i class='fa fa-save'></i></button>";
		}

		var topbuttons = "";
		if(data.top == undefined || data.top.close == undefined || data.top.close == "true"){
			if(data.theme == "mac")		topbuttons += '<span id="window_close" class="btn" style="background:#ED594A; margin-right: 20px;"><i class="fa fa-times" style="vertical-align: sub;"></i></span>';
			else if(data.theme == "win10") topbuttons += '<span id="window_close" class="btn" style="margin-right: 0px;"><i class="fa fa-times"></i></span>';
			else if(data.theme == "winXP") topbuttons += '<span id="window_close" class="btn"><i class="fa fa-times"></i></span>';
		}
		
		if(data.top == undefined || data.top.maximize == undefined || data.top.maximize == "true"){
			if(data.theme == "mac")		topbuttons += '<span id="window_maximize" class="btn" style="background:#FDD800;"><i class="fa fa-window-maximize" style="vertical-align: sub;"></i></span>';
			else if(data.theme == "win10" || data.theme == "winXP") topbuttons += '<span id="window_maximize" class="btn"><i class="fa fa-window-maximize"></i></span>';
		}
		
		if(data.top == undefined || data.top.minimize == undefined || data.top.minimize == "true"){
			if(data.theme == "mac")		topbuttons += '<span id="window_minimize" class="btn" style="background:#5AC05A;"><i class="fa fa-window-minimize" style="vertical-align: sub;"></i></span>';
			else if(data.theme == "win10" || data.theme == "winXP") topbuttons += '<span id="window_minimize" class="btn"><i class="fa fa-window-minimize"></i></span>';
		}
		

		$('body').append(`
			<div id="` + this.window_id + `" style='display: none;' class="window">
				<div id="top">
					` + topbuttons +
					`<p class="title">` + data.title + `</p>
				</div>

				<div id="content">
					` + content + `
				</div>

				<div id="footer">
					` + buttons + `
				</div>
				` +
				(data.theme_selector ? `<select id="theme_dropdown" value="Theme">
					<option value="std" style="display: none;">Theme</option>
					<option value="mac">Mac</option>
					<option value="win10">Windows 10</option>
					<option value="winXP">Windows XP</option>
				</select>` : "") + `
			</div>
		`);

		this.makeDragable($('#' + this.window_id)[0], $('#' + this.window_id).find("#top")[0], true);

        var confirm_close = "Unsaved changes. Discard changes?";
        var confirm_revert = "Reset all changes?";
        var confirm_reset = "Bring settings back to factory settings?";
        if(data.confirm_close != undefined) confirm_close = data.confirm_close;
        if(data.confirm_revert != undefined) confirm_revert = data.confirm_revert;
        if(data.confirm_reset != undefined) confirm_reset = data.confirm_reset;

		$('#' + this.window_id).find('#revertButton').click(function(){
            if(confirm(confirm_revert)) configurationWindow.revertChanges();
		});
		
		$('#' + this.window_id).find('#saveButton').click(function(){
			configurationWindow.saveChanges();
            $('#' + configurationWindow.window_id).find('#saveButton').css("background", "lime");
            setTimeout(function(){
                $('#' + configurationWindow.window_id).find('#saveButton').css("background", "");
            }, 1000);
		});

        $('#' + this.window_id).find('#completeResetButton').click(function(){
			if(confirm(confirm_reset)) configurationWindow.ResetSettings();
		});

        $('#' + this.window_id).find('#window_close').click(function(){
            configurationWindow.close();
		});

		//================ WINDOW RESIZE BUTTONS ===================//
		$('#' + this.window_id).find('#window_maximize').click(function(){
			if(configurationWindow.maximized && !configurationWindow.minimized)
				configurationWindow.normalize();
			else
				configurationWindow.maximize();
		});

		$('#' + this.window_id).find('#window_minimize').click(function(){
			configurationWindow.minimize();
		});

		$('#' + this.window_id).find("#top").dblclick(function(){
			if(configurationWindow.minimized){
				if(configurationWindow.maximized)
					configurationWindow.maximize();
				else
					configurationWindow.normalize();
			}else{
				if(configurationWindow.maximized)
					configurationWindow.normalize();
				else
					configurationWindow.maximize();
			}
			configurationWindow.clearSelection();
		});

		//==================== THEME SELECTOR =======================//
		$('#' + this.window_id).find("#theme_dropdown").change(function(){
			if(! configurationWindow.close()) return;
			GM_setValue("config_theme", this.value);
			configurationWindow.create(configurationWindow.data);
			configurationWindow.open();
		});
		

		//==================== FIELD CHANGE LISTENER =====================//
		$('#' + this.window_id).find("#content").find("input[type=text], input[type=number], input[type=password], input[type=color], textarea").change(function(){
			if($(this).attr("value") != $(this).val())
				$(this).css("border", "#fff400 solid 2px");
			else
				$(this).css("border", "");

			configurationWindow.updateChanged();
		});
		 
		$('#' + this.window_id).find("#content").find("input[type=number]").change(function(){
			if($(this).attr("min") != undefined && $(this).val() < parseFloat($(this).attr("min")))
				$(this).val($(this).attr("min"));
			else if($(this).attr("max") != undefined && $(this).val() > parseFloat($(this).attr("max"))){
				$(this).val($(this).attr("max"));
			}
			
			configurationWindow.updateChanged();
		});

		

		$('#' + this.window_id).find("#content").find("select").change(function(){
			if(this.value != $(this).find("option[selected]").val())
				$(this).css("border", "#fff400 solid 2px");
			else
				$(this).css("border", "");

			configurationWindow.updateChanged();
		});

		$('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').change(function() {
			if(this.checked != ($(this).attr("default") == "true")){
				$(this).css("outline", "#fff400 solid 3px");
			}else{
				$(this).css("outline", "");
			}
			
			$('[require="' + this.id + '"]').prop("disabled", !this.checked);
			
			configurationWindow.updateChanged();
		});
		
		$('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').trigger("change");
		
		$(document).keyup(function(e) {
			if (e.keyCode == 27) {
				configurationWindow.close();
			}
		});
		
		this.updateChanged();
	}
};