GM_option

support tool for UserConfig.(library)

此脚本不应直接安装。它是供其他脚本使用的外部库,要使用该库请加入元指令 // @require https://update.gf.qytechs.cn/scripts/9507/151184/GM_option.js

  1. // ==UserScript==
  2. // @name GM_option
  3. // @namespace https://gf.qytechs.cn/ja/scripts/9507
  4. // @homepageURL https://gf.qytechs.cn/ja/scripts/9507
  5. // @license http://creativecommons.org/licenses/by-nc-sa/4.0/
  6. // @include http://*
  7. // @include https://*
  8. // @include file:*
  9. // @copyright Noi & Noisys & NoiSystem & NoiProject
  10. // @author noi
  11. // @description support tool for UserConfig.(library)
  12. // @version 1.04
  13. // @grant GM_registerMenuCommand
  14. // @grant GM_setValue
  15. // @grant GM_getValue
  16. // @grant GM_deleteValue
  17. // @grant GM_log
  18. // ==/UserScript==
  19.  
  20. /*************************************************************************
  21. [about]
  22.  
  23. This script is the library to make a setting screen.
  24. I made this support tool in order to make more easily.
  25.  
  26. *************************************************************************
  27. [How to use]
  28.  
  29. Sample code is end of this Script.
  30. Plz test it.
  31.  
  32.  
  33. If savedata is none....?
  34. <first start-up or no savedata or parameter(HTML tag) changed>
  35. This script make GM_option window and save default.
  36. <next time>
  37. This script never make GM_option window without running open-function.
  38.  
  39. <@grant>----------------------------------------------
  40. you need to add @grant.
  41. // @grant GM_setValue
  42. // @grant GM_getValue
  43. // @grant GM_deleteValue
  44. // @grant GM_registerMenuCommand
  45.  
  46. GM_setValue and GM_getValue and GM_deleteValue is required.
  47. GM_registerMenuCommand is optional.
  48.  
  49.  
  50. <start function>----------------------------------------------
  51. GM_option.open(String,String,HashArray);
  52.  
  53. first String is HTML Tag(header ex: style or script or etc...)
  54. second String is HTML Tag(document.body).
  55. third HashArray is optional,it's messages for dialog.
  56.  
  57. Message List
  58. 'save' - when click save button.
  59. 'reset' - when click reset button.(discard changes)
  60. 'clear' - when click clear button.(delete savedata)
  61. 'delete' - when click del button.(delete multiple)
  62.  
  63.  
  64. <user function>--------------------------------------
  65. At first,get user's settings.
  66. GM_option.get();
  67.  
  68. return hashArray(Associative array).
  69.  
  70.  
  71. <HTML tag>-------------------------------------------
  72. use form inputs.
  73. 'name' is save-key.
  74. 'value' is save-data.
  75.  
  76. ex)
  77. HTML tag is...
  78. <input type="text" name="this_is_Key" value="this_is_Data" />
  79.  
  80. Save Data is...
  81. {"this_is_Key":"this_is_Data"}
  82.  
  83.  
  84. <multiple text>--------------------------------------
  85. 'name' is ****_multiple9999.(required)
  86. 9999 is number of array.(required)
  87. 'value' is default.(optional)
  88. 'defArray' is default array.(optional)
  89. <button id="this_is_required"> is addButton.(required)
  90.  
  91. ex)
  92. HTML tag is...
  93. <input type="text" name="freeName_multiple2" value="data1" /> <input type="text" name="freeName_multiple2" value="data2" /> <button id="addButton">add</button>
  94.  
  95. Save Data is...
  96. {"freeName_multiple2":[["data1","data2"],["data3","data4"], and more ]}
  97. "data3" and "data4" are input by user.
  98.  
  99. ex2)
  100. HTML tag is...
  101. <input type="text" name="freeName_multiple2" defArray="data1-2,data1-3,data1-4" value="data1-1" /> <input type="text" name="freeName_multiple2" defArray="data2-2,data2-3,data2-4" value="data2-1" /> <button id="addButton">add</button>
  102.  
  103. Save Data is...
  104. {"freeName_multiple2":[["data1-1","data2-1"],["data1-2","data2-2"],["data1-3","data2-3"],["data1-4","data2-4"],["data1-5","data2-5"], and more ]}
  105. "data1-5" and "data2-5" are input by user.
  106.  
  107. ## caution ##
  108. If elements's 'name' are same, defArray are same array.length.
  109.  
  110. <select-multiple(HTML5)>----------------------------
  111. selected is checked.(optional)
  112.  
  113. ex)
  114. HTML tag is...
  115. <select name="selectName" multiple size=5>
  116. <option name="optionName1" value="data1" >item1</option>
  117. <option name="optionName2" value="data2" selected>item2</option>
  118. <option name="optionName3" value="data3" >item3</option>
  119. <option name="optionName4" value="data4" selected>item4</option>
  120. <option name="optionName5" value="data5" >item5</option>
  121.  
  122. Save Data is...
  123. {"selectName":"{\"data2\":true,\"data4\":true}"}
  124.  
  125. To use...
  126. var userSettings = GM_option.get();
  127. var selectArray = JSON.parse(userSettings['selectName']);
  128.  
  129.  
  130. <addEventListener>----------------------------------
  131. 'GM_option_loaded'
  132.  
  133. this event is dispatched...
  134. when made GM_option frame (@first start-up)
  135. when loaded User's Settings from GM_getValue (@next time)
  136.  
  137. ex)
  138. window.addEventListener('GM_option_loaded',userFunction,false);
  139.  
  140.  
  141. <access GM_option document>----------------------------------
  142. GM_option.frame
  143. GM_option.doc
  144.  
  145. ex)
  146. var frame = GM_option.frame;
  147. var doc = GM_option.doc.head;
  148. var head = GM_option.doc.body;
  149. var form = GM_option.doc.opForm;
  150.  
  151.  
  152. <other function>----------------------------------
  153. after GM_option opened
  154. GM_option.show(); - show GM_option
  155. GM_option.close(); - hide GM_option
  156. GM_option.save(); - save settings & reload
  157. GM_option.reset(); - discard changes
  158. GM_option.clear(); - delete SaveData & reload
  159.  
  160.  
  161. *************************************************************************
  162. [history]
  163.  
  164. 10/07/2016 - v1.04 add:multiple設定でreadonly属性の引き継ぎ
  165. 04/30/2015 - v1.03 add:sandbox
  166. 04/29/2015 - v1.01 add:第二引数(body)に変更があった場合は変更箇所の初期値を保存する。初期値配列の指定方法追加。
  167. 04/29/2015 - v1.01 fix:入力欄でENTERキーを押すとaddボタンを押した時と同じ動作をするバグ。第一引数(head)にスクリプトタグを指定しても動作しないバグ修正。resetボタン修正
  168. 04/26/2015 - v1.0 release
  169. *************************************************************************/
  170.  
  171. var GM_option = {
  172. init: function(){
  173. GM_option.defScroll = window.onscroll; //save default scroll
  174. var head = GM_option.head;
  175. var htmlText = GM_option.htmlText;
  176.  
  177. //iframe
  178. var obj = GM_option.frame = window.document.createElement('iframe');
  179. obj.id = 'GM_option';
  180. obj.srcdoc = '<head>' + GM_option.head + '</head><body style="background:white;">' + GM_option.htmlText + '</body>';
  181. obj.setAttribute('style','position:fixed;top:0;left:0;right:0;bottom:0; margin:auto; z-index:999999;width:calc(100% - 40px);height:calc(100% - 60px); max-height:90%; max-width:90%; overflow:auto; visibility:hidden; border:none;');
  182. obj.sandbox = "allow-same-origin allow-scripts";
  183. document.body.appendChild(obj);
  184.  
  185. obj.addEventListener('load', GM_option.make(head,htmlText) ,false);
  186. },
  187. open: function(head,htmlText,msgArray){
  188. GM_option.get();
  189. if(htmlText) GM_option.htmlTextCheck(htmlText);
  190.  
  191. var oType = Object.prototype.toString.call(htmlText).slice(8, -1);
  192. if(!htmlText && htmlText != 'String' && !htmlText.match(/\<.*?\>/)){
  193. alert('second parameter(htmltext) is not correct.');
  194. return;
  195. }
  196. if(!GM_option.event){
  197. GM_option.event = document.createEvent('HTMLEvents');
  198. GM_option.event.initEvent('GM_option_loaded', true, false);
  199.  
  200. GM_option.msgArray = msgArray;
  201. }
  202.  
  203. if(!GM_option.makeFlg && GM_option.saveData){
  204. GM_option.makeFlg = true;
  205. window.dispatchEvent(GM_option.event);
  206. return;
  207. }
  208.  
  209. GM_option.head = head || '';
  210. GM_option.htmlText = htmlText = [
  211. '<form name="opForm" action="javascript:void(0);" onSubmit="return false;">',
  212. '<table id="opTable" style="padding:20px;height:98%;width:98%;"><tr><td align="center" valign="middle">',
  213. htmlText,
  214. '<span id="consol">',
  215. '<input type="button" id="saveConfig" value="save" title="save option" /> ',
  216. '<input type="button" id="resetConfig" value="reset" title="Revert To Last Save" /> ',
  217. '<input type="button" id="clearConfig" value="clear" title="clear userSettings" /> ',
  218. '<button id="closeConfig" title="close option window">close</button>',
  219. '</span>',
  220. '</td></tr></table></form>'
  221. ].join('');
  222.  
  223. if(htmlText && (!GM_option.frame || !GM_option.layer)) GM_option.init();
  224. GM_option.show();
  225. },
  226. make: function() { return function(){
  227. var head = GM_option.head;
  228. var htmlText = GM_option.htmlText;
  229.  
  230. this.removeEventListener("load", GM_option.make(head,htmlText) ,false);
  231.  
  232. var opDoc = GM_option.doc = this.contentDocument;
  233.  
  234. //close
  235. var closeButton = opDoc.getElementById('closeConfig');
  236. closeButton.addEventListener('click',GM_option.close,false);
  237.  
  238. //save
  239. var saveButton = opDoc.getElementById('saveConfig');
  240. saveButton.addEventListener('click',GM_option.save,false);
  241.  
  242. //clear
  243. var defaultButton = opDoc.getElementById('clearConfig');
  244. defaultButton.addEventListener('click',GM_option.clear,false);
  245.  
  246. //reset
  247. var resetButton = opDoc.getElementById('resetConfig');
  248. resetButton.addEventListener('click',GM_option.reset,false);
  249.  
  250. GM_option.load(); //デフォルト読み込み
  251. if(!GM_option.saveData || GM_option.htmlChangeFlg) GM_option.save();
  252.  
  253. //layer
  254. var layer = GM_option.layer = window.document.createElement('div');
  255. layer.id = 'opLayer';
  256. layer.setAttribute('style','position:fixed; top:0px; left:0px; width:100%; height:100%; background-color:black; z-index:5000; opacity:0.7;');
  257. document.body.appendChild(layer);
  258. layer.addEventListener('click', GM_option.close,false);
  259.  
  260. window.addEventListener('beforeunload', function() {
  261. window.removeEventListener("beforeunload", arguments.callee,false);
  262. layer.removeEventListener('click', GM_option.close,false);
  263. closeButton.removeEventListener('click',GM_option.close,false);
  264. saveButton.removeEventListener('click',GM_option.save,false);
  265. defaultButton.removeEventListener('click',GM_option.clear,false);
  266. resetButton.removeEventListener('click',GM_option.reset,false);
  267.  
  268. GM_option.remove();
  269. },false);
  270.  
  271. if(GM_option.makeFlg) GM_option.show();
  272. else{
  273. GM_option.load();
  274. GM_option.close();
  275. window.dispatchEvent(GM_option.event);
  276. }
  277. GM_option.makeFlg = true;
  278.  
  279. opDoc = style = head = htmlText = null;
  280. }},
  281. show: function(){
  282. if(!GM_option.frame || !GM_option.layer) return;
  283. GM_option.scrollStop(true);
  284. GM_option.frame.style.visibility = 'visible';
  285. GM_option.layer.style.visibility = 'visible';
  286. },
  287. save: function(clickFlg){
  288. if(clickFlg){
  289. var txt = 'Do you want to save?(ok:reload)';
  290. if(GM_option.msgArray) txt = GM_option.msgArray['save'] || txt;
  291. if(confirm(txt) == false) return
  292. }
  293.  
  294. var userData = GM_option.get();
  295. var form = GM_option.doc.opForm;
  296. var array={};
  297. var multiArray = {};
  298. for(var i=0,j=form.length;i<j;i++){
  299. var obj = form[i];
  300. var name =obj.name;
  301. if(!name) continue;
  302. switch(obj.type){
  303. case 'checkbox':
  304. if(obj.checked)array[name] = true;
  305. else array[name] = false;
  306. continue;
  307. case 'radio':
  308. if(obj.checked)array[name] = obj.value;
  309. continue;
  310. case 'text':
  311. if(!name.match(/_multiple(\d+)$/)){
  312. array[name] = obj.value;
  313. continue;
  314. }else{
  315. var num = RegExp.$1;
  316. if(!array[name])array[name] = [];
  317. var arrayNum = array[name].length - 1;
  318. if(arrayNum < 0) arrayNum = 0;
  319.  
  320. if(!array[name][arrayNum]) array[name][arrayNum] = [];
  321. if(array[name][arrayNum].length < num) array[name][arrayNum].push(obj.value);
  322. else{
  323. arrayNum++;
  324. if(!array[name][arrayNum]) array[name].push([]);
  325. array[name][arrayNum].push(obj.value);
  326. }
  327.  
  328. if(!obj.hasAttribute('defArray') || (userData && userData[name])) continue;
  329.  
  330. if(!multiArray[name]) multiArray[name] = [];
  331. multiArray[name].push(obj.getAttribute('defArray'));
  332.  
  333. continue;
  334. }
  335. continue;
  336. case 'select-one':
  337. var opt = obj.getElementsByTagName('option');
  338. for(var op=0,opLength=opt.length;op<opLength;op++){
  339. var optObj = opt[op];
  340. if(optObj.selected){ array[name] = optObj.value; break;}
  341. }
  342. continue;
  343. case 'select-multiple':
  344. var opt = obj.getElementsByTagName('option');
  345. var tmpArray = {};
  346. for(var op=0,opLength=opt.length;op<opLength;op++){
  347. var optObj = opt[op];
  348. if(optObj.selected) tmpArray[optObj.value] = true;
  349. }
  350. array[name] = JSON.stringify(tmpArray);
  351. continue;
  352. default:
  353.  
  354. array[name] = obj.value;
  355. continue;
  356. }
  357. }
  358. //example) multiArray is {"textTest5_5_multiple3":["aa,22,33,44","bb,44,55,66","cc,88,99,00"]}
  359. //want to change "textTest5_5_multiple3" to "textTest5_5_multiple3":[["dataA","Multi test2","Multi testA"],["aa","bb","cc"],["22","44","88"],["33","55","99"],["44","66","00"]]
  360. for(var key in multiArray){
  361. var num = parseInt(key.replace(/.*_multiple(\d+)$/,"$1"));
  362. var multiList = multiArray[key];
  363. for(var i=0,j=multiList.length;i<j;i++){
  364. var multiData = multiList[i].split(',');
  365. for(var x=0,y=multiData.length;x<y;x++){
  366. var next = x+1;
  367. if(!array[key][next]) array[key][next] = [];
  368. array[key][next][i] = multiData[x];
  369. }
  370. }
  371. }
  372.  
  373. GM_option.saveData = JSON.stringify(array);
  374.  
  375. GM_setValue('opData',GM_option.saveData);
  376. if(clickFlg) location.reload();
  377. },
  378. //discard changes
  379. reset: function(){
  380. var txt = 'discard changes?';
  381. if(GM_option.msgArray) txt = GM_option.msgArray['reset'] || txt;
  382. if(confirm(txt) == false) return;
  383.  
  384. var dels = GM_option.doc.getElementsByClassName('delSpans');
  385. for (var i = dels.length-1; i >= 0; i--) {
  386. dels[i].parentNode.removeChild(dels[i]);
  387. }
  388. GM_option.doc.opForm.reset();
  389. GM_option.load();
  390.  
  391. },
  392. //delete SaveData
  393. clear: function(){
  394. var txt = 'delete settings?(ok:reload)';
  395. if(GM_option.msgArray) txt = GM_option.msgArray['clear'] || txt;
  396. if(confirm(txt) == false) return;
  397.  
  398. GM_deleteValue('opData');
  399. GM_option.close();
  400. location.reload();
  401. },
  402. //delete line for Multiple
  403. deleteLine: function(e){
  404. var txt = 'delete this line?';
  405. if(GM_option.msgArray) txt = GM_option.msgArray['delete'] || txt;
  406. if(confirm(txt) == false) return;
  407.  
  408. e.target.removeEventListener("click", arguments.callee,false);
  409. e.target.parentNode.parentNode.removeChild(e.target.parentNode);
  410. },
  411. //GM_option.saveData is String,return object Array
  412. get: function(){
  413. if(GM_option.saveData) return JSON.parse(GM_option.saveData);
  414. if(!GM_getValue('opData')) return undefined;
  415.  
  416. GM_option.saveData = GM_getValue('opData');
  417. return JSON.parse(GM_option.saveData);
  418. },
  419. //set data
  420. load: function(){
  421. var userSet = GM_option.get();
  422. if(userSet == undefined) return;
  423. var form = GM_option.doc.opForm;
  424. var lastName = "";
  425. var cntMulti = 0;
  426. var multipleArray = {};
  427.  
  428. for(var i=0,j=form.length;i<j;i++){
  429. var obj = form[i];
  430. var name = obj.name;
  431. var readonly = '';
  432. if(obj.getAttribute('readonly') == 'readonly') readonly = 'readonly="readonly"';
  433. var userData = userSet[name];
  434. if(userData == undefined) continue;
  435. switch(obj.type){
  436. case 'checkbox':
  437. if(userData)obj.setAttribute('checked',true);
  438. else obj.removeAttribute('checked');
  439. continue;
  440. case 'radio':
  441. if(obj.value == userData)obj.setAttribute('checked',true);
  442. else obj.removeAttribute('checked');
  443. continue;
  444. case 'textarea':
  445. obj.innerHTML = obj.value = userData;
  446. continue;
  447. case 'text':
  448. if(!name.match(/_multiple(\d+)$/)){
  449. obj.setAttribute('value',userData);
  450. continue;
  451. }else{
  452. var num = RegExp.$1;
  453. if(lastName != name){
  454. lastName = name;
  455. cntMulti = 0;
  456. }
  457.  
  458.  
  459. obj.setAttribute('value',userData[Math.floor(cntMulti / num)][cntMulti % num]);
  460.  
  461. cntMulti++;
  462.  
  463. if(num == cntMulti){
  464. var addObj = obj.parentNode.getElementsByTagName('button');
  465. if(!addObj[0]){
  466. alert('addButton is nothing for multiple select.');
  467. GM_option.remove();
  468. return;
  469. }
  470. var id = addObj[0].id;
  471.  
  472. GM_option.addMultiple(name,num,id,readonly);
  473. j = form.length;
  474. }
  475.  
  476.  
  477. continue;
  478. }
  479. continue;
  480. case 'select-one':
  481. var opt = obj.getElementsByTagName('option');
  482. for(var op=0,opLength=opt.length;op<opLength;op++){
  483. var optObj = opt[op];
  484. if(optObj.value == userData) optObj.setAttribute('selected',true);
  485. else optObj.removeAttribute('selected');
  486. }
  487. continue;
  488. case 'select-multiple':
  489. var tmpArray = JSON.parse(userData);
  490. var opt = obj.getElementsByTagName('option');
  491. for(var op=0,opLength=opt.length;op<opLength;op++){
  492. var optObj = opt[op];
  493. if(tmpArray[optObj.value]) optObj.setAttribute('selected',true);
  494. else optObj.removeAttribute('selected');
  495. }
  496. continue;
  497. default:
  498. obj.setAttribute('value',userData);
  499. continue;
  500. }
  501. }
  502. },
  503. close: function(){
  504. GM_option.scrollStop(false);
  505. if(!GM_option.frame) return;
  506.  
  507. GM_option.frame.style.visibility = 'hidden';
  508. if(!GM_option.layer) return;
  509. GM_option.layer.style.visibility = 'hidden';
  510. },
  511. remove: function(){
  512. if(GM_option.frame) document.body.removeChild(GM_option.frame);
  513. if(GM_option.layer) document.body.removeChild(GM_option.layer);
  514. GM_option = null;
  515. },
  516. scrollStop: function(stopFlg){
  517. GM_option.scrollY = document.documentElement.scrollTop || document.body.scrollTop;
  518.  
  519. if(stopFlg) window.onscroll = function () { window.scrollTo(0, GM_option.scrollY); };
  520. else window.onscroll = GM_option.defScroll;
  521. },
  522. //make line for Multiple
  523. addLine: function(obj,txt,addID){
  524. var num = parseInt(obj.getAttribute('num')) || 0;
  525. var strID = addID + '_delItem' + num;
  526. if(GM_option.doc.getElementById(strID)) return false;
  527. obj.parentNode.insertAdjacentHTML('beforeend',txt + '<button id="' + strID + '">del</button></span>');
  528.  
  529. //del button
  530. var delButton = GM_option.doc.getElementById(strID);
  531. delButton.addEventListener('click',GM_option.deleteLine,true);
  532. window.addEventListener('beforeunload', function() {
  533. window.removeEventListener("beforeunload", arguments.callee,false);
  534. delButton.removeEventListener('click',GM_option.deleteLine,true);
  535. },false);
  536.  
  537.  
  538. obj.setAttribute('num',num + 1);
  539. return true;
  540. },
  541. //Multiple main
  542. addMultiple: function(name,num,addID,readonly){
  543. var addButton = GM_option.doc.getElementById(addID);
  544. var strTxt = '<span class="delSpans"><br>';
  545. for(var x=0;x<num;x++){
  546. strTxt += '<input type="text" name="' + name + '" ' + readonly + ' /> ';
  547. }
  548.  
  549. //addEvent
  550. if(!addButton.hasAttribute('num')){
  551. var addEvent = function(e){
  552. GM_option.addLine(e.target,strTxt,addID);
  553. };
  554. addButton.addEventListener('mouseup',addEvent,false);
  555. window.addEventListener('beforeunload', function() {
  556. window.removeEventListener("beforeunload", arguments.callee,false);
  557. addButton.removeEventListener('click',addEvent,false);
  558. },false);
  559. }
  560.  
  561. //addInput(複数選択肢)
  562. var testArray = GM_option.get()[name];
  563. addButton.setAttribute('num',1);
  564. for(var i=1,j=testArray.length;i<j;i++){
  565. if(!GM_option.addLine(addButton,strTxt,addID)) break;
  566. }
  567. },
  568. htmlTextCheck: function(htmlText){
  569. var txt = GM_getValue('htmlText');
  570. if(!txt || (txt && txt != htmlText)){
  571. GM_setValue('htmlText',htmlText);
  572. if(!txt) return;
  573. GM_option.saveData = null;
  574. GM_option.htmlChangeFlg = true;
  575. }
  576. }
  577. };
  578.  
  579.  
  580.  
  581. //sample code
  582. /*********************************************************************************************************************
  583.  
  584.  
  585. //sample header(ex:style, script etc...)
  586. const strHeader = [
  587. '<style id ="cfgCSS" type="text/css">',
  588. '#cfgTable{ border: solid #ccc 1px; border-spacing:0; border-radius:6px 6px 0 0; -webkit-border-radius:6px 6px 0 0; box-shadow: 0 1px 1px #ccc; -webkit-box-shadow: 0 1px 1px #ccc; }',
  589. '#cfgTable tr:hover{ transition: all 0.1s ease-in-out; background:#fbf8e9; -webkit-transition: all 0.1s ease-in-out; }',
  590. '#cfgTable th, #cfgTable td{ border-left: 1px solid #ccc; border-top: 1px solid #ccc; vertical-align: top; white-space: nowrap; padding: 3px; }',
  591. '#cfgTable th{ color: #151; background: #E3F6E7;}',
  592. '#cfgTitle, #cfgTable th:first-child, #cfgTable td:first-child { border-left: none;}',
  593. '#cfgTable tr:first-child th:first-child{ border-top: none; color: #151; border-bottom: 3px solid #036; background: #A0D0A0; padding: 6px; }',
  594. '#cfgTable label{ padding:1px 5px 2px 5px; }',
  595. '#cfgTable label:hover{ background:#ada; }',
  596. '</style>'
  597. ].join('');
  598.  
  599.  
  600. //sample HTML
  601. var strHTML = [
  602. '<table id="cfgTable" align="center">',
  603. '<thead>',
  604. '<tr>',
  605. '<th id="cfgTitle" colspan=2>Config Title</th>',
  606. '</tr>',
  607. '<tr>',
  608. '<th>Settings</th>',
  609. '<th>Select</th>',
  610. '</tr>',
  611. '</thead>',
  612. '<tbody>',
  613. '<tr>',
  614. '<td>',
  615. 'checkbox test',
  616. '</td>',
  617. '<td>',
  618. '<input type="checkbox" id="flg1" name="check1" checked />',
  619. '<label for="flg1">check1</label>',
  620. '<input type="checkbox" id="flg2" name="check2" />',
  621. '<label for="flg2">check2</label>',
  622. '<input type="checkbox" id="flg3" name="check3" />',
  623. '<label for="flg3">check3</label>',
  624. '</td>',
  625. '</tr>',
  626. '<tr>',
  627. '<td>',
  628. 'radiobutton test1',
  629. '</td>',
  630. '<td>',
  631. '<input type="radio" id="firstOn" name="radio1" value=true checked />',
  632. '<label for="firstOn">on</label>',
  633. '<input type="radio" id="firstOff" name="radio1" value=false />',
  634. '<label for="firstOff">off</label>',
  635. '</td>',
  636. '</tr>',
  637. '<tr>',
  638. '<td>',
  639. 'radiobutton test2',
  640. '</td>',
  641. '<td>',
  642. '<input type="radio" id="secondOn" name="radio2" value="1" />',
  643. '<label for="secondOn">type1</label>',
  644. '<input type="radio" id="secondOff" name="radio2" value="2" checked />',
  645. '<label for="secondOff">type2</label>',
  646. '</td>',
  647. '</tr>',
  648. '<tr>',
  649. '<td>text(inline) test</td>',
  650. '<td>',
  651. '<input type="text" name="textTest1" value="input text" />',
  652. '</td>',
  653. '</tr>',
  654. '<tr>',
  655. '<td>textarea test</td>',
  656. '<td>',
  657. '<textarea name="textarea">textarea test\rthis\ris\rsample\rdata</textarea>',
  658. '</td>',
  659. '</tr>',
  660. '<tr>',
  661. '<td>text(inline) for Multiple test</td>',
  662. '<td>',
  663. '<input type="text" name="textTest3_multiple1" value="test" /> <button id="addItem">add</button>',
  664. '</td>',
  665. '</tr>',
  666. '<tr>',
  667. '<td>text(inline) for Multiple test1</td>',
  668. '<td>',
  669. '<input type="text" name="textTest3_3_multiple1" defArray="BB,CC,DD" value="AA" /> <button id="addItem1">add</button>',
  670. '</td>',
  671. '</tr>',
  672. '<tr>',
  673. '<td>text(inline) for Multiple test2</td>',
  674. '<td>',
  675. '<input type="text" name="textTest4_multiple2" value="data1" /> <input type="text" name="textTest4_multiple2" value="Multi test" /> <button id="addItem2">add</button>',
  676. '</td>',
  677. '</tr>',
  678. '<tr>',
  679. '<td>text(inline) for Multiple test3</td>',
  680. '<td>',
  681. '<input type="text" name="textTest5_multiple3" value="dataA" /> <input type="text" name="textTest5_multiple3" value="Multi test2" /> <input type="text" name="textTest5_multiple3" value="Multi testA" /> <button id="addItem3">add</button>',
  682. '</td>',
  683. '</tr>',
  684. '<tr>',
  685. '<td>text(inline) for Multiple test4</td>',
  686. '<td>',
  687. '<input type="text" name="textTest5_5_multiple3" defArray="aa,22,33,44" value="dataA" readonly="readonly" /> <input type="text" name="textTest5_5_multiple3" defArray="bb,44,55,66" value="Multi test2" readonly="readonly" /> <input type="text" name="textTest5_5_multiple3" defArray="cc,88,99,00" value="Multi testA" readonly="readonly" /> <button id="addItem4">add</button>',
  688. '</td>',
  689. '</tr>',
  690. '<tr>',
  691. '<td>select option test</td>',
  692. '<td>',
  693. '<select name="select">',
  694. '<option name="nameop1" value="op1">item1</option>',
  695. '<option name="nameop2" value="op2" selected>item2</option>',
  696. '<option name="nameop3" value="op3">item3</option>',
  697. '</select>',
  698. '</td>',
  699. '</tr>',
  700. '<tr>',
  701. '<td>select option test2</td>',
  702. '<td>',
  703. '<select name="select2" size=5>',
  704. '<option name="nameopA" value="opA">itemA</option>',
  705. '<option name="nameopB" value="opB" selected>itemB</option>',
  706. '<option name="nameopC" value="opC">itemC</option>',
  707. '<option name="nameopD" value="opE">itemE</option>',
  708. '<option name="nameopE" value="opF">itemF</option>',
  709. '</select>',
  710. '</td>',
  711. '</tr>',
  712. '<tr>',
  713. '<td>select option test3 multiple</td>',
  714. '<td>',
  715. '<select name="select3" multiple size=5>',
  716. '<option name="nameopAA" value="opAA">itemAA</option>',
  717. '<option name="nameopBB" value="opBB" selected>itemBB</option>',
  718. '<option name="nameopCC" value="opCC">itemCC</option>',
  719. '<option name="nameopDD" value="opEE" selected>itemEE</option>',
  720. '<option name="nameopEE" value="opFF">itemFF</option>',
  721. '</select>',
  722. '</td>',
  723. '</tr>',
  724. '</tbody>',
  725. '</table>',
  726. ].join('');
  727.  
  728.  
  729.  
  730.  
  731. //userFunction(sample)
  732. var userConfig = function(){
  733. var options = GM_option.get(); //load userConfig Data(hashArray)
  734.  
  735. //example
  736. var strTxt = "";
  737. var check1 = options['check1'];
  738. strTxt += 'check1:' + check1 + '\n';
  739.  
  740. var check2 = options['check2'];
  741. strTxt += 'check2:' + check2 + '\n';
  742.  
  743. var check3 = options['check3'];
  744. strTxt += 'check3:' + check3 + '\n';
  745.  
  746. var radio1 = options['radio1'];
  747. if(radio1 == 'true') strTxt += 'radio1:on\n';
  748. else strTxt += 'radio1:off\n';
  749.  
  750. var radio2 = options['radio2'];
  751. strTxt += 'radio2:' + radio2 + '\n';
  752.  
  753. var textTest1 = options['textTest1'];
  754. strTxt += 'textTest1:' + textTest1 + '\n';
  755.  
  756. var textarea = options['textarea'];
  757. textarea = textarea.split('\n');
  758. for(var i=0,j=textarea.length;i<j;i++){
  759. strTxt += 'textarea[' + i + ']:' + textarea[i] + '\n';
  760. }
  761.  
  762. var expand = function(text){
  763. var obj = eval(text);
  764. for(var i=0,j=obj.length;i<j;i++){
  765. var objTemp = obj[i];
  766. for(var x=0,y=objTemp.length;x<y;x++){
  767. strTxt += text + '[' + i + '][' + x + ']:' + objTemp[x] + '\n';
  768. }
  769. }
  770. };
  771.  
  772. var textTest3_multiple1 = options['textTest3_multiple1'];
  773. expand('textTest3_multiple1');
  774.  
  775.  
  776. var textTest3_3_multiple1 = options['textTest3_3_multiple1'];
  777. expand('textTest3_3_multiple1');
  778.  
  779. var textTest4_multiple2 = options['textTest4_multiple2'];
  780. expand('textTest4_multiple2');
  781.  
  782.  
  783. var textTest5_multiple3 = options['textTest5_multiple3'];
  784. expand('textTest5_multiple3');
  785.  
  786. var textTest5_5_multiple3 = options['textTest5_5_multiple3'];
  787. expand('textTest5_5_multiple3');
  788.  
  789. var select = options['select'];
  790. strTxt += 'select:' + select + '\n';
  791.  
  792. var select2 = options['select2'];
  793. strTxt += 'select2:' + select2 + '\n';
  794.  
  795. var select3 = JSON.parse(options['select3']);
  796. for(var key in select3){
  797. strTxt += 'select3:' + key + '\n';
  798. }
  799.  
  800. alert(strTxt);
  801.  
  802.  
  803. //make OpenButton(sample)
  804. var openButton = document.createElement('button');
  805. openButton.id = 'openButton';
  806. openButton.innerHTML = 'click here!(open GM_option)';
  807. openButton.style = 'position:fixed;top:0;left:0;right:0;bottom:0;margin:auto; height:100px;';
  808. document.body.appendChild(openButton);
  809. var openConfig = function(){
  810. GM_option.open(strHeader,strHTML);
  811. }
  812. openButton.addEventListener('click', openConfig,false);
  813.  
  814. window.addEventListener('beforeunload', function() {
  815. window.removeEventListener("beforeunload", arguments.callee,false);
  816. openButton.removeEventListener('click',openConfig,false);
  817. userConfig = null;
  818. },false);
  819. }
  820.  
  821. //optional messages
  822. var msgArray = {
  823. 'save':'save?(ok:reload)',
  824. 'reset':'discard changes?(load savedata)',
  825. 'clear':'delete your settings?(ok:reload)',
  826. 'delete':'delete this line?(Don\'t forget to save.)',
  827. };
  828. window.addEventListener('GM_option_loaded',userConfig,false); //userFunction
  829. GM_option.open(strHeader,strHTML,msgArray); //load
  830.  
  831. //script menu
  832. GM_registerMenuCommand('Open GM_option',function(){
  833. GM_option.open(strHeader,strHTML,msgArray);
  834. });
  835.  
  836.  
  837.  
  838. window.addEventListener('beforeunload', function() {
  839. window.removeEventListener("beforeunload", arguments.callee,false);
  840. window.removeEventListener('GM_option_loaded',userConfig,false);
  841. },false);
  842.  
  843.  
  844.  
  845. *********************************************************************************************************************/

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址