js_lis 2.0.7 → 2.0.8

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 (2) hide show
  1. package/VirtualKeyboard.js +121 -12
  2. package/package.json +1 -1
@@ -79,15 +79,26 @@ export class VirtualKeyboard {
79
79
  const target = e.target;
80
80
  if ((target.tagName === "INPUT" || target.tagName === "TEXTAREA") && target === this.currentInput) {
81
81
  if (!this.isVirtualKeyboardActive) {
82
- this.handleRealKeyboardInput(target);
82
+ this.handleRealKeyboardInput(target, e);
83
83
  }
84
84
  }
85
85
  });
86
86
 
87
- // Add real keyboard arrow key support
87
+ // Add real keyboard keydown listener for proper character tracking
88
88
  document.addEventListener("keydown", (e) => {
89
89
  const target = e.target;
90
90
  if ((target.tagName === "INPUT" || target.tagName === "TEXTAREA") && target === this.currentInput) {
91
+ // Reset the virtual keyboard flag when real keyboard is used
92
+ if (!['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.code)) {
93
+ this.isVirtualKeyboardActive = false;
94
+ }
95
+
96
+ // Handle real keyboard input
97
+ if (!this.isVirtualKeyboardActive) {
98
+ this.handleRealKeyboardKeydown(target, e);
99
+ }
100
+
101
+ // Handle arrow keys for all input types
91
102
  if (['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End'].includes(e.code)) {
92
103
  setTimeout(() => {
93
104
  target.focus();
@@ -156,6 +167,7 @@ export class VirtualKeyboard {
156
167
 
157
168
  const layoutSelector = document.createElement("select");
158
169
  layoutSelector.id = "layout-selector";
170
+ layoutSelector.setAttribute("aria-label", "Select keyboard layout"); // ✅ เพิ่มบรรทัดนี้
159
171
  layoutSelector.onchange = (e) => this.changeLayout(e.target.value);
160
172
 
161
173
  const layouts = ["full", "en", "th", "numpad", "symbols"];
@@ -168,6 +180,7 @@ export class VirtualKeyboard {
168
180
  layoutSelector.value = this.currentLayout;
169
181
  controlsContainer.appendChild(layoutSelector);
170
182
 
183
+
171
184
  keyboard.appendChild(controlsContainer);
172
185
 
173
186
  const layout = this.layouts[this.currentLayout];
@@ -188,13 +201,14 @@ export class VirtualKeyboard {
188
201
  keyElement.classList.add("concat-keys");
189
202
  }
190
203
 
191
- if (key === "Space") {
204
+ if (key === " ") {
192
205
  keyElement.className += " space";
206
+ keyElement.innerHTML = 'ฺ';
193
207
  }
194
208
 
195
209
  if (key === "backspace" || key === "Backspace") {
196
210
  keyElement.className += " backspacew";
197
- keyElement.innerHTML = '<i class="fa fa-backspace"></i>';
211
+ keyElement.innerHTML = '<i class="fa fa-backspace"></i>ฺ';
198
212
  }
199
213
 
200
214
  keyElement.onclick = (e) => {
@@ -474,6 +488,9 @@ export class VirtualKeyboard {
474
488
  this.currentInput.focus();
475
489
  const event = new Event("input", { bubbles: true });
476
490
  this.currentInput.dispatchEvent(event);
491
+
492
+ // Reset the flag after virtual keyboard operation is complete
493
+ this.isVirtualKeyboardActive = false;
477
494
  }
478
495
 
479
496
  // [3]
@@ -525,18 +542,110 @@ export class VirtualKeyboard {
525
542
  }
526
543
  }
527
544
 
528
- // Handle real keyboard input and encrypt it
529
- handleRealKeyboardInput(input) {
545
+ // Handle real keyboard keydown events to track actual input before masking
546
+ handleRealKeyboardKeydown(input, event) {
530
547
  if (!input) return;
531
548
 
532
- // Get the current value from the input
533
- const currentValue = input.value;
549
+ const key = event.key;
550
+ const start = input.selectionStart;
551
+ const end = input.selectionEnd;
552
+ const buffer = this.getCurrentBuffer();
553
+
554
+ // Skip modifier keys and special keys
555
+ if (event.ctrlKey || event.altKey || event.metaKey ||
556
+ ['Shift', 'Control', 'Alt', 'Meta', 'CapsLock', 'Tab', 'Escape',
557
+ 'ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'Home', 'End',
558
+ 'F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12'].includes(key)) {
559
+ return;
560
+ }
534
561
 
535
- // Update the plaintext buffer with the real keyboard input
536
- this.inputPlaintextBuffers.set(input, currentValue);
562
+ let newBuffer = buffer;
563
+
564
+ if (key === 'Backspace') {
565
+ if (start === end && start > 0) {
566
+ // Single character deletion
567
+ newBuffer = buffer.slice(0, start - 1) + buffer.slice(start);
568
+ } else if (start !== end) {
569
+ // Range deletion
570
+ newBuffer = buffer.slice(0, start) + buffer.slice(end);
571
+ }
572
+
573
+ // Prevent default and update manually
574
+ event.preventDefault();
575
+ this.setCurrentBuffer(newBuffer);
576
+ this.updateDisplayedValue(false);
577
+
578
+ // Set cursor position
579
+ const newCursorPos = start === end ? Math.max(0, start - 1) : start;
580
+ setTimeout(() => {
581
+ input.setSelectionRange(newCursorPos, newCursorPos);
582
+ input.focus();
583
+ }, 0);
584
+
585
+ } else if (key === 'Delete') {
586
+ if (start === end && start < buffer.length) {
587
+ // Single character deletion forward
588
+ newBuffer = buffer.slice(0, start) + buffer.slice(start + 1);
589
+ } else if (start !== end) {
590
+ // Range deletion
591
+ newBuffer = buffer.slice(0, start) + buffer.slice(end);
592
+ }
593
+
594
+ // Prevent default and update manually
595
+ event.preventDefault();
596
+ this.setCurrentBuffer(newBuffer);
597
+ this.updateDisplayedValue(false);
598
+
599
+ // Set cursor position
600
+ setTimeout(() => {
601
+ input.setSelectionRange(start, start);
602
+ input.focus();
603
+ }, 0);
604
+
605
+ } else if (key === 'Enter') {
606
+ if (input.tagName === 'TEXTAREA') {
607
+ newBuffer = buffer.slice(0, start) + '\n' + buffer.slice(end);
608
+
609
+ // Prevent default and update manually
610
+ event.preventDefault();
611
+ this.setCurrentBuffer(newBuffer);
612
+ this.updateDisplayedValue(false);
613
+
614
+ // Set cursor position
615
+ const newCursorPos = start + 1;
616
+ setTimeout(() => {
617
+ input.setSelectionRange(newCursorPos, newCursorPos);
618
+ input.focus();
619
+ }, 0);
620
+ }
621
+ // For input fields, let the default behavior handle form submission
622
+
623
+ } else if (key.length === 1) {
624
+ // Regular character input
625
+ newBuffer = buffer.slice(0, start) + key + buffer.slice(end);
626
+
627
+ // Prevent default and update manually
628
+ event.preventDefault();
629
+ this.setCurrentBuffer(newBuffer);
630
+ this.updateDisplayedValue(false);
631
+
632
+ // Set cursor position
633
+ const newCursorPos = start + key.length;
634
+ setTimeout(() => {
635
+ input.setSelectionRange(newCursorPos, newCursorPos);
636
+ input.focus();
637
+ }, 0);
638
+ }
639
+ }
640
+
641
+ // Handle real keyboard input and encrypt it (simplified version)
642
+ handleRealKeyboardInput(input, event) {
643
+ if (!input) return;
537
644
 
538
- // Encrypt and store in data-encrypted attribute
539
- this.updateDomEncrypted(input, currentValue);
645
+ // For most cases, the keydown handler already took care of updating the buffer
646
+ // This method now just ensures the encryption is up to date
647
+ const currentBuffer = this.getCurrentBuffer();
648
+ this.updateDomEncrypted(input, currentBuffer);
540
649
  }
541
650
 
542
651
  // Helper: encrypt and store ciphertext in DOM attribute
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "js_lis",
3
- "version": "2.0.7",
3
+ "version": "2.0.8",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"