Greasy Fork is available in English.

GM_config

GreaseMonkey Script Configurator

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/1884/4836/GM_config.js

// ==UserScript==
// @name           GM_config
// @namespace      http://userscripts.org/users/23652
// @description    GreaseMonkey Script Configurator
// @include        http://*
// @include        https://*
// @include        file:*
// @copyright      JoeSimmons & Sizzlemctwizzle & IzzySoft
// @version        1.2.57
// @license        LGPL version 3 or any later version; http://www.gnu.org/copyleft/lgpl.html
// ==/UserScript==

/* Instructions ---------------------------------------------------------------------------------------------------

GM_config is cross-browser compatible.

To use it in a Greasemonkey/Tampermonkey/Violentmonkey script, you can just @require it.

If you can't @require it, you will need to manually include the code at the beginning of your user script.

In non-Greasemonkey, stored settings will only be accessible on the same domain in which they were saved.

---------------------------------------------------------------------------------------------------------------- */



/* CHANGELOG --------------------------------------------------------------------------

1.2.57
	- Fixed TypeError with the "options" setting of a "select" field
			The "options" setting needs to be a JSON object, not an array

1.2.56
	- started keeping changelog in source
	- added type "password"
	- fixed error when user doesn't define any sections

------------------------------------------------------------------------------------- */



