SamSunder commited on
Commit
c6e833c
1 Parent(s): 1e7f646

Provide settings page with full functionality.

Browse files
public/static/colorschemes/catppuccin-mocha.css CHANGED
@@ -2,10 +2,8 @@
2
  --bg: #1e1e2e;
3
  --fg: #cdd6f4;
4
  --1: #45475a;
5
- --1_1: #4f5169;
6
  --2: #f38ba8;
7
  --3: #a6e3a1;
8
- --3_1: #7ce073;
9
  --4: #f9e2af;
10
  --5: #89b4fa;
11
  --6: #f5c2e7;
 
2
  --bg: #1e1e2e;
3
  --fg: #cdd6f4;
4
  --1: #45475a;
 
5
  --2: #f38ba8;
6
  --3: #a6e3a1;
 
7
  --4: #f9e2af;
8
  --5: #89b4fa;
9
  --6: #f5c2e7;
public/static/settings.js CHANGED
@@ -1,130 +1,32 @@
1
- function toggleSelectOptions(elem, state) {
2
- elem.classList.remove("invalid");
3
- try { elem.parentElement.querySelector('.errTxt').remove();} catch (error) {}
4
- let options = elem.querySelector('.options');
5
- const pos = elem.getBoundingClientRect();
6
- const windowWidth = document.getElementsByTagName("body")[0].clientHeight;
7
- if(pos.y + 250 > windowWidth) {
8
- options.style.bottom = '40px';
9
- } else { options.style.bottom = null }
10
- options.style.display = state != 'close' ? getComputedStyle(options).display == 'none' ? 'block': 'none' : 'none';
11
- }
12
-
13
- let selectElements = document.querySelectorAll('.custom-select');
14
- Array.from(selectElements).forEach(element => {
15
- element.childNodes[0].nodeValue = (element.hasAttribute('data-multiple') ? element.getAttribute('data-placeholder') : element.getAttribute('data-default'));
16
- element.addEventListener('click', (e) => {if (e.target === element) toggleSelectOptions(element)});
17
- element.addEventListener('focusout', (e) => {if (e.target === element) toggleSelectOptions(element, 'close')});
18
- });
19
-
20
- function removeSelectOption(elem, optionId) {
21
- let option = document.querySelector('#'+optionId);
22
- let selectDiv = option.closest('.custom-select');
23
- let input = document.querySelector(`[name="${selectDiv.getAttribute('data-input')}"]`);
24
- elem.parentElement.remove();
25
- option.removeAttribute('selected');
26
- option.querySelector('svg').remove();
27
- input.value = input.value.replace(option.getAttribute('data-value') ? option.getAttribute('data-value') + "," : '', '');
28
- }
29
-
30
- function multiSelectClickHandler(elem) {
31
- let selectDiv = elem.closest('.custom-select');
32
- let input = document.querySelector(`[name="${selectDiv.getAttribute('data-input')}"]`);
33
- if (!elem.hasAttribute('selected')) {
34
- document.querySelector('#'+elem.closest(".custom-select").getAttribute("data-showDivId")).innerHTML +=
35
- `<span class='selected-multiple-option' id='${elem.getAttribute('id')}-selected'>${elem.innerText} &ensp;
36
- <span onclick="removeSelectOption(this, '${elem.getAttribute('id')}')">
37
- <svg fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 384 512"><path d="M376.6 84.5c11.3-13.6 9.5-33.8-4.1-45.1s-33.8-9.5-45.1 4.1L192 206 56.6 43.5C45.3 29.9 25.1 28.1 11.5 39.4S-3.9 70.9 7.4 84.5L150.3 256 7.4 427.5c-11.3 13.6-9.5 33.8 4.1 45.1s33.8 9.5 45.1-4.1L192 306 327.4 468.5c11.3 13.6 31.5 15.4 45.1 4.1s15.4-31.5 4.1-45.1L233.7 256 376.6 84.5z"/>
38
- </svg>
39
- </span>
40
- </span>`;
41
- elem.setAttribute('selected', '');
42
- elem.innerHTML = `${elem.innerText}
43
- <svg fill="currentColor" height="1.5rem" width="1.5rem" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 490 490" xml:space="preserve">
44
- <g id="SVGRepo_iconCarrier"> <polygon points="452.253,28.326 197.831,394.674 29.044,256.875 0,292.469 207.253,461.674 490,54.528 "></polygon> </g></svg>`
45
-
46
- // Code where value in inserted into input
47
- input.value += elem.getAttribute('data-value') ? elem.getAttribute('data-value') + "," : '';
48
- } else {
49
- // similar to removeSelectOption method
50
- document.querySelector('#'+elem.getAttribute('id')+'-selected').remove();
51
- elem.removeAttribute('selected');
52
- elem.querySelector('svg').remove();
53
-
54
- input.value = input.value.replace(elem.getAttribute('data-value') ? elem.getAttribute('data-value') + "," : '', '');
55
- }
56
-
57
- }
58
-
59
- function singleSelectClickHandler(elem) {
60
- let selectDiv = elem.closest('.custom-select');
61
- let selectedOption = selectDiv.querySelector('span[selected]');
62
- let input = document.querySelector(`[name="${selectDiv.getAttribute('data-input')}"]`);
63
- if (!elem.hasAttribute('selected')) {
64
- if (selectedOption != null) {
65
- selectedOption.removeAttribute('selected');
66
- selectedOption.querySelector('svg').remove();
67
  }
68
- elem.setAttribute('selected', '');
69
- elem.innerHTML = `${elem.innerText}
70
- <svg fill="currentColor" height="1.5rem" width="1.5rem" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 490 490" xml:space="preserve">
71
- <g id="SVGRepo_iconCarrier"> <polygon points="452.253,28.326 197.831,394.674 29.044,256.875 0,292.469 207.253,461.674 490,54.528 "></polygon> </g></svg>`
72
- // Code where value is inserted to input
73
- input.value = elem.getAttribute('data-value') ? elem.getAttribute('data-value') : '';
74
- selectDiv.childNodes[0].nodeValue = elem.innerText;
 
 
 
75
  } else {
76
- elem.removeAttribute('selected');
77
- elem.querySelector('svg').remove();
78
- selectDiv.childNodes[0].nodeValue = selectDiv.getAttribute('data-default');
79
-
80
- input.value = "";
81
  }
82
- selectDiv.blur();
83
  }
