MonkeyConfig-branch

Easy configuration dialog builder for user scripts

Script này sẽ không được không được cài đặt trực tiếp. Nó là một thư viện cho các script khác để bao gồm các chỉ thị meta // @require https://update.greatest.deepsurf.us/scripts/486241/1321368/MonkeyConfig-branch.js

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