js_lis 1.0.25 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/VirtualKeyboard.js +186 -312
  2. package/layouts.js +12 -27
  3. package/package.json +1 -1
@@ -12,10 +12,7 @@ export class VirtualKeyboard {
12
12
  this.offsetY = 0;
13
13
  this.shiftActive = false;
14
14
  this.capsLockActive = false;
15
-
16
- // กำหนดคีย์และ IV สำหรับการเข้ารหัส
17
- this.secretKey = "1234567890abcdef1234567890abcdef"; // คีย์ความยาว 32 bytes
18
- this.iv = CryptoJS.lib.WordArray.random(16); // สร้าง IV ความยาว 16 bytes
15
+ this.isScrambled = false;
19
16
 
20
17
  this.initialize();
21
18
  }
@@ -30,64 +27,18 @@ export class VirtualKeyboard {
30
27
  }
31
28
  }
32
29
 
33
- encodeText(text) {
34
- const encrypted = CryptoJS.AES.encrypt(
35
- text,
36
- CryptoJS.enc.Hex.parse(this.secretKey),
37
- {
38
- iv: this.iv,
39
- mode: CryptoJS.mode.CBC,
40
- padding: CryptoJS.pad.Pkcs7,
41
- }
42
- );
43
- return {
44
- encrypted: encrypted.ciphertext.toString(CryptoJS.enc.Base64),
45
- iv: this.iv.toString(CryptoJS.enc.Base64),
46
- };
47
- }
48
-
49
- decodeText(encryptedData) {
50
- if (!encryptedData || !encryptedData.encrypted || !encryptedData.iv) {
51
- if (encryptedData === "\t") {
52
- return "\t";
53
- } else {
54
- return " ";
55
- }
56
- }
57
-
58
- try {
59
- const decrypted = CryptoJS.AES.decrypt(
60
- { ciphertext: CryptoJS.enc.Base64.parse(encryptedData.encrypted) },
61
- CryptoJS.enc.Hex.parse(this.secretKey),
62
- {
63
- iv: CryptoJS.enc.Base64.parse(encryptedData.iv),
64
- mode: CryptoJS.mode.CBC,
65
- padding: CryptoJS.pad.Pkcs7,
66
- }
67
- );
68
- return decrypted.toString(CryptoJS.enc.Utf8);
69
- } catch (error) {
70
- console.error("Error decoding text:", error);
71
- return " ";
72
- }
73
- }
74
-
75
30
  getLayoutName(layout) {
76
31
  switch (layout) {
77
32
  case "full":
78
33
  return "Full Keyboard";
79
34
  case "en":
80
35
  return "English Keyboard";
81
- case "enSc":
82
- return "English scrambled";
83
36
  case "th":
84
37
  return "Thai keyboard";
85
- case "thSc":
86
- return "Thai scrambled";
87
38
  case "numpad":
88
39
  return "Numpad Keyboard";
89
- case "scNum":
90
- return "Scrambled Keyboard";
40
+ case "symbols":
41
+ return "Symbols Keyboard";
91
42
  default:
92
43
  return "Unknown Layout";
93
44
  }
@@ -127,6 +78,7 @@ export class VirtualKeyboard {
127
78
  this.currentInput.classList.add("keyboard-active");
128
79
  }
129
80
 
81
+ // [1]
130
82
  render() {
131
83
  const keyboard = document.createElement("div");
132
84
  keyboard.className = `virtual-keyboard ${this.currentLayout}`;
@@ -144,7 +96,7 @@ export class VirtualKeyboard {
144
96
  layoutSelector.id = "layout-selector";
145
97
  layoutSelector.onchange = (e) => this.changeLayout(e.target.value);
146
98
 
147
- const layouts = ["full", "en", "enSc", "th", "thSc", "numpad", "scNum"];
99
+ const layouts = ["full", "en", "th", "numpad", "symbols"];
148
100
  layouts.forEach((layout) => {
149
101
  const option = document.createElement("option");
150
102
  option.value = layout;
@@ -202,24 +154,12 @@ export class VirtualKeyboard {
202
154
  this.container.innerHTML = "";
203
155
  this.container.appendChild(keyboard);
204
156
 
205
- if (this.currentLayout === "scNum") {
206
- this.scrambleKeyboard();
207
- }
208
-
209
- if (this.currentLayout === "enSc") {
210
- this.scrambleEnglishKeys();
211
- }
212
-
213
- if (this.currentLayout === "thSc") {
214
- this.scrambleThaiKeys();
215
- }
216
-
217
157
  keyboard.addEventListener("mousedown", (event) => this.startDrag(event));
218
158
  }
219
159
 
160
+ // [2]
220
161
  async handleKeyPress(keyPressed) {
221
162
  if (!this.currentInput) return;
222
-
223
163
  const start = this.currentInput.selectionStart;
224
164
  const end = this.currentInput.selectionEnd;
225
165
  const value = this.currentInput.value;
@@ -234,21 +174,72 @@ export class VirtualKeyboard {
234
174
  return char.toLowerCase();
235
175
  };
236
176
 
237
- if (!keyPressed) {
238
- console.error("Invalid key pressed.");
177
+ if (!keyPressed) return console.error("Invalid key pressed.");
178
+
179
+ if (keyPressed === "scr" || keyPressed === "scrambled") {
180
+ if (this.currentLayout === "en") {
181
+ if (this.isScrambled) {
182
+ this.unscrambleKeys();
183
+ } else {
184
+ this.scrambleEnglishKeys();
185
+ }
186
+ this.isScrambled = !this.isScrambled;
187
+ document
188
+ .querySelectorAll('.key[data-key="scrambled"]')
189
+ .forEach((key) => {
190
+ key.classList.toggle("active", this.isScrambled);
191
+ });
192
+ }
193
+
194
+ if (this.currentLayout === "th") {
195
+ if (this.isScrambled) {
196
+ this.unscrambleKeys();
197
+ } else {
198
+ this.scrambleThaiKeys();
199
+ }
200
+ this.isScrambled = !this.isScrambled;
201
+ document
202
+ .querySelectorAll('.key[data-key="scrambled"]')
203
+ .forEach((key) => {
204
+ key.classList.toggle("active", this.isScrambled);
205
+ });
206
+ }
207
+
208
+ if (this.currentLayout === "numpad") {
209
+ if (this.isScrambled) {
210
+ this.unscrambleKeys();
211
+ } else {
212
+ this.scrambleKeyboard();
213
+ }
214
+ this.isScrambled = !this.isScrambled;
215
+ document.querySelectorAll('.key[data-key="scr"]').forEach((key) => {
216
+ key.classList.toggle("active", this.isScrambled);
217
+ });
218
+ }
219
+
220
+ if (this.currentLayout === "symbols") {
221
+ if (this.isScrambled) {
222
+ this.unscrambleKeys();
223
+ } else {
224
+ this.scrambleSymbols();
225
+ }
226
+ this.isScrambled = !this.isScrambled;
227
+ document.querySelectorAll('.key[data-key="scr"]').forEach((key) => {
228
+ key.classList.toggle("active", this.isScrambled);
229
+ });
230
+ }
239
231
  return;
240
232
  }
241
233
 
242
234
  switch (keyPressed) {
243
235
  case "Esc":
244
- // ปิดหน้าต่างป๊อปอัพหรือยกเลิกการทำงานปัจจุบัน
245
236
  const modals = document.querySelectorAll(".modal");
246
237
  if (modals.length === 0) {
247
238
  document.exitFullscreen();
248
239
  console.warn("No modals found to close.");
249
240
  }
250
241
  modals.forEach((modal) => {
251
- modal.classList.add("hidden"); // ซ่อน modal
242
+ modal.classList.add("hidden");
252
243
  });
253
244
  break;
254
245
 
@@ -332,27 +323,21 @@ export class VirtualKeyboard {
332
323
  case "Backspace":
333
324
  case "backspace":
334
325
  if (start === end && start > 0) {
335
- this.currentInput.value =
336
- value.slice(0, start - 1) + value.slice(end);
337
- this.currentInput.selectionStart = this.currentInput.selectionEnd =
338
- start - 1;
326
+ this.currentInput.value = value.slice(0, start - 1) + value.slice(end);
327
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start - 1;
339
328
  } else {
340
329
  this.currentInput.value = value.slice(0, start) + value.slice(end);
341
- this.currentInput.selectionStart = this.currentInput.selectionEnd =
342
- start;
330
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
343
331
  }
344
332
  break;
345
333
 
346
334
  case "DEL⌦":
347
335
  if (start === end && start < value.length) {
348
- this.currentInput.value =
349
- value.slice(0, start) + value.slice(end + 1);
350
- this.currentInput.selectionStart = this.currentInput.selectionEnd =
351
- start;
336
+ this.currentInput.value = value.slice(0, start) + value.slice(end + 1);
337
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
352
338
  } else {
353
339
  this.currentInput.value = value.slice(0, start) + value.slice(end);
354
- this.currentInput.selectionStart = this.currentInput.selectionEnd =
355
- start;
340
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
356
341
  }
357
342
  break;
358
343
 
@@ -366,23 +351,14 @@ export class VirtualKeyboard {
366
351
 
367
352
  case "Enter":
368
353
  if (this.currentInput.tagName === "TEXTAREA") {
369
- this.currentInput.value =
370
- value.slice(0, start) + "\n" + value.slice(end);
354
+ this.currentInput.value = value.slice(0, start) + "\n" + value.slice(end);
371
355
  this.currentInput.setSelectionRange(start + 1, start + 1);
372
- } else if (
373
- this.currentInput.tagName === "INPUT" ||
374
- this.currentInput.type === "password" ||
375
- this.currentInput.type === "text"
376
- ) {
356
+ } else if (this.currentInput.tagName === "INPUT" || this.currentInput.type === "password" || this.currentInput.type === "text" ) {
377
357
  if (this.currentInput.form) {
378
358
  const submitButton = this.currentInput.form.querySelector(
379
359
  'input[type="submit"], button[type="submit"], button[type="button"], button[onclick]'
380
360
  );
381
- if (submitButton) {
382
- submitButton.click();
383
- } else {
384
- this.currentInput.form.submit();
385
- }
361
+ if (submitButton) submitButton.click(); else this.currentInput.form.submit();
386
362
  } else {
387
363
  this.currentInput.value += "\n";
388
364
  }
@@ -418,267 +394,154 @@ export class VirtualKeyboard {
418
394
 
419
395
  if (keyPressed === "↑" && currentLineIndex > 0) {
420
396
  const prevLineLength = lines[currentLineIndex - 1].length;
421
- const newPos =
422
- start -
423
- currentLine.length -
424
- 1 -
425
- Math.min(columnIndex, prevLineLength);
397
+ const newPos = start - currentLine.length - 1 - Math.min(columnIndex, prevLineLength);
426
398
  this.currentInput.setSelectionRange(newPos, newPos);
427
399
  } else if (keyPressed === "↓" && currentLineIndex < lines.length - 1) {
428
400
  const nextLine = lines[currentLineIndex + 1];
429
- const newPos =
430
- start +
431
- currentLine.length +
432
- 1 +
433
- Math.min(columnIndex, nextLine.length);
401
+ const newPos = start + currentLine.length + 1 + Math.min(columnIndex, nextLine.length);
434
402
  this.currentInput.setSelectionRange(newPos, newPos);
435
403
  }
436
404
  break;
437
405
 
438
406
  default:
439
- const encryptedText = await this.encodeText(
440
- convertToCorrectCase(keyPressed)
441
- );
442
- await this.insertText(encryptedText);
407
+ const textvalue = await convertToCorrectCase(keyPressed);
408
+ await this.insertText(textvalue);
443
409
  }
444
410
 
445
- if (isShiftActive && !isCapsActive) {
446
- this.toggleShift();
447
- }
411
+ if (isShiftActive && !isCapsActive) this.toggleShift();
448
412
 
449
413
  this.currentInput.focus();
450
414
  const event = new Event("input", { bubbles: true });
451
415
  this.currentInput.dispatchEvent(event);
452
416
  }
453
417
 
418
+ // [3]
454
419
  async insertText(text) {
455
420
  const start = this.currentInput.selectionStart;
456
421
  const end = this.currentInput.selectionEnd;
457
- const decodedText = await this.decodeText(text); // ใช้ถอดรหัสก่อนแทรก
458
-
459
- this.currentInput.value =
460
- this.currentInput.value.slice(0, start) +
461
- decodedText +
462
- this.currentInput.value.slice(end);
463
- this.currentInput.selectionStart = this.currentInput.selectionEnd =
464
- start + decodedText.length;
422
+ const textvalue = text;
423
+
424
+ this.currentInput.value = this.currentInput.value.slice(0, start) + textvalue + this.currentInput.value.slice(end);
425
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start + textvalue.length;
465
426
  }
466
427
 
428
+ // [4]
429
+ unscrambleKeys() {
430
+ this.keys = this.originalKeys;
431
+ this.render();
432
+ }
433
+
434
+ // [5]
467
435
  toggleCapsLock() {
468
436
  this.capsLockActive = !this.capsLockActive;
437
+
469
438
  document.querySelectorAll('.key[data-key="Caps 🄰"]').forEach((key) => {
470
439
  key.classList.toggle("active", this.capsLockActive);
471
440
  key.classList.toggle("bg-gray-400", this.capsLockActive);
472
441
  });
473
442
 
474
443
  document.querySelectorAll(".key").forEach((key) => {
475
- if (key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key)) {
444
+ const isLetter = key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key);
445
+
446
+ if (isLetter) {
476
447
  key.textContent = this.capsLockActive
477
448
  ? key.dataset.key.toUpperCase()
478
449
  : key.dataset.key.toLowerCase();
479
450
  }
451
+ this.updateKeyContent(key, this.capsLockActive);
480
452
  });
481
-
482
- const keyboardKeys = document.querySelectorAll(
483
- ".key:not([data-key='Caps 🄰'])"
484
- );
485
- keyboardKeys.forEach((key) => {
486
- const currentChar = key.textContent.trim();
487
- if (
488
- this.capsLockActive &&
489
- this.currentLayout === "th" &&
490
- this.ThaiAlphabetShift[currentChar]
491
- ) {
492
- key.textContent = this.ThaiAlphabetShift[currentChar];
493
- key.dataset.key = this.ThaiAlphabetShift[currentChar];
494
- } else if (
495
- !this.capsLockActive &&
496
- this.currentLayout === "th" &&
497
- Object.values(this.ThaiAlphabetShift).includes(currentChar)
498
- ) {
499
- // เปลี่ยนกลับเมื่อปิด Shift
500
- const originalKey = Object.keys(this.ThaiAlphabetShift).find(
501
- (key) => this.ThaiAlphabetShift[key] === currentChar
502
- );
503
- if (originalKey) {
504
- key.textContent = originalKey;
505
- key.dataset.key = originalKey;
506
- }
507
- }
508
-
509
- if (
510
- this.capsLockActive &&
511
- (this.currentLayout === "en" || this.currentLayout === "enSc") &&
512
- this.EngAlphabetShift[currentChar]
513
- ) {
514
- key.textContent = this.EngAlphabetShift[currentChar];
515
- key.dataset.key = this.EngAlphabetShift[currentChar];
516
- } else if (
517
- !this.capsLockActive &&
518
- (this.currentLayout === "en" || this.currentLayout === "enSc") &&
519
- Object.values(this.EngAlphabetShift).includes(currentChar)
520
- ) {
521
- const originalKey = Object.keys(this.EngAlphabetShift).find(
522
- (key) => this.EngAlphabetShift[key] === currentChar
523
- );
524
- if (originalKey) {
525
- key.textContent = originalKey;
526
- key.dataset.key = originalKey;
527
- }
453
+ }
454
+ updateKeyContent(key, capsLockActive) {
455
+ const currentChar = key.textContent.trim();
456
+
457
+ const layouts = {
458
+ th: this.ThaiAlphabetShift,
459
+ en: this.EngAlphabetShift,
460
+ enSc: this.EngAlphabetShift,
461
+ full: this.FullAlphabetShift,
462
+ };
463
+ const layout = layouts[this.currentLayout];
464
+
465
+ if (!layout) return;
466
+
467
+ if (capsLockActive && layout[currentChar]) {
468
+ key.textContent = layout[currentChar];
469
+ key.dataset.key = layout[currentChar];
470
+ } else if (!capsLockActive && Object.values(layout).includes(currentChar)) {
471
+ const originalKey = Object.keys(layout).find((k) => layout[k] === currentChar);
472
+ if (originalKey) {
473
+ key.textContent = originalKey;
474
+ key.dataset.key = originalKey;
528
475
  }
529
- });
476
+ }
530
477
  }
531
478
 
479
+ // [6]
532
480
  toggleShift() {
481
+ if (this.capsLockActive) {
482
+ return this.toggleCapsLock();
483
+ }
484
+
533
485
  this.shiftActive = !this.shiftActive;
534
486
  document.querySelectorAll('.key[data-key="Shift ⇧"]').forEach((key) => {
535
487
  key.classList.toggle("active", this.shiftActive);
488
+ key.classList.toggle("bg-gray-400", this.shiftActive);
536
489
  });
537
-
490
+
538
491
  document.querySelectorAll(".key").forEach((key) => {
539
- if (key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key)) {
492
+ const isLetter = key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key);
493
+
494
+ if (isLetter) {
540
495
  key.textContent = this.shiftActive
541
496
  ? key.dataset.key.toUpperCase()
542
497
  : key.dataset.key.toLowerCase();
543
498
  }
499
+ this.updateKeyContent(key, this.shiftActive);
544
500
  });
545
-
546
- const keyboardKeys = document.querySelectorAll(
547
- ".key:not([data-key='Shift ⇧'])"
548
- );
549
- keyboardKeys.forEach((key) => {
550
- const currentChar = key.textContent.trim();
551
- keyboardKeys.className += " space";
552
- if (
553
- this.shiftActive &&
554
- this.currentLayout === "th" &&
555
- this.ThaiAlphabetShift[currentChar]
556
- ) {
557
- key.textContent = this.ThaiAlphabetShift[currentChar];
558
- key.dataset.key = this.ThaiAlphabetShift[currentChar];
559
- } else if (
560
- !this.shiftActive &&
561
- this.currentLayout === "th" &&
562
- Object.values(this.ThaiAlphabetShift).includes(currentChar)
563
- ) {
564
- // เปลี่ยนกลับเมื่อปิด Shift
565
- const originalKey = Object.keys(this.ThaiAlphabetShift).find(
566
- (key) => this.ThaiAlphabetShift[key] === currentChar
567
- );
568
- if (originalKey) {
569
- key.textContent = originalKey;
570
- key.dataset.key = originalKey;
571
- }
572
- }
573
-
574
- if (
575
- this.shiftActive &&
576
- (this.currentLayout === "en" || this.currentLayout === "enSc") &&
577
- this.EngAlphabetShift[currentChar]
578
- ) {
579
- key.textContent = this.EngAlphabetShift[currentChar];
580
- key.dataset.key = this.EngAlphabetShift[currentChar];
581
- } else if (
582
- !this.shiftActive &&
583
- (this.currentLayout === "en" || this.currentLayout === "enSc") &&
584
- Object.values(this.EngAlphabetShift).includes(currentChar)
585
- ) {
586
- // เปลี่ยนกลับเมื่อปิด Shift
587
- const originalKey = Object.keys(this.EngAlphabetShift).find(
588
- (key) => this.EngAlphabetShift[key] === currentChar
589
- );
590
- if (originalKey) {
591
- key.textContent = originalKey;
592
- key.dataset.key = originalKey;
593
- }
501
+ }
502
+ updateKeyContent(key, shiftActive) {
503
+ const currentChar = key.textContent.trim();
504
+
505
+ const layouts = {
506
+ th: this.ThaiAlphabetShift,
507
+ en: this.EngAlphabetShift,
508
+ enSc: this.EngAlphabetShift,
509
+ full: this.FullAlphabetShift,
510
+ };
511
+ const layout = layouts[this.currentLayout];
512
+
513
+ if (!layout) return;
514
+
515
+ if (shiftActive && layout[currentChar]) {
516
+ key.textContent = layout[currentChar];
517
+ key.dataset.key = layout[currentChar];
518
+ } else if (!shiftActive && Object.values(layout).includes(currentChar)) {
519
+ const originalKey = Object.keys(layout).find((k) => layout[k] === currentChar);
520
+ if (originalKey) {
521
+ key.textContent = originalKey;
522
+ key.dataset.key = originalKey;
594
523
  }
595
- });
524
+ }
596
525
  }
597
526
 
598
- EngAlphabetShift = {
599
- "`": "~",
600
- 1: "!",
601
- 2: "@",
602
- 3: "#",
603
- 4: "$",
604
- 5: "%",
605
- 6: "^",
606
- 7: "&",
607
- 8: "*",
608
- 9: "(",
609
- 0: ")",
610
- "-": "_",
611
- "=": "+",
612
- "[": "{",
613
- "]": "}",
614
- "\\": "|",
615
- ";": ":",
616
- "'": '"',
617
- ",": "<",
618
- ".": ">",
619
- "/": "?",
620
- };
621
-
622
- ThaiAlphabetShift = {
623
- _: "%",
624
- ๅ: "+",
625
- "/": "๑",
626
- "-": "๒",
627
- ภ: "๓",
628
- ถ: "๔",
629
- "ุ": "ู",
630
- "ึ": "฿",
631
- ค: "๕",
632
- ต: "๖",
633
- จ: "๗",
634
- ข: "๘",
635
- ช: "๙",
636
- ๆ: "๐",
637
- ไ: '"',
638
- ำ: "ฎ",
639
- พ: "ฑ",
640
- ะ: "ธ",
641
- "ั": "ํ",
642
- "ี": "๋",
643
- ร: "ณ",
644
- น: "ฯ",
645
- ย: "ญ",
646
- บ: "ฐ",
647
- ล: ",",
648
- ฃ: "ฅ",
649
- ฟ: "ฤ",
650
- ห: "ฆ",
651
- ก: "ฏ",
652
- ด: "โ",
653
- เ: "ฌ",
654
- "้": "็",
655
- "่": "๋",
656
- า: "ษ",
657
- ส: "ศ",
658
- ว: "ซ",
659
- ง: ".",
660
- ผ: "(",
661
- ป: ")",
662
- แ: "ฉ",
663
- อ: "ฮ",
664
- "ิ": "ฺ",
665
- "ื": "์",
666
- ท: "?",
667
- ม: "ฒ",
668
- ใ: "ฬ",
669
- ฝ: "ฦ",
670
- };
527
+ // [7]
528
+ EngAlphabetShift = { "`": "~", 1: "!", 2: "@", 3: "#", 4: "$", 5: "%", 6: "^", 7: "&", 8: "*", 9: "(", 0: ")", "-": "_", "=": "+", "[": "{", "]": "}", "\\": "|", ";": ":", "'": '"', ",": "<", ".": ">", "/": "?", };
529
+ ThaiAlphabetShift = { _: "%", ๅ: "+", "/": "๑", "-": "๒", ภ: "๓", ถ: "๔", "ุ": "ู", "ึ": "฿", ค: "๕", ต: "๖", จ: "๗", ข: "๘", ช: "๙", ๆ: "๐", ไ: '"', ำ: "ฎ", พ: "ฑ", ะ: "ธ", "ั": "ํ", "ี": "๋", ร: "ณ", น: "ฯ", ย: "ญ", บ: "ฐ", ล: ",", ฃ: "ฅ", ฟ: "ฤ", ห: "ฆ", ก: "ฏ", ด: "โ", เ: "ฌ", "้": "็", "่": "๋", า: "ษ", ส: "ศ", ว: "ซ", ง: ".", ผ: "(", ป: ")", แ: "ฉ", อ: "ฮ", "ิ": "ฺ", "ื": "์", ท: "?", ม: "ฒ", ใ: "ฬ", ฝ: "ฦ"};
530
+ FullAlphabetShift = { "[": "{", "]": "}", "\\": "|", ";": ":", "'": '"', ",": "<", ".": ">", "/": "?", };
671
531
 
532
+ // [8]
672
533
  toggle() {
673
534
  this.isVisible = !this.isVisible;
674
535
  this.render();
675
536
  }
676
537
 
538
+ // [9]
677
539
  changeLayout(layout) {
678
540
  this.currentLayout = layout;
679
541
  this.render();
680
542
  }
681
543
 
544
+ // [10]
682
545
  shuffleArray(array) {
683
546
  for (let i = array.length - 1; i > 0; i--) {
684
547
  const j = Math.floor(Math.random() * (i + 1));
@@ -686,11 +549,12 @@ export class VirtualKeyboard {
686
549
  }
687
550
  }
688
551
 
552
+ // [11]
689
553
  scrambleKeyboard() {
690
554
  const keys = document.querySelectorAll(
691
- ".key:not([data-key=backspace]):not([data-key='+']):not([data-key='-']):not([data-key='*']):not([data-key='/']):not([data-key='%']):not([data-key='=']):not([data-key='.']):not([data-key='(']):not([data-key=')']):not([data-key='_'])"
555
+ ":not([data-key='std']):not([data-key='scr']).key:not([data-key=backspace]"
692
556
  );
693
- const numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
557
+ const numbers = "1234567890-=+%/*.()".split("");
694
558
  this.shuffleArray(numbers);
695
559
  keys.forEach((key, index) => {
696
560
  key.textContent = numbers[index];
@@ -698,11 +562,12 @@ export class VirtualKeyboard {
698
562
  });
699
563
  }
700
564
 
565
+ // [12]
701
566
  scrambleEnglishKeys() {
702
567
  const keys = document.querySelectorAll(
703
- ".key:not([data-key='Space']):not([data-key='Backspace']):not([data-key='Caps 🄰']):not([data-key='Shift ⇧']):not([data-key='Enter']):not([data-key='Tab ']):not([data-key='`']):not([data-key='1']):not([data-key='2']):not([data-key='3']):not([data-key='4']):not([data-key='5']):not([data-key='6']):not([data-key='7']):not([data-key='8']):not([data-key='9']):not([data-key='0']):not([data-key='-']):not([data-key='+']):not([data-key='=']):not([data-key='~']):not([data-key='!']):not([data-key='@']):not([data-key='#']):not([data-key='$']):not([data-key='%']):not([data-key='^']):not([data-key='&']):not([data-key='*']):not([data-key='(']):not([data-key=')']):not([data-key='_'])"
568
+ ".key:not([data-key='scrambled']):not([data-key='std']):not([data-key='scr']):not([data-key='Space']):not([data-key='Backspace']):not([data-key='Caps 🄰']):not([data-key='Shift ⇧']):not([data-key='Enter']):not([data-key='Tab ↹'])"
704
569
  );
705
- const englishAlphabet = "abcdefghijklmnopqrstuvwxyz".split("");
570
+ const englishAlphabet = "abcdefghijklmnopqrstuvwxyz/.,';\\][`1234567890-=".split("");
706
571
  this.shuffleArray(englishAlphabet);
707
572
  keys.forEach((key, index) => {
708
573
  key.textContent = englishAlphabet[index];
@@ -710,37 +575,46 @@ export class VirtualKeyboard {
710
575
  });
711
576
  }
712
577
 
578
+ // [13]
713
579
  scrambleThaiKeys() {
714
580
  const keys = document.querySelectorAll(
715
- ".key:not([data-key='Backspace']):not([data-key='Caps 🄰']):not([data-key='Shift ⇧']):not([data-key='Enter']):not([data-key='Space'])"
716
- );
717
- const ThaiAlphabet = "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮ".split(
718
- ""
581
+ ".key:not([data-key='scrambled']):not([data-key='scr']):not([data-key='Backspace']):not([data-key='Caps 🄰']):not([data-key='Shift ⇧']):not([data-key='Enter']):not([data-key='Space']):not([data-key='Tab ↹'])"
719
582
  );
720
- this.shuffleArray(ThaiAlphabet); // สับเปลี่ยนลำดับของตัวอักษร
721
-
583
+ const ThaiAlphabet = '_ๅ/-ภถุึคตจขชๆไำพะัีรนยบลฃฟหกดเ้่าสวงผปแอิืทมใฝ%+๑๒๓๔ู฿๕๖๗๘๙๐"ฎฑธํ๊ณฯญฐ,ฅฤฆฏโฌ็๋ษศซ.ฦฬฒ?์ฺฮฉ)('.split("");
584
+ this.shuffleArray(ThaiAlphabet);
722
585
  keys.forEach((key, index) => {
723
- // อัพเดต textContent และ dataset.key ให้ตรงกับค่าใหม่ที่สับเปลี่ยน
724
586
  key.textContent = ThaiAlphabet[index];
725
- key.dataset.key = ThaiAlphabet[index]; // อัพเดต dataset.key ด้วยค่าใหม่
587
+ key.dataset.key = ThaiAlphabet[index];
588
+ });
589
+ }
590
+
591
+ // []
592
+ scrambleSymbols() {
593
+ const keys = document.querySelectorAll(
594
+ ":not([data-key='std']):not([data-key='scr']).key:not([data-key=backspace]"
595
+ );
596
+ const numbers = "@#$%^&*()_+~`{}|\\:'<>?/[]±§¶!€£¥¢©®™℅‰†".split("");
597
+ this.shuffleArray(numbers);
598
+ keys.forEach((key, index) => {
599
+ key.textContent = numbers[index];
600
+ key.dataset.key = numbers[index];
726
601
  });
727
602
  }
728
603
 
729
- // จัดการการลากคีย์บอร์ด
604
+ // [14] จัดการการลากคีย์บอร์ด
730
605
  startDrag(event) {
731
606
  this.isDragging = true;
732
- this.offsetX =
733
- event.clientX - document.getElementById("keyboard").offsetLeft;
734
- this.offsetY =
735
- event.clientY - document.getElementById("keyboard").offsetTop;
607
+ this.offsetX = event.clientX - document.getElementById("keyboard").offsetLeft;
608
+ this.offsetY = event.clientY - document.getElementById("keyboard").offsetTop;
736
609
 
737
- document.addEventListener("mousemove", this.drag.bind(this)); // Use bind to preserve `this` context
610
+ document.addEventListener("mousemove", this.drag.bind(this));
738
611
  document.addEventListener("mouseup", () => {
739
612
  this.isDragging = false;
740
613
  document.removeEventListener("mousemove", this.drag.bind(this));
741
614
  });
742
615
  }
743
616
 
617
+ // [15]
744
618
  drag(event) {
745
619
  if (this.isDragging) {
746
620
  const keyboard = document.getElementById("keyboard");
@@ -748,4 +622,4 @@ export class VirtualKeyboard {
748
622
  keyboard.style.top = `${event.clientY - this.offsetY}px`;
749
623
  }
750
624
  }
751
- }
625
+ }
package/layouts.js CHANGED
@@ -12,43 +12,28 @@ export const layouts = {
12
12
  ["Tab ↹", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\"],
13
13
  ["Caps 🄰", "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "Enter"],
14
14
  ["Shift ⇧", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "Shift ⇧"],
15
- ["Space"],
15
+ ["scrambled", "Space"],
16
16
  ],
17
17
  th: [
18
18
  ["_", "ๅ", "/", "-", "ภ", "ถ", "ุ", "ึ", "ค", "ต", "จ", "ข", "ช", "Backspace"],
19
19
  ["Tab ↹", "ๆ", "ไ", "ำ", "พ", "ะ", "ั", "ี", "ร", "น", "ย", "บ", "ล", "ฃ"],
20
20
  ["Caps 🄰", "ฟ", "ห", "ก", "ด", "เ", "้", "่", "า", "ส", "ว", "ง", "Enter"],
21
21
  ["Shift ⇧", "ผ", "ป", "แ", "อ", "ิ", "ื", "ท", "ม", "ใ", "ฝ", "Shift ⇧"],
22
- ["Space"],
22
+ ["scrambled" ,"Space"],
23
23
  ],
24
24
  numpad: [
25
- ["+", "-", "*", "/"],
26
- ["1", "2", "3", "%"],
27
- ["4", "5", "6", "_"],
25
+ ["scr", "+", "-", "*"],
26
+ ["1", "2", "3", "/"],
27
+ ["4", "5", "6", "%"],
28
28
  ["7", "8", "9", "."],
29
29
  ["(", "0", ")", "="],
30
30
  ["backspace"]
31
31
  ],
32
- scNum: [
33
- ["+", "-", "*", "/"],
34
- ["1", "2", "3", "%"],
35
- ["4", "5", "6", "_"],
36
- ["7", "8", "9", "."],
37
- ["(", "0", ")", "="],
32
+ symbols: [
33
+ ['scr', '@', '#', '$', '%', '^', '&', '*', '(', ')'],
34
+ ['_', '+', '~', '`', '{', '}', '|', '\\', ':', '!'],
35
+ ["'", '<', '>', '?', '/', '[', ']', '±', '§', '¶'],
36
+ ['€', '£', '¥', '¢', '©', '®', '™', '℅', '‰', '†'],
38
37
  ["backspace"]
39
- ],
40
- thSc: [
41
- ["ก", "ข", "ฃ", "ค", "ฅ", "ฆ", "ง", "จ", "ฉ", "ช", "ซ", "ฌ", "Backspace"],
42
- ["ญ", "ฎ", "ฏ", "ฐ", "ฑ", "ฒ", "ณ", "ด", "ต", "ถ", "ท", "ธ", "น"],
43
- ["บ", "ป", "ผ", "ฝ", "พ", "ฟ", "ภ", "ม", "ย", "ร", "ฤ", "Enter"],
44
- ["ล", "ฦ", "ว", "ศ", "ษ", "ส", "ห", "ฬ", "อ", "ฮ"],
45
- ["Space"],
46
- ],
47
- enSc: [
48
- ["`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "="],
49
- ["Tab ↹", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "Backspace"],
50
- ["Caps 🄰", "a", "s", "d", "f", "g", "h", "j", "k", "l", "Enter"],
51
- ["Shift ⇧", "z", "x", "c", "v", "b", "n", "m", "Shift ⇧"],
52
- ["Space"],
53
- ],
54
- };
38
+ ]
39
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js_lis",
3
- "version": "1.0.25",
3
+ "version": "2.0.1",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"