js_lis 1.0.24 → 1.0.25

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.
@@ -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;
@@ -74,6 +74,8 @@ export class VirtualKeyboard {
74
74
 
75
75
  getLayoutName(layout) {
76
76
  switch (layout) {
77
+ case "full":
78
+ return "Full Keyboard";
77
79
  case "en":
78
80
  return "English Keyboard";
79
81
  case "enSc":
@@ -127,7 +129,7 @@ export class VirtualKeyboard {
127
129
 
128
130
  render() {
129
131
  const keyboard = document.createElement("div");
130
- keyboard.className = "virtual-keyboard";
132
+ keyboard.className = `virtual-keyboard ${this.currentLayout}`;
131
133
  keyboard.style.display = this.isVisible ? "block" : "none";
132
134
  keyboard.id = "keyboard";
133
135
 
@@ -142,7 +144,7 @@ export class VirtualKeyboard {
142
144
  layoutSelector.id = "layout-selector";
143
145
  layoutSelector.onchange = (e) => this.changeLayout(e.target.value);
144
146
 
145
- const layouts = ["en", "enSc", "th", "thSc", "numpad", "scNum"];
147
+ const layouts = ["full", "en", "enSc", "th", "thSc", "numpad", "scNum"];
146
148
  layouts.forEach((layout) => {
147
149
  const option = document.createElement("option");
148
150
  option.value = layout;
@@ -160,7 +162,7 @@ export class VirtualKeyboard {
160
162
  const rowElement = document.createElement("div");
161
163
  rowElement.className = "keyboard-row";
162
164
 
163
- row.forEach((key) => {
165
+ row.forEach((key, index) => {
164
166
  const keyElement = document.createElement("button");
165
167
  keyElement.className = "keyboard-key key";
166
168
  keyElement.textContent = key;
@@ -168,6 +170,10 @@ export class VirtualKeyboard {
168
170
 
169
171
  keyElement.dataset.key = key;
170
172
 
173
+ if (index >= row.length - 4) {
174
+ keyElement.classList.add("concat-keys");
175
+ }
176
+
171
177
  if (key === "Space") {
172
178
  keyElement.className += " space";
173
179
  }
@@ -234,6 +240,95 @@ export class VirtualKeyboard {
234
240
  }
235
241
 
236
242
  switch (keyPressed) {
243
+ case "Esc":
244
+ // ปิดหน้าต่างป๊อปอัพหรือยกเลิกการทำงานปัจจุบัน
245
+ const modals = document.querySelectorAll(".modal");
246
+ if (modals.length === 0) {
247
+ document.exitFullscreen();
248
+ console.warn("No modals found to close.");
249
+ }
250
+ modals.forEach((modal) => {
251
+ modal.classList.add("hidden"); // ซ่อน modal
252
+ });
253
+ break;
254
+
255
+ case "F1":
256
+ break;
257
+
258
+ case "F2":
259
+ // เปิดโหมดแก้ไขสำหรับ element ที่เลือก
260
+ const activeElement = document.activeElement;
261
+ if (activeElement && activeElement.contentEditable !== undefined) {
262
+ activeElement.contentEditable = true;
263
+ activeElement.focus();
264
+ console.log(activeElement.contentEditable);
265
+ } else {
266
+ console.warn("No editable element found.");
267
+ }
268
+ break;
269
+
270
+ case "F3":
271
+ // เปิดการค้นหา
272
+ event.preventDefault();
273
+ this.option.openSearch();
274
+ break;
275
+
276
+ case "F4":
277
+ // เปิดเมนูการตั้งค่า
278
+ event.preventDefault();
279
+ this.option.openSettings();
280
+ break;
281
+
282
+ case "F5":
283
+ // รีโหลดหน้าเว็บ (คงเดิม)
284
+ window.location.reload();
285
+ break;
286
+
287
+ case "F6":
288
+ // สลับระหว่างโหมดกลางวัน/กลางคืน
289
+ document.body.classList.toggle("dark-mode");
290
+ break;
291
+
292
+ case "F7":
293
+ break;
294
+
295
+ case "F8":
296
+ break;
297
+
298
+ case "F9":
299
+ break;
300
+
301
+ case "F10":
302
+ break;
303
+
304
+ case "F11":
305
+ if (!document.fullscreenElement) {
306
+ document.documentElement
307
+ .requestFullscreen()
308
+ .catch((err) =>
309
+ console.error("Error attempting to enable fullscreen:", err)
310
+ );
311
+ } else {
312
+ document
313
+ .exitFullscreen()
314
+ .catch((err) =>
315
+ console.error("Error attempting to exit fullscreen:", err)
316
+ );
317
+ }
318
+ break;
319
+
320
+ case "F12":
321
+ break;
322
+
323
+ case "HOME":
324
+ this.currentInput.setSelectionRange(Math.max(0, 0), Math.max(0, 0));
325
+ break;
326
+
327
+ case "END":
328
+ const length = this.currentInput.value.length;
329
+ this.currentInput.setSelectionRange(length, length);
330
+ break;
331
+
237
332
  case "Backspace":
238
333
  case "backspace":
239
334
  if (start === end && start > 0) {
@@ -248,43 +343,98 @@ export class VirtualKeyboard {
248
343
  }
249
344
  break;
250
345
 
346
+ case "DEL⌦":
347
+ 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;
352
+ } else {
353
+ this.currentInput.value = value.slice(0, start) + value.slice(end);
354
+ this.currentInput.selectionStart = this.currentInput.selectionEnd =
355
+ start;
356
+ }
357
+ break;
358
+
251
359
  case "Space":
252
360
  await this.insertText(" ");
253
361
  break;
254
362
 
255
- case "Tab":
363
+ case "Tab":
256
364
  await this.insertText("\t");
257
365
  break;
258
366
 
259
- case 'Enter':
367
+ case "Enter":
260
368
  if (this.currentInput.tagName === "TEXTAREA") {
261
- const start = this.currentInput.selectionStart;
262
- const end = this.currentInput.selectionEnd;
263
- const value = this.currentInput.value;
264
- this.currentInput.value = value.slice(0, start) + "\n" + value.slice(end);
369
+ this.currentInput.value =
370
+ value.slice(0, start) + "\n" + value.slice(end);
265
371
  this.currentInput.setSelectionRange(start + 1, start + 1);
266
- } else if (this.currentInput.tagName === "INPUT" || this.currentInput.type === "password" || this.currentInput.type === "text") {
372
+ } else if (
373
+ this.currentInput.tagName === "INPUT" ||
374
+ this.currentInput.type === "password" ||
375
+ this.currentInput.type === "text"
376
+ ) {
267
377
  if (this.currentInput.form) {
268
- const submitButton = this.currentInput.form.querySelector('input[type="submit"], button[type="submit"], button[type="button"], button[onclick]');
378
+ const submitButton = this.currentInput.form.querySelector(
379
+ 'input[type="submit"], button[type="submit"], button[type="button"], button[onclick]'
380
+ );
269
381
  if (submitButton) {
270
382
  submitButton.click();
271
383
  } else {
272
- this.currentInput.form.submit();
384
+ this.currentInput.form.submit();
273
385
  }
274
386
  } else {
275
- this.currentInput.value += '\n';
387
+ this.currentInput.value += "\n";
276
388
  }
277
389
  }
278
390
  break;
279
391
 
280
- case "Caps":
392
+ case "Caps 🄰":
281
393
  this.toggleCapsLock();
282
394
  break;
283
395
 
284
- case "Shift":
396
+ case "Shift":
285
397
  this.toggleShift();
286
398
  break;
287
399
 
400
+ case "←":
401
+ this.currentInput.setSelectionRange(
402
+ Math.max(0, start - 1),
403
+ Math.max(0, start - 1)
404
+ );
405
+ break;
406
+
407
+ case "→":
408
+ this.currentInput.setSelectionRange(start + 1, start + 1);
409
+ break;
410
+
411
+ case "↑":
412
+ case "↓":
413
+ const text = this.currentInput.value;
414
+ const lines = text.substring(0, start).split("\n");
415
+ const currentLineIndex = lines.length - 1;
416
+ const currentLine = lines[currentLineIndex];
417
+ const columnIndex = start - text.lastIndexOf("\n", start - 1) - 1;
418
+
419
+ if (keyPressed === "↑" && currentLineIndex > 0) {
420
+ const prevLineLength = lines[currentLineIndex - 1].length;
421
+ const newPos =
422
+ start -
423
+ currentLine.length -
424
+ 1 -
425
+ Math.min(columnIndex, prevLineLength);
426
+ this.currentInput.setSelectionRange(newPos, newPos);
427
+ } else if (keyPressed === "↓" && currentLineIndex < lines.length - 1) {
428
+ const nextLine = lines[currentLineIndex + 1];
429
+ const newPos =
430
+ start +
431
+ currentLine.length +
432
+ 1 +
433
+ Math.min(columnIndex, nextLine.length);
434
+ this.currentInput.setSelectionRange(newPos, newPos);
435
+ }
436
+ break;
437
+
288
438
  default:
289
439
  const encryptedText = await this.encodeText(
290
440
  convertToCorrectCase(keyPressed)
@@ -299,8 +449,6 @@ export class VirtualKeyboard {
299
449
  this.currentInput.focus();
300
450
  const event = new Event("input", { bubbles: true });
301
451
  this.currentInput.dispatchEvent(event);
302
- // console.log(this.encodeText(convertToCorrectCase(keyPressed)));
303
- // console.log(keyPressed);
304
452
  }
305
453
 
306
454
  async insertText(text) {
@@ -318,7 +466,7 @@ export class VirtualKeyboard {
318
466
 
319
467
  toggleCapsLock() {
320
468
  this.capsLockActive = !this.capsLockActive;
321
- document.querySelectorAll('.key[data-key="Caps"]').forEach((key) => {
469
+ document.querySelectorAll('.key[data-key="Caps 🄰"]').forEach((key) => {
322
470
  key.classList.toggle("active", this.capsLockActive);
323
471
  key.classList.toggle("bg-gray-400", this.capsLockActive);
324
472
  });
@@ -332,7 +480,7 @@ export class VirtualKeyboard {
332
480
  });
333
481
 
334
482
  const keyboardKeys = document.querySelectorAll(
335
- ".key:not([data-key='Caps'])"
483
+ ".key:not([data-key='Caps 🄰'])"
336
484
  );
337
485
  keyboardKeys.forEach((key) => {
338
486
  const currentChar = key.textContent.trim();
@@ -360,17 +508,16 @@ export class VirtualKeyboard {
360
508
 
361
509
  if (
362
510
  this.capsLockActive &&
363
- this.currentLayout === "en" &&
511
+ (this.currentLayout === "en" || this.currentLayout === "enSc") &&
364
512
  this.EngAlphabetShift[currentChar]
365
513
  ) {
366
514
  key.textContent = this.EngAlphabetShift[currentChar];
367
515
  key.dataset.key = this.EngAlphabetShift[currentChar];
368
516
  } else if (
369
517
  !this.capsLockActive &&
370
- this.currentLayout === "en" &&
518
+ (this.currentLayout === "en" || this.currentLayout === "enSc") &&
371
519
  Object.values(this.EngAlphabetShift).includes(currentChar)
372
520
  ) {
373
- // เปลี่ยนกลับเมื่อปิด Shift
374
521
  const originalKey = Object.keys(this.EngAlphabetShift).find(
375
522
  (key) => this.EngAlphabetShift[key] === currentChar
376
523
  );
@@ -383,14 +530,9 @@ export class VirtualKeyboard {
383
530
  }
384
531
 
385
532
  toggleShift() {
386
- if (this.capsLockActive) {
387
- return this.toggleCapsLock();
388
- }
389
-
390
533
  this.shiftActive = !this.shiftActive;
391
- document.querySelectorAll('.key[data-key="Shift"]').forEach((key) => {
534
+ document.querySelectorAll('.key[data-key="Shift"]').forEach((key) => {
392
535
  key.classList.toggle("active", this.shiftActive);
393
- key.classList.toggle("bg-gray-400", this.shiftActive);
394
536
  });
395
537
 
396
538
  document.querySelectorAll(".key").forEach((key) => {
@@ -402,10 +544,11 @@ export class VirtualKeyboard {
402
544
  });
403
545
 
404
546
  const keyboardKeys = document.querySelectorAll(
405
- ".key:not([data-key='Shift'])"
547
+ ".key:not([data-key='Shift'])"
406
548
  );
407
549
  keyboardKeys.forEach((key) => {
408
550
  const currentChar = key.textContent.trim();
551
+ keyboardKeys.className += " space";
409
552
  if (
410
553
  this.shiftActive &&
411
554
  this.currentLayout === "th" &&
@@ -430,14 +573,14 @@ export class VirtualKeyboard {
430
573
 
431
574
  if (
432
575
  this.shiftActive &&
433
- this.currentLayout === "en" &&
576
+ (this.currentLayout === "en" || this.currentLayout === "enSc") &&
434
577
  this.EngAlphabetShift[currentChar]
435
578
  ) {
436
579
  key.textContent = this.EngAlphabetShift[currentChar];
437
580
  key.dataset.key = this.EngAlphabetShift[currentChar];
438
581
  } else if (
439
582
  !this.shiftActive &&
440
- this.currentLayout === "en" &&
583
+ (this.currentLayout === "en" || this.currentLayout === "enSc") &&
441
584
  Object.values(this.EngAlphabetShift).includes(currentChar)
442
585
  ) {
443
586
  // เปลี่ยนกลับเมื่อปิด Shift
@@ -545,7 +688,7 @@ export class VirtualKeyboard {
545
688
 
546
689
  scrambleKeyboard() {
547
690
  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'])"
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='_'])"
549
692
  );
550
693
  const numbers = ["1", "2", "3", "4", "5", "6", "7", "8", "9", "0"];
551
694
  this.shuffleArray(numbers);
@@ -557,7 +700,7 @@ export class VirtualKeyboard {
557
700
 
558
701
  scrambleEnglishKeys() {
559
702
  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='='])"
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='_'])"
561
704
  );
562
705
  const englishAlphabet = "abcdefghijklmnopqrstuvwxyz".split("");
563
706
  this.shuffleArray(englishAlphabet);
@@ -569,7 +712,7 @@ export class VirtualKeyboard {
569
712
 
570
713
  scrambleThaiKeys() {
571
714
  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'])"
715
+ ".key:not([data-key='Backspace']):not([data-key='Caps 🄰']):not([data-key='Shift']):not([data-key='Enter']):not([data-key='Space'])"
573
716
  );
574
717
  const ThaiAlphabet = "กขฃคฅฆงจฉชซฌญฎฏฐฑฒณดตถทธนบปผฝพฟภมยรฤลฦวศษสหฬอฮ".split(
575
718
  ""
package/layouts.js CHANGED
@@ -1,31 +1,41 @@
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"],
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"],
7
15
  ["Space"],
8
16
  ],
9
17
  th: [
10
18
  ["_", "ๅ", "/", "-", "ภ", "ถ", "ุ", "ึ", "ค", "ต", "จ", "ข", "ช", "Backspace"],
11
- ["Tab", "ๆ", "ไ", "ำ", "พ", "ะ", "ั", "ี", "ร", "น", "ย", "บ", "ล", "ฃ"],
12
- ["Caps", "ฟ", "ห", "ก", "ด", "เ", "้", "่", "า", "ส", "ว", "ง", "Enter"],
13
- ["Shift", "ผ", "ป", "แ", "อ", "ิ", "ื", "ท", "ม", "ใ", "ฝ", "Shift"],
19
+ ["Tab", "ๆ", "ไ", "ำ", "พ", "ะ", "ั", "ี", "ร", "น", "ย", "บ", "ล", "ฃ"],
20
+ ["Caps 🄰", "ฟ", "ห", "ก", "ด", "เ", "้", "่", "า", "ส", "ว", "ง", "Enter"],
21
+ ["Shift", "ผ", "ป", "แ", "อ", "ิ", "ื", "ท", "ม", "ใ", "ฝ", "Shift"],
14
22
  ["Space"],
15
23
  ],
16
24
  numpad: [
17
25
  ["+", "-", "*", "/"],
18
26
  ["1", "2", "3", "%"],
19
- ["4", "5", "6", "."],
20
- ["7", "8", "9", "="],
21
- ["00", "0", "backspace"],
27
+ ["4", "5", "6", "_"],
28
+ ["7", "8", "9", "."],
29
+ ["(", "0", ")", "="],
30
+ ["backspace"]
22
31
  ],
23
32
  scNum: [
24
33
  ["+", "-", "*", "/"],
25
34
  ["1", "2", "3", "%"],
26
- ["4", "5", "6", "."],
27
- ["7", "8", "9", "="],
28
- ["00", "0", "backspace"],
35
+ ["4", "5", "6", "_"],
36
+ ["7", "8", "9", "."],
37
+ ["(", "0", ")", "="],
38
+ ["backspace"]
29
39
  ],
30
40
  thSc: [
31
41
  ["ก", "ข", "ฃ", "ค", "ฅ", "ฆ", "ง", "จ", "ฉ", "ช", "ซ", "ฌ", "Backspace"],
@@ -36,9 +46,9 @@ export const layouts = {
36
46
  ],
37
47
  enSc: [
38
48
  ["`", "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"],
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"],
42
52
  ["Space"],
43
53
  ],
44
54
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js_lis",
3
- "version": "1.0.24",
3
+ "version": "1.0.25",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"