You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

233 lines
8.7 KiB

  1. class VirtualKeyboard {
  2. static show(inputElement) {
  3. // Create the virtual keyboard container
  4. const keyboardContainer = document.createElement('div');
  5. keyboardContainer.classList.add('virtual-keyboard');
  6. document.body.appendChild(keyboardContainer);
  7. // Create the display container for input characters
  8. const displayContainer = document.createElement('div');
  9. displayContainer.classList.add('virtual-keyboard-display');
  10. document.body.appendChild(displayContainer);
  11. // Create the text display box above the number keys
  12. const textDisplayBox = document.createElement('div');
  13. textDisplayBox.classList.add('virtual-keyboard-text-display');
  14. textDisplayBox.style.height = '40px'; // Initialize height
  15. textDisplayBox.textContent = inputElement.value; // Initialize content
  16. keyboardContainer.appendChild(textDisplayBox);
  17. // Define the keys for the virtual keyboard
  18. const keyLayout = [
  19. ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'Backspace'],
  20. ['Tab', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'Del'],
  21. ['CapsLock', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'Enter'],
  22. ['Shift', 'z', 'x', 'c', 'v', 'b', 'n', 'm', 'Shift'],
  23. ['Space']
  24. ];
  25. let isShift = false;
  26. let isCapsLock = false;
  27. // Create buttons for each key
  28. keyLayout.forEach(row => {
  29. const rowContainer = document.createElement('div');
  30. rowContainer.classList.add('virtual-keyboard-row');
  31. row.forEach(key => {
  32. const keyButton = document.createElement('button');
  33. keyButton.textContent = key;
  34. keyButton.classList.add(`key-${key.toLowerCase()}`);
  35. keyButton.addEventListener('mousedown', (event) => {
  36. event.preventDefault(); // Prevent losing focus from the input element
  37. keyButton.classList.add('active'); // Add active class on mousedown
  38. if (key === 'Backspace') {
  39. inputElement.value = inputElement.value.slice(0, -1);
  40. } else if (key === 'Del') {
  41. inputElement.value = '';
  42. } else if (key === 'Tab') {
  43. inputElement.value += '\t';
  44. } else if (key === 'Space') {
  45. inputElement.value += ' ';
  46. } else if (key === 'Enter') {
  47. document.body.removeChild(keyboardContainer);
  48. document.body.removeChild(displayContainer);
  49. } else if (key === 'Shift') {
  50. // isShift = !isShift;
  51. // this.toggleShift(keyButton, isShift);
  52. } else if (key === 'CapsLock') {
  53. isCapsLock = !isCapsLock;
  54. this.toggleCapsLock(keyButton, isCapsLock);
  55. } else {
  56. inputElement.value += isCapsLock ? key.toUpperCase() : key.toLowerCase();
  57. }
  58. inputElement.dispatchEvent(new Event('input')); // Trigger input event to update Vue binding
  59. displayContainer.textContent = inputElement.value; // Update display container with input value
  60. textDisplayBox.textContent = inputElement.value; // Update text display box with input value
  61. });
  62. keyButton.addEventListener('mouseup', () => {
  63. keyButton.classList.remove('active'); // Remove active class on mouseup
  64. keyButton.style.background = '#fff'; // Reset background immediately
  65. });
  66. keyButton.addEventListener('mouseleave', () => {
  67. keyButton.classList.remove('active'); // Remove active class if mouse leaves the button
  68. keyButton.style.background = '#fff'; // Reset background immediately
  69. });
  70. rowContainer.appendChild(keyButton);
  71. });
  72. keyboardContainer.appendChild(rowContainer);
  73. });
  74. // Position the keyboard at the bottom of the screen
  75. keyboardContainer.style.position = 'fixed';
  76. keyboardContainer.style.bottom = '0';
  77. keyboardContainer.style.left = '50%';
  78. keyboardContainer.style.transform = 'translateX(-50%)';
  79. keyboardContainer.style.width = '100%';
  80. keyboardContainer.style.maxWidth = '800px';
  81. keyboardContainer.style.margin = '0 auto';
  82. keyboardContainer.style.border = '1px solid #999';
  83. // Position the display container above the keyboard
  84. displayContainer.style.position = 'fixed';
  85. displayContainer.style.bottom = 'calc(100% + 10px)';
  86. displayContainer.style.left = '50%';
  87. displayContainer.style.transform = 'translateX(-50%)';
  88. displayContainer.style.width = '100%';
  89. displayContainer.style.maxWidth = '800px';
  90. displayContainer.style.textAlign = 'center';
  91. displayContainer.style.padding = '10px';
  92. displayContainer.style.background = '#f0f0f0';
  93. displayContainer.style.borderTop = '1px solid #999';
  94. displayContainer.style.boxShadow = '0 -2px 10px rgba(0, 0, 0, 0.1)';
  95. displayContainer.style.zIndex = '1000';
  96. // Style the text display box
  97. textDisplayBox.style.width = '100%';
  98. textDisplayBox.style.padding = '10px';
  99. textDisplayBox.style.background = '#e0e0e0';
  100. textDisplayBox.style.textAlign = 'center';
  101. textDisplayBox.style.fontSize = '18px';
  102. textDisplayBox.style.marginBottom = '10px';
  103. // Hide the keyboard and display container when the input loses focus
  104. inputElement.addEventListener('blur', () => {
  105. setTimeout(() => {
  106. if (document.activeElement !== inputElement) {
  107. document.body.removeChild(keyboardContainer);
  108. document.body.removeChild(displayContainer);
  109. }
  110. }, 30);
  111. });
  112. }
  113. static toggleShift(button, isShift) {
  114. button.classList.toggle('active', isShift);
  115. }
  116. static toggleCapsLock(button, isCapsLock) {
  117. const keys = document.querySelectorAll('.virtual-keyboard button');
  118. keys.forEach(key => {
  119. if (key.textContent.length === 1 && key.textContent.match(/[a-z]/i)) {
  120. key.textContent = isCapsLock ? key.textContent.toUpperCase() : key.textContent.toLowerCase();
  121. }
  122. });
  123. }
  124. }
  125. // Add some basic styles for the virtual keyboard
  126. const style = document.createElement('style');
  127. style.textContent = `
  128. .virtual-keyboard {
  129. display: flex;
  130. flex-direction: column;
  131. background: #f0f0f0;
  132. padding: 10px;
  133. border-top: 1px solid #999;
  134. border: 1px solid #999;
  135. box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.1);
  136. z-index: 1000;
  137. max-width: 800px;
  138. margin: 0 auto;
  139. }
  140. .virtual-keyboard-row {
  141. display: flex;
  142. justify-content: center;
  143. margin-bottom: 5px;
  144. }
  145. .virtual-keyboard button {
  146. margin: 5px;
  147. padding: 15px;
  148. font-size: 18px;
  149. cursor: pointer;
  150. border: none;
  151. border-radius: 5px;
  152. background: #fff;
  153. box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
  154. transition: background 0.3s, box-shadow 0.3s;
  155. flex: 1 1 8%;
  156. max-width: 60px;
  157. }
  158. .virtual-keyboard button:hover {
  159. background: #e0e0e0;
  160. }
  161. .virtual-keyboard button:active {
  162. background: #d0d0d0;
  163. box-shadow: inset 0 2px 5px rgba(0, 0, 0, 0.2);
  164. }
  165. .virtual-keyboard button.active {
  166. background: #d0d0d0;
  167. }
  168. .virtual-keyboard .key-backspace {
  169. flex: 1 1 10%;
  170. max-width: 100px;
  171. text-align: center;
  172. display: flex;
  173. align-items: center;
  174. justify-content: center;
  175. }
  176. .virtual-keyboard .key-enter {
  177. flex: 1 1 10%;
  178. max-width: 100px;
  179. }
  180. .virtual-keyboard .key-shift {
  181. flex: 1 1 15%;
  182. max-width: 150px;
  183. }
  184. .virtual-keyboard .key-capslock,
  185. .virtual-keyboard .key-tab,
  186. .virtual-keyboard .key-del {
  187. flex: 1 1 10%;
  188. max-width: 100px;
  189. }
  190. .virtual-keyboard .key-space {
  191. flex: 1 1 60%;
  192. max-width: 400px;
  193. }
  194. .virtual-keyboard-display {
  195. font-size: 24px;
  196. color: #333;
  197. }
  198. .virtual-keyboard-text-display {
  199. width: 100%;
  200. padding: 10px;
  201. background: #e0e0e0;
  202. text-align: center;
  203. font-size: 18px;
  204. margin-bottom: 10px;
  205. }
  206. .virtual-keyboard-row:first-child {
  207. justify-content: space-between;
  208. }
  209. .virtual-keyboard-row:nth-child(2) {
  210. justify-content: space-between;
  211. }
  212. .virtual-keyboard-row:nth-child(3) {
  213. justify-content: space-between;
  214. }
  215. .virtual-keyboard-row:nth-child(4) {
  216. justify-content: space-between;
  217. }
  218. .virtual-keyboard-row:nth-child(5) {
  219. justify-content: center;
  220. }
  221. `;
  222. document.head.appendChild(style);