이 스크립트는 직접 설치해서 쓰는 게 아닙니다. 다른 스크립트가 메타 명령 // @require https://update.greasyfork.org/scripts/7212/156587/GM_config%20%28eight%27s%20version%29.js
(으)로 포함하여 쓰는 라이브러리입니다.
/* exported GM_config */
/*
Copyright 2009+, GM_config Contributors (https://github.com/sizzlemctwizzle/GM_config)
GM_config Contributors:
Mike Medley <medleymind@gmail.com>
Joe Simmons
Izzy Soft
Marti Martz
GM_config is distributed under the terms of the GNU Lesser General Public License.
GM_config is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// ==UserScript==
// @name GM_config (eight's version)
// @description A library to help you set up configure in greasemonkey script.
// @namespace eight04.blogspot.com
// @version 2.2.0
// @grant GM_setValue
// @grant GM_getValue
// @license LGPL version 3 or any later version; http://www.gnu.org/copyleft/lgpl.html
// @copyright 2015+, eight <https://github.com/eight04/GM_config>
// @homepageURL https://github.com/eight04/GM_config
// @supportURL https://github.com/eight04/GM_config/issues
// @attribution sizzlemctwizzle (https://github.com/sizzlemctwizzle/GM_config)
// @attribution Joe Simmons (https://greasyfork.org/en/scripts/1884-gm-config)
// ==/UserScript==
var GM_config = function(){
"use strict";
var config = {
title: null,
settings: null,
local: false
}, dialog, css, GM_config;
function addChild(e, children) {
if (!children) {
return;
}
if (!Array.isArray(children)) {
children = [children];
}
var i;
for (i = 0; i < children.length; i++) {
if (typeof children[i] == "string") {
children[i] = document.createTextNode(children[i]);
}
e.appendChild(children[i]);
}
}
function element(tag, attr, children) {
var e, key, key2;
e = document.createElement(tag);
if (attr) {
for (key in attr) {
if (typeof attr[key] == "boolean") {
if (attr[key]) {
e.setAttribute(key, "");
} else {
e.removeAttribute(key);
}
} else if (key == "event") {
for (key2 in attr[key]) {
e["on" + key2] = attr[key][key2];
}
} else {
e.setAttribute(key, attr[key]);
}
}
}
addChild(e, children);
return e;
}
function frag(children) {
var fragment = document.createDocumentFragment();
addChild(fragment, children);
return fragment;
}
function getValue(key) {
if (config.local) {
key = location.hostname + "/" + key;
}
var value = GM_getValue(key);
if (GM_getValue(key + "/type") == "object") {
value = JSON.parse(value);
}
return value;
}
function setValue(key, value) {
if (config.local) {
key = location.hostname + "/" + key;
}
if (typeof value == "object") {
GM_setValue(key + "/type", "object");
value = JSON.stringify(value);
}
GM_setValue(key, value);
}
function read() {
var key, s;
config.local = GM_getValue(location.hostname, false);
for (key in config.settings) {
s = config.settings[key];
s.value = getValue(key, s.type);
if (s.value == null) {
s.value = s.default;
}
}
}
function save() {
var key, s;
GM_setValue(location.hostname, config.local);
for (key in config.settings) {
s = config.settings[key];
if (s.value == null) {
setValue(key, s.default);
} else {
setValue(key, s.value);
}
}
}
function destroyDialog() {
dialog.element.classList.remove("config-dialog-ani");
setTimeout(function() {
document.body.classList.remove("config-dialog-open");
document.body.style.paddingRight = "";
dialog.element.parentNode.removeChild(dialog.element);
dialog = null;
}, 220);
}
function createDialog(title) {
var iframe = element("iframe", {"class": "config-dialog-content"});
var modal = element("div", {"class": "config-dialog", "tabindex": "-1"}, [
element("style", null, "body.config-dialog-open { padding-right: " + (window.innerWidth - document.documentElement.offsetWidth) + "px; }"),
iframe
]);
var head = element("div", {"class": "config-dialog-head"}, title);
var body = element("div", {"class": "config-dialog-body"});
var footer = element("div", {"class": "config-dialog-footer form-inline"});
var style = element("style", null, getConfigCssString());
document.body.classList.add("config-dialog-open");
document.body.appendChild(modal);
function manipulateIframe() {
var doc = iframe.contentDocument;
doc.head.appendChild(style);
doc.body.appendChild(head);
doc.body.appendChild(body);
doc.body.appendChild(footer);
}
iframe.contentWindow.onload = manipulateIframe;
manipulateIframe();
function render() {
var body = iframe.contentDocument.body,
w = body.offsetWidth,
h = body.scrollHeight;
iframe.style.width = w + "px";
iframe.style.height = h + "px";
modal.focus();
modal.classList.add("config-dialog-ani");
}
return {
element: modal,
head: head,
body: body,
footer: footer,
render: render
};
}
function close(saveFlag) {
var key, s;
if (!dialog) {
return;
}
destroyDialog();
for (key in config.settings) {
s = config.settings[key];
if (saveFlag) {
switch (s.type) {
case "number":
s.value = +s.element.value;
break;
case "checkbox":
s.value = s.element.checked;
break;
case "radio":
s.value = s.element.querySelector("input:checked").value;
break;
case "select":
if (!s.multiple) {
s.value = s.element.value;
} else {
s.value = Array.prototype.map.call(
s.element.selectedOptions,
function(ele){
return ele.value;
}
);
}
break;
default:
s.value = s.element.value;
}
// Create inputs
}
// Create inputs
s.element = null;
}
if (saveFlag) {
save();
if (GM_config.onload) {
GM_config.onload();
}
}
if (GM_config.onclose) {
GM_config.onclose(saveFlag);
}
}
function getConfigCssString() {
return "*,*:before,*:after{box-sizing:border-box}a{transition:all .2s linear}a:link,a:visited{color:#707070}a:hover{color:#0a53f8}a:active{color:#0a53f8}.link{color:#707070;text-decoration:underline;cursor:pointer}body{font-size:16px;font-family:\"Helvetica Neue\",Helvetica,Arial,\"微軟正黑體\",sans-serif;color:#3d3d3d;padding:0;margin:0;line-height:1}h1,h2,h3,h4,h5,h6{margin-top:30px;margin-bottom:15px;font-weight:bold}h1 small,h2 small,h3 small,h4 small,h5 small,h6 small{font-size:70%;color:#8a8a8a}h1 .head-reset,h2 .head-reset,h3 .head-reset,h4 .head-reset,h5 .head-reset,h6 .head-reset{font-size:16px;font-weight:normal}h1{font-size:260%}h2{font-size:215%;border-bottom:1px solid #808080;padding-bottom:.25em}h3{font-size:170%}h4{font-size:125%}h5{font-size:100%}h6{font-size:85%}p{margin-top:.9375em;margin-bottom:.9375em;line-height:1.55}input,textarea,select,button{font-size:inherit;font-family:inherit;line-height:inherit;margin:0;padding:0;vertical-align:middle;height:2em;color:inherit;background-color:transparent;border:none}input:focus,textarea:focus,select:focus,button:focus{outline:none}::-moz-placeholder,:-moz-placeholder{opacity:1}:invalid{outline:none;box-shadow:none}textarea{height:auto;line-height:1.55;padding-top:.225em;padding-bottom:.225em}select{cursor:pointer;line-height:1.55}select[multiple]{height:auto}button{cursor:pointer;text-align:center;background-image:none}button::-moz-focus-inner{border:0;padding:0}img{vertical-align:text-bottom;max-width:100%;max-height:100%}code{font-family:Menlo,Monaco,Consolas,\"Courier New\",\"細明體\",monospace;background-color:#f0f0f0;font-size:90%;padding:.25em}pre{margin-top:1em;margin-bottom:1em;font-family:Menlo,Monaco,Consolas,\"Courier New\",\"細明體\",monospace}small{font-size:90%}hr{border:none;border-top:1px solid #808080;margin:15px 0}::selection{background-color:rgba(255,169,46,0.4)}::-moz-selection{background-color:rgba(255,169,46,0.4)}fieldset,legend{border:0 none;margin:0;padding:0}input[type=\"checkbox\"],input[type=\"radio\"]{padding:0}.row-gap>fieldset>legend{position:relative;top:15px}input.ng-invalid,textarea.ng-invalid,select.ng-invalid,input.ng-invalid:hover,textarea.ng-invalid:hover,select.ng-invalid:hover,input.ng-invalid:focus,textarea.ng-invalid:focus,select.ng-invalid:focus{border-color:#cb1b1b}input[type=\"checkbox\"].ng-invalid,input[type=\"radio\"].ng-invalid,input[type=\"checkbox\"].ng-invalid:hover,input[type=\"radio\"].ng-invalid:hover,input[type=\"checkbox\"].ng-invalid:focus,input[type=\"radio\"].ng-invalid:focus{box-shadow:0 0 0 1px #cb1b1b}::-webkit-input-placeholder{color:#c9c9c9}::-moz-placeholder{color:#c9c9c9}:-ms-input-placeholder{color:#c9c9c9}:-moz-placeholder{color:#c9c9c9}.form-group{margin-top:1em;margin-bottom:1em}.row>.form-group{margin:0}label,legend{vertical-align:bottom}label+.form-control,legend+.form-control,label+.input-group,legend+.input-group,label+.radio,legend+.radio,label+.checkbox,legend+.checkbox,label .form-control,legend .form-control,label .input-group,legend .input-group,label .radio,legend .radio,label .checkbox,legend .checkbox{margin-top:.3em}.form-control{border:1px solid #808080;border-radius:.1875em;display:block;width:100%;line-height:1;display:inline-block;padding-left:.5em;padding-right:.5em;color:#707070;transition:.2s all linear}.form-control:hover{border-color:#ccc}.form-control:focus{border-color:#0a53f8;color:#242424}.form-control[disabled]{background-color:#f0f0f0;border-color:#ccc;cursor:not-allowed}.form-control[disabled]:hover,.form-control[disabled]:active{border-color:#ccc}.radio,.checkbox{position:relative}.radio input[type=\"radio\"],.checkbox input[type=\"radio\"],.radio input[type=\"checkbox\"],.checkbox input[type=\"checkbox\"]{color:inherit;position:absolute;width:auto;height:auto;top:0;bottom:0;left:0;margin:auto 0}.radio label,.checkbox label,label.radio,label.checkbox{display:table;padding-left:1.5em;cursor:pointer;line-height:1.55;transition:.2s all linear}.radio label:hover,.checkbox label:hover,label.radio:hover,label.checkbox:hover{color:#707070}.radio+.radio,.radio+.checkbox,.checkbox+.radio,.checkbox+.checkbox{margin-top:0}.form-inline input,.form-inline select,.form-inline button,.form-inline .radio,.form-inline .checkbox,.form-inline fieldset,.form-inline .form-group{display:inline-block;vertical-align:middle;width:auto;margin:0}.btn-default{border:1px solid #808080;border-radius:.1875em;transition-property:border-color,box-shadow;transition-duration:.2s;transition-timing-function:linear;padding-left:.5em;padding-right:.5em;min-width:4.25em}.btn-default:hover{border-color:#ccc}.btn-default:focus{color:#3d3d3d;border-color:#0a53f8}.btn-default:active{border-color:#0a53f8;box-shadow:inset .12em .12em .5em #dedede}.btn-default[disabled]{background-color:#f0f0f0;border-color:#ccc;cursor:not-allowed}.btn-default[disabled]:hover,.btn-default[disabled]:active{border-color:#ccc}.btn-sm{border:1px solid #808080;border-radius:.1875em;transition-property:border-color,box-shadow;transition-duration:.2s;transition-timing-function:linear;width:2em;line-height:.8}.btn-sm:hover{border-color:#ccc}.btn-sm:focus{color:#3d3d3d;border-color:#0a53f8}.btn-sm:active{border-color:#0a53f8;box-shadow:inset .12em .12em .5em #dedede}.btn-sm[disabled]{background-color:#f0f0f0;border-color:#ccc;cursor:not-allowed}.btn-sm[disabled]:hover,.btn-sm[disabled]:active{border-color:#ccc}.btn-close{width:1em;height:1em;vertical-align:baseline;color:#707070}.btn-close:hover{color:inherit}.btn-circle{display:inline-block;width:1.25em;height:1.25em;text-align:center;line-height:1.25;font-size:80%;vertical-align:baseline;border-radius:50%;border:1px solid #707070;margin:-1px 0;color:#707070}.btn-circle:hover{color:inherit;border-color:inherit}.btn-block{display:block;width:100%}.btn-group{display:block;display:inline-block;border:1px solid #808080;border-radius:.1875em}.btn-group>*{display:table-cell;vertical-align:middle;white-space:nowrap}.btn-group>*{border-width:0 1px;border-radius:0;margin-right:-1px}.btn-group>*:first-child{margin-left:-1px}body{display:inline-block;padding:30px;overflow:hidden}.config-dialog-head{font-weight:bold;font-size:120%}.config-dialog-head .btn-sm{font-size:50%;font-weight:normal;width:auto;padding:0 2px;float:right}.config-dialog-head .btn-sm+*{margin-right:5px}.config-dialog-footer.form-inline{white-space:nowrap}.config-dialog-footer.form-inline>*+*{margin-left:15px}.config-dialog-footer.form-inline label.radio{padding:4px 0 1px 18px}";
}
function getCssString() {
return ".config-dialog-open{overflow:hidden}.config-dialog{position:fixed;top:0;left:0;right:0;bottom:0;vertical-align:middle;text-align:center;background:rgba(0,0,0,0.5);overflow:auto;z-index:99999;opacity:0;transition:opacity .2s linear;white-space:nowrap}.config-dialog:before{content:\"\";display:inline-block;height:100%;vertical-align:middle}.config-dialog-ani{opacity:1}.config-dialog-content{text-align:left;display:inline-block;width:90%;vertical-align:middle;background:white;margin:30px 0;box-shadow:0 0 30px black;border-width:0;transition:transform .2s linear;transform:translateY(-20px)}.config-dialog-ani .config-dialog-content{transform:none}";
}
function setupDialogValue (reset, imports) {
var key, setting, value;
for (key in config.settings) {
setting = config.settings[key];
if (reset) {
value = setting.default;
} else {
if (imports && imports[key] != undefined) {
value = imports[key];
} else {
value = setting.value;
}
}
switch (setting.type) {
case "number":
setting.element.value = value.toString();
break;
case "checkbox":
setting.element.checked = value;
break;
case "radio":
setting.element.querySelector("[value=" + value + "]").checked = true;
break;
case "select":
if (!setting.multiple) {
setting.element.querySelector("[value=" + value + "]").selected = true;
} else {
while (setting.element.selectedOptions.length) {
setting.element.selectedOptions[0].selected = false;
}
value.forEach(function(value){
setting.element.querySelector("[value=" + value + "]").selected = true;
});
}
break;
default:
setting.element.value = value;
break;
}
}
}
function createInputs(dialog) {
var key, s, group;
for (key in config.settings) {
s = config.settings[key];
if (s.type == "textarea") {
s.element = element("textarea", {"id": key});
s.element.classList.add("form-control");
group = [
element("label", {"for": key}, s.label),
s.element
];
} else if (s.type == "radio") {
s.element = element("fieldset", null, [element("legend", null, s.label)].concat(Object.keys(s.options).map(function(optKey){
return element("label", {class: "radio"}, [
element("input", {type: "radio", name: key, value: optKey}),
s.options[optKey]
]);
})));
group = [
s.element
];
} else if (s.type == "select") {
s.element = element(
"select",
{class: "form-control", multiple: !!s.multiple},
Object.keys(s.options).map(function(optKey){
return element(
"option",
{value: optKey},
s.options[optKey]
);
})
);
group = element("label", null, [
s.label,
s.element
]);
} else {
s.element = element("input", {"id": key, "type": s.type});
switch (s.type) {
case "number":
s.element.classList.add("form-control");
group = [
element("label", {"for": key}, s.label),
s.element
];
break;
case "checkbox":
group = element("div", {"class": "checkbox"}, [
s.element,
element("label", {"for": key}, s.label)
]);
break;
default:
s.element.classList.add("form-control");
group = [
element("label", {"for": key}, s.label),
s.element
];
}
}
dialog.body.appendChild(
element("div", {"class": "form-group"}, group)
);
}
}
function createFooter(dialog) {
var local = config.local;
dialog.footer.appendChild(frag([
element("button", {"class": "btn-default", event: {
click: function () {
config.local = local;
close(true);
}
}}, "Save"),
element("button", {"class": "btn-default", event: {
click: function() {
close();
}
}}, "Cancel"),
element("button", {class: "btn-default", event: {
click: function() {
setupDialogValue(true);
}
}}, "Default"),
element("label", {class: "radio"}, [
element("input", {type: "radio", name: "working-scope", checked: !local, event: {
change: function () {
local = !this.checked;
}
}}),
"Global setting"
]),
element("label", {class: "radio"}, [
element("input", {type: "radio", name: "working-scope", checked: local, event: {
change: function () {
local = this.checked;
}
}}),
"On " + location.hostname
])
]));
}
function exportSetting() {
var exports = JSON.stringify(getConfigObj());
prompt("Copy:", exports);
}
function importSetting() {
var imports = prompt("Paste your setting:"), setting;
if (!imports) {
return;
}
try {
setting = JSON.parse(imports);
} catch (err) {
alert("Invalid JSON!");
return;
}
setupDialogValue(false, setting);
}
function createHead(dialog) {
dialog.head.appendChild(frag([
element("button", {class: "btn-sm", event: {
click: exportSetting
}}, "Export"),
element("button", {class: "btn-sm", event: {
click: importSetting
}}, "Import")
]));
}
function open() {
if (!css) {
css = element("style", {"id": "config-css"}, getCssString());
document.head.appendChild(css);
}
if (!dialog) {
dialog = createDialog(config.title);
// Create head
createHead(dialog);
// Create inputs
createInputs(dialog);
// Setup values
setupDialogValue();
// Create footer
createFooter(dialog);
// Render
dialog.render();
}
}
function getConfigObj(key) {
var con;
if (typeof key == "string") {
return config.settings[key].value;
} else {
if (typeof key == "object") {
con = key;
} else {
con = {};
}
for (key in config.settings) {
con[key] = config.settings[key].value;
}
return con;
}
}
function setup(options, loadCallback) {
GM_config.init(GM_info.script.name, options);
GM_config.onload = loadCallback;
GM_registerMenuCommand(GM_info.script.name + " - Configure", GM_config.open);
loadCallback();
}
GM_config = {
init: function(title, settings) {
config.title = title;
config.settings = settings;
read();
return GM_config.get();
},
open: open,
close: close,
get: getConfigObj,
setup: setup
};
return GM_config;
}();