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