keyboard.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. const Keyboard = {
  2. elements: {
  3. main: null,
  4. keysContainer: null,
  5. keys: []
  6. },
  7. eventHandlers: {
  8. oninput: null,
  9. onclose: null
  10. },
  11. properties: {
  12. value: "",
  13. capsLock: false
  14. },
  15. init() {
  16. // Create main elements
  17. this.elements.main = document.createElement("div");
  18. this.elements.keysContainer = document.createElement("div");
  19. // Setup main elements
  20. this.elements.main.classList.add("keyboard");
  21. this.elements.keysContainer.classList.add("keyboard__keys");
  22. this.elements.keysContainer.appendChild(this._createKeys());
  23. this.elements.keys = this.elements.keysContainer.querySelectorAll(".keyboard__key");
  24. // Add to DOM
  25. this.elements.main.appendChild(this.elements.keysContainer);
  26. document.body.appendChild(this.elements.main);
  27. // Automatically use keyboard for elements with .use-keyboard-input
  28. document.querySelectorAll(".use-keyboard-input").forEach(element => {
  29. element.addEventListener("focus", () => {
  30. this.open(element.value, currentValue => {
  31. element.value = currentValue;
  32. });
  33. });
  34. });
  35. },
  36. _createKeys() {
  37. const fragment = document.createDocumentFragment();
  38. const keyLayout = [
  39. "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "backspace",
  40. "q", "w", "e", "r", "t", "y", "u", "i", "o", "p",
  41. "caps", "a", "s", "d", "f", "g", "h", "j", "k", "l", "enter",
  42. "z", "x", "c", "v", "b", "n", "m", ",", ".", "?",
  43. "space"
  44. ];
  45. keyLayout.forEach(key => {
  46. const keyElement = document.createElement("button");
  47. const insertLineBreak = ["backspace", "p", "enter", "?"].indexOf(key) !== -1;
  48. // Add attributes/classes
  49. keyElement.setAttribute("type", "button");
  50. keyElement.classList.add("keyboard__key");
  51. switch (key) {
  52. case "backspace":
  53. keyElement.classList.add("keyboard__key--wide");
  54. keyElement.innerHTML = `<i class="ui long arrow alternate left icon"></i>`;
  55. keyElement.addEventListener("click", (event) => {
  56. event.preventDefault();
  57. event.stopImmediatePropagation()
  58. event.stopPropagation();
  59. backSpace();
  60. //this.properties.value = this.properties.value.substring(0, this.properties.value.length - 1);
  61. //this._triggerEvent("oninput");
  62. });
  63. break;
  64. case "caps":
  65. keyElement.classList.add("keyboard__key--wide", "keyboard__key--activatable");
  66. keyElement.innerHTML = `<i class="ui chevron up icon"></i>`;
  67. keyElement.addEventListener("click", () => {
  68. this._toggleCapsLock();
  69. keyElement.classList.toggle("keyboard__key--active", this.properties.capsLock);
  70. });
  71. break;
  72. case "enter":
  73. keyElement.classList.add("keyboard__key--wide");
  74. keyElement.innerHTML = `<i style="transform: rotate(90deg);" class="ui level down alternate icon"></i>`;
  75. keyElement.addEventListener("click", (event) => {
  76. event.preventDefault();
  77. event.stopImmediatePropagation()
  78. event.stopPropagation();
  79. addtext("\n");
  80. //this.properties.value += "\n";
  81. //this._triggerEvent("oninput");
  82. });
  83. break;
  84. case "space":
  85. keyElement.classList.add("keyboard__key--extra-wide");
  86. keyElement.innerHTML = ``;
  87. keyElement.addEventListener("click", (event) => {
  88. event.preventDefault();
  89. event.stopImmediatePropagation()
  90. event.stopPropagation();
  91. addtext(" ");
  92. //this.properties.value += " ";
  93. //this._triggerEvent("oninput");
  94. });
  95. break;
  96. case "done":
  97. /*
  98. keyElement.classList.add("keyboard__key--wide", "keyboard__key--dark");
  99. keyElement.innerHTML = createIconHTML("check_circle");
  100. keyElement.addEventListener("click", () => {
  101. this.close();
  102. this._triggerEvent("onclose");
  103. });
  104. */
  105. break;
  106. default:
  107. keyElement.textContent = key.toLowerCase();
  108. keyElement.addEventListener("click", (event) => {
  109. event.preventDefault();
  110. event.stopImmediatePropagation()
  111. event.stopPropagation();
  112. addtext(this.properties.capsLock ? key.toUpperCase() : key.toLowerCase());
  113. //this.properties.value += this.properties.capsLock ? key.toUpperCase() : key.toLowerCase();
  114. //this._triggerEvent("oninput");
  115. });
  116. break;
  117. }
  118. fragment.appendChild(keyElement);
  119. if (insertLineBreak) {
  120. fragment.appendChild(document.createElement("br"));
  121. }
  122. });
  123. return fragment;
  124. },
  125. _triggerEvent(handlerName) {
  126. if (typeof this.eventHandlers[handlerName] == "function") {
  127. this.eventHandlers[handlerName](this.properties.value);
  128. }
  129. },
  130. _toggleCapsLock() {
  131. this.properties.capsLock = !this.properties.capsLock;
  132. for (const key of this.elements.keys) {
  133. if (key.childElementCount === 0) {
  134. key.textContent = this.properties.capsLock ? key.textContent.toUpperCase() : key.textContent.toLowerCase();
  135. }
  136. }
  137. },
  138. open(initialValue, oninput, onclose) {
  139. this.properties.value = initialValue || "";
  140. this.eventHandlers.oninput = oninput;
  141. this.eventHandlers.onclose = onclose;
  142. this.elements.main.classList.remove("keyboard--hidden");
  143. },
  144. close() {
  145. this.properties.value = "";
  146. this.eventHandlers.oninput = oninput;
  147. this.eventHandlers.onclose = onclose;
  148. this.elements.main.classList.add("keyboard--hidden");
  149. }
  150. };
  151. window.addEventListener("DOMContentLoaded", function () {
  152. Keyboard.init();
  153. });