js_lis 1.0.24 → 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.
Files changed (3) hide show
  1. package/VirtualKeyboard.js +293 -303
  2. package/layouts.js +23 -35
  3. package/package.json +1 -1
@@ -2,7 +2,7 @@ import { layouts } from "./layouts.js";
2
2
 
3
3
  export class VirtualKeyboard {
4
4
  constructor() {
5
- this.currentLayout = "en";
5
+ this.currentLayout = "full";
6
6
  this.isVisible = false;
7
7
  this.container = document.getElementById("keyboard-container");
8
8
  this.currentInput = null;
@@ -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,62 +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) {
32
+ case "full":
33
+ return "Full Keyboard";
77
34
  case "en":
78
35
  return "English Keyboard";
79
- case "enSc":
80
- return "English scrambled";
81
36
  case "th":
82
37
  return "Thai keyboard";
83
- case "thSc":
84
- return "Thai scrambled";
85
38
  case "numpad":
86
39
  return "Numpad Keyboard";
87
- case "scNum":
88
- return "Scrambled Keyboard";
89
40
  default:
90
41
  return "Unknown Layout";
91
42
  }
@@ -125,9 +76,10 @@ export class VirtualKeyboard {
125
76
  this.currentInput.classList.add("keyboard-active");
126
77
  }
127
78
 
79
+ // [1]
128
80
  render() {
129
81
  const keyboard = document.createElement("div");
130
- keyboard.className = "virtual-keyboard";
82
+ keyboard.className = `virtual-keyboard ${this.currentLayout}`;
131
83
  keyboard.style.display = this.isVisible ? "block" : "none";
132
84
  keyboard.id = "keyboard";
133
85
 
@@ -142,7 +94,7 @@ export class VirtualKeyboard {
142
94
  layoutSelector.id = "layout-selector";
143
95
  layoutSelector.onchange = (e) => this.changeLayout(e.target.value);
144
96
 
145
- const layouts = ["en", "enSc", "th", "thSc", "numpad", "scNum"];
97
+ const layouts = ["full", "en", "th", "numpad"];
146
98
  layouts.forEach((layout) => {
147
99
  const option = document.createElement("option");
148
100
  option.value = layout;
@@ -160,7 +112,7 @@ export class VirtualKeyboard {
160
112
  const rowElement = document.createElement("div");
161
113
  rowElement.className = "keyboard-row";
162
114
 
163
- row.forEach((key) => {
115
+ row.forEach((key, index) => {
164
116
  const keyElement = document.createElement("button");
165
117
  keyElement.className = "keyboard-key key";
166
118
  keyElement.textContent = key;
@@ -168,6 +120,10 @@ export class VirtualKeyboard {
168
120
 
169
121
  keyElement.dataset.key = key;
170
122
 
123
+ if (index >= row.length - 4) {
124
+ keyElement.classList.add("concat-keys");
125
+ }
126
+
171
127
  if (key === "Space") {
172
128
  keyElement.className += " space";
173
129
  }
@@ -196,24 +152,12 @@ export class VirtualKeyboard {
196
152
  this.container.innerHTML = "";
197
153
  this.container.appendChild(keyboard);
198
154
 
199
- if (this.currentLayout === "scNum") {
200
- this.scrambleKeyboard();
201
- }
202
-
203
- if (this.currentLayout === "enSc") {
204
- this.scrambleEnglishKeys();
205
- }
206
-
207
- if (this.currentLayout === "thSc") {
208
- this.scrambleThaiKeys();
209
- }
210
-
211
155
  keyboard.addEventListener("mousedown", (event) => this.startDrag(event));
212
156
  }
213
157
 
158
+ // [2]
214
159
  async handleKeyPress(keyPressed) {
215
160
  if (!this.currentInput) return;
216
-
217
161
  const start = this.currentInput.selectionStart;
218
162
  const end = this.currentInput.selectionEnd;
219
163
  const value = this.currentInput.value;
@@ -228,23 +172,158 @@ export class VirtualKeyboard {
228
172
  return char.toLowerCase();
229
173
  };
230
174
 
231
- if (!keyPressed) {
232
- console.error("Invalid key pressed.");
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
+ }
233
217
  return;
234
218
  }
235
219
 
236
220
  switch (keyPressed) {
221
+ case "Esc":
222
+ const modals = document.querySelectorAll(".modal");
223
+ if (modals.length === 0) {
224
+ document.exitFullscreen();
225
+ console.warn("No modals found to close.");
226
+ }
227
+ modals.forEach((modal) => {
228
+ modal.classList.add("hidden");
229
+ });
230
+ break;
231
+
232
+ case "F1":
233
+ break;
234
+
235
+ case "F2":
236
+ // เปิดโหมดแก้ไขสำหรับ element ที่เลือก
237
+ const activeElement = document.activeElement;
238
+ if (activeElement && activeElement.contentEditable !== undefined) {
239
+ activeElement.contentEditable = true;
240
+ activeElement.focus();
241
+ console.log(activeElement.contentEditable);
242
+ } else {
243
+ console.warn("No editable element found.");
244
+ }
245
+ break;
246
+
247
+ case "F3":
248
+ // เปิดการค้นหา
249
+ event.preventDefault();
250
+ this.option.openSearch();
251
+ break;
252
+
253
+ case "F4":
254
+ // เปิดเมนูการตั้งค่า
255
+ event.preventDefault();
256
+ this.option.openSettings();
257
+ break;
258
+
259
+ case "F5":
260
+ // รีโหลดหน้าเว็บ (คงเดิม)
261
+ window.location.reload();
262
+ break;
263
+
264
+ case "F6":
265
+ // สลับระหว่างโหมดกลางวัน/กลางคืน
266
+ document.body.classList.toggle("dark-mode");
267
+ break;
268
+
269
+ case "F7":
270
+ break;
271
+
272
+ case "F8":
273
+ break;
274
+
275
+ case "F9":
276
+ break;
277
+
278
+ case "F10":
279
+ break;
280
+
281
+ case "F11":
282
+ if (!document.fullscreenElement) {
283
+ document.documentElement
284
+ .requestFullscreen()
285
+ .catch((err) =>
286
+ console.error("Error attempting to enable fullscreen:", err)
287
+ );
288
+ } else {
289
+ document
290
+ .exitFullscreen()
291
+ .catch((err) =>
292
+ console.error("Error attempting to exit fullscreen:", err)
293
+ );
294
+ }
295
+ break;
296
+
297
+ case "F12":
298
+ break;
299
+
300
+ case "HOME":
301
+ this.currentInput.setSelectionRange(Math.max(0, 0), Math.max(0, 0));
302
+ break;
303
+
304
+ case "END":
305
+ const length = this.currentInput.value.length;
306
+ this.currentInput.setSelectionRange(length, length);
307
+ break;
308
+
237
309
  case "Backspace":
238
310
  case "backspace":
239
311
  if (start === end && start > 0) {
240
- this.currentInput.value =
241
- value.slice(0, start - 1) + value.slice(end);
242
- this.currentInput.selectionStart = this.currentInput.selectionEnd =
243
- start - 1;
312
+ this.currentInput.value = value.slice(0, start - 1) + value.slice(end);
313
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start - 1;
314
+ } else {
315
+ this.currentInput.value = value.slice(0, start) + value.slice(end);
316
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
317
+ }
318
+ break;
319
+
320
+ case "DEL⌦":
321
+ if (start === end && start < value.length) {
322
+ this.currentInput.value = value.slice(0, start) + value.slice(end + 1);
323
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
244
324
  } else {
245
325
  this.currentInput.value = value.slice(0, start) + value.slice(end);
246
- this.currentInput.selectionStart = this.currentInput.selectionEnd =
247
- start;
326
+ this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
248
327
  }
249
328
  break;
250
329
 
@@ -252,290 +331,203 @@ export class VirtualKeyboard {
252
331
  await this.insertText(" ");
253
332
  break;
254
333
 
255
- case "Tab":
334
+ case "Tab":
256
335
  await this.insertText("\t");
257
336
  break;
258
337
 
259
- case 'Enter':
338
+ case "Enter":
260
339
  if (this.currentInput.tagName === "TEXTAREA") {
261
- const start = this.currentInput.selectionStart;
262
- const end = this.currentInput.selectionEnd;
263
- const value = this.currentInput.value;
264
340
  this.currentInput.value = value.slice(0, start) + "\n" + value.slice(end);
265
341
  this.currentInput.setSelectionRange(start + 1, start + 1);
266
- } else if (this.currentInput.tagName === "INPUT" || this.currentInput.type === "password" || this.currentInput.type === "text") {
342
+ } else if (this.currentInput.tagName === "INPUT" || this.currentInput.type === "password" || this.currentInput.type === "text" ) {
267
343
  if (this.currentInput.form) {
268
- const submitButton = this.currentInput.form.querySelector('input[type="submit"], button[type="submit"], button[type="button"], button[onclick]');
269
- if (submitButton) {
270
- submitButton.click();
271
- } else {
272
- this.currentInput.form.submit();
273
- }
344
+ const submitButton = this.currentInput.form.querySelector(
345
+ 'input[type="submit"], button[type="submit"], button[type="button"], button[onclick]'
346
+ );
347
+ if (submitButton) submitButton.click(); else this.currentInput.form.submit();
274
348
  } else {
275
- this.currentInput.value += '\n';
349
+ this.currentInput.value += "\n";
276
350
  }
277
351
  }
278
352
  break;
279
353
 
280
- case "Caps":
354
+ case "Caps 🄰":
281
355
  this.toggleCapsLock();
282
356
  break;
283
357
 
284
- case "Shift":
358
+ case "Shift":
285
359
  this.toggleShift();
286
360
  break;
287
361
 
288
- default:
289
- const encryptedText = await this.encodeText(
290
- convertToCorrectCase(keyPressed)
362
+ case "←":
363
+ this.currentInput.setSelectionRange(
364
+ Math.max(0, start - 1),
365
+ Math.max(0, start - 1)
291
366
  );
292
- await this.insertText(encryptedText);
293
- }
367
+ break;
294
368
 
295
- if (isShiftActive && !isCapsActive) {
296
- this.toggleShift();
369
+ case "→":
370
+ this.currentInput.setSelectionRange(start + 1, start + 1);
371
+ break;
372
+
373
+ case "↑":
374
+ case "↓":
375
+ const text = this.currentInput.value;
376
+ const lines = text.substring(0, start).split("\n");
377
+ const currentLineIndex = lines.length - 1;
378
+ const currentLine = lines[currentLineIndex];
379
+ const columnIndex = start - text.lastIndexOf("\n", start - 1) - 1;
380
+
381
+ if (keyPressed === "↑" && currentLineIndex > 0) {
382
+ const prevLineLength = lines[currentLineIndex - 1].length;
383
+ const newPos = start - currentLine.length - 1 - Math.min(columnIndex, prevLineLength);
384
+ this.currentInput.setSelectionRange(newPos, newPos);
385
+ } else if (keyPressed === "↓" && currentLineIndex < lines.length - 1) {
386
+ const nextLine = lines[currentLineIndex + 1];
387
+ const newPos = start + currentLine.length + 1 + Math.min(columnIndex, nextLine.length);
388
+ this.currentInput.setSelectionRange(newPos, newPos);
389
+ }
390
+ break;
391
+
392
+ default:
393
+ const textvalue = await convertToCorrectCase(keyPressed);
394
+ await this.insertText(textvalue);
297
395
  }
298
396
 
397
+ if (isShiftActive && !isCapsActive) this.toggleShift();
398
+
299
399
  this.currentInput.focus();
300
400
  const event = new Event("input", { bubbles: true });
301
401
  this.currentInput.dispatchEvent(event);
302
- // console.log(this.encodeText(convertToCorrectCase(keyPressed)));
303
- // console.log(keyPressed);
304
402
  }
305
403
 
404
+ // [3]
306
405
  async insertText(text) {
307
406
  const start = this.currentInput.selectionStart;
308
407
  const end = this.currentInput.selectionEnd;
309
- const decodedText = await this.decodeText(text); // ใช้ถอดรหัสก่อนแทรก
310
-
311
- this.currentInput.value =
312
- this.currentInput.value.slice(0, start) +
313
- decodedText +
314
- this.currentInput.value.slice(end);
315
- this.currentInput.selectionStart = this.currentInput.selectionEnd =
316
- start + decodedText.length;
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();
317
418
  }
318
419
 
420
+ // [5]
319
421
  toggleCapsLock() {
320
422
  this.capsLockActive = !this.capsLockActive;
321
- document.querySelectorAll('.key[data-key="Caps"]').forEach((key) => {
423
+
424
+ document.querySelectorAll('.key[data-key="Caps 🄰"]').forEach((key) => {
322
425
  key.classList.toggle("active", this.capsLockActive);
323
426
  key.classList.toggle("bg-gray-400", this.capsLockActive);
324
427
  });
325
428
 
326
429
  document.querySelectorAll(".key").forEach((key) => {
327
- if (key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key)) {
430
+ const isLetter = key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key);
431
+
432
+ if (isLetter) {
328
433
  key.textContent = this.capsLockActive
329
434
  ? key.dataset.key.toUpperCase()
330
435
  : key.dataset.key.toLowerCase();
331
436
  }
437
+ this.updateKeyContent(key, this.capsLockActive);
332
438
  });
333
-
334
- const keyboardKeys = document.querySelectorAll(
335
- ".key:not([data-key='Caps'])"
336
- );
337
- keyboardKeys.forEach((key) => {
338
- const currentChar = key.textContent.trim();
339
- if (
340
- this.capsLockActive &&
341
- this.currentLayout === "th" &&
342
- this.ThaiAlphabetShift[currentChar]
343
- ) {
344
- key.textContent = this.ThaiAlphabetShift[currentChar];
345
- key.dataset.key = this.ThaiAlphabetShift[currentChar];
346
- } else if (
347
- !this.capsLockActive &&
348
- this.currentLayout === "th" &&
349
- Object.values(this.ThaiAlphabetShift).includes(currentChar)
350
- ) {
351
- // เปลี่ยนกลับเมื่อปิด Shift
352
- const originalKey = Object.keys(this.ThaiAlphabetShift).find(
353
- (key) => this.ThaiAlphabetShift[key] === currentChar
354
- );
355
- if (originalKey) {
356
- key.textContent = originalKey;
357
- key.dataset.key = originalKey;
358
- }
359
- }
360
-
361
- if (
362
- this.capsLockActive &&
363
- this.currentLayout === "en" &&
364
- this.EngAlphabetShift[currentChar]
365
- ) {
366
- key.textContent = this.EngAlphabetShift[currentChar];
367
- key.dataset.key = this.EngAlphabetShift[currentChar];
368
- } else if (
369
- !this.capsLockActive &&
370
- this.currentLayout === "en" &&
371
- Object.values(this.EngAlphabetShift).includes(currentChar)
372
- ) {
373
- // เปลี่ยนกลับเมื่อปิด Shift
374
- const originalKey = Object.keys(this.EngAlphabetShift).find(
375
- (key) => this.EngAlphabetShift[key] === currentChar
376
- );
377
- if (originalKey) {
378
- key.textContent = originalKey;
379
- key.dataset.key = originalKey;
380
- }
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;
381
461
  }
382
- });
462
+ }
383
463
  }
384
464
 
465
+ // [6]
385
466
  toggleShift() {
386
467
  if (this.capsLockActive) {
387
468
  return this.toggleCapsLock();
388
469
  }
389
470
 
390
471
  this.shiftActive = !this.shiftActive;
391
- document.querySelectorAll('.key[data-key="Shift"]').forEach((key) => {
472
+ document.querySelectorAll('.key[data-key="Shift"]').forEach((key) => {
392
473
  key.classList.toggle("active", this.shiftActive);
393
474
  key.classList.toggle("bg-gray-400", this.shiftActive);
394
475
  });
395
-
476
+
396
477
  document.querySelectorAll(".key").forEach((key) => {
397
- if (key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key)) {
478
+ const isLetter = key.dataset.key.length === 1 && /[a-zA-Zก-๙]/.test(key.dataset.key);
479
+
480
+ if (isLetter) {
398
481
  key.textContent = this.shiftActive
399
482
  ? key.dataset.key.toUpperCase()
400
483
  : key.dataset.key.toLowerCase();
401
484
  }
485
+ this.updateKeyContent(key, this.shiftActive);
402
486
  });
403
-
404
- const keyboardKeys = document.querySelectorAll(
405
- ".key:not([data-key='Shift'])"
406
- );
407
- keyboardKeys.forEach((key) => {
408
- const currentChar = key.textContent.trim();
409
- if (
410
- this.shiftActive &&
411
- this.currentLayout === "th" &&
412
- this.ThaiAlphabetShift[currentChar]
413
- ) {
414
- key.textContent = this.ThaiAlphabetShift[currentChar];
415
- key.dataset.key = this.ThaiAlphabetShift[currentChar];
416
- } else if (
417
- !this.shiftActive &&
418
- this.currentLayout === "th" &&
419
- Object.values(this.ThaiAlphabetShift).includes(currentChar)
420
- ) {
421
- // เปลี่ยนกลับเมื่อปิด Shift
422
- const originalKey = Object.keys(this.ThaiAlphabetShift).find(
423
- (key) => this.ThaiAlphabetShift[key] === currentChar
424
- );
425
- if (originalKey) {
426
- key.textContent = originalKey;
427
- key.dataset.key = originalKey;
428
- }
429
- }
430
-
431
- if (
432
- this.shiftActive &&
433
- this.currentLayout === "en" &&
434
- this.EngAlphabetShift[currentChar]
435
- ) {
436
- key.textContent = this.EngAlphabetShift[currentChar];
437
- key.dataset.key = this.EngAlphabetShift[currentChar];
438
- } else if (
439
- !this.shiftActive &&
440
- this.currentLayout === "en" &&
441
- Object.values(this.EngAlphabetShift).includes(currentChar)
442
- ) {
443
- // เปลี่ยนกลับเมื่อปิด Shift
444
- const originalKey = Object.keys(this.EngAlphabetShift).find(
445
- (key) => this.EngAlphabetShift[key] === currentChar
446
- );
447
- if (originalKey) {
448
- key.textContent = originalKey;
449
- key.dataset.key = originalKey;
450
- }
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;
451
509
  }
452
- });
510
+ }
453
511
  }
454
512
 
455
- EngAlphabetShift = {
456
- "`": "~",
457
- 1: "!",
458
- 2: "@",
459
- 3: "#",
460
- 4: "$",
461
- 5: "%",
462
- 6: "^",
463
- 7: "&",
464
- 8: "*",
465
- 9: "(",
466
- 0: ")",
467
- "-": "_",
468
- "=": "+",
469
- "[": "{",
470
- "]": "}",
471
- "\\": "|",
472
- ";": ":",
473
- "'": '"',
474
- ",": "<",
475
- ".": ">",
476
- "/": "?",
477
- };
478
-
479
- ThaiAlphabetShift = {
480
- _: "%",
481
- ๅ: "+",
482
- "/": "๑",
483
- "-": "๒",
484
- ภ: "๓",
485
- ถ: "๔",
486
- "ุ": "ู",
487
- "ึ": "฿",
488
- ค: "๕",
489
- ต: "๖",
490
- จ: "๗",
491
- ข: "๘",
492
- ช: "๙",
493
- ๆ: "๐",
494
- ไ: '"',
495
- ำ: "ฎ",
496
- พ: "ฑ",
497
- ะ: "ธ",
498
- "ั": "ํ",
499
- "ี": "๋",
500
- ร: "ณ",
501
- น: "ฯ",
502
- ย: "ญ",
503
- บ: "ฐ",
504
- ล: ",",
505
- ฃ: "ฅ",
506
- ฟ: "ฤ",
507
- ห: "ฆ",
508
- ก: "ฏ",
509
- ด: "โ",
510
- เ: "ฌ",
511
- "้": "็",
512
- "่": "๋",
513
- า: "ษ",
514
- ส: "ศ",
515
- ว: "ซ",
516
- ง: ".",
517
- ผ: "(",
518
- ป: ")",
519
- แ: "ฉ",
520
- อ: "ฮ",
521
- "ิ": "ฺ",
522
- "ื": "์",
523
- ท: "?",
524
- ม: "ฒ",
525
- ใ: "ฬ",
526
- ฝ: "ฦ",
527
- };
513
+ // [7]
514
+ EngAlphabetShift = { "`": "~", 1: "!", 2: "@", 3: "#", 4: "$", 5: "%", 6: "^", 7: "&", 8: "*", 9: "(", 0: ")", "-": "_", "=": "+", "[": "{", "]": "}", "\\": "|", ";": ":", "'": '"', ",": "<", ".": ">", "/": "?", };
515
+ ThaiAlphabetShift = { _: "%", ๅ: "+", "/": "๑", "-": "๒", ภ: "๓", ถ: "๔", "ุ": "ู", "ึ": "฿", ค: "๕", ต: "๖", จ: "๗", ข: "๘", ช: "๙", ๆ: "๐", ไ: '"', ำ: "ฎ", พ: "ฑ", ะ: "ธ", "ั": "ํ", "ี": "๋", ร: "ณ", น: "ฯ", ย: "ญ", บ: "ฐ", ล: ",", ฃ: "ฅ", ฟ: "ฤ", ห: "ฆ", ก: "ฏ", ด: "โ", เ: "ฌ", "้": "็", "่": "๋", า: "ษ", ส: "ศ", ว: "ซ", ง: ".", ผ: "(", ป: ")", แ: "ฉ", อ: "ฮ", "ิ": "ฺ", "ื": "์", ท: "?", ม: "ฒ", ใ: "ฬ", ฝ: "ฦ"};
516
+ FullAlphabetShift = { "[": "{", "]": "}", "\\": "|", ";": ":", "'": '"', ",": "<", ".": ">", "/": "?", };
528
517
 
518
+ // [8]
529
519
  toggle() {
530
520
  this.isVisible = !this.isVisible;
531
521
  this.render();
532
522
  }
533
523
 
524
+ // [9]
534
525
  changeLayout(layout) {
535
526
  this.currentLayout = layout;
536
527
  this.render();
537
528
  }
538
529
 
530
+ // [10]
539
531
  shuffleArray(array) {
540
532
  for (let i = array.length - 1; i > 0; i--) {
541
533
  const j = Math.floor(Math.random() * (i + 1));
@@ -543,11 +535,12 @@ export class VirtualKeyboard {
543
535
  }
544
536
  }
545
537
 
538
+ // [11]
546
539
  scrambleKeyboard() {
547
540
  const keys = document.querySelectorAll(
548
- ".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='00'])"
541
+ ":not([data-key='std']):not([data-key='scr']).key:not([data-key=backspace]"
549
542
  );
550
- const numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
543
+ const numbers = "1234567890-=+%/*.()".split("");
551
544
  this.shuffleArray(numbers);
552
545
  keys.forEach((key, index) => {
553
546
  key.textContent = numbers[index];
@@ -555,11 +548,12 @@ export class VirtualKeyboard {
555
548
  });
556
549
  }
557
550
 
551
+ // [12]
558
552
  scrambleEnglishKeys() {
559
553
  const keys = document.querySelectorAll(
560
- ".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='='])"
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 ↹'])"
561
555
  );
562
- const englishAlphabet = "abcdefghijklmnopqrstuvwxyz".split("");
556
+ const englishAlphabet = "abcdefghijklmnopqrstuvwxyz/.,';\\][`1234567890-=".split("");
563
557
  this.shuffleArray(englishAlphabet);
564
558
  keys.forEach((key, index) => {
565
559
  key.textContent = englishAlphabet[index];
@@ -567,37 +561,33 @@ export class VirtualKeyboard {
567
561
  });
568
562
  }
569
563
 
564
+ // [13]
570
565
  scrambleThaiKeys() {
571
566
  const keys = document.querySelectorAll(
572
- ".key:not([data-key='Backspace']):not([data-key='Caps']):not([data-key='Shift']):not([data-key='Enter']):not([data-key='Space'])"
573
- );
574
- const ThaiAlphabet = "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮ".split(
575
- ""
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 ↹'])"
576
568
  );
577
- this.shuffleArray(ThaiAlphabet); // สับเปลี่ยนลำดับของตัวอักษร
578
-
569
+ const ThaiAlphabet = '_ๅ/-ภถุึคตจขชๆไำพะัีรนยบลฃฟหกดเ้่าสวงผปแอิืทมใฝ%+๑๒๓๔ู฿๕๖๗๘๙๐"ฎฑธํ๊ณฯญฐ,ฅฤฆฏโฌ็๋ษศซ.ฦฬฒ?์ฺฮฉ)('.split("");
570
+ this.shuffleArray(ThaiAlphabet);
579
571
  keys.forEach((key, index) => {
580
- // อัพเดต textContent และ dataset.key ให้ตรงกับค่าใหม่ที่สับเปลี่ยน
581
572
  key.textContent = ThaiAlphabet[index];
582
- key.dataset.key = ThaiAlphabet[index]; // อัพเดต dataset.key ด้วยค่าใหม่
573
+ key.dataset.key = ThaiAlphabet[index];
583
574
  });
584
575
  }
585
576
 
586
- // จัดการการลากคีย์บอร์ด
577
+ // [14] จัดการการลากคีย์บอร์ด
587
578
  startDrag(event) {
588
579
  this.isDragging = true;
589
- this.offsetX =
590
- event.clientX - document.getElementById("keyboard").offsetLeft;
591
- this.offsetY =
592
- event.clientY - document.getElementById("keyboard").offsetTop;
580
+ this.offsetX = event.clientX - document.getElementById("keyboard").offsetLeft;
581
+ this.offsetY = event.clientY - document.getElementById("keyboard").offsetTop;
593
582
 
594
- document.addEventListener("mousemove", this.drag.bind(this)); // Use bind to preserve `this` context
583
+ document.addEventListener("mousemove", this.drag.bind(this));
595
584
  document.addEventListener("mouseup", () => {
596
585
  this.isDragging = false;
597
586
  document.removeEventListener("mousemove", this.drag.bind(this));
598
587
  });
599
588
  }
600
589
 
590
+ // [15]
601
591
  drag(event) {
602
592
  if (this.isDragging) {
603
593
  const keyboard = document.getElementById("keyboard");
package/layouts.js CHANGED
@@ -1,44 +1,32 @@
1
1
  export const layouts = {
2
+ full: [
3
+ ["Esc", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "DEL⌦", "HOME", "END"],
4
+ ["`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "Backspace"].concat(["+", "-", "*","/"]),
5
+ ["Tab ↹", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\"].concat(["7", "8", "9", "%"]),
6
+ ["Caps 🄰", "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "Enter"].concat(["4", "5", "6", "_"]),
7
+ ["Shift ⇧", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "Shift ⇧", "↑"].concat(["1", "2", "3", "="]),
8
+ ["Space", "←", "↓", "→"].concat(["0", "."]),
9
+ ],
2
10
  en: [
3
11
  ["`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "-", "=", "Backspace"],
4
- ["Tab", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\"],
5
- ["Caps", "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "Enter"],
6
- ["Shift", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "Shift"],
7
- ["Space"],
12
+ ["Tab", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "[", "]", "\\"],
13
+ ["Caps 🄰", "a", "s", "d", "f", "g", "h", "j", "k", "l", ";", "'", "Enter"],
14
+ ["Shift", "z", "x", "c", "v", "b", "n", "m", ",", ".", "/", "Shift"],
15
+ ["scrambled", "Space"],
8
16
  ],
9
17
  th: [
10
18
  ["_", "ๅ", "/", "-", "ภ", "ถ", "ุ", "ึ", "ค", "ต", "จ", "ข", "ช", "Backspace"],
11
- ["Tab", "ๆ", "ไ", "ำ", "พ", "ะ", "ั", "ี", "ร", "น", "ย", "บ", "ล", "ฃ"],
12
- ["Caps", "ฟ", "ห", "ก", "ด", "เ", "้", "่", "า", "ส", "ว", "ง", "Enter"],
13
- ["Shift", "ผ", "ป", "แ", "อ", "ิ", "ื", "ท", "ม", "ใ", "ฝ", "Shift"],
14
- ["Space"],
19
+ ["Tab", "ๆ", "ไ", "ำ", "พ", "ะ", "ั", "ี", "ร", "น", "ย", "บ", "ล", "ฃ"],
20
+ ["Caps 🄰", "ฟ", "ห", "ก", "ด", "เ", "้", "่", "า", "ส", "ว", "ง", "Enter"],
21
+ ["Shift", "ผ", "ป", "แ", "อ", "ิ", "ื", "ท", "ม", "ใ", "ฝ", "Shift"],
22
+ ["scrambled" ,"Space"],
15
23
  ],
16
24
  numpad: [
17
- ["+", "-", "*", "/"],
18
- ["1", "2", "3", "%"],
19
- ["4", "5", "6", "."],
20
- ["7", "8", "9", "="],
21
- ["00", "0", "backspace"],
22
- ],
23
- scNum: [
24
- ["+", "-", "*", "/"],
25
- ["1", "2", "3", "%"],
26
- ["4", "5", "6", "."],
27
- ["7", "8", "9", "="],
28
- ["00", "0", "backspace"],
29
- ],
30
- thSc: [
31
- ["ก", "ข", "ฃ", "ค", "ฅ", "ฆ", "ง", "จ", "ฉ", "ช", "ซ", "ฌ", "Backspace"],
32
- ["ญ", "ฎ", "ฏ", "ฐ", "ฑ", "ฒ", "ณ", "ด", "ต", "ถ", "ท", "ธ", "น"],
33
- ["บ", "ป", "ผ", "ฝ", "พ", "ฟ", "ภ", "ม", "ย", "ร", "ฤ", "Enter"],
34
- ["ล", "ฦ", "ว", "ศ", "ษ", "ส", "ห", "ฬ", "อ", "ฮ"],
35
- ["Space"],
36
- ],
37
- enSc: [
38
- ["`", "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "="],
39
- ["Tab", "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "Backspace"],
40
- ["Caps", "a", "s", "d", "f", "g", "h", "j", "k", "l", "Enter"],
41
- ["Shift", "z", "x", "c", "v", "b", "n", "m", "Shift"],
42
- ["Space"],
43
- ],
25
+ ["scr", "+", "-", "*"],
26
+ ["1", "2", "3", "/"],
27
+ ["4", "5", "6", "%"],
28
+ ["7", "8", "9", "."],
29
+ ["(", "0", ")", "="],
30
+ ["backspace"]
31
+ ]
44
32
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js_lis",
3
- "version": "1.0.24",
3
+ "version": "2.0.0",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"