js_lis 1.0.7 → 1.0.9
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 +112 -61
- package/package.json +1 -1
package/VirtualKeyboard.js
CHANGED
|
@@ -5,18 +5,71 @@ export class VirtualKeyboard {
|
|
|
5
5
|
this.currentLayout = 'en';
|
|
6
6
|
this.isVisible = false;
|
|
7
7
|
this.container = document.getElementById('keyboard-container');
|
|
8
|
-
this.currentInput = null;
|
|
8
|
+
this.currentInput = null;
|
|
9
9
|
this.layouts = layouts;
|
|
10
10
|
this.isDragging = false;
|
|
11
11
|
this.offsetX = 0;
|
|
12
12
|
this.offsetY = 0;
|
|
13
13
|
this.shiftActive = false;
|
|
14
14
|
this.capsLockActive = false;
|
|
15
|
-
|
|
15
|
+
this.secretKey = '1234567890abcdef'; // คีย์ที่ใช้ในการเข้ารหัส
|
|
16
|
+
// ใช้ Web Crypto API สำหรับการจัดการคีย์
|
|
17
|
+
this.cryptoKey = null;
|
|
18
|
+
this.iv = window.crypto.getRandomValues(new Uint8Array(12)); // สร้าง IV สำหรับการเข้ารหัส/ถอดรหัส
|
|
19
|
+
this.generateKey();
|
|
20
|
+
|
|
16
21
|
this.render();
|
|
17
22
|
this.initializeInputListeners();
|
|
18
23
|
}
|
|
19
24
|
|
|
25
|
+
async generateKey() {
|
|
26
|
+
this.cryptoKey = await window.crypto.subtle.generateKey(
|
|
27
|
+
{ name: "AES-GCM", length: 256 },
|
|
28
|
+
true,
|
|
29
|
+
["encrypt", "decrypt"]
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async encodeText(text) {
|
|
34
|
+
const encodedData = new TextEncoder().encode(text);
|
|
35
|
+
const encryptedData = await window.crypto.subtle.encrypt(
|
|
36
|
+
{ name: "AES-GCM", iv: this.iv },
|
|
37
|
+
this.cryptoKey,
|
|
38
|
+
encodedData
|
|
39
|
+
);
|
|
40
|
+
return this.arrayBufferToBase64(encryptedData); // แปลงเป็น Base64
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async decodeText(base64Text) {
|
|
44
|
+
const encryptedData = this.base64ToArrayBuffer(base64Text);
|
|
45
|
+
const decryptedData = await window.crypto.subtle.decrypt(
|
|
46
|
+
{ name: "AES-GCM", iv: this.iv },
|
|
47
|
+
this.cryptoKey,
|
|
48
|
+
encryptedData
|
|
49
|
+
);
|
|
50
|
+
return new TextDecoder().decode(decryptedData);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
arrayBufferToBase64(buffer) {
|
|
54
|
+
let binary = '';
|
|
55
|
+
const bytes = new Uint8Array(buffer);
|
|
56
|
+
const len = bytes.byteLength;
|
|
57
|
+
for (let i = 0; i < len; i++) {
|
|
58
|
+
binary += String.fromCharCode(bytes[i]);
|
|
59
|
+
}
|
|
60
|
+
return window.btoa(binary);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
base64ToArrayBuffer(base64) {
|
|
64
|
+
const binaryString = window.atob(base64);
|
|
65
|
+
const len = binaryString.length;
|
|
66
|
+
const bytes = new Uint8Array(len);
|
|
67
|
+
for (let i = 0; i < len; i++) {
|
|
68
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
69
|
+
}
|
|
70
|
+
return bytes.buffer;
|
|
71
|
+
}
|
|
72
|
+
|
|
20
73
|
getLayoutName(layout) {
|
|
21
74
|
switch (layout) {
|
|
22
75
|
case 'en': return 'English Keyboard';
|
|
@@ -29,7 +82,6 @@ export class VirtualKeyboard {
|
|
|
29
82
|
}
|
|
30
83
|
|
|
31
84
|
initializeInputListeners() {
|
|
32
|
-
// เพิ่ม event listener สำหรับทุก input และ textarea
|
|
33
85
|
document.addEventListener('click', (e) => {
|
|
34
86
|
const target = e.target;
|
|
35
87
|
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
|
|
@@ -37,46 +89,45 @@ export class VirtualKeyboard {
|
|
|
37
89
|
}
|
|
38
90
|
});
|
|
39
91
|
|
|
40
|
-
// เพิ่ม event listener สำหรับ focus
|
|
41
92
|
document.addEventListener('focus', (e) => {
|
|
42
93
|
const target = e.target;
|
|
43
94
|
if (target.tagName === 'INPUT' || target.tagName === 'TEXTAREA') {
|
|
44
95
|
this.setCurrentInput(target);
|
|
45
96
|
}
|
|
46
97
|
}, true);
|
|
98
|
+
|
|
99
|
+
document.addEventListener('click', (e) => {
|
|
100
|
+
const target = document.getElementById("toggle");
|
|
101
|
+
target.addEventListener('click', this.toggle.bind(this), { once: true });
|
|
102
|
+
});
|
|
47
103
|
}
|
|
48
104
|
|
|
49
105
|
setCurrentInput(inputElement) {
|
|
50
|
-
// ถ้ามี input เก่า ให้ลบ class active
|
|
51
106
|
if (this.currentInput) {
|
|
52
107
|
this.currentInput.classList.remove('keyboard-active');
|
|
53
108
|
}
|
|
54
|
-
|
|
55
|
-
// เซ็ต input ใหม่และเพิ่ม class active
|
|
109
|
+
|
|
56
110
|
this.currentInput = inputElement;
|
|
57
111
|
this.currentInput.classList.add('keyboard-active');
|
|
58
112
|
}
|
|
59
|
-
|
|
113
|
+
|
|
60
114
|
render() {
|
|
61
115
|
const keyboard = document.createElement('div');
|
|
62
116
|
keyboard.className = 'virtual-keyboard';
|
|
63
117
|
keyboard.style.display = this.isVisible ? 'block' : 'none';
|
|
64
|
-
|
|
65
|
-
// Add the ID for easy reference in dragging
|
|
66
118
|
keyboard.id = 'keyboard';
|
|
67
|
-
|
|
68
|
-
// New: Add Layout selector at the top inside the keyboard div
|
|
119
|
+
|
|
69
120
|
const controlsContainer = document.createElement('div');
|
|
70
121
|
controlsContainer.className = 'controls';
|
|
71
122
|
controlsContainer.style.display = 'flex';
|
|
72
123
|
controlsContainer.style.justifyContent = 'center';
|
|
73
124
|
controlsContainer.style.alignItems = 'center';
|
|
74
|
-
controlsContainer.style.marginBottom = '10px';
|
|
75
|
-
|
|
125
|
+
controlsContainer.style.marginBottom = '10px';
|
|
126
|
+
|
|
76
127
|
const layoutSelector = document.createElement('select');
|
|
77
128
|
layoutSelector.id = 'layout-selector';
|
|
78
129
|
layoutSelector.onchange = (e) => this.changeLayout(e.target.value);
|
|
79
|
-
|
|
130
|
+
|
|
80
131
|
const layouts = ['en', 'enSc', 'th', 'thSc', 'numpad', 'scNum'];
|
|
81
132
|
layouts.forEach(layout => {
|
|
82
133
|
const option = document.createElement('option');
|
|
@@ -86,32 +137,31 @@ export class VirtualKeyboard {
|
|
|
86
137
|
});
|
|
87
138
|
layoutSelector.value = this.currentLayout;
|
|
88
139
|
controlsContainer.appendChild(layoutSelector);
|
|
89
|
-
|
|
140
|
+
|
|
90
141
|
keyboard.appendChild(controlsContainer);
|
|
91
|
-
|
|
142
|
+
|
|
92
143
|
const layout = this.layouts[this.currentLayout];
|
|
93
|
-
|
|
144
|
+
|
|
94
145
|
layout.forEach(row => {
|
|
95
146
|
const rowElement = document.createElement('div');
|
|
96
147
|
rowElement.className = 'keyboard-row';
|
|
97
|
-
|
|
148
|
+
|
|
98
149
|
row.forEach(key => {
|
|
99
150
|
const keyElement = document.createElement('button');
|
|
100
|
-
keyElement.className = 'keyboard-key key';
|
|
151
|
+
keyElement.className = 'keyboard-key key';
|
|
101
152
|
keyElement.textContent = key;
|
|
102
153
|
keyElement.type = 'button';
|
|
103
|
-
|
|
104
|
-
// Add data-key to each key for reference
|
|
154
|
+
|
|
105
155
|
keyElement.dataset.key = key;
|
|
106
|
-
|
|
156
|
+
|
|
107
157
|
if (key === 'Space') {
|
|
108
158
|
keyElement.className += ' space';
|
|
109
159
|
}
|
|
110
|
-
|
|
160
|
+
|
|
111
161
|
if (key === 'backspace') {
|
|
112
162
|
keyElement.className += ' backspacew';
|
|
113
163
|
}
|
|
114
|
-
|
|
164
|
+
|
|
115
165
|
keyElement.onclick = (e) => {
|
|
116
166
|
e.preventDefault();
|
|
117
167
|
const keyPressed = keyElement.dataset.key || keyElement.textContent;
|
|
@@ -121,57 +171,53 @@ export class VirtualKeyboard {
|
|
|
121
171
|
console.error("The key element does not have a valid key value.");
|
|
122
172
|
}
|
|
123
173
|
};
|
|
124
|
-
|
|
174
|
+
|
|
125
175
|
rowElement.appendChild(keyElement);
|
|
126
176
|
});
|
|
127
|
-
|
|
177
|
+
|
|
128
178
|
keyboard.appendChild(rowElement);
|
|
129
179
|
});
|
|
130
|
-
|
|
180
|
+
|
|
131
181
|
this.container.innerHTML = '';
|
|
132
182
|
this.container.appendChild(keyboard);
|
|
133
|
-
|
|
183
|
+
|
|
134
184
|
if (this.currentLayout === "scNum") {
|
|
135
185
|
this.scrambleKeyboard();
|
|
136
186
|
}
|
|
137
|
-
|
|
187
|
+
|
|
138
188
|
if (this.currentLayout === "enSc") {
|
|
139
189
|
this.scrambleEnglishKeys();
|
|
140
190
|
}
|
|
141
|
-
|
|
191
|
+
|
|
142
192
|
if (this.currentLayout === "thSc") {
|
|
143
193
|
this.scrambleThaiKeys();
|
|
144
194
|
}
|
|
145
|
-
|
|
146
|
-
// Add drag functionality to the keyboard
|
|
195
|
+
|
|
147
196
|
keyboard.addEventListener('mousedown', (event) => this.startDrag(event));
|
|
148
197
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
handleKeyPress(keyPressed) {
|
|
198
|
+
|
|
199
|
+
async handleKeyPress(keyPressed) {
|
|
153
200
|
if (!this.currentInput) return;
|
|
154
|
-
|
|
201
|
+
|
|
155
202
|
const start = this.currentInput.selectionStart;
|
|
156
203
|
const end = this.currentInput.selectionEnd;
|
|
157
204
|
const value = this.currentInput.value;
|
|
158
|
-
|
|
205
|
+
|
|
159
206
|
const isCapsActive = this.capsLockActive;
|
|
160
207
|
const isShiftActive = this.shiftActive;
|
|
161
|
-
|
|
208
|
+
|
|
162
209
|
const convertToCorrectCase = (char) => {
|
|
163
210
|
if (isCapsActive || isShiftActive) {
|
|
164
211
|
return char.toUpperCase();
|
|
165
212
|
}
|
|
166
213
|
return char.toLowerCase();
|
|
167
214
|
};
|
|
168
|
-
|
|
169
|
-
// ตรวจสอบค่า keyPressed
|
|
215
|
+
|
|
170
216
|
if (!keyPressed) {
|
|
171
217
|
console.error("Invalid key pressed.");
|
|
172
218
|
return;
|
|
173
219
|
}
|
|
174
|
-
|
|
220
|
+
|
|
175
221
|
switch(keyPressed) {
|
|
176
222
|
case 'Backspace':
|
|
177
223
|
case 'backspace':
|
|
@@ -183,32 +229,32 @@ export class VirtualKeyboard {
|
|
|
183
229
|
this.currentInput.selectionStart = this.currentInput.selectionEnd = start;
|
|
184
230
|
}
|
|
185
231
|
break;
|
|
186
|
-
|
|
232
|
+
|
|
187
233
|
case 'Space':
|
|
188
|
-
this.insertText(' ');
|
|
234
|
+
await this.insertText(' ');
|
|
189
235
|
break;
|
|
190
|
-
|
|
236
|
+
|
|
191
237
|
case 'Tab':
|
|
192
|
-
this.insertText('\t');
|
|
238
|
+
await this.insertText('\t');
|
|
193
239
|
break;
|
|
194
|
-
|
|
240
|
+
|
|
195
241
|
case 'Enter':
|
|
196
242
|
if (this.currentInput.tagName === 'TEXTAREA') {
|
|
197
|
-
this.insertText('\n');
|
|
243
|
+
await this.insertText('\n');
|
|
198
244
|
}
|
|
199
245
|
break;
|
|
200
|
-
|
|
246
|
+
|
|
201
247
|
case 'Caps':
|
|
202
248
|
this.toggleCapsLock();
|
|
203
249
|
break;
|
|
204
|
-
|
|
250
|
+
|
|
205
251
|
case 'Shift':
|
|
206
252
|
this.toggleShift();
|
|
207
253
|
break;
|
|
208
|
-
|
|
254
|
+
|
|
209
255
|
default:
|
|
210
|
-
this.
|
|
211
|
-
|
|
256
|
+
const encryptedText = await this.encodeText(convertToCorrectCase(keyPressed));
|
|
257
|
+
await this.insertText(encryptedText);
|
|
212
258
|
}
|
|
213
259
|
|
|
214
260
|
if (isShiftActive && !isCapsActive) {
|
|
@@ -218,6 +264,17 @@ export class VirtualKeyboard {
|
|
|
218
264
|
this.currentInput.focus();
|
|
219
265
|
const event = new Event('input', { bubbles: true });
|
|
220
266
|
this.currentInput.dispatchEvent(event);
|
|
267
|
+
// console.log(this.encodeText(convertToCorrectCase(keyPressed)));
|
|
268
|
+
// console.log(keyPressed);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async insertText(text) {
|
|
272
|
+
const start = this.currentInput.selectionStart;
|
|
273
|
+
const end = this.currentInput.selectionEnd;
|
|
274
|
+
const decodedText = await this.decodeText(text); // ใช้ถอดรหัสก่อนแทรก
|
|
275
|
+
|
|
276
|
+
this.currentInput.value = this.currentInput.value.slice(0, start) + decodedText + this.currentInput.value.slice(end);
|
|
277
|
+
this.currentInput.selectionStart = this.currentInput.selectionEnd = start + decodedText.length;
|
|
221
278
|
}
|
|
222
279
|
|
|
223
280
|
toggleCapsLock() {
|
|
@@ -351,13 +408,6 @@ export class VirtualKeyboard {
|
|
|
351
408
|
ฝ: "ฦ",
|
|
352
409
|
};
|
|
353
410
|
|
|
354
|
-
insertText(text) {
|
|
355
|
-
const start = this.currentInput.selectionStart;
|
|
356
|
-
const end = this.currentInput.selectionEnd;
|
|
357
|
-
this.currentInput.value = this.currentInput.value.slice(0, start) + text + this.currentInput.value.slice(end);
|
|
358
|
-
this.currentInput.selectionStart = this.currentInput.selectionEnd = start + text.length;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
411
|
toggle() {
|
|
362
412
|
this.isVisible = !this.isVisible;
|
|
363
413
|
this.render();
|
|
@@ -434,4 +484,5 @@ export class VirtualKeyboard {
|
|
|
434
484
|
keyboard.style.top = `${event.clientY - this.offsetY}px`;
|
|
435
485
|
}
|
|
436
486
|
}
|
|
487
|
+
|
|
437
488
|
}
|