js_lis 1.0.25 → 2.0.0
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.
- package/VirtualKeyboard.js +158 -311
- package/layouts.js +6 -28
- package/package.json +1 -1
package/VirtualKeyboard.js
CHANGED
|
@@ -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,16 @@ 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";
|
|
91
40
|
default:
|
|
92
41
|
return "Unknown Layout";
|
|
93
42
|
}
|
|
@@ -127,6 +76,7 @@ export class VirtualKeyboard {
|
|
|
127
76
|
this.currentInput.classList.add("keyboard-active");
|
|
128
77
|
}
|
|
129
78
|
|
|
79
|
+
// [1]
|
|
130
80
|
render() {
|
|
131
81
|
const keyboard = document.createElement("div");
|
|
132
82
|
keyboard.className = `virtual-keyboard ${this.currentLayout}`;
|
|
@@ -144,7 +94,7 @@ export class VirtualKeyboard {
|
|
|
144
94
|
layoutSelector.id = "layout-selector";
|
|
145
95
|
layoutSelector.onchange = (e) => this.changeLayout(e.target.value);
|
|
146
96
|
|
|
147
|
-
const layouts = ["full", "en", "
|
|
97
|
+
const layouts = ["full", "en", "th", "numpad"];
|
|
148
98
|
layouts.forEach((layout) => {
|
|
149
99
|
const option = document.createElement("option");
|
|
150
100
|
option.value = layout;
|
|
@@ -202,24 +152,12 @@ export class VirtualKeyboard {
|
|
|
202
152
|
this.container.innerHTML = "";
|
|
203
153
|
this.container.appendChild(keyboard);
|
|
204
154
|
|
|
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
155
|
keyboard.addEventListener("mousedown", (event) => this.startDrag(event));
|
|
218
156
|
}
|
|
219
157
|
|
|
158
|
+
// [2]
|
|
220
159
|
async handleKeyPress(keyPressed) {
|
|
221
160
|
if (!this.currentInput) return;
|
|
222
|
-
|
|
223
161
|
const start = this.currentInput.selectionStart;
|
|
224
162
|
const end = this.currentInput.selectionEnd;
|
|
225
163
|
const value = this.currentInput.value;
|
|
@@ -234,21 +172,60 @@ export class VirtualKeyboard {
|
|
|
234
172
|
return char.toLowerCase();
|
|
235
173
|
};
|
|
236
174
|
|
|
237
|
-
if (!keyPressed)
|
|
238
|
-
|
|
175
|
+
if (!keyPressed) return console.error("Invalid key pressed.");
|
|
176
|
+
|
|
177
|
+
if (keyPressed === "scr" || keyPressed === "scrambled") {
|
|
178
|
+
if (this.currentLayout === "en") {
|
|
179
|
+
if (this.isScrambled) {
|
|
180
|
+
this.unscrambleEnglishKeys();
|
|
181
|
+
} else {
|
|
182
|
+
this.scrambleEnglishKeys();
|
|
183
|
+
}
|
|
184
|
+
this.isScrambled = !this.isScrambled;
|
|
185
|
+
document
|
|
186
|
+
.querySelectorAll('.key[data-key="scrambled"]')
|
|
187
|
+
.forEach((key) => {
|
|
188
|
+
key.classList.toggle("active", this.isScrambled);
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (this.currentLayout === "th") {
|
|
193
|
+
if (this.isScrambled) {
|
|
194
|
+
this.unscrambleEnglishKeys();
|
|
195
|
+
} else {
|
|
196
|
+
this.scrambleThaiKeys();
|
|
197
|
+
}
|
|
198
|
+
this.isScrambled = !this.isScrambled;
|
|
199
|
+
document
|
|
200
|
+
.querySelectorAll('.key[data-key="scrambled"]')
|
|
201
|
+
.forEach((key) => {
|
|
202
|
+
key.classList.toggle("active", this.isScrambled);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (this.currentLayout === "numpad") {
|
|
207
|
+
if (this.isScrambled) {
|
|
208
|
+
this.unscrambleEnglishKeys();
|
|
209
|
+
} else {
|
|
210
|
+
this.scrambleKeyboard();
|
|
211
|
+
}
|
|
212
|
+
this.isScrambled = !this.isScrambled;
|
|
213
|
+
document.querySelectorAll('.key[data-key="scr"]').forEach((key) => {
|
|
214
|
+
key.classList.toggle("active", this.isScrambled);
|
|
215
|
+
});
|
|
216
|
+
}
|
|
239
217
|
return;
|
|
240
218
|
}
|
|
241
219
|
|
|
242
220
|
switch (keyPressed) {
|
|
243
221
|
case "Esc":
|
|
244
|
-
// ปิดหน้าต่างป๊อปอัพหรือยกเลิกการทำงานปัจจุบัน
|
|
245
222
|
const modals = document.querySelectorAll(".modal");
|
|
246
223
|
if (modals.length === 0) {
|
|
247
224
|
document.exitFullscreen();
|
|
248
225
|
console.warn("No modals found to close.");
|
|
249
226
|
}
|
|
250
227
|
modals.forEach((modal) => {
|
|
251
|
-
modal.classList.add("hidden");
|
|
228
|
+
modal.classList.add("hidden");
|
|
252
229
|
});
|
|
253
230
|
break;
|
|
254
231
|
|
|
@@ -332,27 +309,21 @@ export class VirtualKeyboard {
|
|
|
332
309
|
case "Backspace":
|
|
333
310
|
case "backspace":
|
|
334
311
|
if (start === end && start > 0) {
|
|
335
|
-
this.currentInput.value =
|
|
336
|
-
|
|
337
|
-
this.currentInput.selectionStart = this.currentInput.selectionEnd =
|
|
338
|
-
start - 1;
|
|
312
|
+
this.currentInput.value = value.slice(0, start - 1) + value.slice(end);
|
|
313
|
+
this.currentInput.selectionStart = this.currentInput.selectionEnd = start - 1;
|
|
339
314
|
} else {
|
|
340
315
|
this.currentInput.value = value.slice(0, start) + value.slice(end);
|
|
341
|
-
this.currentInput.selectionStart = this.currentInput.selectionEnd =
|
|
342
|
-
start;
|
|
316
|
+
this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
|
|
343
317
|
}
|
|
344
318
|
break;
|
|
345
319
|
|
|
346
320
|
case "DEL⌦":
|
|
347
321
|
if (start === end && start < value.length) {
|
|
348
|
-
this.currentInput.value =
|
|
349
|
-
|
|
350
|
-
this.currentInput.selectionStart = this.currentInput.selectionEnd =
|
|
351
|
-
start;
|
|
322
|
+
this.currentInput.value = value.slice(0, start) + value.slice(end + 1);
|
|
323
|
+
this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
|
|
352
324
|
} else {
|
|
353
325
|
this.currentInput.value = value.slice(0, start) + value.slice(end);
|
|
354
|
-
this.currentInput.selectionStart = this.currentInput.selectionEnd =
|
|
355
|
-
start;
|
|
326
|
+
this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
|
|
356
327
|
}
|
|
357
328
|
break;
|
|
358
329
|
|
|
@@ -366,23 +337,14 @@ export class VirtualKeyboard {
|
|
|
366
337
|
|
|
367
338
|
case "Enter":
|
|
368
339
|
if (this.currentInput.tagName === "TEXTAREA") {
|
|
369
|
-
this.currentInput.value =
|
|
370
|
-
value.slice(0, start) + "\n" + value.slice(end);
|
|
340
|
+
this.currentInput.value = value.slice(0, start) + "\n" + value.slice(end);
|
|
371
341
|
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
|
-
) {
|
|
342
|
+
} else if (this.currentInput.tagName === "INPUT" || this.currentInput.type === "password" || this.currentInput.type === "text" ) {
|
|
377
343
|
if (this.currentInput.form) {
|
|
378
344
|
const submitButton = this.currentInput.form.querySelector(
|
|
379
345
|
'input[type="submit"], button[type="submit"], button[type="button"], button[onclick]'
|
|
380
346
|
);
|
|
381
|
-
if (submitButton)
|
|
382
|
-
submitButton.click();
|
|
383
|
-
} else {
|
|
384
|
-
this.currentInput.form.submit();
|
|
385
|
-
}
|
|
347
|
+
if (submitButton) submitButton.click(); else this.currentInput.form.submit();
|
|
386
348
|
} else {
|
|
387
349
|
this.currentInput.value += "\n";
|
|
388
350
|
}
|
|
@@ -418,267 +380,154 @@ export class VirtualKeyboard {
|
|
|
418
380
|
|
|
419
381
|
if (keyPressed === "↑" && currentLineIndex > 0) {
|
|
420
382
|
const prevLineLength = lines[currentLineIndex - 1].length;
|
|
421
|
-
const newPos =
|
|
422
|
-
start -
|
|
423
|
-
currentLine.length -
|
|
424
|
-
1 -
|
|
425
|
-
Math.min(columnIndex, prevLineLength);
|
|
383
|
+
const newPos = start - currentLine.length - 1 - Math.min(columnIndex, prevLineLength);
|
|
426
384
|
this.currentInput.setSelectionRange(newPos, newPos);
|
|
427
385
|
} else if (keyPressed === "↓" && currentLineIndex < lines.length - 1) {
|
|
428
386
|
const nextLine = lines[currentLineIndex + 1];
|
|
429
|
-
const newPos =
|
|
430
|
-
start +
|
|
431
|
-
currentLine.length +
|
|
432
|
-
1 +
|
|
433
|
-
Math.min(columnIndex, nextLine.length);
|
|
387
|
+
const newPos = start + currentLine.length + 1 + Math.min(columnIndex, nextLine.length);
|
|
434
388
|
this.currentInput.setSelectionRange(newPos, newPos);
|
|
435
389
|
}
|
|
436
390
|
break;
|
|
437
391
|
|
|
438
392
|
default:
|
|
439
|
-
const
|
|
440
|
-
|
|
441
|
-
);
|
|
442
|
-
await this.insertText(encryptedText);
|
|
393
|
+
const textvalue = await convertToCorrectCase(keyPressed);
|
|
394
|
+
await this.insertText(textvalue);
|
|
443
395
|
}
|
|
444
396
|
|
|
445
|
-
if (isShiftActive && !isCapsActive)
|
|
446
|
-
this.toggleShift();
|
|
447
|
-
}
|
|
397
|
+
if (isShiftActive && !isCapsActive) this.toggleShift();
|
|
448
398
|
|
|
449
399
|
this.currentInput.focus();
|
|
450
400
|
const event = new Event("input", { bubbles: true });
|
|
451
401
|
this.currentInput.dispatchEvent(event);
|
|
452
402
|
}
|
|
453
403
|
|
|
404
|
+
// [3]
|
|
454
405
|
async insertText(text) {
|
|
455
406
|
const start = this.currentInput.selectionStart;
|
|
456
407
|
const end = this.currentInput.selectionEnd;
|
|
457
|
-
const
|
|
458
|
-
|
|
459
|
-
this.currentInput.value =
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
408
|
+
const textvalue = text;
|
|
409
|
+
|
|
410
|
+
this.currentInput.value = this.currentInput.value.slice(0, start) + textvalue + this.currentInput.value.slice(end);
|
|
411
|
+
this.currentInput.selectionStart = this.currentInput.selectionEnd = start + textvalue.length;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// [4]
|
|
415
|
+
unscrambleEnglishKeys() {
|
|
416
|
+
this.keys = this.originalKeys;
|
|
417
|
+
this.render();
|
|
465
418
|
}
|
|
466
419
|
|
|
420
|
+
// [5]
|
|
467
421
|
toggleCapsLock() {
|
|
468
422
|
this.capsLockActive = !this.capsLockActive;
|
|
423
|
+
|
|
469
424
|
document.querySelectorAll('.key[data-key="Caps 🄰"]').forEach((key) => {
|
|
470
425
|
key.classList.toggle("active", this.capsLockActive);
|
|
471
426
|
key.classList.toggle("bg-gray-400", this.capsLockActive);
|
|
472
427
|
});
|
|
473
428
|
|
|
474
429
|
document.querySelectorAll(".key").forEach((key) => {
|
|
475
|
-
|
|
430
|
+
const isLetter = key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key);
|
|
431
|
+
|
|
432
|
+
if (isLetter) {
|
|
476
433
|
key.textContent = this.capsLockActive
|
|
477
434
|
? key.dataset.key.toUpperCase()
|
|
478
435
|
: key.dataset.key.toLowerCase();
|
|
479
436
|
}
|
|
437
|
+
this.updateKeyContent(key, this.capsLockActive);
|
|
480
438
|
});
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
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
|
-
}
|
|
439
|
+
}
|
|
440
|
+
updateKeyContent(key, capsLockActive) {
|
|
441
|
+
const currentChar = key.textContent.trim();
|
|
442
|
+
|
|
443
|
+
const layouts = {
|
|
444
|
+
th: this.ThaiAlphabetShift,
|
|
445
|
+
en: this.EngAlphabetShift,
|
|
446
|
+
enSc: this.EngAlphabetShift,
|
|
447
|
+
full: this.FullAlphabetShift,
|
|
448
|
+
};
|
|
449
|
+
const layout = layouts[this.currentLayout];
|
|
450
|
+
|
|
451
|
+
if (!layout) return;
|
|
452
|
+
|
|
453
|
+
if (capsLockActive && layout[currentChar]) {
|
|
454
|
+
key.textContent = layout[currentChar];
|
|
455
|
+
key.dataset.key = layout[currentChar];
|
|
456
|
+
} else if (!capsLockActive && Object.values(layout).includes(currentChar)) {
|
|
457
|
+
const originalKey = Object.keys(layout).find((k) => layout[k] === currentChar);
|
|
458
|
+
if (originalKey) {
|
|
459
|
+
key.textContent = originalKey;
|
|
460
|
+
key.dataset.key = originalKey;
|
|
528
461
|
}
|
|
529
|
-
}
|
|
462
|
+
}
|
|
530
463
|
}
|
|
531
464
|
|
|
465
|
+
// [6]
|
|
532
466
|
toggleShift() {
|
|
467
|
+
if (this.capsLockActive) {
|
|
468
|
+
return this.toggleCapsLock();
|
|
469
|
+
}
|
|
470
|
+
|
|
533
471
|
this.shiftActive = !this.shiftActive;
|
|
534
472
|
document.querySelectorAll('.key[data-key="Shift ⇧"]').forEach((key) => {
|
|
535
473
|
key.classList.toggle("active", this.shiftActive);
|
|
474
|
+
key.classList.toggle("bg-gray-400", this.shiftActive);
|
|
536
475
|
});
|
|
537
|
-
|
|
476
|
+
|
|
538
477
|
document.querySelectorAll(".key").forEach((key) => {
|
|
539
|
-
|
|
478
|
+
const isLetter = key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key);
|
|
479
|
+
|
|
480
|
+
if (isLetter) {
|
|
540
481
|
key.textContent = this.shiftActive
|
|
541
482
|
? key.dataset.key.toUpperCase()
|
|
542
483
|
: key.dataset.key.toLowerCase();
|
|
543
484
|
}
|
|
485
|
+
this.updateKeyContent(key, this.shiftActive);
|
|
544
486
|
});
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
)
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
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
|
-
}
|
|
487
|
+
}
|
|
488
|
+
updateKeyContent(key, shiftActive) {
|
|
489
|
+
const currentChar = key.textContent.trim();
|
|
490
|
+
|
|
491
|
+
const layouts = {
|
|
492
|
+
th: this.ThaiAlphabetShift,
|
|
493
|
+
en: this.EngAlphabetShift,
|
|
494
|
+
enSc: this.EngAlphabetShift,
|
|
495
|
+
full: this.FullAlphabetShift,
|
|
496
|
+
};
|
|
497
|
+
const layout = layouts[this.currentLayout];
|
|
498
|
+
|
|
499
|
+
if (!layout) return;
|
|
500
|
+
|
|
501
|
+
if (shiftActive && layout[currentChar]) {
|
|
502
|
+
key.textContent = layout[currentChar];
|
|
503
|
+
key.dataset.key = layout[currentChar];
|
|
504
|
+
} else if (!shiftActive && Object.values(layout).includes(currentChar)) {
|
|
505
|
+
const originalKey = Object.keys(layout).find((k) => layout[k] === currentChar);
|
|
506
|
+
if (originalKey) {
|
|
507
|
+
key.textContent = originalKey;
|
|
508
|
+
key.dataset.key = originalKey;
|
|
594
509
|
}
|
|
595
|
-
}
|
|
510
|
+
}
|
|
596
511
|
}
|
|
597
512
|
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
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
|
-
};
|
|
513
|
+
// [7]
|
|
514
|
+
EngAlphabetShift = { "`": "~", 1: "!", 2: "@", 3: "#", 4: "$", 5: "%", 6: "^", 7: "&", 8: "*", 9: "(", 0: ")", "-": "_", "=": "+", "[": "{", "]": "}", "\\": "|", ";": ":", "'": '"', ",": "<", ".": ">", "/": "?", };
|
|
515
|
+
ThaiAlphabetShift = { _: "%", ๅ: "+", "/": "๑", "-": "๒", ภ: "๓", ถ: "๔", "ุ": "ู", "ึ": "฿", ค: "๕", ต: "๖", จ: "๗", ข: "๘", ช: "๙", ๆ: "๐", ไ: '"', ำ: "ฎ", พ: "ฑ", ะ: "ธ", "ั": "ํ", "ี": "๋", ร: "ณ", น: "ฯ", ย: "ญ", บ: "ฐ", ล: ",", ฃ: "ฅ", ฟ: "ฤ", ห: "ฆ", ก: "ฏ", ด: "โ", เ: "ฌ", "้": "็", "่": "๋", า: "ษ", ส: "ศ", ว: "ซ", ง: ".", ผ: "(", ป: ")", แ: "ฉ", อ: "ฮ", "ิ": "ฺ", "ื": "์", ท: "?", ม: "ฒ", ใ: "ฬ", ฝ: "ฦ"};
|
|
516
|
+
FullAlphabetShift = { "[": "{", "]": "}", "\\": "|", ";": ":", "'": '"', ",": "<", ".": ">", "/": "?", };
|
|
671
517
|
|
|
518
|
+
// [8]
|
|
672
519
|
toggle() {
|
|
673
520
|
this.isVisible = !this.isVisible;
|
|
674
521
|
this.render();
|
|
675
522
|
}
|
|
676
523
|
|
|
524
|
+
// [9]
|
|
677
525
|
changeLayout(layout) {
|
|
678
526
|
this.currentLayout = layout;
|
|
679
527
|
this.render();
|
|
680
528
|
}
|
|
681
529
|
|
|
530
|
+
// [10]
|
|
682
531
|
shuffleArray(array) {
|
|
683
532
|
for (let i = array.length - 1; i > 0; i--) {
|
|
684
533
|
const j = Math.floor(Math.random() * (i + 1));
|
|
@@ -686,11 +535,12 @@ export class VirtualKeyboard {
|
|
|
686
535
|
}
|
|
687
536
|
}
|
|
688
537
|
|
|
538
|
+
// [11]
|
|
689
539
|
scrambleKeyboard() {
|
|
690
540
|
const keys = document.querySelectorAll(
|
|
691
|
-
"
|
|
541
|
+
":not([data-key='std']):not([data-key='scr']).key:not([data-key=backspace]"
|
|
692
542
|
);
|
|
693
|
-
const numbers =
|
|
543
|
+
const numbers = "1234567890-=+%/*.()".split("");
|
|
694
544
|
this.shuffleArray(numbers);
|
|
695
545
|
keys.forEach((key, index) => {
|
|
696
546
|
key.textContent = numbers[index];
|
|
@@ -698,11 +548,12 @@ export class VirtualKeyboard {
|
|
|
698
548
|
});
|
|
699
549
|
}
|
|
700
550
|
|
|
551
|
+
// [12]
|
|
701
552
|
scrambleEnglishKeys() {
|
|
702
553
|
const keys = document.querySelectorAll(
|
|
703
|
-
".key:not([data-key='
|
|
554
|
+
".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
555
|
);
|
|
705
|
-
const englishAlphabet = "abcdefghijklmnopqrstuvwxyz".split("");
|
|
556
|
+
const englishAlphabet = "abcdefghijklmnopqrstuvwxyz/.,';\\][`1234567890-=".split("");
|
|
706
557
|
this.shuffleArray(englishAlphabet);
|
|
707
558
|
keys.forEach((key, index) => {
|
|
708
559
|
key.textContent = englishAlphabet[index];
|
|
@@ -710,37 +561,33 @@ export class VirtualKeyboard {
|
|
|
710
561
|
});
|
|
711
562
|
}
|
|
712
563
|
|
|
564
|
+
// [13]
|
|
713
565
|
scrambleThaiKeys() {
|
|
714
566
|
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'])"
|
|
567
|
+
".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 ↹'])"
|
|
716
568
|
);
|
|
717
|
-
const ThaiAlphabet = "
|
|
718
|
-
|
|
719
|
-
);
|
|
720
|
-
this.shuffleArray(ThaiAlphabet); // สับเปลี่ยนลำดับของตัวอักษร
|
|
721
|
-
|
|
569
|
+
const ThaiAlphabet = '_ๅ/-ภถุึคตจขชๆไำพะัีรนยบลฃฟหกดเ้่าสวงผปแอิืทมใฝ%+๑๒๓๔ู฿๕๖๗๘๙๐"ฎฑธํ๊ณฯญฐ,ฅฤฆฏโฌ็๋ษศซ.ฦฬฒ?์ฺฮฉ)('.split("");
|
|
570
|
+
this.shuffleArray(ThaiAlphabet);
|
|
722
571
|
keys.forEach((key, index) => {
|
|
723
|
-
// อัพเดต textContent และ dataset.key ให้ตรงกับค่าใหม่ที่สับเปลี่ยน
|
|
724
572
|
key.textContent = ThaiAlphabet[index];
|
|
725
|
-
key.dataset.key = ThaiAlphabet[index];
|
|
573
|
+
key.dataset.key = ThaiAlphabet[index];
|
|
726
574
|
});
|
|
727
575
|
}
|
|
728
576
|
|
|
729
|
-
// จัดการการลากคีย์บอร์ด
|
|
577
|
+
// [14] จัดการการลากคีย์บอร์ด
|
|
730
578
|
startDrag(event) {
|
|
731
579
|
this.isDragging = true;
|
|
732
|
-
this.offsetX =
|
|
733
|
-
|
|
734
|
-
this.offsetY =
|
|
735
|
-
event.clientY - document.getElementById("keyboard").offsetTop;
|
|
580
|
+
this.offsetX = event.clientX - document.getElementById("keyboard").offsetLeft;
|
|
581
|
+
this.offsetY = event.clientY - document.getElementById("keyboard").offsetTop;
|
|
736
582
|
|
|
737
|
-
document.addEventListener("mousemove", this.drag.bind(this));
|
|
583
|
+
document.addEventListener("mousemove", this.drag.bind(this));
|
|
738
584
|
document.addEventListener("mouseup", () => {
|
|
739
585
|
this.isDragging = false;
|
|
740
586
|
document.removeEventListener("mousemove", this.drag.bind(this));
|
|
741
587
|
});
|
|
742
588
|
}
|
|
743
589
|
|
|
590
|
+
// [15]
|
|
744
591
|
drag(event) {
|
|
745
592
|
if (this.isDragging) {
|
|
746
593
|
const keyboard = document.getElementById("keyboard");
|
package/layouts.js
CHANGED
|
@@ -12,43 +12,21 @@ 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
|
-
]
|
|
32
|
-
scNum: [
|
|
33
|
-
["+", "-", "*", "/"],
|
|
34
|
-
["1", "2", "3", "%"],
|
|
35
|
-
["4", "5", "6", "_"],
|
|
36
|
-
["7", "8", "9", "."],
|
|
37
|
-
["(", "0", ")", "="],
|
|
38
|
-
["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
|
-
],
|
|
31
|
+
]
|
|
54
32
|
};
|