2 changed files with 256 additions and 2 deletions
@ -0,0 +1,234 @@ |
|||
class VirtualKeyboard { |
|||
static show(inputElement) { |
|||
// Create the virtual keyboard container
|
|||
const keyboardContainer = document.createElement('div'); |
|||
keyboardContainer.classList.add('virtual-keyboard'); |
|||
document.body.appendChild(keyboardContainer); |
|||
|
|||
// Create the display container for input characters
|
|||
const displayContainer = document.createElement('div'); |
|||
displayContainer.classList.add('virtual-keyboard-display'); |
|||
document.body.appendChild(displayContainer); |
|||
|
|||
// Create the text display box above the number keys
|
|||
const textDisplayBox = document.createElement('div'); |
|||
textDisplayBox.classList.add('virtual-keyboard-text-display'); |
|||
textDisplayBox.style.height = '40px'; // Initialize height
|
|||
textDisplayBox.textContent = inputElement.value; // Initialize content
|
|||
keyboardContainer.appendChild(textDisplayBox); |
|||
|
|||
// Define the keys for the virtual keyboard
|
|||
const keyLayout = [ |
|||
['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'Backspace'], |
|||
['Tab', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'Del'], |
|||
['CapsLock', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'Enter'], |
|||
['Shift', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'Shift'], |
|||
['Space'] |
|||
]; |
|||
|
|||
let isShift = false; |
|||
let isCapsLock = false; |
|||
|
|||
// Create buttons for each key
|
|||
keyLayout.forEach(row => { |
|||
const rowContainer = document.createElement('div'); |
|||
rowContainer.classList.add('virtual-keyboard-row'); |
|||
row.forEach(key => { |
|||
const keyButton = document.createElement('button'); |
|||
keyButton.textContent = key; |
|||
keyButton.classList.add(`key-${key.toLowerCase()}`); |
|||
keyButton.addEventListener('mousedown', (event) => { |
|||
event.preventDefault(); // Prevent losing focus from the input element
|
|||
keyButton.classList.add('active'); // Add active class on mousedown
|
|||
if (key === 'Backspace') { |
|||
inputElement.value = inputElement.value.slice(0, -1); |
|||
} else if (key === 'Del') { |
|||
inputElement.value = ''; |
|||
} else if (key === 'Tab') { |
|||
inputElement.value += '\t'; |
|||
} else if (key === 'Space') { |
|||
inputElement.value += ' '; |
|||
} else if (key === 'Enter') { |
|||
document.body.removeChild(keyboardContainer); |
|||
document.body.removeChild(displayContainer); |
|||
} else if (key === 'Shift') { |
|||
// isShift = !isShift;
|
|||
// this.toggleShift(keyButton, isShift);
|
|||
} else if (key === 'CapsLock') { |
|||
isCapsLock = !isCapsLock; |
|||
this.toggleCapsLock(keyButton, isCapsLock); |
|||
} else { |
|||
inputElement.value += isCapsLock ? key.toUpperCase() : key.toLowerCase(); |
|||
} |
|||
inputElement.dispatchEvent(new Event('input')); // Trigger input event to update Vue binding
|
|||
displayContainer.textContent = inputElement.value; // Update display container with input value
|
|||
textDisplayBox.textContent = inputElement.value; // Update text display box with input value
|
|||
}); |
|||
keyButton.addEventListener('mouseup', () => { |
|||
keyButton.classList.remove('active'); // Remove active class on mouseup
|
|||
keyButton.style.background = '#fff'; // Reset background immediately
|
|||
}); |
|||
keyButton.addEventListener('mouseleave', () => { |
|||
keyButton.classList.remove('active'); // Remove active class if mouse leaves the button
|
|||
keyButton.style.background = '#fff'; // Reset background immediately
|
|||
}); |
|||
rowContainer.appendChild(keyButton); |
|||
}); |
|||
keyboardContainer.appendChild(rowContainer); |
|||
}); |
|||
|
|||
// Position the keyboard at the bottom of the screen
|
|||
keyboardContainer.style.position = 'fixed'; |
|||
keyboardContainer.style.bottom = '0'; |
|||
keyboardContainer.style.left = '50%'; |
|||
keyboardContainer.style.transform = 'translateX(-50%)'; |
|||
keyboardContainer.style.width = '100%'; |
|||
keyboardContainer.style.maxWidth = '800px'; |
|||
keyboardContainer.style.margin = '0 auto'; |
|||
keyboardContainer.style.border = '1px solid #999'; |
|||
|
|||
// Position the display container above the keyboard
|
|||
displayContainer.style.position = 'fixed'; |
|||
displayContainer.style.bottom = 'calc(100% + 10px)'; |
|||
displayContainer.style.left = '50%'; |
|||
displayContainer.style.transform = 'translateX(-50%)'; |
|||
displayContainer.style.width = '100%'; |
|||
displayContainer.style.maxWidth = '800px'; |
|||
displayContainer.style.textAlign = 'center'; |
|||
displayContainer.style.padding = '10px'; |
|||
displayContainer.style.background = '#f0f0f0'; |
|||
displayContainer.style.borderTop = '1px solid #999'; |
|||
displayContainer.style.boxShadow = '0 -2px 10px rgba(0, 0, 0, 0.1)'; |
|||
displayContainer.style.zIndex = '1000'; |
|||
|
|||
// Style the text display box
|
|||
textDisplayBox.style.width = '100%'; |
|||
textDisplayBox.style.padding = '10px'; |
|||
textDisplayBox.style.background = '#e0e0e0'; |
|||
textDisplayBox.style.textAlign = 'center'; |
|||
textDisplayBox.style.fontSize = '18px'; |
|||
textDisplayBox.style.marginBottom = '10px'; |
|||
|
|||
// Hide the keyboard and display container when the input loses focus
|
|||
inputElement.addEventListener('blur', () => { |
|||
setTimeout(() => { |
|||
if (document.activeElement !== inputElement) { |
|||
document.body.removeChild(keyboardContainer); |
|||
document.body.removeChild(displayContainer); |
|||
} |
|||
}, 30); |
|||
}); |
|||
} |
|||
|
|||
static toggleShift(button, isShift) { |
|||
button.classList.toggle('active', isShift); |
|||
} |
|||
|
|||
static toggleCapsLock(button, isCapsLock) { |
|||
const keys = document.querySelectorAll('.virtual-keyboard button'); |
|||
keys.forEach(key => { |
|||
if (key.textContent.length === 1 && key.textContent.match(/[a-z]/i)) { |
|||
key.textContent = isCapsLock ? key.textContent.toUpperCase() : key.textContent.toLowerCase(); |
|||
} |
|||
}); |
|||
} |
|||
} |
|||
|
|||
// Add some basic styles for the virtual keyboard
|
|||
const style = document.createElement('style'); |
|||
style.textContent = `
|
|||
.virtual-keyboard { |
|||
display: flex; |
|||
flex-direction: column; |
|||
background: #f0f0f0; |
|||
padding: 10px; |
|||
border-top: 1px solid #999; |
|||
border: 1px solid #999; |
|||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1); |
|||
z-index: 1000; |
|||
max-width: 800px; |
|||
margin: 0 auto; |
|||
} |
|||
.virtual-keyboard-row { |
|||
display: flex; |
|||
justify-content: center; |
|||
margin-bottom: 5px; |
|||
} |
|||
.virtual-keyboard button { |
|||
margin: 5px; |
|||
padding: 15px; |
|||
font-size: 18px; |
|||
cursor: pointer; |
|||
border: none; |
|||
border-radius: 5px; |
|||
background: #fff; |
|||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1); |
|||
transition: background 0.3s, box-shadow 0.3s; |
|||
flex: 1 1 8%; |
|||
max-width: 60px; |
|||
} |
|||
.virtual-keyboard button:hover { |
|||
background: #e0e0e0; |
|||
} |
|||
.virtual-keyboard button:active { |
|||
background: #d0d0d0; |
|||
box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.2); |
|||
} |
|||
.virtual-keyboard button.active { |
|||
background: #d0d0d0; |
|||
} |
|||
.virtual-keyboard .key-backspace { |
|||
flex: 1 1 10%; |
|||
max-width: 100px; |
|||
text-align: center; |
|||
display: flex; |
|||
align-items: center; |
|||
justify-content: center; |
|||
} |
|||
.virtual-keyboard .key-enter { |
|||
flex: 1 1 10%; |
|||
max-width: 100px; |
|||
} |
|||
.virtual-keyboard .key-shift { |
|||
flex: 1 1 15%; |
|||
max-width: 150px; |
|||
} |
|||
.virtual-keyboard .key-capslock, |
|||
.virtual-keyboard .key-tab, |
|||
.virtual-keyboard .key-del { |
|||
flex: 1 1 10%; |
|||
max-width: 100px; |
|||
} |
|||
.virtual-keyboard .key-space { |
|||
flex: 1 1 60%; |
|||
max-width: 400px; |
|||
} |
|||
.virtual-keyboard-display { |
|||
font-size: 24px; |
|||
color: #333; |
|||
} |
|||
.virtual-keyboard-text-display { |
|||
width: 100%; |
|||
padding: 10px; |
|||
background: #e0e0e0; |
|||
text-align: center; |
|||
font-size: 18px; |
|||
margin-bottom: 10px; |
|||
} |
|||
.virtual-keyboard-row:first-child { |
|||
justify-content: space-between; |
|||
} |
|||
.virtual-keyboard-row:nth-child(2) { |
|||
justify-content: space-between; |
|||
} |
|||
.virtual-keyboard-row:nth-child(3) { |
|||
justify-content: space-between; |
|||
} |
|||
.virtual-keyboard-row:nth-child(4) { |
|||
justify-content: space-between; |
|||
} |
|||
.virtual-keyboard-row:nth-child(5) { |
|||
justify-content: center; |
|||
} |
|||
`;
|
|||
document.head.appendChild(style); |
Write
Preview
Loading…
Cancel
Save
Reference in new issue