var GM_config = {
 storage: 'GM_config',
 init: function() {
        // loop through GM_config.init() arguments
	for(var i=0,l=arguments.length,arg; i<l; ++i) {
		arg=arguments[i];
		switch(typeof arg) {
            case 'object': for(var j in arg) { // could be a callback functions or settings object
							switch(j) {
							case "open": GM_config.onOpen=arg[j]; delete arg[j]; break; // called when frame is gone
							case "close": GM_config.onClose=arg[j]; delete arg[j]; break; // called when settings have been saved
							case "save": GM_config.onSave=arg[j]; delete arg[j]; break; // store the settings objects
							default: var settings = arg;
							}
			} break;
            case 'function': GM_config.onOpen = arg; break; // passing a bare function is set to open
                        // could be custom CSS or the title string
			case 'string': if(arg.indexOf('{') !== -1 && arg.indexOf('}') !== -1) var css = arg;
				else GM_config.title = arg;
				break;
		}
	}
	if(!GM_config.title) GM_config.title = 'Settings - Anonymous Script'; // if title wasn't passed through init()

	// give the script a unique saving ID for non-firefox browsers
	GM_config.storage = GM_config.title.replace(/\W+/g, "").toLowerCase();

	var stored = GM_config.read(); // read the stored settings
	GM_config.passed_values = {};
	for(var i in settings) {
		GM_config.doSettingValue(settings, stored, i, null, false);
		if(settings[i].kids) for(var kid in settings[i].kids) GM_config.doSettingValue(settings, stored, kid, i, true);
	}
	GM_config.values = GM_config.passed_values;
	GM_config.settings = settings;
	if (css) GM_config.css.stylish = css;
 },
 open: function() {
 if(document.evaluate("//iframe[@id='GM_config']",document,null,9,null).singleNodeValue) return;
	// Create frame
	document.body.appendChild((GM_config.frame=GM_config.create('iframe',{id:'GM_config', style:'position: fixed; top: 0; left: 0; opacity: 0; display: none; z-index: 999999; width: 75%; height: 75%; max-height: 95%; max-width: 95%; border:3px ridge #000000; overflow: auto;'})));
        GM_config.frame.src = 'about:blank'; // In WebKit src cant be set until it is added to the page
	GM_config.frame.addEventListener('load', function() {
		var obj = GM_config, doc = this.contentDocument, frameBody = doc.getElementsByTagName('body')[0], create=obj.create, settings=obj.settings, anch, secNo;
		obj.frame.contentDocument.getElementsByTagName('head')[0].appendChild(create('style',{type:'text/css',textContent:obj.css.basic + "\n\n" + obj.css.stylish}));

		// Add header and title
		frameBody.appendChild(create('div', {id:'header',className:'config_header block center', innerHTML:obj.title}));

		// Append elements
		anch = frameBody; // define frame body
		secNo = 0; // anchor to append elements
		for(var i in settings) {
			var type, field = settings[i], value = obj.values[i], section = (field.section ? field.section : ["Main Options"]),
				headerExists = doc.evaluate(".//div[@class='section_header_holder' and starts-with(@id, 'section_')]", frameBody, null, 9, null).singleNodeValue;

			if(typeof field.section !== "undefined" || headerExists === null) {
				anch = frameBody.appendChild(create('div', {className:'section_header_holder', id:'section_'+secNo, kids:new Array(
				  create('a', {className:'section_header center', href:"javascript:void(0);", id:'c_section_kids_'+secNo, textContent:section[0], onclick:function(){GM_config.toggle(this.id.substring(2));}}),
				  create('div', {id:'section_kids_'+secNo, className:'section_kids', style:obj.getValue('section_kids_'+secNo, "")==""?"":"display: none;"})
				)}));
				if(section[1]) anch.appendChild(create('p', {className:'section_desc center',innerHTML:section[1]}));
				secNo++;
			}
			anch.childNodes[1].appendChild(GM_config.addToFrame(field, i, false));
		}

		// Add save and close buttons
		frameBody.appendChild(obj.create('div', {id:'buttons_holder', kids:new Array(
			obj.create('button',{id:'saveBtn',textContent:'Save',title:'Save options and close window',className:'saveclose_buttons',onclick:function(){GM_config.close(true)}}),
			obj.create('button',{id:'cancelBtn', textContent:'Cancel',title:'Close window',className:'saveclose_buttons',onclick:function(){GM_config.close(false)}}),
			obj.create('div', {className:'reset_holder block', kids:new Array(
				obj.create('a',{id:'resetLink',textContent:'Restore to default',href:'#',title:'Restore settings to default configuration',className:'reset',onclick:obj.reset})
		)}))}));

		obj.center(); // Show and center it
		window.addEventListener('resize', obj.center, false); // Center it on resize
		if (obj.onOpen) obj.onOpen(); // Call the open() callback function
		
		// Close frame on window close
		window.addEventListener('beforeunload', function(){GM_config.remove(this);}, false);
	}, false);
 },
 close: function(save) {
	if(save) {
		var type, fields = GM_config.settings, typewhite=/radio|text|hidden|password|checkbox/;
		for(f in fields) {
			var field = GM_config.frame.contentDocument.getElementById('field_'+f), kids=fields[f].kids;
			if(typewhite.test(field.type)) type=field.type;
				else type=field.tagName.toLowerCase();
			GM_config.doSave(f, field, type);
			if(kids) for(var kid in kids) {
			var field = GM_config.frame.contentDocument.getElementById('field_'+kid);
			if(typewhite.test(field.type)) type=field.type;
				else type=field.tagName.toLowerCase();
			GM_config.doSave(kid, field, type, f);
			}
		}
                if(GM_config.onSave) GM_config.onSave(); // Call the save() callback function
                GM_config.save();
	}
	if(GM_config.frame) GM_config.remove(GM_config.frame);
	delete GM_config.frame;
        if(GM_config.onClose) GM_config.onClose(); //  Call the close() callback function
 },
 set: function(name,val) {
	GM_config.values[name] = val;
 },
 get: function(name) {
	return GM_config.values[name];
 },
 isGM: (typeof window.opera === "undefined" && typeof window.chrome === "undefined" && typeof GM_info === "object" && typeof GM_registerMenuCommand === "function"),
 log: function(str) {

	if(this.isGM) return GM_log(str);
		else if(window.opera) return window.opera.postError(str);
		else return console.log(str);

 },
 getValue : function(name, d) {
	var r, def = (typeof d !== "undefined" ? d : "");
	switch(this.isGM === true) {
		case true: r = GM_getValue(name, def); break;
		case false: r = localStorage.getItem(name) || def; break;
	}
	return r;
},
 setValue : function(name, value) {
	switch(this.isGM === true) {
		case true: GM_setValue(name, value); break;
		case false: localStorage.setItem(name, value); break;
	}
 },
  deleteValue : function(name) {
	switch(this.isGM === true) {
		case true: GM_deleteValue(name); break;
		case false: localStorage.removeItem(name); break;
	}
},
 save: function(store, obj) {
    try {
		var val = JSON.stringify(obj || GM_config.values);
		GM_config.setValue((store||GM_config.storage),val);
    } catch(e) {
		GM_config.log("GM_config failed to save settings!\n" + e);
    }
 },
 read: function(store) {
	var val = GM_config.getValue((store || GM_config.storage), '{}');
	switch(typeof val) {
		case "string": var rval = JSON.parse(val); break;
		case "object": var rval = val; break;
		default: var rval = {};
	}
    return rval;
 },
 reset: function(e) {
	e.preventDefault();
	var type, obj = GM_config, fields = obj.settings;
	for(f in fields) {
		var field = obj.frame.contentDocument.getElementById('field_'+f), kids=fields[f].kids;
		if(field.type=='radio'||field.type=='text'||field.type=='checkbox') type=field.type;
		else type=field.tagName.toLowerCase();
		GM_config.doReset(field, type, null, f, null, false);
		if(kids) for(var kid in kids) {
			var field = GM_config.frame.contentDocument.getElementById('field_'+kid);
			if(field.type=='radio'||field.type=='text'||field.type=='checkbox') type=field.type;
				else type=field.tagName.toLowerCase();
			GM_config.doReset(field, type, f, kid, true);
		}
	}
 },
 addToFrame : function(field, i, k) {
	var elem, obj = this, anch = this.frame, value = obj.values[i], Options = field.options, label = field.label, create=obj.create, isKid = (k !== null && k === true);
		switch(field.type) {
				case 'textarea':
					elem = create(isKid ? "span" : "div", {title:field.title||'', kids:new Array(
						create('span', {textContent:label, className:'field_label'}),
						create('textarea', {id:'field_'+i,innerHTML:value, cols:(field.cols?field.cols:20), rows:(field.rows?field.rows:2)})
					), className: 'config_var'});
					break;
				case 'radio':
					var boxes = new Array();
					for (var j = 0,len = Options.length; j<len; j++) {
						boxes.push(create('span', {textContent:Options[j]}));
						boxes.push(create('input', {value:Options[j], type:'radio', name:i, checked:Options[j]==value?true:false}));
					}
					elem = create(isKid ? "span" : "div", {title:field.title||'', kids:new Array(
						create('span', {textContent:label, className:'field_label'}),
						create('span', {id:'field_'+i, kids:boxes})
					), className: 'config_var'});
					break;
				case 'select':
					var options = [];
					if(typeof Options === "object" && typeof Options.push !== "function") for(var j in Options) options.push(create('option',{textContent:Options[j],value:j,selected:(j==value)}));
						else options.push(create("option", {textContent:"Error - \"options\" needs to be a JSON object.", value:"error", selected:"selected"}));
					elem = create(isKid ? "span" : "div", {title:field.title||'', kids:new Array(
						create('span', {textContent:label, className:'field_label'}),
						create('select',{id:'field_'+i, kids:options})
					), className: 'config_var'});
					break;
				case 'checkbox':
					elem = create(isKid ? "span" : "div", {title:field.title||'', kids:new Array(
						create('label', {textContent:label, className:'field_label', "for":'field_'+i}),
						create('input', {id:'field_'+i, type:'checkbox', value:value, checked:value})
					), className: 'config_var'});
					break;
				case 'button':
				var tmp;
					elem = create(isKid ? "span" : "div", {kids:new Array(
						(tmp=create('input', {id:'field_'+i, type:'button', value:label, size:(field.size?field.size:25), title:field.title||''}))
					), className: 'config_var'});
					if(field.script) obj.addEvent(tmp, 'click', field.script);
					break;
				case 'hidden':
					elem = create(isKid ? "span" : "div", {title:field.title||'', kids:new Array(
						create('input', {id:'field_'+i, type:'hidden', value:value})
					), className: 'config_var'});
					break;
				case 'password':
					elem = create(isKid ? "span" : "div", {title:field.title||'', kids:new Array(
						create('span', {textContent:label, className:'field_label'}),
						create('input', {id:'field_'+i, type:'password', value:value, size:(field.size?field.size:25)})
					), className: 'config_var'});
					break;
				default:
					elem = create(isKid ? "span" : "div", {title:field.title||'', kids:new Array(
						create('span', {textContent:label, className:'field_label'}),
						create('input', {id:'field_'+i, type:'text', value:value, size:(field.size?field.size:25)})
					), className: 'config_var'});
			}
	if(field.kids) {
		var kids=field.kids;
		for(var kid in kids) elem.appendChild(obj.addToFrame(kids[kid], kid, true));
	}
return elem;
},
 doSave : function(f, field, type, oldf) {
 var isNum=/^[\d\.]+$/, set = oldf ? GM_config.settings[oldf]["kids"] : GM_config.settings;
 switch(type) {
				case 'text':
					GM_config.values[f] = ((set[f].type=='text') ? field.value : ((isNum.test(field.value) && ",int,float".indexOf(","+set[f].type)!=-1) ? parseFloat(field.value) : false));
					if(set[f]===false) {
						alert('Invalid type for field: '+f+'\nPlease use type: '+set[f].type);
						return;
					}
					break;
				case 'hidden': case 'password':
					GM_config.values[f] = field.value.toString();
					break;
				case 'textarea':
					GM_config.values[f] = field.value;
					break;
				case 'checkbox':
					GM_config.values[f] = field.checked;
					break;
				case 'select':
					GM_config.values[f] = field.options[field.selectedIndex].value;
					break;
				case 'span':
					var radios = field.getElementsByTagName('input');
					if(radios.length>0) for(var i=radios.length-1; i>=0; i--) {
						if(radios[i].checked) GM_config.values[f] = radios[i].value;
					}
					break;
			}
 },
 doSettingValue : function(settings, stored, i, oldi, k) {
		var set = k!=null && k==true && oldi!=null ? settings[oldi]["kids"][i] : settings[i];
			if(",save,open,close".indexOf(","+i) == -1) {
            // The code below translates to:
            // if a setting was passed to init but wasn't stored then 
            //      if a default value wasn't passed through init() then use null
            //      else use the default value passed through init()
            // 		else use the stored value
            try {
            var value = (stored[i]==undefined ? (set["default"]==undefined ? null : set["default"]) : stored[i]);
			} catch(e) {
			var value = (stored[i]=="undefined" ? (set["default"]=="undefined" ? null : set["default"]) : stored[i]);
			}
            
            // If the value isn't stored and no default was passed through init()
            // try to predict a default value based on the type
            if (value === null) {
                switch(set["type"]) {
                    case 'radio': case 'select':
                        value = set.options[0]; break;
                    case 'checkbox':
                        value = false; break;
                    case 'int': case 'float':
                        value = 0; break;
                    default:
					value = (typeof stored[i]=="function") ? stored[i] : "";
                }
			}
			
			}
	GM_config.passed_values[i] = value;
 },
 doReset : function(field, type, oldf, f, k) {
 var isKid = k!=null && k==true, obj=GM_config,
	 set = isKid ? obj.settings[oldf]["kids"][f] : obj.settings[f];
 switch(type) {
			case 'text':
				field.value = set['default'] || '';
				break;
			case 'hidden': case 'password':
				field.value = set['default'] || '';
				break;
			case 'textarea':
				field.value = set['default'] || '';
				break;
			case 'checkbox':
				field.checked = set['default'] || false;
				break;
			case 'select':
				if(set['default']) {
					for(var i=field.options.length-1; i>=0; i--)
					if(field.options[i].value==set['default']) field.selectedIndex=i;
				}
				else field.selectedIndex=0;
				break;
			case 'span':
				var radios = field.getElementsByTagName('input');
				if(radios.length>0) for(var i=radios.length-1; i>=0; i--) {
					if(radios[i].value==set['default']) {
						radios[i].checked=true;
					}
				}
				break;
		}
 },
 values: {},
 settings: {},
 css: {
	 basic: 'body {background:#FFFFFF;}\n' +
	 '.indent40 {margin-left:40%;}\n' +
	 '* {font-family: arial, tahoma, sans-serif, myriad pro;}\n' +
	 '.field_label {font-weight:bold; font-size:12px; margin-right:6px;}\n' +
	 '.block {display:block;}\n' +
	 '.saveclose_buttons {\n' +
	 'margin:16px 10px 10px 10px;\n' +
	 'padding:2px 12px 2px 12px;\n' +
	 '}\n' +
	 '.reset, #buttons_holder, .reset a {text-align:right; color:#000000;}\n' +
	 '.config_header {font-size:20pt; margin:0;}\n' +
	 '.config_desc, .section_desc, .reset {font-size:9pt;}\n' +
	 '.center {text-align:center;}\n' +
	 '.section_header_holder {margin-top:8px;}\n' +
	 '.config_var {margin:0 0 4px 0; display:block;}\n' +
	 '.config_var {font-size: 13px !important;}\n' +
	 '.section_header {font-size:13pt; background:#414141; color:#FFFFFF; border:1px solid #000000; margin:0;}\n' +
	 '.section_desc {font-size:9pt; background:#EFEFEF; color:#575757; border:1px solid #CCCCCC; margin:0 0 6px 0;}\n' +
	 'input[type="radio"] {margin-right:8px;}',
	 stylish: ''
 },
 create: function(a,b) {
	var ret=window.document.createElement(a);
	if(b) for(var prop in b) {
		if(prop.indexOf('on')==0) ret.addEventListener(prop.substring(2),b[prop],false);
		else if(prop=="kids" && (prop=b[prop])) for(var i=0; i<prop.length; i++) ret.appendChild(prop[i]);
		else if(",style,accesskey,id,name,src,href,for".indexOf(","+prop.toLowerCase())!=-1) ret.setAttribute(prop, b[prop]);
		else ret[prop]=b[prop];
	}
	return ret;
 },
 center: function() {
	var node = GM_config.frame, style = node.style, beforeOpacity = style.opacity;
	if(style.display=='none') style.opacity='0';
	style.display = '';
	style.top = Math.floor((window.innerHeight/2)-(node.offsetHeight/2)) + 'px';
	style.left = Math.floor((window.innerWidth/2)-(node.offsetWidth/2)) + 'px';
	style.opacity = '1';
 },
 run: function() {
    var script=GM_config.getAttribute('script');
    if(script && typeof script=='string' && script!='') {
      func = new Function(script);
      window.setTimeout(func, 0);
    }
 },
 addEvent: function(el, ev, scr) {
	if(el) el.addEventListener(ev, function() {
		typeof scr === 'function' ? window.setTimeout(scr, 0) : eval(scr)
	}, false);
},
 remove: function(el) {
	if(el && el.parentNode) el.parentNode.removeChild(el);
},
 toggle : function(e) {
	var node=GM_config.frame.contentDocument.getElementById(e);
	node.style.display=(node.style.display!='none')?'none':'';
	GM_config.setValue(e, node.style.display);
 },
};


/* EXAMPLE CODE BELOW --------------------------

GM_config.init("Test", {
	"one" : {
		"label" : "Option One",
		"type" : "checkbox",
		"default" : false
	},
	"two" : {
		"label" : "Option Two",
		"type" : "checkbox",
		"default" : false
	},
	"three" : {
		"label" : "Option Three",
		"type" : "password"
	},
	 "four" : {
		"label" : "Option Four",
		"type" : "select",
		"options" : {
			"one" : "One",
			"two" : "Two"
		}
	}
});

GM_config.open();

------------------------------------------------- */