GM_config_lz-string

Refactor GM_config, this version uses lz-string to access data for a Library script

目前為 2018-10-02 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/372760/633461/GM_config_lz-string.js

  1. // ==UserScript==
  2. // @namespace http://tampermonkey.net/
  3. // @exclude *
  4.  
  5. // ==UserLibrary==
  6. // @name GM_config_lz-string
  7. // @description Refactor GM_config, this version uses lz-string to access data for a Library script
  8. // @author avan
  9. // @license MIT
  10. // @version 0.4
  11.  
  12. // ==/UserScript==
  13.  
  14. // ==/UserLibrary==
  15.  
  16. GM_configStruct.prototype.read = function (store) {
  17. var rval, cKey, dValue;
  18. try {
  19. cKey = LZString.compressToUTF16(store || this.id);
  20. dValue = LZString.decompressFromUTF16(this.getValue(cKey, '{}'));
  21. rval = this.parser(dValue);
  22. } catch(e) {
  23. this.log("GM_config failed to read saved settings!");
  24. rval = {};
  25. }
  26. return rval;
  27. };
  28.  
  29. GM_configStruct.prototype.write = function (store, obj) {
  30. if (!obj) {
  31. var values = {},
  32. forgotten = {},
  33. fields = this.fields;
  34.  
  35. for (var id in fields) {
  36. var field = fields[id];
  37. var value = field.toValue();
  38.  
  39. if (field.save) {
  40. if (value !== null) {
  41. values[id] = value;
  42. field.value = value;
  43. } else
  44. values[id] = field.value;
  45. } else
  46. forgotten[id] = value;
  47. }
  48. }
  49. try {
  50. var cKey = LZString.compressToUTF16(store || this.id),
  51. cValue = LZString.compressToUTF16(this.stringify(obj || values));
  52. this.setValue(cKey, cValue);
  53. } catch(e) {
  54. this.log("GM_config failed to save settings!");
  55. }
  56.  
  57. return forgotten;
  58. };
  59. GM_configField.prototype.toNode = function() {
  60. var field = this.settings,
  61. value = this.value,
  62. options = field.options,
  63. type = field.type,
  64. className = field.class,
  65. style = field.style,
  66. id = this.id,
  67. configId = this.configId,
  68. labelPos = field.labelPos,
  69. create = this.create;
  70. function addLabel(pos, labelEl, parentNode, beforeEl) {
  71. if (!beforeEl) beforeEl = parentNode.firstChild;
  72. switch (pos) {
  73. case 'right':
  74. case 'below':
  75. if (pos == 'below')
  76. parentNode.appendChild(create('br', {}));
  77. parentNode.appendChild(labelEl);
  78. break;
  79. default:
  80. if (pos == 'above')
  81. parentNode.insertBefore(create('br', {}), beforeEl);
  82. parentNode.insertBefore(labelEl, beforeEl);
  83. }
  84. }
  85. var retNode = create('div', {
  86. className: 'config_var',
  87. id: configId + '_' + id + '_var',
  88. title: field.title || '',
  89. }),
  90. firstProp;
  91. // Retrieve the first prop
  92. for (var i in field) {
  93. firstProp = i;
  94. break;
  95. }
  96. var label = field.label && type != "button" ?
  97. create('label', {
  98. id: configId + '_' + id + '_field_label',
  99. for: configId + '_field_' + id,
  100. className: 'field_label'
  101. }, field.label) : null;
  102. var props = {className: className || '', style: style || ''};
  103. switch (type) {
  104. case 'textarea':
  105. props.innerHTML = value;
  106. props.id = configId + '_field_' + id;
  107. props.className = (props.className ? props.className + ' ' : '') + 'block';
  108. props.cols = (field.cols ? field.cols : 20);
  109. props.rows = (field.rows ? field.rows : 2);
  110. retNode.appendChild((this.node = create('textarea', props)));
  111. break;
  112. case 'radio':
  113. props.id = configId + '_field_' + id;
  114. var wrap = create('div', props);
  115. this.node = wrap;
  116. for (var i = 0, len = options.length; i < len; ++i) {
  117. var radLabel = create('label', {
  118. className: 'radio_label'
  119. }, options[i]);
  120. var rad = wrap.appendChild(create('input', {
  121. value: options[i],
  122. type: 'radio',
  123. name: id,
  124. checked: options[i] == value
  125. }));
  126. var radLabelPos = labelPos &&
  127. (labelPos == 'left' || labelPos == 'right') ?
  128. labelPos : firstProp == 'options' ? 'left' : 'right';
  129. addLabel(radLabelPos, radLabel, wrap, rad);
  130. }
  131. retNode.appendChild(wrap);
  132. break;
  133. case 'select':
  134. props.id = configId + '_field_' + id;
  135. var wrap = create('select', props);
  136. this.node = wrap;
  137. for (var i = 0, len = options.length; i < len; ++i) {
  138. var option = options[i];
  139. wrap.appendChild(create('option', {
  140. value: option,
  141. selected: option == value
  142. }, option));
  143. }
  144. retNode.appendChild(wrap);
  145. break;
  146. default: // fields using input elements
  147. props.id = configId + '_field_' + id;
  148. props.type = type;
  149. props.value = type == 'button' ? field.label : value;
  150. switch (type) {
  151. case 'checkbox':
  152. props.checked = value;
  153. break;
  154. case 'button':
  155. props.size = field.size ? field.size : 25;
  156. if (field.script) field.click = field.script;
  157. if (field.click) props.onclick = field.click;
  158. break;
  159. case 'hidden':
  160. break;
  161. case 'password':
  162. props.size = field.size ? field.size : 25;
  163. break;
  164. default:
  165. // type = text, int, or float
  166. props.type = 'text';
  167. props.size = field.size ? field.size : 25;
  168. }
  169. retNode.appendChild((this.node = create('input', props)));
  170. }
  171. if (label) {
  172. // If the label is passed first, insert it before the field
  173. // else insert it after
  174. if (!labelPos)
  175. labelPos = firstProp == "label" || type == "radio" ?
  176. "left" : "right";
  177. addLabel(labelPos, label, retNode);
  178. }
  179. return retNode;
  180. };