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