84
 
85
- let multiSelectOptions = document.querySelectorAll('.custom-select[data-multiple="1"]>.options span');
86
- for (let i = 0; i < multiSelectOptions.length; i++) {
87
- multiSelectOptions[i].addEventListener('click', () => {multiSelectClickHandler(multiSelectOptions[i])});
88
- multiSelectOptions[i].setAttribute('id', 'option-'+i.toString());
89
- }
90
-
91
- let singleSelectOptions = document.querySelectorAll('.custom-select:not([data-multiple="1"])>.options span');
92
- for (let i = 0; i < singleSelectOptions.length; i++) {
93
- singleSelectOptions[i].addEventListener('click', () => {singleSelectClickHandler(singleSelectOptions[i])});
94
- singleSelectOptions[i].setAttribute('id', 'option-'+i.toString());
95
- }
96
-
97
- function selectAllHandler(elem) {
98
- let options = elem.parentElement.querySelectorAll('.custom-select[data-multiple="1"]>.options span');
99
- Array.from(options).forEach((option) => {
100
- try {
101
- let selectedShownElem = document.getElementById(option.getAttribute('id')+'-selected');
102
- removeSelectOption(selectedShownElem.querySelector('span'), option.getAttribute('id'))
103
- } catch (err) {}
104
- if (elem.innerText == 'select all') { option.click() };
105
- });
106
- elem.innerText = elem.innerText == 'select all' ? 'deselect all' : 'select all'
107
- }
108
-
109
-
110
- // On settings form submit
111
- function submitSettings() {
112
- let form = document.settings;
113
- document.querySelectorAll('.errTxt').forEach(e => e.remove());
114
- for(let i = 0; i < form.elements.length; i++) {
115
- let input = form.elements[i];
116
- if (input.value == "" && input.hasAttribute('required')) {
117
- let elem = input.parentElement.querySelector('[takeInput]')
118
- let errTxt = document.createElement('p')
119
- errTxt.classList.add('errTxt')
120
- errTxt.innerText = 'This setting can\'t be empty!!'
121
- elem.classList.add('invalid');
122
- elem.parentElement.insertBefore(errTxt, elem);
123
- }
124
- }
125
- return false;
126
- }
127
 
 
128
  document.querySelectorAll('.settings-sidebar .set-name').forEach(filter => {
129
  let target = filter.getAttribute('data-detailId');
130
  filter.addEventListener('click', () => {
@@ -145,29 +47,70 @@ document.querySelectorAll('.settings-sidebar .set-name').forEach(filter => {
145
  })
146
  })
147
 
148
- function fadeOut(element) {
149
- var op = 1; // initial opacity
150
- var timer = setInterval(function () {
151
- if (op <= 0.1){
152
- clearInterval(timer);
153
- element.style.display = 'none';
154
- element.classList.add('fade');
 
 
 
 
 
 
 
 
 
 
 
 
155
  }
156
- element.style.opacity = op;
157
- element.style.filter = 'alpha(opacity=' + op * 100 + ")";
158
- op -= op * 0.1;
159
- }, 50);
 
 
 
 
 
 
 
 
160
  }
161
 
162
- function fadeIn(element) {
163
- var op = 0.1; // initial opacity
164
- element.style.display = 'block';
165
- var timer = setInterval(function () {
166
- if (op >= 1){
167
- clearInterval(timer);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
168
  }
169
- element.style.opacity = op;
170
- element.style.filter = 'alpha(opacity=' + op * 100 + ")";
171
- op += op * 0.1;
172
- }, 10);
173
  }
 
 
 
1
+ // UI: Method for selecting all search engines
2
+ function selectAllHandler(elem) {
3
+ let span = elem.parentElement.querySelector('span');
4
+ let mainInput = document.getElementsByName('searchEng')[0];
5
+ let prevStateSelectAll = span.innerText == 'Select all' ? true : false;
6
+ document.querySelectorAll('.searchEng-elem').forEach(engine => {
7
+ if (prevStateSelectAll) {
8
+ engine.querySelector('input[type="checkbox"]').checked = true;
9
+ } else {
10
+ engine.querySelector('input[type="checkbox"]').checked = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  }
12
+ })
13
+ if (prevStateSelectAll) {
14
+ let getValues = () => {
15
+ let value = ""
16
+ document.querySelectorAll('[data-isCheckbox]:not([data-value="all"])').forEach(elem => {
17
+ value += elem.getAttribute("data-value") + ",";
18
+ });
19
+ return value;
20
+ }
21
+ mainInput.value = getValues();
22
  } else {
23
+ mainInput.value = '';
 
 
 
 
24
  }
25
+ span.innerText = prevStateSelectAll ? 'Deselect all' : 'Select all';
26
  }
27
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
+ // UI: Filter settings as per category
30
  document.querySelectorAll('.settings-sidebar .set-name').forEach(filter => {
31
  let target = filter.getAttribute('data-detailId');
32
  filter.addEventListener('click', () => {
 
47
  })
48
  })
49
 
50
+
51
+ // On settings form submit
52
+ function submitSettings() {
53
+ let form = document.settings;
54
+ let stopProceeding = false;
55
+ document.querySelectorAll('.errTxt').forEach(e => e.remove());
56
+ for(let i = 0; i < form.elements.length; i++) {
57
+ let input = form.elements[i];
58
+ if (input.value == "" && input.hasAttribute('required')) {
59
+ stopProceeding = true;
60
+ let elem = input.parentElement.querySelector('[takeInput]')
61
+ let errTxt = document.createElement('p')
62
+ errTxt.classList.add('errTxt')
63
+ errTxt.innerText = 'This setting can\'t be empty!!'
64
+ elem.classList.add('invalid');
65
+ elem.parentElement.insertBefore(errTxt, elem);
66
+ let sidebarElement = input.closest('.set-item').getAttribute('data-id')
67
+ document.querySelector(`.settings-sidebar .set-name[data-detailId="${sidebarElement}`).click();
68
+ stopProceeding = true;
69
  }
70
+ }
71
+ if (!stopProceeding) {
72
+ var expiration_date = new Date();
73
+ expiration_date.setFullYear(expiration_date.getFullYear() + 1);
74
+ let formData = new FormData(document.querySelector('form'));
75
+ for (var [key, value] of formData.entries()) {
76
+ document.cookie = `${key}=${value}; expires=${expiration_date.toUTCString()}`
77
+ }
78
+ } else { return false; }
79
+ // On settings saved successfully
80
+ alert("Settings saved succssfully!");
81
+ window.location.reload();
82
  }
83
 
84
+ // Autoload existing settings
85
+ function loadUserSettings() {
86
+ let inputs = ["searchEng", "theme", "color-sch"]
87
+ var keyValuePairs = document.cookie.split(';');
88
+ for(var i = 0; i < keyValuePairs.length; i++) {
89
+ var name = keyValuePairs[i].substring(0, keyValuePairs[i].indexOf('='));
90
+ var value = keyValuePairs[i].substring(keyValuePairs[i].indexOf('=')+1);
91
+ name = name.trim();
92
+ if (!inputs.includes(name)) { return; }
93
+ let input = document.getElementsByName(name)[0];
94
+ input.value = value;
95
+ if (name == "searchEng") {
96
+ // Unload all checked engine
97
+ document.querySelectorAll(".searchEng-elem input[type=checkbox]").forEach(e => {
98
+ e.checked = false;
99
+ })
100
+ value = value.replace(" ", "");
101
+ value.split(",").forEach(val => {
102
+ if (!val) {return}
103
+ document.querySelector(`[data-isCheckbox][data-value="${val}"]`).
104
+ parentElement.querySelector('input').checked = true
105
+ })
106
+ } else {
107
+ // Unload all selected options
108
+ document.querySelector(`[data-input="${name}"] .options span[data-value="${value}"]`).
109
+ removeAttribute('selected');
110
+ singleSelectClickHandler(document.querySelector(`.options span[data-value="${value}"]`));
111
  }
112
+ }
113
+
 
 
114
  }
115
+
116
+ loadUserSettings();
public/static/themes/simple.css CHANGED
@@ -302,6 +302,7 @@ footer {
302
  width: 80%;
303
  }
304
 
 
305
  .settings {
306
  margin: 2rem;
307
  width: 80%;
@@ -323,6 +324,7 @@ footer {
323
  .settings-view {
324
  display: flex;
325
  flex: 1 0 auto;
 
326
  }
327
 
328
  .settings-sidebar {
@@ -339,16 +341,17 @@ footer {
339
  padding: .7rem;
340
  border-radius: 5px;
341
  font-weight: bold;
 
342
  }
343
 
344
  .settings-sidebar .set-name:hover, .settings-sidebar .set-name.active {
345
- background-color: var(--1_1);
 
346
  }
347
 
348
  .settings-detail {
349
  border-left: 1.5px solid var(--3);
350
  padding-left: 3rem;
351
- margin-top: .7rem;
352
  }
353
 
354
  .settings-detail .set-item {
@@ -367,6 +370,7 @@ footer {
367
  margin-bottom: .5rem;
368
  }
369
 
 
370
  .custom-select, .options {
371
  font-size: 1.5rem;
372
  background-color: var(--bg);
@@ -411,7 +415,7 @@ footer {
411
  }
412
 
413
  .options span:hover {
414
- background-color: var(--1_1);
415
  }
416
 
417
  .selected-multiple-option {
@@ -447,23 +451,21 @@ footer {
447
  background: var(--3);
448
  color: var(--bg);
449
  border-radius: .5rem;
450
- border: 1px solid transparent;
451
  font-weight: bold;
452
- transition: background .5s ease-in;
453
  cursor: pointer;
454
- }
455
-
456
- .settings .submit-btn:hover {
457
- border: 1px solid var(--bg);
458
- background: var(--3_1);
459
- box-shadow: 0px 0px 2px 2px var(--fg);
460
  }
461
 
462
  .settings .submit-btn:active {
463
  outline: none;
464
- border: 2px solid var(--bg);
 
465
  }
466
 
 
 
467
  .errTxt {
468
  color: white;
469
  background: red;
@@ -471,4 +473,112 @@ footer {
471
  border-radius: 5px;
472
  font-size: 1.3rem;
473
  width: max-content;
474
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
302
  width: 80%;
303
  }
304
 
305
+ /* css for settings page t */
306
  .settings {
307
  margin: 2rem;
308
  width: 80%;
 
324
  .settings-view {
325
  display: flex;
326
  flex: 1 0 auto;
327
+ margin: 1.5rem 0;
328
  }
329
 
330
  .settings-sidebar {
 
341
  padding: .7rem;
342
  border-radius: 5px;
343
  font-weight: bold;
344
+ margin-bottom: .5rem;
345
  }
346
 
347
  .settings-sidebar .set-name:hover, .settings-sidebar .set-name.active {
348
+ background-color: rgba(255, 255, 255, 0.15);
349
+
350
  }
351
 
352
  .settings-detail {
353
  border-left: 1.5px solid var(--3);
354
  padding-left: 3rem;
 
355
  }
356
 
357
  .settings-detail .set-item {
 
370
  margin-bottom: .5rem;
371
  }
372
 
373
+ /* css for custom select */
374
  .custom-select, .options {
375
  font-size: 1.5rem;
376
  background-color: var(--bg);
 
415
  }
416
 
417
  .options span:hover {
418
+ background-color: var(--1);
419
  }
420
 
421
  .selected-multiple-option {
 
451
  background: var(--3);
452
  color: var(--bg);
453
  border-radius: .5rem;
454
+ border: 2px solid transparent;
455
  font-weight: bold;
456
+ transition: all .1s ease-out;
457
  cursor: pointer;
458
+ box-shadow: 5px 5px;
 
 
 
 
 
459
  }
460
 
461
  .settings .submit-btn:active {
462
  outline: none;
463
+ box-shadow: none;
464
+ translate: 5px 5px;
465
  }
466
 
467
+ /* Css for error text */
468
+
469
  .errTxt {
470
  color: white;
471
  background: red;
 
473
  border-radius: 5px;
474
  font-size: 1.3rem;
475
  width: max-content;
476
+ }
477
+
478
+ /* Css for toggle element */
479
+
480
+ label,
481
+ label::before,
482
+ label::after {
483
+ transition: 200ms all ease-in-out 50ms;
484
+ box-sizing: border-box;
485
+ backface-visibility: hidden;
486
+ }
487
+
488
+ input[type="checkbox"] {
489
+ display: none;
490
+ }
491
+
492
+ /*Button is :CHECKED*/
493
+
494
+ input[type="checkbox"]:checked ~ div[data-isCheckbox] {
495
+ background: rgba(73,168,68,1);
496
+ box-shadow: 0 0 2px rgba(73,168,68,1);
497
+ }
498
+
499
+ input[type="checkbox"]:checked ~ div[data-isCheckbox] label {
500
+ left: 25px;
501
+ transform: rotate(360deg);
502
+ }
503
+
504
+
505
+ /*shared*/
506
+
507
+ div[data-isCheckbox],
508
+ label {
509
+ border-radius: 50px;
510
+ }
511
+
512
+
513
+ /*'un':checked state*/
514
+
515
+ div[data-isCheckbox] {
516
+ height: 25px;
517
+ width: 50px;
518
+ background: rgba(43, 43, 43, 1);
519
+ position: relative;
520
+ box-shadow: 0 0 2px rgba(43,43,43,1);
521
+
522
+ }
523
+
524
+ label {
525
+ height: 20px;
526
+ width: 20px;
527
+ background: rgba(255, 255, 255, 1);
528
+ position: absolute;
529
+ top: 3px;
530
+ left: 3px;
531
+ cursor: pointer;
532
+ }
533
+
534
+ label::before {
535
+ content: '';
536
+ height: 15px;
537
+ width: 3px;
538
+ position: absolute;
539
+ top: calc(50% - 8px);
540
+ left: calc(50% - 1.5px);
541
+ transform: rotate(45deg);
542
+ }
543
+
544
+ label::after {
545
+ content: '';
546
+ height: 3px;
547
+ width: 15px;
548
+ position: absolute;
549
+ top: calc(50% - 2.5px);
550
+ left: calc(50% - 8px);
551
+ transform: rotate(45deg);
552
+ }
553
+
554
+ label::before,
555
+ label::after{
556
+ background: rgba(43,43,43,1);
557
+ border-radius: 5px;
558
+ }
559
+
560
+ /* pesduo class on toggle */
561
+
562
+ input[type="checkbox"]:checked ~ div label::before{
563
+ height: 15px;
564
+ top: calc(55% - 8px);
565
+ left: calc(60% - 2px);
566
+ background: rgba(73,168,68,1);
567
+ }
568
+
569
+ input[type="checkbox"]:checked ~ div label::after{
570
+ width: 7px;
571
+ top: calc(95% - 7px);
572
+ left: calc(22.5% - 2px);
573
+ background: rgba(73,168,68,1);
574
+ }
575
+
576
+ .searchEng-elem {
577
+ display: flex;
578
+ gap: 3rem;
579
+ align-items: center;
580
+ font-size: 1.5rem;
581
+ margin: 1rem 0;
582
+ }
583
+
584
+ .settings-sidebar .set-name[data-detailId="theme"]
public/static/ui_plugins.js ADDED
@@ -0,0 +1,110 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ Select plugin
3
+ Note: Only for single select option
4
+ Usage example:
5
+ ```
6
+ <input name="theme" disabled style="display: none;" required></input>
7
+ <div class="custom-select" tabindex="0" data-input="theme" data-default="Select" takeInput>
8
+ Svg Icon here
9
+ <div class="options">
10
+ <span data-value="simple">Simple</span>
11
+ </div>
12
+ </div>
13
+ ```
14
+ */
15
+
16
+ let svg_tick = `
17
+ <svg fill="currentColor" height="1.5rem" width="1.5rem" viewBox="0 0 490 490" xml:space="preserve">
18
+ <g id="SVGRepo_iconCarrier">
19
+ <polygon points="452.253,28.326 197.831,394.674 29.044,256.875 0,292.469 207.253,461.674 490,54.528 "></polygon>
20
+ </g>
21
+ </svg>`;
22
+
23
+ function toggleSelectOptions(elem, state) {
24
+ elem.classList.remove("invalid");
25
+ try { elem.parentElement.querySelector('.errTxt').remove();} catch (error) {}
26
+ let options = elem.querySelector('.options');
27
+ const pos = elem.getBoundingClientRect();
28
+ const windowWidth = document.getElementsByTagName("body")[0].clientHeight;
29
+ if(pos.y + 250 > windowWidth) {
30
+ options.style.bottom = '40px';
31
+ } else { options.style.bottom = null }
32
+ options.style.display = state != 'close' ? getComputedStyle(options).display == 'none' ? 'block': 'none' : 'none';
33
+ }
34
+
35
+ let selectElements = document.querySelectorAll('.custom-select').forEach(element => {
36
+ let value = element.getAttribute('data-default')
37
+ element.childNodes[0].nodeValue = value;
38
+ element.querySelector(`.options span[data-value="${value.toLowerCase()}"]`).
39
+ innerHTML = `${value} ${svg_tick}`;
40
+ element.addEventListener('click', (e) => {if (e.target === element) toggleSelectOptions(element)});
41
+ element.addEventListener('focusout', (e) => {if (e.target === element) toggleSelectOptions(element, 'close')});
42
+ });
43
+
44
+ function singleSelectClickHandler(elem) {
45
+ let selectDiv = elem.closest('.custom-select');
46
+ let selectedOption = selectDiv.querySelector('span[selected]');
47
+ let input = document.querySelector(`[name="${selectDiv.getAttribute('data-input')}"]`);
48
+ if (!elem.hasAttribute('selected')) {
49
+ if (selectedOption != null) {
50
+ selectedOption.removeAttribute('selected');
51
+ selectedOption.querySelector('svg').remove();
52
+ }
53
+ elem.setAttribute('selected', '');
54
+ elem.innerHTML = `${elem.innerText} ${svg_tick}`
55
+ // Code where value is inserted to input
56
+ input.value = elem.getAttribute('data-value') ? elem.getAttribute('data-value') : '';
57
+ selectDiv.childNodes[0].nodeValue = elem.innerText;
58
+ } else {
59
+ elem.removeAttribute('selected');
60
+ elem.querySelector('svg').remove();
61
+ selectDiv.childNodes[0].nodeValue = selectDiv.getAttribute('data-defaultIfNone');
62
+
63
+ input.value = "";
64
+ }
65
+ selectDiv.blur();
66
+ }
67
+
68
+ let singleSelectOptions = document.querySelectorAll('.custom-select:not([data-multiple="1"])>.options span');
69
+ for (let i = 0; i < singleSelectOptions.length; i++) {
70
+ singleSelectOptions[i].addEventListener('click', () => {singleSelectClickHandler(singleSelectOptions[i])});
71
+ singleSelectOptions[i].setAttribute('id', 'option-'+i.toString());
72
+ }
73
+
74
+
75
+ /*
76
+ Toggle switch plugin
77
+ Usage example:
78
+ ```
79
+ <input type="hidden" name="searchEng" disabled>
80
+ <div class="searchEng">
81
+ <div class="searchEng-elem">
82
+ <input type="checkbox" id="toggle"/>
83
+ <div data-isCheckbox data-input="searchEng" data-value="ddg">
84
+ <label for="toggle"></label>
85
+ </div>
86
+ <span>Duck duck go</span>
87
+ </div>
88
+ <div class="searchEng-elem">
89
+ <input type="checkbox" id="toggle1"/>
90
+ <div data-isCheckbox data-input="searchEng" data-value="searx">
91
+ <label for="toggle1"></label>
92
+ </div>
93
+ <span>Searx</span>
94
+ </div>
95
+ </div>
96
+ ```
97
+ */
98
+
99
+ document.querySelectorAll('[data-isCheckbox]:not([data-value="all"]) label').forEach(checkBoxLabel => {
100
+ checkBoxLabel.addEventListener('click', () => {
101
+ let checkBox = checkBoxLabel.parentElement;
102
+ let helperInput = checkBox.parentElement.querySelector('input[type="checkbox"]');
103
+ let mainInput = document.getElementsByName(checkBox.getAttribute('data-input'))[0];
104
+ if (helperInput.checked == true) {
105
+ mainInput.value = mainInput.value.replace(checkBox.getAttribute('data-value') + ',', '');
106
+ } else {
107
+ mainInput.value += checkBox.getAttribute('data-value') + ',';
108
+ }
109
+ });
110
+ })
public/templates/header.html CHANGED
@@ -4,9 +4,26 @@
4
  <title>Websurfx</title>
5
  <meta charset="UTF-8" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <link href="static/colorschemes/{{colorscheme}}.css" rel="stylesheet" type="text/css" />
8
- <link href="static/themes/{{theme}}.css" rel="stylesheet" type="text/css" />
9
  </head>
10
 
11
  <body>
12
  <header>{{>navbar}}</header>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
  <title>Websurfx</title>
5
  <meta charset="UTF-8" />
6
  <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <!-- <link href="static/colorschemes/{{colorscheme}}.css" rel="stylesheet" type="text/css" /> -->
8
+ <!-- <link href="static/themes/{{theme}}.css" rel="stylesheet" type="text/css" /> -->
9
  </head>
10
 
11
  <body>
12
  <header>{{>navbar}}</header>
13
+ <script>
14
+ const cookies = document.cookie.split(';').map(item => item.split('=')).
15
+ reduce((acc, [k, v]) => (acc[k.trim().replace('"', '')] = v) && acc, {});
16
+ // Load colorscheme and theme from cookie
17
+ function addCss(fileName) {
18
+ var head = document.head;
19
+ var link = document.createElement("link");
20
+
21
+ link.type = "text/css";
22
+ link.rel = "stylesheet";
23
+ link.href = fileName;
24
+
25
+ head.appendChild(link);
26
+ }
27
+ addCss('static/themes/'+ (cookies["theme"] || {{theme}}) + '.css');
28
+ addCss('static/colorschemes/'+ (cookies["color-sch"] || {{colorscheme}}) + '.css');
29
+ </script>
public/templates/settings.html CHANGED
@@ -9,25 +9,37 @@
9
  <span class="set-name" data-detailId="theme">Theme</span>
10
  </div>
11
  <div class="settings-detail">
12
- <form method="post" name="settings" onsubmit="return submitSettings();">
13
  <!-- Search engine settings -->
14
  <div class="set-item" data-id="searchEng">
15
  <h3 class="set-name">Select search engines</h3>
16
  <p class="set-desc">Select the search engines from the list of engines that you want results from</p>
17
- <!-- Select element -->
18
- <input name="search-engine" disabled style="display: none;" required></input>
19
- <div id="engines-selected" class="select-multiple-show">
20
- <span>Selected Engines: </span>
21
- </div>
22
- <div class="custom-select" tabindex="0" data-multiple="1" data-showDivId="engines-selected" data-input="search-engine" data-placeholder="Select" takeInput>
23
- <svg viewBox="0 0 24 24" width="2rem" height="2rem" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
24
- <path d="M6.1018 8C5.02785 8 4.45387 9.2649 5.16108 10.0731L10.6829 16.3838C11.3801 17.1806 12.6197 17.1806 13.3169 16.3838L18.8388 10.0731C19.5459 9.2649 18.972 8 17.898 8H6.1018Z"></path></svg>
25
- <div class="options">
26
- <span data-value="ddg">Duck duck go</span>
27
- <span data-value="searx">Searx</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  </div>
29
  </div>
30
- <u class="underlined-text" onclick="selectAllHandler(this)">select all</u>
31
  <!-- End search select -->
32
  </div>
33
  <!-- End search engine setting -->
@@ -37,13 +49,16 @@
37
  <h3 class="set-name">Select theme</h3>
38
  <p class="set-desc">Select the theme from the available themes to be used in user interface</p>
39
  <!-- Select element -->
40
- <input name="theme" disabled style="display: none;" required></input>
41
- <div class="custom-select" tabindex="0" data-input="theme" data-default="Select" takeInput>
 
42
  <svg viewBox="0 0 24 24" width="2rem" height="2rem" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
43
- <path d="M6.1018 8C5.02785 8 4.45387 9.2649 5.16108 10.0731L10.6829 16.3838C11.3801 17.1806 12.6197 17.1806 13.3169 16.3838L18.8388 10.0731C19.5459 9.2649 18.972 8 17.898 8H6.1018Z"></path>
 
 
44
  </svg>
45
  <div class="options">
46
- <span data-value="simple">Simple</span>
47
  </div>
48
  </div>
49
  <!-- End select element -->
@@ -55,13 +70,16 @@
55
  <h3 class="set-name">Select Color Scheme</h3>
56
  <p class="set-desc">Select the color scheme for your theme to be used in user interface</p>
57
  <!-- Select element -->
58
- <input name="color-sch" disabled style="display: none;" required></input>
59
- <div class="custom-select" tabindex="0" data-input="color-sch" data-default="Select" takeInput>
 
60
  <svg viewBox="0 0 24 24" width="2rem" height="2rem" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
61
- <path d="M6.1018 8C5.02785 8 4.45387 9.2649 5.16108 10.0731L10.6829 16.3838C11.3801 17.1806 12.6197 17.1806 13.3169 16.3838L18.8388 10.0731C19.5459 9.2649 18.972 8 17.898 8H6.1018Z"></path>
 
 
62
  </svg>
63
  <div class="options">
64
- <span data-value="catppuccin-mocha">catppuccin-mocha</span>
65
  <span data-value="dracula">dracula</span>
66
  <span data-value="monokai">monokai</span>
67
  <span data-value="nord">nord</span>
@@ -84,5 +102,6 @@
84
  </div>
85
  </div>
86
  </main>
 
87
  <script src="static/settings.js"></script>
88
  {{>footer}}
 
9
  <span class="set-name" data-detailId="theme">Theme</span>
10
  </div>
11
  <div class="settings-detail">
12
+ <form name="settings" onsubmit="submitSettings(); return false;">
13
  <!-- Search engine settings -->
14
  <div class="set-item" data-id="searchEng">
15
  <h3 class="set-name">Select search engines</h3>
16
  <p class="set-desc">Select the search engines from the list of engines that you want results from</p>
17
+ <!-- toggle element -->
18
+ <input type="hidden" name="searchEng" required value="ddg,searx,">
19
+ <div class="searchEng" takeInput>
20
+ <div class="searchEng-elem">
21
+ <input type="checkbox" id="selectAll-eng" onclick="return selectAllHandler(this);"/>
22
+ <div data-isCheckbox data-input="searchEng" data-value="all">
23
+ <label for="selectAll-eng"></label>
24
+ </div>
25
+ <span>Select all</span>
26
+ </div>
27
+ <hr>
28
+ <div class="searchEng-elem">
29
+ <input type="checkbox" id="toggle" checked/>
30
+ <div data-isCheckbox data-input="searchEng" data-value="ddg">
31
+ <label for="toggle"></label>
32
+ </div>
33
+ <span>Duck duck go</span>
34
+ </div>
35
+ <div class="searchEng-elem">
36
+ <input type="checkbox" id="toggle1" checked/>
37
+ <div data-isCheckbox data-input="searchEng" data-value="searx">
38
+ <label for="toggle1"></label>
39
+ </div>
40
+ <span>Searx</span>
41
  </div>
42
  </div>
 
43
  <!-- End search select -->
44
  </div>
45
  <!-- End search engine setting -->
 
49
  <h3 class="set-name">Select theme</h3>
50
  <p class="set-desc">Select the theme from the available themes to be used in user interface</p>
51
  <!-- Select element -->
52
+ <input type="hidden" name="theme" style="display: none;" required value="simple"></input>
53
+ <div class="custom-select" tabindex="0" data-input="theme" data-default="simple" takeInput
54
+ data-defaultIfNone="Select">
55
  <svg viewBox="0 0 24 24" width="2rem" height="2rem" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
56
+ <path d="M6.1018 8C5.02785 8 4.45387 9.2649 5.16108 10.0731L10.6829 16.3838C11.3801 17.1806 12.6197 17.1806
57
+ 13.3169 16.3838L18.8388 10.0731C19.5459 9.2649 18.972 8 17.898 8H6.1018Z">
58
+ </path>
59
  </svg>
60
  <div class="options">
61
+ <span data-value="simple" selected>simple</span>
62
  </div>
63
  </div>
64
  <!-- End select element -->
 
70
  <h3 class="set-name">Select Color Scheme</h3>
71
  <p class="set-desc">Select the color scheme for your theme to be used in user interface</p>
72
  <!-- Select element -->
73
+ <input type="hidden" name="color-sch" style="display: none;" required value="catppuccin-mocha"></input>
74
+ <div class="custom-select" tabindex="0" data-input="color-sch" data-default="catppuccin-mocha" takeInput
75
+ data-defaultIfNone="Select">
76
  <svg viewBox="0 0 24 24" width="2rem" height="2rem" fill="currentColor" xmlns="http://www.w3.org/2000/svg">
77
+ <path d="M6.1018 8C5.02785 8 4.45387 9.2649 5.16108 10.0731L10.6829 16.3838C11.3801 17.1806 12.6197 17.1806
78
+ 13.3169 16.3838L18.8388 10.0731C19.5459 9.2649 18.972 8 17.898 8H6.1018Z">
79
+ </path>
80
  </svg>
81
  <div class="options">
82
+ <span data-value="catppuccin-mocha" selected>catppuccin-mocha</span>
83
  <span data-value="dracula">dracula</span>
84
  <span data-value="monokai">monokai</span>
85
  <span data-value="nord">nord</span>
 
102
  </div>
103
  </div>
104
  </main>
105
+ <script src="static/ui_plugins.js"></script>
106
  <script src="static/settings.js"></script>
107
  {{>footer}}