Configuration Dialog

A enhanced configuration dialog for Userscripts.

Αυτός ο κώδικας δεν πρέπει να εγκατασταθεί άμεσα. Είναι μια βιβλιοθήκη για άλλους κώδικες που περιλαμβάνεται μέσω της οδηγίας meta // @require https://update.greatest.deepsurf.us/scripts/45343/759338/Configuration%20Dialog.js

  1. /*
  2. /////////////////////////////////////////////////////
  3. # #
  4. # Script made by Marius Adam #
  5. # ©DevForce 2019 #
  6. # Code Version 0.4 #
  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 + $('[style*="outline: 3px solid rgb(255, 244, 0);"]').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], textarea").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)).change();
  207. this.updateChanged();
  208. },
  209.  
  210. saveChanges : function(){
  211. $('#' + this.window_id).find("#content").find("input[type=text], input[type=password], input[type=number], input[type=color], textarea").each(function(){
  212. configurationWindow.set(this.id, this.value);
  213. $(this).attr("value", this.value);
  214. $(this).css("border", "");
  215. });
  216.  
  217. $('#' + this.window_id).find("#content").find("select").each(function(){
  218. configurationWindow.set(this.id, this.value);
  219.  
  220. var main_val = this.value;
  221.  
  222. $(this).find("option[selected]").removeAttr("selected");
  223. $(this).find("option").filter(function() {
  224. return this.innerHTML == main_val;
  225. }).attr("selected", "selected");
  226.  
  227. this.value = main_val;
  228.  
  229. $(this).css("border", "");
  230. });
  231.  
  232. $('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').each(function() {
  233. configurationWindow.set(this.id, this.checked);
  234. $(this).attr("default", this.checked);
  235. $(this).css("outline", "");
  236. });
  237.  
  238. this.updateChanged();
  239. this.save();
  240. },
  241.  
  242. ResetSettings : function(){
  243. if(this.isArray(this.data.content)){
  244. for(i = 0; i < this.data.content.length; i++){
  245. if(this.isObject(this.data.content[i])){
  246. var object = this.data.content[i];
  247. object.default = (object.default == undefined ? "" : object.default);
  248. var elem = $('#' + this.window_id).find("#content").find("#" + object.id);
  249. var type = elem.attr("type");
  250. if(type == undefined && elem.is("select")) type = "select";
  251. switch(type){
  252. case "text":
  253. case "number":
  254. case "password":
  255. case "select":
  256. case "textarea":
  257. $(elem).val(object.default);
  258. break;
  259. case "checkbox":
  260. $(elem).prop("checked", object.default);
  261. break;
  262. default: break;
  263. }
  264. $(elem).change();
  265. }
  266. }
  267. }
  268. this.updateChanged();
  269. },
  270.  
  271. close : function(){
  272. if(this.changed){
  273. if(!confirm(this.data.confirm_close)){
  274. return false;
  275. }
  276. }
  277. $('#' + this.window_id).attr("style", "display: none;");
  278. return true;
  279. },
  280. open : function(data){
  281. $('#' + this.window_id).attr("style", "");
  282. },
  283.  
  284. create : function(data){
  285. //var data = JSON.parse(content);
  286.  
  287. this.data = data;
  288. if(this.window_id != undefined)
  289. $('#' + this.window_id).remove();
  290.  
  291. $('#window_style').remove();
  292. $('#font-awesome').remove();
  293.  
  294. if(data.id == undefined) data.id = "window";
  295. this.window_id = data.id;
  296.  
  297. this.load();
  298. $('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">');
  299.  
  300. if (data.theme == undefined) data.theme = "mac";
  301. if (!(data.theme == "mac" || data.theme == "win10" || data.theme == "winXP")) data.theme = "mac";
  302. var saved_theme = GM_getValue("config_theme");
  303. if(data.theme_selector == undefined || data.theme_selector == true || data.theme_selector == "true"){
  304. data.theme_selector = true;
  305. if(saved_theme != undefined) data.theme = saved_theme;
  306. }else{
  307. data.theme_selector = false;
  308. }
  309. if(data.width == undefined) data.width = 50;
  310. if(data.height == undefined) data.height = 50;
  311. var section_color = "#c9c9c9";
  312. var subsection_color = "#f1f1f1";
  313. var style = "<style id='window_style'>";
  314. if(data.theme == "mac"){
  315. style += `
  316. #` + this.window_id + ` > #top > .btn {
  317. height: 16px;
  318. width: 16px;
  319. background-color: #bbb;
  320. border-radius: 50%;
  321. float: right;
  322. margin-right: 10px;
  323. display: inline-block;
  324. font-size: 10px;
  325. text-align: center;
  326. color: white;
  327. cursor: pointer;
  328. //font-weight: bold;
  329. }
  330.  
  331. #` + this.window_id + ` > #top > .title {
  332. margin: auto;
  333. font-size: 16px;
  334. font-weight: bold;
  335. cursor: move;
  336. }
  337.  
  338. #` + this.window_id + ` {
  339. border: 3px solid #f1f1f1;
  340. border-top-left-radius: 3px;
  341. border-top-right-radius: 3px;
  342. height: ` + data.height + `%;
  343. width: ` + data.width + `%;
  344. top: ` + ((100 - data.height) / 2) + `%;
  345. left: ` + ((100 - data.width) / 2) + `%;
  346. position: fixed;
  347. z-index: 11000;
  348. background: white;
  349. min-width: 250px;
  350. min-height: 250px;
  351. resize: both;
  352. overflow: auto;
  353. line-height: unset;
  354. overflow-y: hidden;`
  355. + (data.font != undefined ?
  356. (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "") +
  357. (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
  358. : "") +
  359. `}
  360.  
  361. #` + this.window_id + ` > #top {
  362. padding: 10px;
  363. //height: 20px;
  364. background: #f1f1f1;
  365. border-top-left-radius: 4px;
  366. border-top-right-radius: 4px;
  367. position: absolute;
  368. width: calc(100% - 20px);
  369. }
  370. `;
  371. }else if(data.theme == "win10"){
  372. section_color = "#1f9cff";
  373. subsection_color = "#9dd4ff";
  374. style += `
  375. #` + this.window_id + ` > #top > .btn {
  376. height: 22px;
  377. width: 30px;
  378. float: right;
  379. margin-right: 5px;
  380. display: inline-block;
  381. font-size: 16px;
  382. text-align: center;
  383. color: white;
  384. cursor: pointer;
  385. color: black;
  386. padding: 2px;
  387. }
  388. #` + this.window_id + ` > #top > #window_minimize:hover, #` + this.window_id + ` > #top > #window_maximize:hover {
  389. background-color: #ddd;
  390. }
  391. #` + this.window_id + ` > #top > #window_close:hover {
  392. background-color: red;
  393. }
  394.  
  395. #` + this.window_id + ` > #top > .title {
  396. margin: auto;
  397. font-size: 16px;
  398. font-weight: bold;
  399. cursor: move;
  400. padding: 10px;
  401. }
  402.  
  403. #` + this.window_id + ` {
  404. border: 3px solid #1f9cff;
  405. height: ` + data.height + `%;
  406. width: ` + data.width + `%;
  407. top: ` + ((100 - data.height) / 2) + `%;
  408. left: ` + ((100 - data.width) / 2) + `%;
  409. position: fixed;
  410. z-index: 11000;
  411. background: white;
  412. min-width: 250px;
  413. min-height: 250px;
  414. resize: both;
  415. overflow: auto;
  416. line-height: unset;
  417. overflow-y: hidden;`
  418. + (data.font != undefined ?
  419. (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "") +
  420. (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
  421. : "") +
  422. `}
  423.  
  424. #` + this.window_id + ` > #top {
  425. //padding: 10px;
  426. //height: 20px;
  427. background: #1f9cff;
  428. position: absolute;
  429. width: 100%;
  430. }
  431. `;
  432. }else if(data.theme == "winXP"){
  433. section_color = "#226ce7";
  434. subsection_color = "#4094ff";
  435. style += `
  436. #` + this.window_id + ` > #top > .btn {
  437. height: 20px;
  438. width: 20px;
  439. float: right;
  440. margin-right: 5px;
  441. margin-top: 5px;
  442. display: inline-block;
  443. font-size: 16px;
  444. text-align: center;
  445. color: white;
  446. cursor: pointer;
  447. color: white;
  448. border-radius: 2px;
  449. padding: 2px;
  450. border: 1px solid white;
  451. background: linear-gradient(135deg, #7EAED6 0%, #1B72FF 50%, #1655BE 100%);
  452. }
  453. #` + this.window_id + ` > #top > #window_minimize:hover, #` + this.window_id + ` > #top > #window_maximize:hover {
  454. background: linear-gradient(135deg, #6a93b5 0%, #1862da 50%, #124499 100%);
  455. }
  456. #` + this.window_id + ` > #top > #window_close {
  457. background: linear-gradient(135deg, #F1A689 0%, #C0442A 50%, #C2311E 100%);
  458. }
  459. #` + this.window_id + ` > #top > #window_close:hover {
  460. background: linear-gradient(135deg, #c3846c 0%, #a43923 50%, #982415 100%);
  461. }
  462.  
  463. #` + this.window_id + ` > #top > .title {
  464. margin: auto;
  465. font-size: 16px;
  466. font-weight: bold;
  467. cursor: move;
  468. padding: 10px;
  469. color: white;
  470. }
  471.  
  472. #` + this.window_id + ` {
  473. border-left: 3px solid #0056e4;
  474. border-right: 3px solid #0056e4;
  475. border-bottom: 3px solid #0056e4;
  476. height: ` + data.height + `%;
  477. width: ` + data.width + `%;
  478. top: ` + ((100 - data.height) / 2) + `%;
  479. left: ` + ((100 - data.width) / 2) + `%;
  480. position: fixed;
  481. z-index: 11000;
  482. background: white;
  483. min-width: 250px;
  484. min-height: 250px;
  485. border-radius: 8px;
  486. resize: both;
  487. overflow: auto;
  488. line-height: unset;
  489. overflow-y: hidden;`
  490. + (data.font != undefined ?
  491. (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "") +
  492. (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
  493. : "") +
  494. `}
  495.  
  496. #` + this.window_id + ` > #top {
  497. //padding: 10px;
  498. //height: 20px;
  499. border-radius: 5px 5px 0px 0px;
  500. background: linear-gradient(to bottom, #4094ff 0%, #0056e4 13%, #0056e4 71%, #16428b 100%);
  501. position: absolute;
  502. width: 100%;
  503. }
  504. `;
  505. }
  506. style += `
  507. #` + this.window_id + ` > #footer {
  508. text-align: right;
  509. margin: 0px 0px 4px -20px;
  510. height: 40px;
  511. border-top-left-radius: 4px;
  512. border-top-right-radius: 4px;
  513. position: absolute;
  514. width: 100%;
  515. bottom: 0;
  516. pointer-events: none;
  517. }
  518.  
  519. #` + this.window_id + ` > #footer > button {
  520. background-color: #f1f1f1;
  521. border: none;
  522. color: black;
  523. padding: 12px 40px;
  524. font-size: 14px;
  525. cursor: pointer;
  526. margin-left: 5px;
  527. pointer-events: all;
  528. }
  529.  
  530. #` + this.window_id + ` > #footer > button:hover {
  531. background-color: RoyalBlue;
  532. color: white;
  533. }
  534. #` + this.window_id + ` > #footer > button:disabled {
  535. background-color: darkgrey;
  536. color: white;
  537. }
  538. #` + this.window_id + ` > #content {
  539. padding: 10px;
  540. margin-top: 40px;
  541. overflow-y: scroll;
  542. height: calc(100% - 75px);
  543. overflow-wrap: break-word;
  544. }
  545.  
  546. #` + this.window_id + ` > #content > input,#` + this.window_id + ` > #content > select {`
  547. + (data.font != undefined ?
  548. (data.font.size != undefined ? "font-size: " + data.font.size + ";" : "") +
  549. (data.font.family != undefined ? "font-family: " + data.font.family + ";" : "")
  550. : "") +
  551. `}
  552.  
  553. #` + this.window_id + ` > #content > br {
  554. display: block;
  555. margin-top: 4px;
  556. content: " ";
  557. }
  558.  
  559. #` + this.window_id + ` > #theme_dropdown {
  560. float: left;
  561. bottom: 5px;
  562. position: absolute;
  563. left: 5px;
  564. border: none;
  565. -webkit-appearance: none;
  566. -moz-appearance: none;
  567. appearance: none;
  568. color: gray;
  569. background-color: transparent;
  570. }
  571. #` + this.window_id + ` > #theme_dropdown > option {
  572. color: black;
  573. }
  574. .no-margin {
  575. margin: 0px;
  576. }
  577. .wrap-collapsible {
  578. margin-bottom: 1.2rem 0;
  579. }
  580.  
  581. .toggle {
  582. display: none;
  583. }
  584.  
  585. .lbl-toggle {
  586. display: block;
  587. cursor: pointer;
  588. transition: all 0.25s ease-out;
  589. }
  590. .lbl-toggle h2, .lbl-toggle h4 {
  591. display: inline;
  592. }
  593.  
  594. .lbl-toggle:hover {
  595. color: white;
  596. }
  597.  
  598. .lbl-toggle::before {
  599. content: ' ';
  600. display: inline-block;
  601.  
  602. border-top: 5px solid transparent;
  603. border-bottom: 5px solid transparent;
  604. border-left: 5px solid currentColor;
  605. vertical-align: middle;
  606. margin-right: .7rem;
  607. transform: translateY(-2px);
  608.  
  609. transition: transform .2s ease-out;
  610. }
  611.  
  612. .toggle:checked + .lbl-toggle::before {
  613. transform: rotate(90deg) translateX(-3px);
  614. }
  615.  
  616. .collapsible-content {
  617. max-height: 0px;
  618. overflow: hidden;
  619. transition: max-height .25s ease-in-out;
  620. }
  621.  
  622. .toggle:checked + .lbl-toggle + .collapsible-content {
  623. max-height: unset;
  624. }
  625.  
  626. .collapsible-content .content-inner {
  627. //background: rgba(161, 161, 161, 0.2);
  628. //border: 1px solid black;
  629. }
  630. `;
  631. style += "<style>";
  632. $('head').append(style);
  633. if(data.theme_section_color == undefined || data.theme_section_color == false){
  634. section_color = "#c9c9c9";
  635. subsection_color = "#f1f1f1";
  636. }
  637. var content = "";
  638.  
  639. if(this.isArray(data.content)){
  640. var section_collapsible = false;
  641. var subsection_collapsible = false;
  642. var collapsible_id = 1;
  643. for(i = 0; i < data.content.length; i++){
  644. if(this.isObject(data.content[i])){
  645. var label_first = undefined;
  646. Object.keys(data.content[i]).forEach(function(key){
  647. if(label_first != undefined) return;
  648.  
  649. if(key == "label") label_first = true;
  650. else if(key == "type") label_first = false;
  651. });
  652.  
  653. var label = this.replaceAll(data.content[i].label, " ", "&nbsp;&nbsp;");
  654.  
  655. var object = data.content[i];
  656.  
  657. if(object.style != undefined) object.style = " style='" + object.style + "'";
  658. else object.style = "";
  659.  
  660. if(object.require != undefined) object.style += " require='" + object.require + "'";
  661. switch(object.type){
  662. case "p":
  663. content += "<p class='no-margin'" + object.style + ">" + label + "</p>";
  664. break;
  665. case "h1":
  666. content += "<h1 class='no-margin'" + object.style + ">" + label + "</h1>";
  667. break;
  668. case "h2":
  669. content += "<h2 class='no-margin'" + object.style + ">" + label + "</h2>";
  670. break;
  671. case "h3":
  672. content += "<h3 class='no-margin'" + object.style + ">" + label + "</h3>";
  673. break;
  674. case "h4":
  675. content += "<h4 class='no-margin'" + object.style + ">" + label + "</h4>";
  676. break;
  677. case "section":
  678. if(object.align == undefined) object.align = "center";
  679. if(object.background == undefined) object.background = section_color;
  680. if(subsection_collapsible){
  681. content += "</div></div></div>";
  682. subsection_collapsible = false;
  683. }
  684. if(section_collapsible){
  685. content += "</div></div></div>";
  686. section_collapsible = false;
  687. }
  688. if(object.collapsible != undefined && object.collapsible){
  689. 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'>";
  690. section_collapsible = true;
  691. collapsible_id++;
  692. }else{
  693. content += "<div width='100%' style='margin: 5px 0px; background: " + object.background + "; text-align: " + object.align + ";'><h2 class='no-margin'>" + label + "</h2></div>";
  694. }
  695. break;
  696. case "subsection":
  697. if(object.align == undefined) object.align = "center";
  698. if(object.background == undefined) object.background = subsection_color;
  699. if(subsection_collapsible){
  700. content += "</div></div></div>";
  701. subsection_collapsible = false;
  702. }
  703. if(object.collapsible != undefined && object.collapsible){
  704. 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'>";
  705. subsection_collapsible = true;
  706. collapsible_id++;
  707. }else{
  708. content += "<div width='100%' style='margin: 5px 0px; background: " + object.background + "; text-align: " + object.align + ";'><h4 class='no-margin'>" + label + "</h4></div>";
  709. }
  710. break;
  711. case "text":
  712. var value = this.getElseSet(object.id, object.default, "");
  713. content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='text' value='" + value + "' />");
  714.  
  715. content += "<br>";
  716. break;
  717. case "textarea":
  718. var value = this.getElseSet(object.id, object.default, "");
  719. content += this.join(label_first, label, "<textarea id='" + object.id + "'" + object.style + " value='" + value + "'>" + value + "</textarea>");
  720.  
  721. content += "<br>";
  722. break;
  723. case "password":
  724. var value = this.getElseSet(object.id, object.default, "");
  725. content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='password' value='" + value + "' />");
  726.  
  727. content += "<br>";
  728. break;
  729. case "checkbox":
  730. var value = this.getElseSet(object.id, object.default, false);
  731. if(value == "true" || value == true) value = true;
  732. else value = false;
  733.  
  734. label = "<label for='" + object.id + "'>" + label + "</label>";
  735. content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " default='" + value + "' type='checkbox' " + (value ? "checked" : "") + "/>");
  736.  
  737. content += "<br>";
  738. break;
  739. case "select":
  740. var value = this.getElseSet(object.id, object.default, "");
  741.  
  742. var select = " <select" + object.style + " id='" + object.id + "'>";
  743. object.options.forEach(function(opt){
  744. if(opt == value){
  745. select += "<option selected>" + opt + "</option>";
  746. }else{
  747. select += "<option>" + opt + "</option>";
  748. }
  749. });
  750. select += "</select> ";
  751.  
  752. content += this.join(label_first, label, select);
  753.  
  754. content += "<br>";
  755. break;
  756. case "numeric":
  757. var value = this.getElseSet(object.id, object.default, 0);
  758. var element = "<input id='" + object.id + "'" + object.style + " type='number' value='" + value + "'";
  759. if(object.min != undefined) element += " min='" + object.min + "'";
  760. if(object.max != undefined) element += " max='" + object.max + "'";
  761. element += " />";
  762. content += this.join(label_first, label, element);
  763.  
  764. content += "<br>";
  765. break;
  766. case "color":
  767. var value = this.getElseSet(object.id, object.default, "#FFFFFF");
  768.  
  769. content += this.join(label_first, label, "<input id='" + object.id + "'" + object.style + " type='color' value='" + value + "' />");
  770.  
  771. content += "<br>";
  772. break;
  773. default: break;
  774. }
  775. }else{
  776. content += "<p>" + data.content[i] + "</p>";
  777. }
  778. }
  779. if(subsection_collapsible){
  780. content += "</div></div></div>";
  781. section_collapsible = false;
  782. }
  783. if(section_collapsible){
  784. content += "</div></div></div>";
  785. section_collapsible = false;
  786. }
  787. }else{
  788. content = data.content;
  789. }
  790. //content += "<br style='height: 25px;' />";
  791. content += "<br><br><br>";
  792. var buttons = "";
  793.  
  794. if(data.completeresetbutton == undefined || data.completeresetbutton == true || data.completeresetbutton == "true"){
  795. buttons += "<button id='completeResetButton'><i class='fa fa-trash'></i></button>";
  796. }
  797.  
  798. if(data.revertbutton == undefined || data.revertbutton == true || data.revertbutton == "true"){
  799. buttons += "<button id='revertButton'><i class='fa fa-undo'></i></button>";
  800. }
  801.  
  802. if(data.savebutton == undefined || data.savebutton == true || data.savebutton == "true"){
  803. buttons += "<button id='saveButton'><i class='fa fa-save'></i></button>";
  804. }
  805.  
  806. var topbuttons = "";
  807. if(data.top == undefined || data.top.close == undefined || data.top.close == "true"){
  808. 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>';
  809. else if(data.theme == "win10") topbuttons += '<span id="window_close" class="btn" style="margin-right: 0px;"><i class="fa fa-times"></i></span>';
  810. else if(data.theme == "winXP") topbuttons += '<span id="window_close" class="btn"><i class="fa fa-times"></i></span>';
  811. }
  812. if(data.top == undefined || data.top.maximize == undefined || data.top.maximize == "true"){
  813. 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>';
  814. else if(data.theme == "win10" || data.theme == "winXP") topbuttons += '<span id="window_maximize" class="btn"><i class="fa fa-window-maximize"></i></span>';
  815. }
  816. if(data.top == undefined || data.top.minimize == undefined || data.top.minimize == "true"){
  817. 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>';
  818. else if(data.theme == "win10" || data.theme == "winXP") topbuttons += '<span id="window_minimize" class="btn"><i class="fa fa-window-minimize"></i></span>';
  819. }
  820.  
  821. $('body').append(`
  822. <div id="` + this.window_id + `" style='display: none;' class="window">
  823. <div id="top">
  824. ` + topbuttons +
  825. `<p class="title">` + data.title + `</p>
  826. </div>
  827.  
  828. <div id="content">
  829. ` + content + `
  830. </div>
  831.  
  832. <div id="footer">
  833. ` + buttons + `
  834. </div>
  835. ` +
  836. (data.theme_selector ? `<select id="theme_dropdown" value="Theme">
  837. <option value="std" style="display: none;">Theme</option>
  838. <option value="mac">Mac</option>
  839. <option value="win10">Windows 10</option>
  840. <option value="winXP">Windows XP</option>
  841. </select>` : "") + `
  842. </div>
  843. `);
  844.  
  845. this.makeDragable($('#' + this.window_id)[0], $('#' + this.window_id).find("#top")[0], true);
  846.  
  847. var confirm_close = "Unsaved changes. Discard changes?";
  848. var confirm_revert = "Reset all changes?";
  849. var confirm_reset = "Bring settings back to factory settings?";
  850. if(data.confirm_close != undefined) confirm_close = data.confirm_close;
  851. if(data.confirm_revert != undefined) confirm_revert = data.confirm_revert;
  852. if(data.confirm_reset != undefined) confirm_reset = data.confirm_reset;
  853.  
  854. $('#' + this.window_id).find('#revertButton').click(function(){
  855. if(confirm(confirm_revert)) configurationWindow.revertChanges();
  856. });
  857. $('#' + this.window_id).find('#saveButton').click(function(){
  858. configurationWindow.saveChanges();
  859. $('#' + configurationWindow.window_id).find('#saveButton').css("background", "lime");
  860. setTimeout(function(){
  861. $('#' + configurationWindow.window_id).find('#saveButton').css("background", "");
  862. }, 1000);
  863. });
  864.  
  865. $('#' + this.window_id).find('#completeResetButton').click(function(){
  866. if(confirm(confirm_reset)) configurationWindow.ResetSettings();
  867. });
  868.  
  869. $('#' + this.window_id).find('#window_close').click(function(){
  870. configurationWindow.close();
  871. });
  872.  
  873. //================ WINDOW RESIZE BUTTONS ===================//
  874. $('#' + this.window_id).find('#window_maximize').click(function(){
  875. if(configurationWindow.maximized && !configurationWindow.minimized)
  876. configurationWindow.normalize();
  877. else
  878. configurationWindow.maximize();
  879. });
  880.  
  881. $('#' + this.window_id).find('#window_minimize').click(function(){
  882. configurationWindow.minimize();
  883. });
  884.  
  885. $('#' + this.window_id).find("#top").dblclick(function(){
  886. if(configurationWindow.minimized){
  887. if(configurationWindow.maximized)
  888. configurationWindow.maximize();
  889. else
  890. configurationWindow.normalize();
  891. }else{
  892. if(configurationWindow.maximized)
  893. configurationWindow.normalize();
  894. else
  895. configurationWindow.maximize();
  896. }
  897. configurationWindow.clearSelection();
  898. });
  899.  
  900. //==================== THEME SELECTOR =======================//
  901. $('#' + this.window_id).find("#theme_dropdown").change(function(){
  902. if(! configurationWindow.close()) return;
  903. GM_setValue("config_theme", this.value);
  904. configurationWindow.create(configurationWindow.data);
  905. configurationWindow.open();
  906. });
  907.  
  908. //==================== FIELD CHANGE LISTENER =====================//
  909. $('#' + this.window_id).find("#content").find("input[type=text], input[type=number], input[type=password], input[type=color], textarea").change(function(){
  910. if($(this).attr("value") != $(this).val())
  911. $(this).css("border", "#fff400 solid 2px");
  912. else
  913. $(this).css("border", "");
  914.  
  915. configurationWindow.updateChanged();
  916. });
  917. $('#' + this.window_id).find("#content").find("input[type=number]").change(function(){
  918. if($(this).attr("min") != undefined && $(this).val() < parseFloat($(this).attr("min")))
  919. $(this).val($(this).attr("min"));
  920. else if($(this).attr("max") != undefined && $(this).val() > parseFloat($(this).attr("max"))){
  921. $(this).val($(this).attr("max"));
  922. }
  923. configurationWindow.updateChanged();
  924. });
  925.  
  926.  
  927. $('#' + this.window_id).find("#content").find("select").change(function(){
  928. if(this.value != $(this).find("option[selected]").val())
  929. $(this).css("border", "#fff400 solid 2px");
  930. else
  931. $(this).css("border", "");
  932.  
  933. configurationWindow.updateChanged();
  934. });
  935.  
  936. $('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').change(function() {
  937. if(this.checked != ($(this).attr("default") == "true")){
  938. $(this).css("outline", "#fff400 solid 3px");
  939. }else{
  940. $(this).css("outline", "");
  941. }
  942. $('[require="' + this.id + '"]').prop("disabled", !this.checked);
  943. configurationWindow.updateChanged();
  944. });
  945. $('#' + this.window_id).find("#content").find('input[type=checkbox]:not(.toggle)').trigger("change");
  946. $(document).keyup(function(e) {
  947. if (e.keyCode == 27) {
  948. configurationWindow.close();
  949. }
  950. });
  951. this.updateChanged();
  952. }
  953. };