Saputra

Easy configuration dialog builder for user scripts

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

  1. // ==UserScript==
  2. // @name Saputra
  3. // @namespace http://odyniec.net/
  4. // @description Easy configuration dialog builder for user scripts
  5. // @include *
  6. // @version 0.0.1.20180110115321
  7. // ==/UserScript==
  8.  
  9. /*
  10. * MonkeyConfig
  11. * version 0.1.4
  12. *
  13. * Copyright (c) 2011-2013 Michal Wojciechowski (odyniec.net)
  14. */
  15.  
  16. function MonkeyConfig() {
  17. var cfg = this,
  18. /* Data object passed to the constructor */
  19. data,
  20. /* Configuration parameters (data.parameters or data.params) */
  21. params,
  22. /* Current values of configuration parameters */
  23. values = {},
  24. /* Identifier used to store/retrieve configuration */
  25. storageKey,
  26. /* Is the configuration dialog displayed? */
  27. displayed,
  28. /* Currently displayed window/layer */
  29. openWin, openLayer,
  30. /* DOM element wrapping the configuration form */
  31. container,
  32. /* Darkened overlay used in the layer display mode */
  33. overlay;
  34. /**
  35. * Initialize configuration
  36. *
  37. * @param newData New data object
  38. */
  39. function init(newData) {
  40. data = newData;
  41.  
  42. if (data) {
  43. params = data.parameters || data.params;
  44. if (data.buttons === undefined)
  45. /* Set default buttons */
  46. data.buttons = [ 'save', 'defaults', 'cancel' ];
  47. if (data.title === undefined)
  48. /*
  49. * If GM_getMetadata is available, get the name of the script
  50. * and use it in the dialog title
  51. */
  52. if (typeof GM_getMetadata == 'function') {
  53. var scriptName = GM_getMetadata('name');
  54. data.title = scriptName + ' Configuration';
  55. }
  56. else
  57. data.title = 'Configuration';
  58. }
  59. /* Make a safe version of title to be used as stored value identifier */
  60. var safeTitle = data && data.title ?
  61. data.title.replace(/[^a-zA-Z0-9]/g, '_') : '';
  62.  
  63. storageKey = '_MonkeyConfig_' + safeTitle + '_cfg';
  64. var storedValues;
  65. /* Load stored values (if present) */
  66. if (GM_getValue(storageKey))
  67. storedValues = JSON.parse(GM_getValue(storageKey));
  68.  
  69. for (var name in params) {
  70. /* If there's a value defined in the passed data object, use it */
  71. if (params[name]['value'] !== undefined)
  72. set(name, params[name].value);
  73. /* Check if there's a stored value for this parameter */
  74. else if (storedValues && storedValues[name] !== undefined)
  75. set(name, storedValues[name]);
  76. /* Otherwise, set the default value (if defined) */
  77. else if (params[name]['default'] !== undefined)
  78. set(name, params[name]['default']);
  79. else
  80. set(name, '');
  81. }
  82.  
  83. if (data.menuCommand) {
  84. /* Add an item to the User Script Commands menu */
  85. var caption = data.menuCommand !== true ? data.menuCommand :
  86. data.title;
  87. GM_registerMenuCommand(caption, function () { cfg.open(); });
  88. }
  89.  
  90. /* Expose public methods */
  91. cfg.open = open;
  92. cfg.close = close;
  93. cfg.get = get;
  94. cfg.set = function (name, value) {
  95. set(name, value);
  96. update();
  97. };
  98. }
  99. /**
  100. * Get the value of a configuration parameter
  101. *
  102. * @param name Name of the configuration parameter
  103. * @returns Value of the configuration parameter
  104. */
  105. function get(name) {
  106. return values[name];
  107. }
  108. /**
  109. * Set the value of a configuration parameter
  110. *
  111. * @param name Name of the configuration parameter
  112. * @param value New value of the configuration parameter
  113. */
  114. function set(name, value) {
  115. values[name] = value;
  116. }
  117. /**
  118. * Reset configuration parameters to default values
  119. */
  120. function setDefaults() {
  121. for (var name in params) {
  122. if (typeof params[name]['default'] !== 'undefined') {
  123. set(name, params[name]['default']);
  124. }
  125. }
  126. }
  127. /**
  128. * Render the configuration dialog
  129. */
  130. function render() {
  131. var html = '<div class="__MonkeyConfig_container">' +
  132. '<h1>' + data.title + '</h1>' +
  133. '<table>';
  134.  
  135. for (var name in params) {
  136. html += MonkeyConfig.formatters['tr'](name, params[name]);}
  137.  
  138. html += '<tr><td colspan="2" class="__MonkeyConfig_buttons">' +
  139. '<table><tr>';
  140.  
  141. /* Render buttons */
  142. for (var button in data.buttons) {
  143. html += '<td>';
  144. switch (data.buttons[button]) {
  145. case 'cancel':
  146. html += '<button type="button" ' +
  147. 'id="__MonkeyConfig_button_cancel">' +
  148. '<img src="data:image/png;base64,' +
  149. MonkeyConfig.res.icons.cancel + '" />&nbsp;' +
  150. 'Cancel</button>';
  151. break;
  152. case 'defaults':
  153. html += '<button type="button" ' +
  154. 'id="__MonkeyConfig_button_defaults">' +
  155. '<img src="data:image/png;base64,' +
  156. MonkeyConfig.res.icons.arrow_undo + '" />&nbsp;' +
  157. 'Set&nbsp;Defaults</button>';
  158. break;
  159. case 'save':
  160. html += '<button type="button" ' +
  161. 'id="__MonkeyConfig_button_save">' +
  162. '<img src="data:image/png;base64,' +
  163. MonkeyConfig.res.icons.tick + '" />&nbsp;' +
  164. 'Save</button>';
  165. break;
  166. }
  167. html += '</td>';
  168. }
  169. html += '</tr></table></td></tr>';
  170. html += "</table><div>";
  171.  
  172. return html;
  173. }
  174. /**
  175. * Update the fields in the dialog to reflect current values
  176. */
  177. function update() {
  178. /* Do nothing if the dialog is not currently displayed */
  179. if (!displayed)
  180. return;
  181. for (var name in params) {
  182. var value = values[name];
  183. switch (params[name].type) {
  184. case 'checkbox':
  185. var elem = container.querySelector('[name="' + name + '"]');
  186. elem.checked = !!value;
  187. break;
  188. case 'custom':
  189. params[name].set(value, container
  190. .querySelector('#__MonkeyConfig_parent_' + name));
  191. break;
  192. case 'number': case 'text':
  193. var elem = container.querySelector('[name="' + name + '"]');
  194. elem.value = value;
  195. break;
  196. case 'select':
  197. var elem = container.querySelector('[name="' + name + '"]');
  198. if (elem.tagName.toLowerCase() == 'input') {
  199. if (elem.type && elem.type == 'radio') {
  200. /* Single selection with radio buttons */
  201. elem = container.querySelector(
  202. '[name="' + name + '"][value="' + value + '"]');
  203. elem.checked = true;
  204. }
  205. else if (elem.type && elem.type == 'checkbox') {
  206. /* Multiple selection with checkboxes */
  207. var checkboxes = container.querySelectorAll(
  208. 'input[name="' + name + '"]');
  209.  
  210. for (var i = 0; i < checkboxes.length; i++)
  211. checkboxes[i].checked =
  212. (value.indexOf(checkboxes[i].value) > -1);
  213. }
  214. }
  215. else if (elem.tagName.toLowerCase() == 'select')
  216. if (elem.multiple) {
  217. /* Multiple selection element */
  218. var options = container.querySelectorAll(
  219. 'select[name="' + name + '"] option');
  220. for (var i = 0; i < options.length; i++)
  221. options[i].selected =
  222. (value.indexOf(options[i].value) > -1);
  223. }
  224. else
  225. /* Single selection element */
  226. elem.value = value;
  227. break;
  228. }
  229. }
  230. }
  231. /**
  232. * Save button click event handler
  233. */
  234. function saveClick() {
  235. for (name in params) {
  236. switch (params[name].type) {
  237. case 'checkbox':
  238. var elem = container.querySelector('[name="' + name + '"]');
  239. values[name] = elem.checked;
  240. break;
  241. case 'custom':
  242. values[name] = params[name].get(container
  243. .querySelector('#__MonkeyConfig_parent_' + name));
  244. break;
  245. case 'number': case 'text':
  246. var elem = container.querySelector('[name="' + name + '"]');
  247. values[name] = elem.value;
  248. break;
  249. case 'select':
  250. var elem = container.querySelector('[name="' + name + '"]');
  251.  
  252. if (elem.tagName.toLowerCase() == 'input') {
  253. if (elem.type && elem.type == 'radio')
  254. /* Single selection with radio buttons */
  255. values[name] = container.querySelector(
  256. '[name="' + name + '"]:checked').value;
  257. else if (elem.type && elem.type == 'checkbox') {
  258. /* Multiple selection with checkboxes */
  259. values[name] = [];
  260. var inputs = container.querySelectorAll(
  261. 'input[name="' + name + '"]');
  262.  
  263. for (var i = 0; i < inputs.length; i++)
  264. if (inputs[i].checked)
  265. values[name].push(inputs[i].value);
  266. }
  267. }
  268. else if (elem.tagName.toLowerCase() == 'select' && elem.multiple) {
  269. /* Multiple selection element */
  270. values[name] = [];
  271. var options = container.querySelectorAll(
  272. 'select[name="' + name + '"] option');
  273.  
  274. for (var i = 0; i < options.length; i++)
  275. if (options[i].selected)
  276. values[name].push(options[i].value);
  277. }
  278. else
  279. values[name] = elem.value;
  280. break;
  281. }
  282. }
  283. GM_setValue(storageKey, JSON.stringify(values));
  284. close();
  285. if (data.onSave)
  286. data.onSave(values);
  287. }
  288. /**
  289. * Cancel button click event handler
  290. */
  291. function cancelClick() {
  292. close();
  293. }
  294. /**
  295. * Set Defaults button click event handler
  296. */
  297. function defaultsClick() {
  298. setDefaults();
  299. update();
  300. }
  301.  
  302. /**
  303. * Open configuration dialog
  304. *
  305. * @param mode
  306. * Display mode ("iframe", "layer", or "window", defaults to
  307. * "iframe")
  308. * @param options
  309. * Display mode options
  310. */
  311. function open(mode, options) {
  312. function openDone() {
  313. /* Attach button event handlers */
  314. var button;
  315. if (button = container.querySelector('#__MonkeyConfig_button_save'))
  316. button.addEventListener('click', saveClick, true);
  317. if (button = container.querySelector('#__MonkeyConfig_button_cancel'))
  318. button.addEventListener('click', cancelClick, true);
  319. if (button = container.querySelector('#__MonkeyConfig_button_defaults'))
  320. button.addEventListener('click', defaultsClick, true);
  321. displayed = true;
  322. update();
  323. }
  324. switch (mode) {
  325. case 'window':
  326. var windowFeatures = {
  327. location: 'no',
  328. status: 'no',
  329. left: window.screenX,
  330. top: window.screenY,
  331. width: 100,
  332. height: 100
  333. };
  334. /* Additional features may be specified as an option */
  335. if (options && options.windowFeatures)
  336. for (var name in options.windowFeatures)
  337. windowFeatures[name] = options.windowFeatures[name];
  338.  
  339. var featuresArray = [];
  340. for (var name in windowFeatures)
  341. featuresArray.push(name + '=' + windowFeatures[name]);
  342.  
  343. var win = window.open('', data.title, featuresArray.join(','));
  344. /* Find head and body (then call the blood spatter analyst) */
  345. var head = win.document.getElementsByTagName('head')[0],
  346. body = win.document.getElementsByTagName('body')[0];
  347.  
  348. head.innerHTML = '<title>' + data.title + '</title>' +
  349. '<style type="text/css">' +
  350. MonkeyConfig.res.stylesheets.main + '</style>';
  351. body.className = '__MonkeyConfig_window';
  352. /* Place the rendered configuration dialog inside the window body */
  353. body.innerHTML = render();
  354.  
  355. /* Find the container (CBAN-3489) */
  356. container = win.document.querySelector('.__MonkeyConfig_container');
  357. /* Resize window to the dimensions of the container div */
  358. win.innerWidth = container.clientWidth;
  359. win.resizeBy(0, -win.innerHeight + container.clientHeight);
  360. /* Place the window centered relative to the parent */
  361. win.moveBy(Math.round((window.outerWidth - win.outerWidth) / 2),
  362. Math.round((window.outerHeight - win.outerHeight) / 2));
  363. openWin = win;
  364. openDone();
  365. break;
  366. case 'layer':
  367. if (!MonkeyConfig.styleAdded) {
  368. GM_addStyle(MonkeyConfig.res.stylesheets.main);
  369. MonkeyConfig.styleAdded = true;
  370. }
  371. var body = document.querySelector('body');
  372. /* Create the layer element */
  373. openLayer = document.createElement('div');
  374. openLayer.className = '__MonkeyConfig_layer';
  375. /* Create the overlay */
  376. overlay = document.createElement('div');
  377. overlay.className = '__MonkeyConfig_overlay';
  378. overlay.style.left = 0;
  379. overlay.style.top = 0;
  380. overlay.style.width = window.innerWidth + 'px';
  381. overlay.style.height = window.innerHeight + 'px';
  382. overlay.style.zIndex = 9999;
  383. body.appendChild(overlay);
  384. body.appendChild(openLayer);
  385. /*
  386. * Place the rendered configuration dialog inside the layer element
  387. */
  388. openLayer.innerHTML = render();
  389. /* Position the layer in the center of the viewport */
  390. openLayer.style.left = Math.round((window.innerWidth -
  391. openLayer.clientWidth) / 2) + 'px';
  392. openLayer.style.top = Math.round((window.innerHeight -
  393. openLayer.clientHeight) / 2) + 'px';
  394. openLayer.style.zIndex = 9999;
  395. container = document.querySelector('.__MonkeyConfig_container');
  396. openDone();
  397. break;
  398. case 'iframe':
  399. default:
  400. if (!MonkeyConfig.styleAdded) {
  401. GM_addStyle(MonkeyConfig.res.stylesheets.main);
  402. MonkeyConfig.styleAdded = true;
  403. }
  404. var body = document.querySelector('body');
  405. var iframe = document.createElement('iframe');
  406. /* Create the layer element */
  407. openLayer = document.createElement('div');
  408. openLayer.className = '__MonkeyConfig_layer';
  409. /* Create the overlay */
  410. overlay = document.createElement('div');
  411. overlay.className = '__MonkeyConfig_overlay';
  412. overlay.style.left = 0;
  413. overlay.style.top = 0;
  414. overlay.style.width = window.innerWidth + 'px';
  415. overlay.style.height = window.innerHeight + 'px';
  416. overlay.style.zIndex = 9999;
  417. iframe.id = '__MonkeyConfig_frame';
  418. /*
  419. * Make the iframe transparent so that it remains invisible until
  420. * the document inside it is ready
  421. */
  422. iframe.style.opacity = 0;
  423. iframe.src = 'about:blank';
  424. /* Make the iframe seamless with no border and no scrollbars */
  425. if (undefined !== iframe.frameborder)
  426. iframe.frameBorder = '0';
  427. if (undefined !== iframe.scrolling)
  428. iframe.scrolling = 'no';
  429. if (undefined !== iframe.seamless)
  430. iframe.seamless = true;
  431. /* Do the rest in the load event handler */
  432. iframe.addEventListener('load', function () {
  433. iframe.contentDocument.body.innerHTML = render();
  434. iframe.style.opacity = 1;
  435. /* Append the style to the head */
  436. var head = iframe.contentDocument.querySelector('head'),
  437. style = iframe.contentDocument.createElement('style');
  438. style.setAttribute('type', 'text/css');
  439. style.appendChild(iframe.contentDocument.createTextNode(
  440. MonkeyConfig.res.stylesheets.main));
  441. head.appendChild(style);
  442. var body = iframe.contentDocument.querySelector('body');
  443. body.className = '__MonkeyConfig_body';
  444. container = iframe.contentDocument
  445. .querySelector('.__MonkeyConfig_container');
  446.  
  447. iframe.width = container.clientWidth;
  448. iframe.height = container.clientHeight;
  449.  
  450. /* Position the layer in the center of the viewport */
  451. openLayer.style.left = Math.round((window.innerWidth -
  452. openLayer.clientWidth) / 2) + 'px';
  453. openLayer.style.top = Math.round((window.innerHeight -
  454. openLayer.clientHeight) / 2) + 'px';
  455. openLayer.style.zIndex = 9999;
  456. openDone();
  457. }, false);
  458.  
  459. setTimeout(function () {
  460. iframe.width = container.clientWidth;
  461. iframe.height = container.clientHeight;
  462. /* Position the layer in the center of the viewport */
  463. openLayer.style.left = Math.round((window.innerWidth -
  464. openLayer.clientWidth) / 2) + 'px';
  465. openLayer.style.top = Math.round((window.innerHeight -
  466. openLayer.clientHeight) / 2) + 'px';
  467. openLayer.style.zIndex = 9999;
  468. }, 0);
  469. body.appendChild(overlay);
  470. body.appendChild(openLayer);
  471. openLayer.appendChild(iframe);
  472. break;
  473. }
  474. }
  475. /**
  476. * Close configuration dialog
  477. */
  478. function close() {
  479. if (openWin) {
  480. openWin.close();
  481. openWin = undefined;
  482. }
  483. else if (openLayer) {
  484. openLayer.parentNode.removeChild(openLayer);
  485. openLayer = undefined;
  486. if (overlay) {
  487. overlay.parentNode.removeChild(overlay);
  488. overlay = undefined;
  489. }
  490. }
  491. displayed = false;
  492. }
  493.  
  494. init(arguments[0]);
  495. }
  496.  
  497. /**
  498. * Replace double quotes with entities so that the string can be safely used
  499. * in a HTML attribute
  500. *
  501. * @param string A string
  502. * @returns String with double quotes replaced with entities
  503. */
  504. MonkeyConfig.esc = function (string) {
  505. return string.replace(/"/g, '&quot;');
  506. };
  507.  
  508. MonkeyConfig.HTML = {
  509. '_field': function (name, options, data) {
  510. var html;
  511. if (options.type && MonkeyConfig.HTML[options.type])
  512. html = MonkeyConfig.HTML[options.type](name, options, data);
  513. else
  514. return;
  515. if (/\[FIELD\]/.test(options.html)) {
  516. html = options.html.replace(/\[FIELD\]/, html);
  517. }
  518. return html;
  519. },
  520. '_label': function (name, options, data) {
  521. var label = options['label'] ||
  522. name.substring(0, 1).toUpperCase() + name.substring(1)
  523. .replace(/_/g, '&nbsp;');
  524.  
  525. return '<label for="__MonkeyConfig_field_' + name + '">' + label +
  526. '</label>';
  527. },
  528. 'checkbox': function (name, options, data) {
  529. return '<input id="__MonkeyConfig_field_' + name +
  530. '" type="checkbox" name="' + name + '" />';
  531. },
  532. 'custom': function (name, options, data) {
  533. return options.html;
  534. },
  535. 'number': function (name, options, data) {
  536. return '<input id="__MonkeyConfig_field_' + name + '" ' +
  537. 'type="text" class="__MonkeyConfig_field_number" ' +
  538. 'name="' + name + '" />';
  539. },
  540. 'select': function (name, options, data) {
  541. var choices = {}, html = '';
  542. if (options.choices.constructor == Array) {
  543. /* options.choices is an array -- build key/value pairs */
  544. for (var i = 0; i < options.choices.length; i++)
  545. choices[options.choices[i]] = options.choices[i];
  546. }
  547. else
  548. /* options.choices is an object -- use it as it is */
  549. choices = options.choices;
  550.  
  551. if (!options.multiple) {
  552. /* Single selection */
  553. if (!/^radio/.test(options.variant)) {
  554. /* Select element */
  555. html += '<select id="__MonkeyConfig_field_' + name + '" ' +
  556. 'class="__MonkeyConfig_field_select" ' +
  557. 'name="' + name + '">';
  558. for (var value in choices)
  559. html += '<option value="' + MonkeyConfig.esc(value) + '">' +
  560. choices[value] + '</option>';
  561. html += '</select>';
  562. }
  563. else {
  564. /* Radio buttons */
  565. for (var value in choices) {
  566. html += '<label><input type="radio" name="' + name + '" ' +
  567. 'value="' + MonkeyConfig.esc(value) + '" />&nbsp;' +
  568. choices[value] + '</label>' +
  569. (/ column/.test(options.variant) ? '<br />' : '');
  570. }
  571. }
  572. }
  573. else {
  574. /* Multiple selection */
  575. if (!/^checkbox/.test(options.variant)) {
  576. /* Checkboxes */
  577. html += '<select id="__MonkeyConfig_field_' + name + '" ' +
  578. 'class="__MonkeyConfig_field_select" ' +
  579. 'multiple="multiple" ' +
  580. 'name="' + name + '">';
  581. for (var value in choices)
  582. html += '<option value="' + MonkeyConfig.esc(value) + '">' +
  583. choices[value] + '</option>';
  584. html += '</select>';
  585. }
  586. else {
  587. /* Select element */
  588. for (var value in choices) {
  589. html += '<label><input type="checkbox" ' +
  590. 'name="' + name + '" ' +
  591. 'value="' + MonkeyConfig.esc(value) + '" />&nbsp;' +
  592. choices[value] + '</label>' +
  593. (/ column/.test(options.variant) ? '<br />' : '');
  594. }
  595. }
  596. }
  597. return html;
  598. },
  599. 'text': function (name, options, data) {
  600. if (options.long)
  601. return '<textarea id="__MonkeyConfig_field_' + name + '" ' +
  602. 'class="__MonkeyConfig_field_text" ' +
  603. (!isNaN(options.long) ? 'rows="' + options.long + '" ' : '') +
  604. 'name="' + name + '"></textarea>';
  605. else
  606. return '<input id="__MonkeyConfig_field_' + name + '" ' +
  607. 'type="text" class="__MonkeyConfig_field_text" ' +
  608. 'name="' + name + '" />';
  609. }
  610. };
  611.  
  612. MonkeyConfig.formatters = {
  613. 'tr': function (name, options, data) {
  614. var html = '<tr>';
  615.  
  616. switch (options.type) {
  617. case 'checkbox':
  618. /* Checkboxes get special treatment */
  619. html += '<td id="__MonkeyConfig_parent_' + name + '" colspan="2">';
  620. html += MonkeyConfig.HTML['_field'](name, options, data) + ' ';
  621. html += MonkeyConfig.HTML['_label'](name, options, data);
  622. html += '</td>';
  623. break;
  624. default:
  625. html += '<td>';
  626. html += MonkeyConfig.HTML['_label'](name, options, data);
  627. html += '</td><td id="__MonkeyConfig_parent_' + name + '">';
  628. html += MonkeyConfig.HTML['_field'](name, options, data);
  629. html += '</td>';
  630. break;
  631. }
  632. html += '</tr>';
  633.  
  634. return html;
  635. }
  636. };
  637.  
  638. /* Has the stylesheet been added? */
  639. MonkeyConfig.styleAdded = false;
  640.  
  641. /* Resources */
  642. MonkeyConfig.res = {};
  643.  
  644. /* Icons */
  645. MonkeyConfig.res.icons = {
  646. 'arrow_undo': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\
  647. U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAIJSURBVDjLpVM9aJNRFD35GsRSoUKKzQ/B\
  648. 0NJJF3EQlKrVgijSCBmC4NBFKihIcXBwEZdSHVoUwUInFUEkQ1DQ4CKiFsQsTrb5xNpgaZHw2Uog\
  649. 5t5zn0NJNFaw0guX97hwzuPcc17IOYfNlIdNVrhxufR6xJkZjAbSQGXjNAorqixSWFDV3KPhJ+UG\
  650. LtSQMPryrDscPwLnAHOEOQc6gkbUpIagGmApWIb/pZRX4fjj889nWiSQtgYyBZ1BTUEj6AjPa0P7\
  651. 1nb0Jfqwa+futIheHrzRn2yRQCUK/lOQhApBJVQJChHfnkCqOwWEQ+iORJHckUyX5ksvAEyGNuJC\
  652. +s6xCRXNHNxzKMmQ4luwgjfvZp69uvr2+IZcyJ8rjIporrxURggetnV0QET3rrPxzMNM2+n7p678\
  653. jUTrCiWhphAjVHR9DlR0WkSzf4IHxg5MSF0zXZEuVKWKSlCBCostS8zeG7oV64wPqxInbw86lbVX\
  654. KEQ8mkAqmUJ4SxieeVhcnANFC02C7N2h69HO2IXeWC8MDj2JnqaFNAMd8f3HKjx6+LxQRmnOz1OZ\
  655. axKIaF1VISYwB9ARZoQaYY6o1WpYCVYxt+zDn/XzVBv/MOWXW5J44ubRyVgkelFpmF/4BJVfOVDl\
  656. VyqLVBZI5manPjajDOdcswfG9k/3X9v3/vfZv7rFBanriIo++J/f+BMT+YWS6hXl7QAAAABJRU5E\
  657. rkJggg==',
  658. 'cancel': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\
  659. U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAHdSURBVDjLpZNraxpBFIb3a0ggISmmNISW\
  660. XmOboKihxpgUNGWNSpvaS6RpKL3Ry//Mh1wgf6PElaCyzq67O09nVjdVlJbSDy8Lw77PmfecMwZg\
  661. /I/GDw3DCo8HCkZl/RlgGA0e3Yfv7+DbAfLrW+SXOvLTG+SHV/gPbuMZRnsyIDL/OASziMxkkKkU\
  662. QTJJsLaGn8/iHz6nd+8mQv87Ahg2H9Th/BxZqxEkEgSrq/iVCvLsDK9awtvfxb2zjD2ARID+lVVl\
  663. babTgWYTv1rFL5fBUtHbbeTJCb3EQ3ovCnRC6xAgzJtOE+ztheYIEkqbFaS3vY2zuIj77AmtYYDu\
  664. sPy8/zuvunJkDKXM7tYWTiyGWFjAqeQnAD6+7ueNx/FLpRGAru7mcoj5ebqzszil7DggeF/DX1nB\
  665. N82rzPqrzbRayIsLhJqMPT2N83Sdy2GApwFqRN7jFPL0tF+10cDd3MTZ2AjNUkGCoyO6y9cRxfQo\
  666. wFUbpufr1ct4ZoHg+Dg067zduTmEbq4yi/UkYidDe+kaTcP4ObJIajksPd/eyx3c+N2rvPbMDPbU\
  667. FPZSLKzcGjKPrbJaDsu+dQO3msfZzeGY2TCvKGYQhdSYeeJjUt21dIcjXQ7U7Kv599f4j/oF55W4\
  668. g/2e3b8AAAAASUVORK5CYII=',
  669. 'tick': 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABGdBTUEAAK/INwWK6QAAABl0RVh0\
  670. U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAGrSURBVDjLvZPZLkNhFIV75zjvYm7VGFNC\
  671. qoZUJ+roKUUpjRuqp61Wq0NKDMelGGqOxBSUIBKXWtWGZxAvobr8lWjChRgSF//dv9be+9trCwAI\
  672. /vIE/26gXmviW5bqnb8yUK028qZjPfoPWEj4Ku5HBspgAz941IXZeze8N1bottSo8BTZviVWrEh5\
  673. 46EO03EXpuJOdG63otJbjBKHkEp/Ml6yNYYzpuezWL4s5VMtT8acCMQcb5XL3eJE8VgBlR7BeMGW\
  674. 9Z4yT9y1CeyucuhdTGDxfftaBO7G4L+zg91UocxVmCiy51NpiP3n2treUPujL8xhOjYOzZYsQWAN\
  675. yRYlU4Y9Br6oHd5bDh0bCpSOixJiWx71YY09J5pM/WEbzFcDmHvwwBu2wnikg+lEj4mwBe5bC5h1\
  676. OUqcwpdC60dxegRmR06TyjCF9G9z+qM2uCJmuMJmaNZaUrCSIi6X+jJIBBYtW5Cge7cd7sgoHDfD\
  677. aAvKQGAlRZYc6ltJlMxX03UzlaRlBdQrzSCwksLRbOpHUSb7pcsnxCCwngvM2Rm/ugUCi84fycr4\
  678. l2t8Bb6iqTxSCgNIAAAAAElFTkSuQmCC'
  679. };
  680.  
  681. /* Stylesheets */
  682. MonkeyConfig.res.stylesheets = {
  683. 'main': '\
  684. body.__MonkeyConfig_window {\
  685. appearance: window !important;\
  686. -moz-appearance: window !important;\
  687. background: auto;\
  688. font-family: sans-serif !important;\
  689. height: 100% !important;\
  690. margin: 0 !important;\
  691. padding: 0 !important;\
  692. width: 100% !important;\
  693. }\
  694. \
  695. div.__MonkeyConfig_container {\
  696. display: table !important;\
  697. font-family: sans-serif !important;\
  698. padding: 0.3em !important;\
  699. }\
  700. \
  701. body.__MonkeyConfig_window div.__MonkeyConfig_container {\
  702. appearance: window !important;\
  703. -moz-appearance: window !important;\
  704. height: 100%;\
  705. width: 100%;\
  706. }\
  707. \
  708. div.__MonkeyConfig_container h1 {\
  709. border-bottom: solid 1px #999 !important;\
  710. font-family: sans-serif !important;\
  711. font-size: 120% !important;\
  712. margin: 0 !important;\
  713. padding: 0 0 0.3em 0 !important;\
  714. }\
  715. \
  716. div.__MonkeyConfig_container table {\
  717. border-spacing: 0 !important;\
  718. margin: 0 !important;\
  719. }\
  720. \
  721. div.__MonkeyConfig_container table td {\
  722. border: none !important;\
  723. line-height: 100% !important;\
  724. padding: 0.3em !important;\
  725. text-align: left !important;\
  726. vertical-align: top !important;\
  727. white-space: nowrap !important;\
  728. }\
  729. \
  730. div.__MonkeyConfig_container table td.__MonkeyConfig_buttons {\
  731. padding: 0.2em 0 !important;\
  732. }\
  733. \
  734. .__MonkeyConfig_field_number {\
  735. width: 5em !important;\
  736. }\
  737. \
  738. div.__MonkeyConfig_container td.__MonkeyConfig_buttons table {\
  739. border-top: solid 1px #999 !important;\
  740. width: 100% !important;\
  741. }\
  742. \
  743. div.__MonkeyConfig_container td.__MonkeyConfig_buttons td {\
  744. padding: 0.6em 0.3em 0.1em 0.3em !important;\
  745. text-align: center !important;\
  746. vertical-align: top;\
  747. }\
  748. \
  749. div.__MonkeyConfig_container td.__MonkeyConfig_buttons button {\
  750. appearance: button !important;\
  751. -moz-appearance: button !important;\
  752. background-position: 8px 50% !important;\
  753. background-repeat: no-repeat !important;\
  754. padding: 3px 8px 3px 24px !important;\
  755. padding: 3px 8px !important;\
  756. white-space: nowrap !important;\
  757. }\
  758. \
  759. div.__MonkeyConfig_container td.__MonkeyConfig_buttons button img {\
  760. vertical-align: middle !important;\
  761. }\
  762. \
  763. div.__MonkeyConfig_layer {\
  764. display: table !important;\
  765. position: fixed !important;\
  766. }\
  767. \
  768. div.__MonkeyConfig_layer div.__MonkeyConfig_container,\
  769. body.__MonkeyConfig_body > div.__MonkeyConfig_container {\
  770. background: #eee linear-gradient(180deg,\
  771. #f8f8f8 0, #ddd 100%) !important;\
  772. border-radius: 0.5em !important;\
  773. box-shadow: 2px 2px 16px #000 !important;\
  774. color: #000 !important;\
  775. font-family: sans-serif !important;\
  776. font-size: 11pt !important;\
  777. padding: 1em 1em 0.4em 1em !important;\
  778. }\
  779. \
  780. div.__MonkeyConfig_layer div.__MonkeyConfig_container td,\
  781. div.__MonkeyConfig_layer div.__MonkeyConfig_container label,\
  782. div.__MonkeyConfig_layer div.__MonkeyConfig_container input,\
  783. div.__MonkeyConfig_layer div.__MonkeyConfig_container select,\
  784. div.__MonkeyConfig_layer div.__MonkeyConfig_container textarea,\
  785. div.__MonkeyConfig_layer div.__MonkeyConfig_container button {\
  786. color: #000 !important;\
  787. font-family: sans-serif !important;\
  788. font-size: 11pt !important;\
  789. line-height: 100% !important;\
  790. margin: 0 !important;\
  791. vertical-align: baseline !important;\
  792. }\
  793. \
  794. div.__MonkeyConfig_container label {\
  795. line-height: 120% !important;\
  796. vertical-align: baseline !important;\
  797. }\
  798. \
  799. div.__MonkeyConfig_container textarea {\
  800. vertical-align: text-top !important;\
  801. width: 100%;\
  802. }\
  803. \
  804. div.__MonkeyConfig_layer div.__MonkeyConfig_container input[type="text"] {\
  805. appearance: textfield !important;\
  806. -moz-appearance: textfield !important;\
  807. background: #fff !important;\
  808. }\
  809. \
  810. div.__MonkeyConfig_layer div.__MonkeyConfig_container h1 {\
  811. font-weight: bold !important;\
  812. text-align: left !important;\
  813. }\
  814. \
  815. div.__MonkeyConfig_layer div.__MonkeyConfig_container td.__MonkeyConfig_buttons button,\
  816. body > div.__MonkeyConfig_container td.__MonkeyConfig_buttons button {\
  817. appearance: button !important;\
  818. -moz-appearance: button !important;\
  819. background: #ccc linear-gradient(180deg,\
  820. #ddd 0, #ccc 45%, #bbb 50%, #aaa 100%) !important;\
  821. border-style: solid !important;\
  822. border-width: 1px !important;\
  823. border-radius: 0.5em !important;\
  824. box-shadow: 0 0 1px #000 !important;\
  825. color: #000 !important;\
  826. font-size: 11pt !important;\
  827. }\
  828. \
  829. div.__MonkeyConfig_layer div.__MonkeyConfig_container td.__MonkeyConfig_buttons button:hover,\
  830. body > div.__MonkeyConfig_container td.__MonkeyConfig_buttons button:hover {\
  831. background: #d2d2d2 linear-gradient(180deg,\
  832. #e2e2e2 0, #d2d2d2 45%, #c2c2c2 50%, #b2b2b2 100%) !important;\
  833. }\
  834. \
  835. div.__MonkeyConfig_overlay {\
  836. background-color: #000 !important;\
  837. opacity: 0.6 !important;\
  838. position: fixed !important;\
  839. }\
  840. \
  841. iframe#__MonkeyConfig_frame {\
  842. border: none !important;\
  843. box-shadow: 2px 2px 16px #000 !important;\
  844. }\
  845. \
  846. body.__MonkeyConfig_body {\
  847. margin: 0 !important;\
  848. padding: 0 !important;\
  849. }\
  850. '
  851. };