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