Configuration Dialog

A enhanced configuration dialog for Userscripts.

目前為 2018-04-30 提交的版本,檢視 最新版本

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

  1. /*
  2. /////////////////////////////////////////////////////
  3. # #
  4. # Script made by Marius Adam #
  5. # ©DevForce 2018 #
  6. # Code Version 0.2 #
  7. # #
  8. /////////////////////////////////////////////////////
  9. */
  10.  
  11. var configurationWindow = {
  12. maximized: false,
  13. minimized: false,
  14.  
  15. changed: false,
  16.  
  17. data: undefined,
  18. window_id: "window",
  19.  
  20. values: {},
  21. get : function(id){
  22. return this.values[id];
  23. },
  24. getElseSet : function(id, def, ifNone){
  25. var val = this.get(id);
  26. if(val == undefined){
  27. if(def == undefined){
  28. val = ifNone;
  29. this.set(id, ifNone);
  30. }else{
  31. val = def;
  32. this.set(id, def);
  33. }
  34. }
  35. return val;
  36. },
  37. set : function(id, value){
  38. this.values[id] = value;
  39. },
  40. save : function(){
  41. GM_setValue(this.window_id, JSON.stringify(this.values));
  42. console.debug("Saved to #" + this.window_id, this.values);
  43. },
  44. load : function(){
  45. var loaded = GM_getValue(this.window_id);
  46. if(loaded == undefined || loaded.length < 2) loaded = "{}";
  47. this.values = JSON.parse(loaded);
  48. console.debug("Loaded Values: ", this.values);
  49. },
  50. updateChanged : function() {
  51. this.changed = ($('[style="border: 2px solid rgb(255, 244, 0);"]').length + $('[style="outline: rgb(255, 244, 0) solid 3px;"]').length) > 0;
  52. $('#' + this.window_id).find('#saveButton').prop("disabled", ! this.changed);
  53. $('#' + this.window_id).find('#revertButton').prop("disabled", ! this.changed);
  54. },
  55. maximize : function() {
  56. $('#' + this.window_id).find('#content').show();
  57. $('#' + this.window_id).find('#footer').show();
  58. $('#' + this.window_id).find('#theme_dropdown').show();
  59. $("#window_minimize").show();
  60. $('#' + this.window_id).width("calc(100% - 20px)");
  61. $('#' + this.window_id).height("calc(100% - 20px)");
  62. $('#' + this.window_id).css("top", "7px");
  63. $('#' + this.window_id).css("left", "7px");
  64. $('#' + this.window_id).css("min-height", "");
  65.  
  66. this.maximized = true;
  67. this.minimized = false;
  68. },
  69.  
  70. minimize : function(){
  71. $('#' + this.window_id).find('#content').hide();
  72. $('#' + this.window_id).find('#footer').hide();
  73. $('#' + this.window_id).find('#theme_dropdown').hide();
  74. $("#window_minimize").hide();
  75. $('#' + this.window_id).width("50%");
  76. $('#' + this.window_id).height("25px");
  77. $('#' + this.window_id).css("top", "calc(100% - 30px)");
  78. $('#' + this.window_id).css("left", "25%");
  79. $('#' + this.window_id).css("min-height", "30px");
  80.  
  81. this.minimized = true;
  82. },
  83.  
  84. normalize : function(){
  85. $('#' + this.window_id).find('#content').show();
  86. $('#' + this.window_id).find('#footer').show();
  87. $('#' + this.window_id).find('#theme_dropdown').show();
  88. $("#window_minimize").show();
  89. $('#' + this.window_id).width("");
  90. $('#' + this.window_id).height("");
  91. $('#' + this.window_id).css("top", "");
  92. $('#' + this.window_id).css("left", "");
  93. $('#' + this.window_id).css("min-height", "");
  94.  
  95. this.maximized = false;
  96. this.minimized = false;
  97. },
  98.  
  99. clearSelection : function(){
  100. if (window.getSelection) {
  101. if (window.getSelection().empty) { // Chrome
  102. window.getSelection().empty();
  103. } else if (window.getSelection().removeAllRanges) { // Firefox
  104. window.getSelection().removeAllRanges();
  105. }
  106. } else if (document.selection) { // IE
  107. document.selection.empty();
  108. }
  109. },
  110.  
  111. makeDragable : function(move, dragbox, useBorder) {
  112. if(dragbox == undefined) dragbox = move;
  113. if(useBorder == undefined) useBorder = true;
  114.  
  115. var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0, dragged = false;
  116.  
  117. dragbox.onmousedown = dragMouseDown;
  118.  
  119. function dragMouseDown(e) {
  120. e = e || window.event;
  121. if(configurationWindow.minimized){
  122. document.onmouseup = null;
  123. document.onmousemove = null;
  124. return;
  125. }
  126. // get the mouse cursor position at startup:
  127. pos3 = e.clientX;
  128. pos4 = e.clientY;
  129. document.onmouseup = closeDragElement;
  130. // call a function whenever the cursor moves:
  131. document.onmousemove = elementDrag;
  132. }
  133.  
  134. function elementDrag(e) {
  135. e = e || window.event;
  136. // calculate the new cursor position:
  137. pos1 = pos3 - e.clientX;
  138. pos2 = pos4 - e.clientY;
  139. pos3 = e.clientX;
  140. pos4 = e.clientY;
  141. // set the element's new position:
  142. var new_top = move.offsetTop - pos2;
  143. var new_left = move.offsetLeft - pos1;
  144. if(configurationWindow.maximized){
  145. configurationWindow.normalize();
  146. new_top = e.clientY;
  147. new_left = e.clientX;
  148. }
  149. if(useBorder){
  150. var max_width = $(window).width() - $(move).width();
  151. var max_height = $(window).height() - $(move).height();
  152. if(new_top < 0) new_top = 0;
  153. else if(new_top > max_height) new_top = max_height;
  154. if(new_left < 0) new_left = 0;
  155. else if(new_left > max_width) new_left = max_width;
  156. }
  157. move.style.left = new_left + "px";
  158. move.style.top = new_top + "px";
  159. dragged = true;
  160. configurationWindow.clearSelection();
  161. }
  162.  
  163. function closeDragElement() {
  164. /* stop moving when mouse button is released:*/
  165. if(useBorder && dragged){
  166. if(move.style.top.indexOf("%") == -1 && move.style.top.replace("px", "") < 2)
  167. configurationWindow.maximize();
  168. }
  169. document.onmouseup = null;
  170. document.onmousemove = null;
  171. }
  172. },
  173.  
  174. isArray : function(what) {
  175. return Object.prototype.toString.call(what) === '[object Array]';
  176. },
  177.  
  178. isObject : function(what) {
  179. return Object.prototype.toString.call(what) === '[object Object]';
  180. },
  181.  
  182. join : function(labelFirst, label, element){
  183. return (labelFirst ? label + " " + element : element + " " + label);
  184. },
  185.  
  186. replaceAll : function(target, search, replacement) {
  187. return target.replace(new RegExp(search, 'g'), replacement);
  188. },
  189.  
  190. revertChanges : function(){
  191. $('#' + this.window_id).find("#content").find("input[type=text], input[type=password], input[type=number], input[type=color]").each(function(){
  192. $(this).val($(this).attr("value"));
  193. $(this).css("border", "");
  194. });
  195.  
  196. $('#' + this.window_id).find("#content").find("select").each(function(){
  197. this.value = $(this).find("option[selected]").val();
  198. $(this).css("border", "");
  199. });
  200.  
  201. $('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').each(function() {
  202. this.checked = $(this).attr("default") == "true";
  203. $(this).css("outline", "");
  204. });
  205.  
  206. this.updateChanged();
  207. },
  208.  
  209. saveChanges : function(){
  210. $('#' + this.window_id).find("#content").find("input[type=text], input[type=password], input[type=number], input[type=color]").each(function(){
  211. configurationWindow.set(this.id, this.value);
  212. $(this).attr("value", this.value);
  213. $(this).css("border", "");
  214. });
  215.  
  216. $('#' + this.window_id).find("#content").find("select").each(function(){
  217. configurationWindow.set(this.id, this.value);
  218.  
  219. var main_val = this.value;
  220.  
  221. $(this).find("option[selected]").removeAttr("selected");
  222. $(this).find("option").filter(function() {
  223. return this.innerHTML == main_val;
  224. }).attr("selected", "selected");
  225.  
  226. this.value = main_val;
  227.  
  228. $(this).css("border", "");
  229. });
  230.  
  231. $('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').each(function() {
  232. configurationWindow.set(this.id, this.checked);
  233. $(this).attr("default", this.checked);
  234. $(this).css("outline", "");
  235. });
  236.  
  237. this.updateChanged();
  238. this.save();
  239. },
  240.  
  241. ResetSettings : function(){
  242. if(this.isArray(this.data.content)){
  243. for(i = 0; i < this.data.content.length; i++){
  244. if(this.isObject(this.data.content[i])){
  245. var object = this.data.content[i];
  246. object.default = (object.default == undefined ? "" : object.default);
  247. var elem = $('#' + this.window_id).find("#content").find("#" + object.id);
  248. var type = elem.attr("type");
  249. if(type == undefined && elem.is("select")) type = "select";
  250. switch(type){
  251. case "text":
  252. case "number":
  253. case "password":
  254. case "select":
  255. $(elem).val(object.default);
  256. break;
  257. case "checkbox":
  258. $(elem).prop("checked", object.default);
  259. break;
  260. default: break;
  261. }
  262. $(elem).change();
  263. }
  264. }
  265. }
  266. this.updateChanged();
  267. },
  268.  
  269. close : function(){
  270. if(this.changed){
  271. if(!confirm(this.data.confirm_close)){
  272. return false;
  273. }
  274. }
  275. $('#' + this.window_id).attr("style", "display: none;");
  276. return true;
  277. },
  278. open : function(data){
  279. $('#' + this.window_id).attr("style", "");
  280. },
  281.  
  282. create : function(data){
  283. //var data = JSON.parse(content);
  284.  
  285. this.data = data;
  286. if(this.window_id != undefined)
  287. $('#' + this.window_id).remove();
  288.  
  289. $('#window_style').remove();
  290. $('#font-awesome').remove();
  291.  
  292. if(data.id == undefined) data.id = "window";
  293. this.window_id = data.id;
  294.  
  295. this.load();
  296. $('head').append('<link id="font-awesome" rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">');
  297.  
  298. if (data.theme == undefined) data.theme = "mac";
  299. if (!(data.theme == "mac" || data.theme == "win10" || data.theme == "winXP")) data.theme = "mac";
  300. var saved_theme = GM_getValue("config_theme");
  301. if(data.theme_selector == undefined || data.theme_selector == true || data.theme_selector == "true"){
  302. data.theme_selector = true;
  303. if(saved_theme != undefined) data.theme = saved_theme;
  304. }else{
  305. data.theme_selector = false;
  306. }
  307. if(data.width == undefined) data.width = 50;
  308. if(data.height == undefined) data.height = 50;
  309. var section_color = "#c9c9c9";
  310. var subsection_color = "#f1f1f1";
  311. var style = "<style id='window_style'>";
  312. if(data.theme == "mac"){
  313. style += `
  314. #` + this.window_id + ` > #top > .btn {
  315. height: 16px;
  316. width: 16px;
  317. background-color: #bbb;
  318. border-radius: 50%;
  319. float: right;
  320. margin-right: 10px;
  321. display: inline-block;
  322. font-size: 10px;
  323. text-align: center;
  324. color: white;
  325. cursor: pointer;
  326. //font-weight: bold;
  327. }
  328.  
  329. #` + this.window_id + ` > #top > .title {
  330. margin: auto;
  331. font-size: 16px;
  332. font-weight: bold;
  333. cursor: move;
  334. }
  335.  
  336. #` + this.window_id + ` {
  337. border: 3px solid #f1f1f1;
  338. border-top-left-radius: 3px;
  339. border-top-right-radius: 3px;
  340. height: ` + data.height + `%;
  341. width: ` + data.width + `%;
  342. top: ` + ((100 - data.height) / 2) + `%;
  343. left: ` + ((100 - data.width) / 2) + `%;
  344. position: fixed;
  345. z-index: 11000;
  346. background: white;
  347. min-width: 250px;
  348. min-height: 250px;
  349. resize: both;
  350. overflow: auto;
  351. line-height: unset;
  352. overflow-y: hidden;`
  353. + (data.font != undefined ?
  354. (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "") +
  355. (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
  356. : "") +
  357. `}
  358.  
  359. #` + this.window_id + ` > #top {
  360. padding: 10px;
  361. //height: 20px;
  362. background: #f1f1f1;
  363. border-top-left-radius: 4px;
  364. border-top-right-radius: 4px;
  365. position: absolute;
  366. width: calc(100% - 20px);
  367. }
  368. `;
  369. }else if(data.theme == "win10"){
  370. section_color = "#1f9cff";
  371. subsection_color = "#9dd4ff";
  372. style += `
  373. #` + this.window_id + ` > #top > .btn {
  374. height: 22px;
  375. width: 30px;
  376. float: right;
  377. margin-right: 5px;
  378. display: inline-block;
  379. font-size: 16px;
  380. text-align: center;
  381. color: white;
  382. cursor: pointer;
  383. color: black;
  384. padding: 2px;
  385. }
  386. #` + this.window_id + ` > #top > #window_minimize:hover, #` + this.window_id + ` > #top > #window_maximize:hover {
  387. background-color: #ddd;
  388. }
  389. #` + this.window_id + ` > #top > #window_close:hover {
  390. background-color: red;
  391. }
  392.  
  393. #` + this.window_id + ` > #top > .title {
  394. margin: auto;
  395. font-size: 16px;
  396. font-weight: bold;
  397. cursor: move;
  398. padding: 10px;
  399. }
  400.  
  401. #` + this.window_id + ` {
  402. border: 3px solid #1f9cff;
  403. height: ` + data.height + `%;
  404. width: ` + data.width + `%;
  405. top: ` + ((100 - data.height) / 2) + `%;
  406. left: ` + ((100 - data.width) / 2) + `%;
  407. position: fixed;
  408. z-index: 11000;
  409. background: white;
  410. min-width: 250px;
  411. min-height: 250px;
  412. resize: both;
  413. overflow: auto;
  414. line-height: unset;
  415. overflow-y: hidden;`
  416. + (data.font != undefined ?
  417. (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "") +
  418. (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
  419. : "") +
  420. `}
  421.  
  422. #` + this.window_id + ` > #top {
  423. //padding: 10px;
  424. //height: 20px;
  425. background: #1f9cff;
  426. position: absolute;
  427. width: 100%;
  428. }
  429. `;
  430. }else if(data.theme == "winXP"){
  431. section_color = "#226ce7";
  432. subsection_color = "#4094ff";
  433. style += `
  434. #` + this.window_id + ` > #top > .btn {
  435. height: 20px;
  436. width: 20px;
  437. float: right;
  438. margin-right: 5px;
  439. margin-top: 5px;
  440. display: inline-block;
  441. font-size: 16px;
  442. text-align: center;
  443. color: white;
  444. cursor: pointer;
  445. color: white;
  446. border-radius: 2px;
  447. padding: 2px;
  448. border: 1px solid white;
  449. background: linear-gradient(135deg, #7EAED6 0%, #1B72FF 50%, #1655BE 100%);
  450. }
  451. #` + this.window_id + ` > #top > #window_minimize:hover, #` + this.window_id + ` > #top > #window_maximize:hover {
  452. background: linear-gradient(135deg, #6a93b5 0%, #1862da 50%, #124499 100%);
  453. }
  454. #` + this.window_id + ` > #top > #window_close {
  455. background: linear-gradient(135deg, #F1A689 0%, #C0442A 50%, #C2311E 100%);
  456. }
  457. #` + this.window_id + ` > #top > #window_close:hover {
  458. background: linear-gradient(135deg, #c3846c 0%, #a43923 50%, #982415 100%);
  459. }
  460.  
  461. #` + this.window_id + ` > #top > .title {
  462. margin: auto;
  463. font-size: 16px;
  464. font-weight: bold;
  465. cursor: move;
  466. padding: 10px;
  467. color: white;
  468. }
  469.  
  470. #` + this.window_id + ` {
  471. border-left: 3px solid #0056e4;
  472. border-right: 3px solid #0056e4;
  473. border-bottom: 3px solid #0056e4;
  474. height: ` + data.height + `%;
  475. width: ` + data.width + `%;
  476. top: ` + ((100 - data.height) / 2) + `%;
  477. left: ` + ((100 - data.width) / 2) + `%;
  478. position: fixed;
  479. z-index: 11000;
  480. background: white;
  481. min-width: 250px;
  482. min-height: 250px;
  483. border-radius: 8px;
  484. resize: both;
  485. overflow: auto;
  486. line-height: unset;
  487. overflow-y: hidden;`
  488. + (data.font != undefined ?
  489. (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "") +
  490. (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
  491. : "") +
  492. `}
  493.  
  494. #` + this.window_id + ` > #top {
  495. //padding: 10px;
  496. //height: 20px;
  497. border-radius: 5px 5px 0px 0px;
  498. background: linear-gradient(to bottom, #4094ff 0%, #0056e4 13%, #0056e4 71%, #16428b 100%);
  499. position: absolute;
  500. width: 100%;
  501. }
  502. `;
  503. }
  504. style += `
  505. #` + this.window_id + ` > #footer {
  506. text-align: right;
  507. margin: 0px 0px 4px -20px;
  508. height: 40px;
  509. border-top-left-radius: 4px;
  510. border-top-right-radius: 4px;
  511. position: absolute;
  512. width: 100%;
  513. bottom: 0;
  514. }
  515.  
  516. #` + this.window_id + ` > #footer > button {
  517. background-color: #f1f1f1;
  518. border: none;
  519. color: black;
  520. padding: 12px 40px;
  521. font-size: 14px;
  522. cursor: pointer;
  523. margin-left: 5px;
  524. }
  525.  
  526. #` + this.window_id + ` > #footer > button:hover {
  527. background-color: RoyalBlue;
  528. color: white;
  529. }
  530. #` + this.window_id + ` > #footer > button:disabled {
  531. background-color: darkgrey;
  532. color: white;
  533. }
  534. #` + this.window_id + ` > #content {
  535. padding: 10px;
  536. margin-top: 40px;
  537. overflow-y: scroll;
  538. height: calc(100% - 75px);
  539. overflow-wrap: break-word;
  540. }
  541.  
  542. #` + this.window_id + ` > #content > input,#` + this.window_id + ` > #content > select {`
  543. + (data.font != undefined ?
  544. (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "") +
  545. (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
  546. : "") +
  547. `}
  548.  
  549. #` + this.window_id + ` > #content > br {
  550. display: block;
  551. margin-top: 4px;
  552. content: " ";
  553. }
  554.  
  555. #` + this.window_id + ` > #theme_dropdown {
  556. float: left;
  557. bottom: 5px;
  558. position: absolute;
  559. left: 5px;
  560. border: none;
  561. -webkit-appearance: none;
  562. -moz-appearance: none;
  563. appearance: none;
  564. color: gray;
  565. }
  566. #` + this.window_id + ` > #theme_dropdown > option {
  567. color: black;
  568. }
  569. .no-margin {
  570. margin: 0px;
  571. }
  572. .wrap-collapsible {
  573. margin-bottom: 1.2rem 0;
  574. }
  575.  
  576. .toggle {
  577. display: none;
  578. }
  579.  
  580. .lbl-toggle {
  581. display: block;
  582. cursor: pointer;
  583. transition: all 0.25s ease-out;
  584. }
  585. .lbl-toggle h2, .lbl-toggle h4 {
  586. display: inline;
  587. }
  588.  
  589. .lbl-toggle:hover {
  590. color: white;
  591. }
  592.  
  593. .lbl-toggle::before {
  594. content: ' ';
  595. display: inline-block;
  596.  
  597. border-top: 5px solid transparent;
  598. border-bottom: 5px solid transparent;
  599. border-left: 5px solid currentColor;
  600. vertical-align: middle;
  601. margin-right: .7rem;
  602. transform: translateY(-2px);
  603.  
  604. transition: transform .2s ease-out;
  605. }
  606.  
  607. .toggle:checked + .lbl-toggle::before {
  608. transform: rotate(90deg) translateX(-3px);
  609. }
  610.  
  611. .collapsible-content {
  612. max-height: 0px;
  613. overflow: hidden;
  614. transition: max-height .25s ease-in-out;
  615. }
  616.  
  617. .toggle:checked + .lbl-toggle + .collapsible-content {
  618. max-height: 350px;
  619. }
  620.  
  621. .collapsible-content .content-inner {
  622. //background: rgba(161, 161, 161, 0.2);
  623. //border: 1px solid black;
  624. }
  625. `;
  626. style += "<style>";
  627. $('head').append(style);
  628. if(data.theme_section_color == undefined || data.theme_section_color == false){
  629. section_color = "#c9c9c9";
  630. subsection_color = "#f1f1f1";
  631. }
  632. var content = "";
  633.  
  634. if(this.isArray(data.content)){
  635. var section_collapsible = false;
  636. var subsection_collapsible = false;
  637. var collapsible_id = 1;
  638. for(i = 0; i < data.content.length; i++){
  639. if(this.isObject(data.content[i])){
  640. var label_first = undefined;
  641. Object.keys(data.content[i]).forEach(function(key){
  642. if(label_first != undefined) return;
  643.  
  644. if(key == "label") label_first = true;
  645. else if(key == "type") label_first = false;
  646. });
  647.  
  648. var label = this.replaceAll(data.content[i].label, " ", "&nbsp;&nbsp;");
  649.  
  650. var object = data.content[i];
  651.  
  652. if(object.style != undefined) object.style = " style='" + object.style + "'";
  653. else object.style = "";
  654.  
  655. if(object.require != undefined) object.style += " require='" + object.require + "'";
  656. switch(object.type){
  657. case "p":
  658. content += "<p class='no-margin'" + object.style + ">" + label + "</p>";
  659. break;
  660. case "h1":
  661. content += "<h1 class='no-margin'" + object.style + ">" + label + "</h1>";
  662. break;
  663. case "h2":
  664. content += "<h2 class='no-margin'" + object.style + ">" + label + "</h2>";
  665. break;
  666. case "h3":
  667. content += "<h3 class='no-margin'" + object.style + ">" + label + "</h3>";
  668. break;
  669. case "h4":
  670. content += "<h4 class='no-margin'" + object.style + ">" + label + "</h4>";
  671. break;
  672. case "section":
  673. if(object.align == undefined) object.align = "center";
  674. if(object.background == undefined) object.background = section_color;
  675. if(subsection_collapsible){
  676. content += "</div></div></div>";
  677. subsection_collapsible = false;
  678. }
  679. if(section_collapsible){
  680. content += "</div></div></div>";
  681. section_collapsible = false;
  682. }
  683. if(object.collapsible != undefined && object.collapsible){
  684. content += "<div class='wrap-collapsible'><input id='collapsible" + collapsible_id + "' class='toggle' type='checkbox' " + (object.collapsed != undefined && object.collapsed == false ? "checked" : "") + "><label style='margin: 5px 0px 0px 0px; background: " + object.background + "; text-align: " + object.align + ";' for='collapsible" + collapsible_id + "' class='lbl-toggle'><h2>" + label + "</h2></label><div class='collapsible-content'><div class='content-inner'>";
  685. section_collapsible = true;
  686. collapsible_id++;
  687. }else{
  688. content += "<div width='100%' style='margin: 5px 0px; background: " + object.background + "; text-align: " + object.align + ";'><h2 class='no-margin'>" + label + "</h2></div>";
  689. }
  690. break;
  691. case "subsection":
  692. if(object.align == undefined) object.align = "center";
  693. if(object.background == undefined) object.background = subsection_color;
  694. if(subsection_collapsible){
  695. content += "</div></div></div>";
  696. subsection_collapsible = false;
  697. }
  698. if(object.collapsible != undefined && object.collapsible){
  699. content += "<div class='wrap-collapsible'><input id='collapsible" + collapsible_id + "' class='toggle' type='checkbox' " + (object.collapsed != undefined && object.collapsed == false ? "checked" : "") + "><label style='margin: 5px 0px 0px 0px; background: " + object.background + "; text-align: " + object.align + ";' for='collapsible" + collapsible_id + "' class='lbl-toggle'><h4>" + label + "</h4></label><div class='collapsible-content'><div class='content-inner'>";
  700. subsection_collapsible = true;
  701. collapsible_id++;
  702. }else{
  703. content += "<div width='100%' style='margin: 5px 0px; background: " + object.background + "; text-align: " + object.align + ";'><h4 class='no-margin'>" + label + "</h4></div>";
  704. }
  705. break;
  706. case "text":
  707. var value = this.getElseSet(object.id, object.default, "");
  708. content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='text' value='" + value + "' />");
  709.  
  710. content += "<br>";
  711. break;
  712. case "password":
  713. var value = this.getElseSet(object.id, object.default, "");
  714. content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='password' value='" + value + "' />");
  715.  
  716. content += "<br>";
  717. break;
  718. case "checkbox":
  719. var value = this.getElseSet(object.id, object.default, false);
  720. if(value == "true" || value == true) value = true;
  721. else value = false;
  722.  
  723. label = "<label for='" + object.id + "'>" + label + "</label>";
  724. content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " default='" + value + "' type='checkbox' " + (value ? "checked" : "") + "/>");
  725.  
  726. content += "<br>";
  727. break;
  728. case "select":
  729. var value = this.getElseSet(object.id, object.default, "");
  730.  
  731. var select = " <select" + object.style + " id='" + object.id + "'>";
  732. object.options.forEach(function(opt){
  733. if(opt == value){
  734. select += "<option selected>" + opt + "</option>";
  735. }else{
  736. select += "<option>" + opt + "</option>";
  737. }
  738. });
  739. select += "</select> ";
  740.  
  741. content += this.join(label_first, label, select);
  742.  
  743. content += "<br>";
  744. break;
  745. case "numeric":
  746. var value = this.getElseSet(object.id, object.default, 0);
  747. var element = "<input id='" + object.id + "'" + object.style + " type='number' value='" + value + "'";
  748. if(object.min != undefined) element += " min='" + object.min + "'";
  749. if(object.max != undefined) element += " max='" + object.max + "'";
  750. element += " />";
  751. content += this.join(label_first, label, element);
  752.  
  753. content += "<br>";
  754. break;
  755. case "color":
  756. var value = this.getElseSet(object.id, object.default, "#FFFFFF");
  757.  
  758. content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='color' value='" + value + "' />");
  759.  
  760. content += "<br>";
  761. break;
  762. default: break;
  763. }
  764. }else{
  765. content += "<p>" + data.content[i] + "</p>";
  766. }
  767. }
  768. if(subsection_collapsible){
  769. content += "</div></div></div>";
  770. section_collapsible = false;
  771. }
  772. if(section_collapsible){
  773. content += "</div></div></div>";
  774. section_collapsible = false;
  775. }
  776. }else{
  777. content = data.content;
  778. }
  779. content += "<br style='height: 25px;' />";
  780. var buttons = "";
  781.  
  782. if(data.completeresetbutton == undefined || data.completeresetbutton == true || data.completeresetbutton == "true"){
  783. buttons += "<button id='completeResetButton'><i class='fa fa-trash'></i></button>";
  784. }
  785.  
  786. if(data.revertbutton == undefined || data.revertbutton == true || data.revertbutton == "true"){
  787. buttons += "<button id='revertButton'><i class='fa fa-undo'></i></button>";
  788. }
  789.  
  790. if(data.savebutton == undefined || data.savebutton == true || data.savebutton == "true"){
  791. buttons += "<button id='saveButton'><i class='fa fa-save'></i></button>";
  792. }
  793.  
  794. var topbuttons = "";
  795. if(data.top == undefined || data.top.close == undefined || data.top.close == "true"){
  796. if(data.theme == "mac") topbuttons += '<span id="window_close" class="btn" style="background:#ED594A; margin-right: 20px;"><i class="fa fa-times" style="vertical-align: sub;"></i></span>';
  797. else if(data.theme == "win10") topbuttons += '<span id="window_close" class="btn" style="margin-right: 0px;"><i class="fa fa-times"></i></span>';
  798. else if(data.theme == "winXP") topbuttons += '<span id="window_close" class="btn"><i class="fa fa-times"></i></span>';
  799. }
  800. if(data.top == undefined || data.top.maximize == undefined || data.top.maximize == "true"){
  801. if(data.theme == "mac") topbuttons += '<span id="window_maximize" class="btn" style="background:#FDD800;"><i class="fa fa-window-maximize" style="vertical-align: sub;"></i></span>';
  802. else if(data.theme == "win10" || data.theme == "winXP") topbuttons += '<span id="window_maximize" class="btn"><i class="fa fa-window-maximize"></i></span>';
  803. }
  804. if(data.top == undefined || data.top.minimize == undefined || data.top.minimize == "true"){
  805. if(data.theme == "mac") topbuttons += '<span id="window_minimize" class="btn" style="background:#5AC05A;"><i class="fa fa-window-minimize" style="vertical-align: sub;"></i></span>';
  806. else if(data.theme == "win10" || data.theme == "winXP") topbuttons += '<span id="window_minimize" class="btn"><i class="fa fa-window-minimize"></i></span>';
  807. }
  808.  
  809. $('body').append(`
  810. <div id="` + this.window_id + `" style='display: none;' class="window">
  811. <div id="top">
  812. ` + topbuttons +
  813. `<p class="title">` + data.title + `</p>
  814. </div>
  815.  
  816. <div id="content">
  817. ` + content + `
  818. </div>
  819.  
  820. <div id="footer">
  821. ` + buttons + `
  822. </div>
  823. ` +
  824. (data.theme_selector ? `<select id="theme_dropdown" value="Theme">
  825. <option value="std" style="display: none;">Theme</option>
  826. <option value="mac">Mac</option>
  827. <option value="win10">Windows 10</option>
  828. <option value="winXP">Windows XP</option>
  829. </select>` : "") + `
  830. </div>
  831. `);
  832.  
  833. this.makeDragable($('#' + this.window_id)[0], $('#' + this.window_id).find("#top")[0], true);
  834.  
  835. var confirm_close = "Unsaved changes. Discard changes?";
  836. var confirm_revert = "Reset all changes?";
  837. var confirm_reset = "Bring settings back to factory settings?";
  838. if(data.confirm_close != undefined) confirm_close = data.confirm_close;
  839. if(data.confirm_revert != undefined) confirm_revert = data.confirm_revert;
  840. if(data.confirm_reset != undefined) confirm_reset = data.confirm_reset;
  841.  
  842. $('#' + this.window_id).find('#revertButton').click(function(){
  843. if(confirm(confirm_revert)) configurationWindow.revertChanges();
  844. });
  845. $('#' + this.window_id).find('#saveButton').click(function(){
  846. configurationWindow.saveChanges();
  847. $('#' + configurationWindow.window_id).find('#saveButton').css("background", "lime");
  848. setTimeout(function(){
  849. $('#' + configurationWindow.window_id).find('#saveButton').css("background", "");
  850. }, 1000);
  851. });
  852.  
  853. $('#' + this.window_id).find('#completeResetButton').click(function(){
  854. if(confirm(confirm_reset)) configurationWindow.ResetSettings();
  855. });
  856.  
  857. $('#' + this.window_id).find('#window_close').click(function(){
  858. configurationWindow.close();
  859. });
  860.  
  861. //================ WINDOW RESIZE BUTTONS ===================//
  862. $('#' + this.window_id).find('#window_maximize').click(function(){
  863. if(configurationWindow.maximized && !configurationWindow.minimized)
  864. configurationWindow.normalize();
  865. else
  866. configurationWindow.maximize();
  867. });
  868.  
  869. $('#' + this.window_id).find('#window_minimize').click(function(){
  870. configurationWindow.minimize();
  871. });
  872.  
  873. $('#' + this.window_id).find("#top").dblclick(function(){
  874. if(configurationWindow.minimized){
  875. if(configurationWindow.maximized)
  876. configurationWindow.maximize();
  877. else
  878. configurationWindow.normalize();
  879. }else{
  880. if(configurationWindow.maximized)
  881. configurationWindow.normalize();
  882. else
  883. configurationWindow.maximize();
  884. }
  885. configurationWindow.clearSelection();
  886. });
  887.  
  888. //==================== THEME SELECTOR =======================//
  889. $('#' + this.window_id).find("#theme_dropdown").change(function(){
  890. if(! configurationWindow.close()) return;
  891. GM_setValue("config_theme", this.value);
  892. configurationWindow.create(configurationWindow.data);
  893. configurationWindow.open();
  894. });
  895.  
  896. //==================== FIELD CHANGE LISTENER =====================//
  897. $('#' + this.window_id).find("#content").find("input[type=text], input[type=number], input[type=password], input[type=color]").change(function(){
  898. if($(this).attr("value") != $(this).val())
  899. $(this).css("border", "#fff400 solid 2px");
  900. else
  901. $(this).css("border", "");
  902.  
  903. configurationWindow.updateChanged();
  904. });
  905. $('#' + this.window_id).find("#content").find("input[type=number]").change(function(){
  906. if($(this).attr("min") != undefined && $(this).val() < parseFloat($(this).attr("min")))
  907. $(this).val($(this).attr("min"));
  908. else if($(this).attr("max") != undefined && $(this).val() > parseFloat($(this).attr("max"))){
  909. $(this).val($(this).attr("max"));
  910. }
  911. configurationWindow.updateChanged();
  912. });
  913.  
  914.  
  915. $('#' + this.window_id).find("#content").find("select").change(function(){
  916. if(this.value != $(this).find("option[selected]").val())
  917. $(this).css("border", "#fff400 solid 2px");
  918. else
  919. $(this).css("border", "");
  920.  
  921. configurationWindow.updateChanged();
  922. });
  923.  
  924. $('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').change(function() {
  925. if(this.checked != ($(this).attr("default") == "true")){
  926. $(this).css("outline", "#fff400 solid 3px");
  927. }else{
  928. $(this).css("outline", "");
  929. }
  930. $('[require="' + this.id + '"]').prop("disabled", !this.checked);
  931. configurationWindow.updateChanged();
  932. });
  933. $('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').trigger("change");
  934. $(document).keyup(function(e) {
  935. if (e.keyCode == 27) {
  936. configurationWindow.close();
  937. }
  938. });
  939. this.updateChanged();
  940. }
  941. };