GM_config 8+

A library to help you set up configure in greasemonkey script.

此脚本不应直接安装,它是一个供其他脚本使用的外部库。如果您需要使用该库,请在脚本元属性加入:// @require https://update.cn-greasyfork.org/scripts/11562/66657/GM_config%208%2B.js

  1. /*
  2. Copyright 2009+, GM_config Contributors (https://github.com/sizzlemctwizzle/GM_config)
  3.  
  4. GM_config Contributors:
  5. Mike Medley <medleymind@gmail.com>
  6. Joe Simmons
  7. Izzy Soft
  8. Marti Martz
  9.  
  10. GM_config is distributed under the terms of the GNU Lesser General Public License.
  11.  
  12. GM_config is free software: you can redistribute it and/or modify
  13. it under the terms of the GNU Lesser General Public License as published by
  14. the Free Software Foundation, either version 3 of the License, or
  15. (at your option) any later version.
  16.  
  17. This program is distributed in the hope that it will be useful,
  18. but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. GNU Lesser General Public License for more details.
  21.  
  22. You should have received a copy of the GNU Lesser General Public License
  23. along with this program. If not, see <http://www.gnu.org/licenses/>.
  24. */
  25.  
  26. // ==UserScript==
  27. // @name GM_config 8+
  28. // @description A library to help you set up configure in greasemonkey script.
  29. // @namespace freMea
  30. // @version 2.1.1
  31. // @grant GM_setValue
  32. // @grant GM_getValue
  33. // @license LGPL version 3 or any later version; http://www.gnu.org/copyleft/lgpl.html
  34. // @copyright 2015+, eight <https://github.com/eight04/GM_config>
  35. // @homepageURL https://github.com/eight04/GM_config
  36. // @supportURL https://github.com/eight04/GM_config/issues
  37. // @attribution sizzlemctwizzle (https://github.com/sizzlemctwizzle/GM_config)
  38. // @attribution Joe Simmons (https://greasyfork.org/en/scripts/1884-gm-config)
  39. // @attribution eight04 (https://greasyfork.org/fr/scripts/7212-gm-config-eight-s-version)
  40. // ==/UserScript==
  41.  
  42. var GM_config = function(){
  43.  
  44. "use strict";
  45.  
  46. var config = {
  47. title: null,
  48. settings: null,
  49. local: false
  50. }, dialog, css, GM_config;
  51.  
  52. function addChild(e, children) {
  53. if (!children) {
  54. return;
  55. }
  56.  
  57. if (!Array.isArray(children)) {
  58. children = [children];
  59. }
  60.  
  61. var i;
  62. for (i = 0; i < children.length; i++) {
  63. if (typeof children[i] == "string") {
  64. children[i] = document.createTextNode(children[i]);
  65. }
  66. e.appendChild(children[i]);
  67. }
  68. }
  69.  
  70. function element(tag, attr, children) {
  71. var e, key, key2;
  72.  
  73. e = document.createElement(tag);
  74.  
  75. if (attr) {
  76. for (key in attr) {
  77. if (typeof attr[key] == "boolean") {
  78. if (attr[key]) {
  79. e.setAttribute(key, "");
  80. } else {
  81. e.removeAttribute(key);
  82. }
  83.  
  84. } else if (key == "event") {
  85. for (key2 in attr[key]) {
  86. e["on" + key2] = attr[key][key2];
  87. }
  88.  
  89. } else {
  90. e.setAttribute(key, attr[key]);
  91. }
  92. }
  93. }
  94.  
  95. addChild(e, children);
  96.  
  97. return e;
  98. }
  99.  
  100. function frag(children) {
  101. var fragment = document.createDocumentFragment();
  102. addChild(fragment, children);
  103. return fragment;
  104. }
  105.  
  106. function getValue(key) {
  107. if (config.local) {
  108. key = location.hostname + "/" + key;
  109. }
  110. var value = GM_getValue(key);
  111. if (GM_getValue(key + "/type") == "object") {
  112. value = JSON.parse(value);
  113. }
  114. return value;
  115. }
  116.  
  117. function setValue(key, value) {
  118. if (config.local) {
  119. key = location.hostname + "/" + key;
  120. }
  121. if (typeof value == "object") {
  122. GM_setValue(key + "/type", "object");
  123. value = JSON.stringify(value);
  124. }
  125. GM_setValue(key, value);
  126. }
  127.  
  128. function read() {
  129. var key, s;
  130. config.local = GM_getValue(location.hostname, false);
  131. for (key in config.settings) {
  132. s = config.settings[key];
  133. s.value = getValue(key, s.type);
  134. if (s.value == null) {
  135. s.value = s.default;
  136. }
  137. }
  138. }
  139.  
  140. function save() {
  141. var key, s;
  142. GM_setValue(location.hostname, config.local);
  143. for (key in config.settings) {
  144. s = config.settings[key];
  145. if (s.value == null) {
  146. setValue(key, s.default);
  147. } else {
  148. setValue(key, s.value);
  149. }
  150. }
  151. }
  152.  
  153. function destroyDialog() {
  154. dialog.element.classList.remove("config-dialog-ani");
  155. setTimeout(function() {
  156. document.body.classList.remove("config-dialog-open");
  157. document.body.style.paddingRight = "";
  158. dialog.element.parentNode.removeChild(dialog.element);
  159. dialog = null;
  160. }, 220);
  161. }
  162.  
  163. function createDialog(title) {
  164. var iframe = element("iframe", {"class": "config-dialog-content"});
  165. var modal = element("div", {"class": "config-dialog", "tabindex": "-1"}, [
  166. element("style", null, "body.config-dialog-open { padding-right: " + (window.innerWidth - document.documentElement.offsetWidth) + "px; }"),
  167. iframe
  168. ]);
  169.  
  170. var head = element("div", {"class": "config-dialog-head"}, title);
  171. var body = element("div", {"class": "config-dialog-body"});
  172. var sep = element("div", {"class": "config-dialog-sep"});
  173. var footer = element("div", {"class": "config-dialog-footer form-inline"});
  174.  
  175. var style = element("style", null, getConfigCssString());
  176.  
  177. document.body.classList.add("config-dialog-open");
  178. document.body.appendChild(modal);
  179.  
  180. function manipulateIframe() {
  181. var doc = iframe.contentDocument;
  182. doc.head.appendChild(style);
  183. doc.body.appendChild(head);
  184. doc.body.appendChild(body);
  185. doc.body.appendChild(sep);
  186. doc.body.appendChild(footer);
  187. }
  188.  
  189. iframe.contentWindow.onload = manipulateIframe;
  190.  
  191. manipulateIframe();
  192.  
  193. function render() {
  194. var body = iframe.contentDocument.body,
  195. w = body.offsetWidth,
  196. h = body.scrollHeight;
  197.  
  198. iframe.style.width = w + "px";
  199. iframe.style.height = h + "px";
  200. modal.focus();
  201.  
  202. modal.classList.add("config-dialog-ani");
  203. }
  204.  
  205. return {
  206. element: modal,
  207. head: head,
  208. body: body,
  209. footer: footer,
  210. render: render
  211. };
  212. }
  213.  
  214. function close(saveFlag) {
  215. var key, s;
  216.  
  217. if (!dialog) {
  218. return;
  219. }
  220. destroyDialog();
  221.  
  222. for (key in config.settings) {
  223. s = config.settings[key];
  224. if (saveFlag) {
  225. switch (s.type) {
  226. case "number":
  227. s.value = +s.element.value;
  228. break;
  229.  
  230. case "checkbox":
  231. s.value = s.element.checked;
  232. break;
  233.  
  234. case "radio":
  235. s.value = s.element.querySelector("input:checked").value;
  236. break;
  237.  
  238. case "select":
  239. if (!s.multiple) {
  240. s.value = s.element.value;
  241. } else {
  242. s.value = Array.prototype.map.call(
  243. s.element.selectedOptions,
  244. function(ele){
  245. return ele.value;
  246. }
  247. );
  248. }
  249. break;
  250.  
  251. default:
  252. s.value = s.element.value;
  253. }
  254. // Create inputs
  255. }
  256. // Create inputs
  257. s.element = null;
  258. }
  259.  
  260. if (saveFlag) {
  261. save();
  262. }
  263.  
  264. if (GM_config.onclose) {
  265. GM_config.onclose(saveFlag);
  266. }
  267. }
  268.  
  269. function getConfigCssString() {
  270. if (config.style) {
  271. return "*,:after,:before{box-sizing:border-box}a{transition:all .2s linear}a:link,a:visited{color:#707070}a:active,a:hover{color:#0a53f8}.link{color:#707070;text-decoration:underline;cursor:pointer}body{font-size:16px;font-family:\"Helvetica Neue\",Helvetica,Arial,\"微軟正黑體\",sans-serif;color:#3d3d3d;margin:0;line-height:1}h1,h2,h3,h4,h5,h6{margin-top:30px;margin-bottom:15px;font-weight:700}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:400}h1{font-size:260%}h2{font-size:215%;border-bottom:1px solid gray;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}button,input,select,textarea{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}button:focus,input:focus,select:focus,textarea:focus{outline:0}:-moz-placeholder,::-moz-placeholder{opacity:1}:invalid{outline:0;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 gray;margin:15px 0}::selection{background-color:rgba(255,169,46,.4)}::-moz-selection{background-color:rgba(255,169,46,.4)}fieldset,legend{border:0;margin:0;padding:0}input[type=checkbox],input[type=radio]{padding:0}.row-gap>fieldset>legend{position:relative;top:15px}input.ng-invalid,input.ng-invalid:focus,input.ng-invalid:hover,select.ng-invalid,select.ng-invalid:focus,select.ng-invalid:hover,textarea.ng-invalid,textarea.ng-invalid:focus,textarea.ng-invalid:hover{border-color:#cb1b1b}input[type=checkbox].ng-invalid,input[type=checkbox].ng-invalid:focus,input[type=checkbox].ng-invalid:hover,input[type=radio].ng-invalid,input[type=radio].ng-invalid:focus,input[type=radio].ng-invalid:hover{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 .checkbox,label .form-control,label .input-group,label .radio,label+.checkbox,label+.form-control,label+.input-group,label+.radio,legend .checkbox,legend .form-control,legend .input-group,legend .radio,legend+.checkbox,legend+.form-control,legend+.input-group,legend+.radio{margin-top:.3em}.form-control{border:1px solid gray;border-radius:.1875em;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]:active,.form-control[disabled]:hover{border-color:#ccc}.checkbox,.radio{position:relative}.checkbox input[type=checkbox],.checkbox input[type=radio],.radio input[type=checkbox],.radio input[type=radio]{color:inherit;position:absolute;width:auto;height:auto;top:0;bottom:0;left:0;margin:auto 0}.checkbox label,.radio label,label.checkbox,label.radio{display:table;padding-left:1.5em;cursor:pointer;line-height:1.55;transition:.2s all linear}.checkbox label:hover,.radio label:hover,label.checkbox:hover,label.radio:hover{color:#707070}.checkbox+.checkbox,.checkbox+.radio,.radio+.checkbox,.radio+.radio{margin-top:0}.form-inline .checkbox,.form-inline .form-group,.form-inline .radio,.form-inline button,.form-inline fieldset,.form-inline input,.form-inline select{display:inline-block;vertical-align:middle;width:auto;margin:0}.btn-default{border:1px solid gray;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]:active,.btn-default[disabled]:hover{border-color:#ccc}.btn-sm{border:1px solid gray;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]:active,.btn-sm[disabled]:hover{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 gray;border-radius:.1875em}.btn-group>*{display:table-cell;vertical-align:middle;white-space:nowrap;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:700;font-size:120%}.config-dialog-head .btn-sm{font-size:50%;font-weight:400;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}.deco{line-height:0.5;text-align:center;font-size:110%;font-weight:bold;color:#999999}.deco span{display:inline-block;position:relative}.deco span:before,.deco span:after{content:'';position:absolute;height:5px;border-bottom:2px groove #999999;top:2px;width:200%}.deco span:before{right:100%;margin-right:15px}.deco span:after{left:100%;margin-left:15px}.config-dialog-sep{position:relative;border-top:2px groove #999999;margin:0 auto 10px auto;width:100%;}"+config.style;
  272. } else {
  273. return "*,:after,:before{box-sizing:border-box}a{transition:all .2s linear}a:link,a:visited{color:#707070}a:active,a:hover{color:#0a53f8}.link{color:#707070;text-decoration:underline;cursor:pointer}body{font-size:16px;font-family:\"Helvetica Neue\",Helvetica,Arial,\"微軟正黑體\",sans-serif;color:#3d3d3d;margin:0;line-height:1}h1,h2,h3,h4,h5,h6{margin-top:30px;margin-bottom:15px;font-weight:700}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:400}h1{font-size:260%}h2{font-size:215%;border-bottom:1px solid gray;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}button,input,select,textarea{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}button:focus,input:focus,select:focus,textarea:focus{outline:0}:-moz-placeholder,::-moz-placeholder{opacity:1}:invalid{outline:0;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 gray;margin:15px 0}::selection{background-color:rgba(255,169,46,.4)}::-moz-selection{background-color:rgba(255,169,46,.4)}fieldset,legend{border:0;margin:0;padding:0}input[type=checkbox],input[type=radio]{padding:0}.row-gap>fieldset>legend{position:relative;top:15px}input.ng-invalid,input.ng-invalid:focus,input.ng-invalid:hover,select.ng-invalid,select.ng-invalid:focus,select.ng-invalid:hover,textarea.ng-invalid,textarea.ng-invalid:focus,textarea.ng-invalid:hover{border-color:#cb1b1b}input[type=checkbox].ng-invalid,input[type=checkbox].ng-invalid:focus,input[type=checkbox].ng-invalid:hover,input[type=radio].ng-invalid,input[type=radio].ng-invalid:focus,input[type=radio].ng-invalid:hover{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 .checkbox,label .form-control,label .input-group,label .radio,label+.checkbox,label+.form-control,label+.input-group,label+.radio,legend .checkbox,legend .form-control,legend .input-group,legend .radio,legend+.checkbox,legend+.form-control,legend+.input-group,legend+.radio{margin-top:.3em}.form-control{border:1px solid gray;border-radius:.1875em;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]:active,.form-control[disabled]:hover{border-color:#ccc}.checkbox,.radio{position:relative}.checkbox input[type=checkbox],.checkbox input[type=radio],.radio input[type=checkbox],.radio input[type=radio]{color:inherit;position:absolute;width:auto;height:auto;top:0;bottom:0;left:0;margin:auto 0}.checkbox label,.radio label,label.checkbox,label.radio{display:table;padding-left:1.5em;cursor:pointer;line-height:1.55;transition:.2s all linear}.checkbox label:hover,.radio label:hover,label.checkbox:hover,label.radio:hover{color:#707070}.checkbox+.checkbox,.checkbox+.radio,.radio+.checkbox,.radio+.radio{margin-top:0}.form-inline .checkbox,.form-inline .form-group,.form-inline .radio,.form-inline button,.form-inline fieldset,.form-inline input,.form-inline select{display:inline-block;vertical-align:middle;width:auto;margin:0}.btn-default{border:1px solid gray;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]:active,.btn-default[disabled]:hover{border-color:#ccc}.btn-sm{border:1px solid gray;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]:active,.btn-sm[disabled]:hover{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 gray;border-radius:.1875em}.btn-group>*{display:table-cell;vertical-align:middle;white-space:nowrap;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:700;font-size:120%}.config-dialog-head .btn-sm{font-size:50%;font-weight:400;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}.deco{line-height:0.5;text-align:center;font-size:110%;font-weight:bold;color:#999999}.deco span{display:inline-block;position:relative}.deco span:before,.deco span:after{content:'';position:absolute;height:5px;border-bottom:2px groove #999999;top:2px;width:200%}.deco span:before{right:100%;margin-right:15px}.deco span:after{left:100%;margin-left:15px}.config-dialog-sep{position:relative;border-top:2px groove #999999;margin:0 auto 10px auto;width:100%;}";
  274. }
  275. }
  276.  
  277. function getCssString() {
  278. 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,.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:#fff;margin:30px 0;box-shadow:0 0 30px #000;border-width:0;transition:transform .2s linear;transform:translateY(-20px)}.config-dialog-ani .config-dialog-content{transform:none}";
  279. }
  280.  
  281. function setupDialogValue (reset, imports) {
  282. var key, setting, value;
  283.  
  284. for (key in config.settings) {
  285. setting = config.settings[key];
  286.  
  287. if (reset) {
  288. value = setting.default;
  289. } else {
  290. if (imports && imports[key] != undefined) {
  291. value = imports[key];
  292. } else {
  293. value = setting.value;
  294. }
  295. }
  296.  
  297. switch (setting.type) {
  298. case "number":
  299. setting.element.value = value.toString();
  300. break;
  301.  
  302. case "checkbox":
  303. setting.element.checked = value;
  304. break;
  305.  
  306. case "radio":
  307. setting.element.querySelector("[value=" + value + "]").checked = true;
  308. break;
  309.  
  310. case "select":
  311. if (!setting.multiple) {
  312. setting.element.querySelector("[value=" + value + "]").selected = true;
  313. } else {
  314. while (setting.element.selectedOptions.length) {
  315. setting.element.selectedOptions[0].selected = false;
  316. }
  317. value.forEach(function(value){
  318. setting.element.querySelector("[value=" + value + "]").selected = true;
  319. });
  320. }
  321. break;
  322.  
  323. default:
  324. setting.element.value = value;
  325. break;
  326. }
  327. }
  328. }
  329.  
  330. function createInputs(dialog) {
  331. var key, s, group;
  332.  
  333. for (key in config.settings) {
  334. s = config.settings[key];
  335.  
  336. if (s.type == "textarea") {
  337. s.element = element("textarea", {"id": key});
  338. s.element.classList.add("form-control");
  339. group = [
  340. element("label", {"for": key}, s.label),
  341. s.element
  342. ];
  343. } else if (s.type == "radio") {
  344. s.element = element("fieldset", null, [element("legend", null, s.label)].concat(Object.keys(s.options).map(function(optKey){
  345. return element("label", {class: "radio"}, [
  346. element("input", {type: "radio", name: key, value: optKey}),
  347. s.options[optKey]
  348. ]);
  349. })));
  350. group = [
  351. s.element
  352. ];
  353. } else if (s.type == "select") {
  354. s.element = element(
  355. "select",
  356. {class: "form-control", multiple: !!s.multiple},
  357. Object.keys(s.options).map(function(optKey){
  358. return element(
  359. "option",
  360. {value: optKey},
  361. s.options[optKey]
  362. );
  363. })
  364. );
  365. group = element("label", null, [
  366. s.label,
  367. s.element
  368. ]);
  369. } else {
  370. s.element = element("input", {"id": key, "type": s.type});
  371.  
  372. switch (s.type) {
  373. case "section":
  374. s.element = element("div", {"class": "section"},
  375. [element("p", {"class": "deco", "id": key},
  376. [element("span",null, s.label)]
  377. )]
  378. );
  379. group = [s.element]
  380. break;
  381. case "number":
  382. s.element.classList.add("form-control");
  383. group = [
  384. element("label", {"for": key}, s.label),
  385. s.element
  386. ];
  387. break;
  388. case "checkbox":
  389. group = element("div", {"class": "checkbox"}, [
  390. s.element,
  391. element("label", {"for": key}, s.label)
  392. ]);
  393. break;
  394. default:
  395. s.element.classList.add("form-control");
  396. group = [
  397. element("label", {"for": key}, s.label),
  398. s.element
  399. ];
  400. }
  401. }
  402.  
  403. dialog.body.appendChild(
  404. element("div", {"class": "form-group"}, group)
  405. );
  406. }
  407. }
  408.  
  409. function createFooter(dialog) {
  410. var local = config.local;
  411.  
  412. dialog.footer.appendChild(frag([
  413. element("button", {"class": "btn-default", event: {
  414. click: function () {
  415. config.local = local;
  416. close(true);
  417. }
  418. }}, "Save"),
  419.  
  420. element("button", {"class": "btn-default", event: {
  421. click: function() {
  422. close();
  423. }
  424. }}, "Cancel"),
  425.  
  426. element("button", {class: "btn-default", event: {
  427. click: function() {
  428. setupDialogValue(true);
  429. }
  430. }}, "Default"),
  431.  
  432. element("label", {class: "radio"}, [
  433. element("input", {type: "radio", name: "working-scope", checked: !local, event: {
  434. change: function () {
  435. local = !this.checked;
  436. }
  437. }}),
  438. "Global setting"
  439. ]),
  440.  
  441. element("label", {class: "radio"}, [
  442. element("input", {type: "radio", name: "working-scope", checked: local, event: {
  443. change: function () {
  444. local = this.checked;
  445. }
  446. }}),
  447. "On " + location.hostname
  448. ])
  449. ]));
  450. }
  451.  
  452. function exportSetting() {
  453. var exports = JSON.stringify(getConfigObj());
  454. prompt("Copy:", exports);
  455. }
  456.  
  457. function importSetting() {
  458. var imports = prompt("Paste your setting:"), setting;
  459. if (!imports) {
  460. return;
  461. }
  462. try {
  463. setting = JSON.parse(imports);
  464. } catch (err) {
  465. alert("Invalid JSON!");
  466. return;
  467. }
  468. setupDialogValue(false, setting);
  469. }
  470.  
  471. function createHead(dialog) {
  472. dialog.head.appendChild(frag([
  473. element("button", {class: "btn-sm", event: {
  474. click: exportSetting
  475. }}, "Export"),
  476. element("button", {class: "btn-sm", event: {
  477. click: importSetting
  478. }}, "Import")
  479. ]));
  480. }
  481.  
  482. function open() {
  483. if (!css) {
  484. css = element("style", {"id": "config-css"}, getCssString());
  485. document.head.appendChild(css);
  486. }
  487.  
  488. if (!dialog) {
  489. dialog = createDialog(config.title);
  490.  
  491. // Create head
  492. createHead(dialog);
  493.  
  494. // Create inputs
  495. createInputs(dialog);
  496.  
  497. // Setup values
  498. setupDialogValue();
  499.  
  500. // Create footer
  501. createFooter(dialog);
  502.  
  503. // Render
  504. dialog.render();
  505. }
  506. }
  507.  
  508. function getConfigObj(key) {
  509. var con;
  510.  
  511. if (typeof key == "string") {
  512. return config.settings[key].value;
  513. } else {
  514. if (typeof key == "object") {
  515. con = key;
  516. } else {
  517. con = {};
  518. }
  519. for (key in config.settings) {
  520. con[key] = config.settings[key].value;
  521. }
  522. return con;
  523. }
  524. }
  525.  
  526. GM_config = {
  527. init: function(title, settings, configstyle) {
  528. config.title = title;
  529. config.settings = settings;
  530. config.style = configstyle;
  531. read();
  532. return GM_config.get();
  533. },
  534. open: open,
  535. close: close,
  536. get: getConfigObj
  537. };
  538.  
  539. return GM_config;
  540. }();