// script.js
const Keyboard = {
elements: {
main: null,
keysContainer: null,
keys: [],
capsKey: null,
},
properties: {
value: "",
capsLock: false,
keyboardInputs: null,
keyLayout: [
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"0",
"backspace",
"q",
"w",
"e",
"r",
"t",
"y",
"u",
"i",
"o",
"p",
"caps",
"a",
"s",
"d",
"f",
"g",
"h",
"j",
"k",
"l",
"enter",
"done",
"z",
"x",
"c",
"v",
"b",
"n",
"m",
",",
".",
"?",
"space",
],
},
init() {
// create and setup main element
this.elements.main =
document.createElement("div");
this.elements.main.classList
.add("keyboard", "keyboard--hidden");
document.body
.appendChild(this.elements.main);
// create and setup child container component
this.elements.keysContainer =
document.createElement("div");
this.elements.keysContainer
.classList.add("keyboard__keys");
this.elements.main
.appendChild(this.elements.keysContainer);
// create and setup key elements
this.elements.keysContainer
.appendChild(this._createKeys());
this.elements.keys =
this.elements.keysContainer
.querySelectorAll(".keyboard__key");
// open keyboard for elements with .use-keyboard-input
this.properties.keyboardInputs =
document.querySelectorAll(
".use-keyboard-input"
);
this.properties
.keyboardInputs
.forEach((element) => {
element.addEventListener("focus", () => {
this
.open(element.value, (currentValue) => {
element.value = currentValue;
});
});
});
},
_createIconHTML(icon_name) {
return `<span class="material-icons">${icon_name}</span>`;
},
_createKeyBtn(iconName, class1, onclick, class2) {
this.keyElement =
document.createElement("button");
// add common attributes and classes
this.keyElement
.setAttribute("type", "button");
this.keyElement
.classList.add("keyboard__key");
// add specific listeners and classes
this.keyElement
.classList.add(class1, class2);
this.keyElement.innerHTML =
this._createIconHTML(iconName);
this.keyElement
.addEventListener("click", onclick);
},
_createKeys() {
const fragment =
document.createDocumentFragment();
this.properties.keyLayout.forEach((key) => {
const insertLineBreak =
["backspace", "p", "enter", "?"].indexOf(key) !== -1;
switch (key) {
case "backspace":
this._createKeyBtn(
"backspace", "keyboard__key--wide",
() => {
this.properties.value =
this.properties.value.slice(0, -1);
this._updateValueInTarget();
});
break;
case "caps":
this._createKeyBtn(
"keyboard_capslock",
"keyboard__key--activatable",
() => {
this.elements.capsKey
.classList
.toggle("keyboard__key--active");
this._toggleCapsLock();
},
"keyboard__key--wide"
);
this.elements.capsKey = this.keyElement;
break;
case "enter":
this._createKeyBtn(
"keyboard_return", "keyboard__key--wide",
() => {
this.properties.value += "\n";
this._updateValueInTarget();
});
break;
case "space":
this._createKeyBtn(
"space_bar", "keyboard__key--extra--wide",
() => {
this.properties.value += " ";
this._updateValueInTarget();
});
break;
case "done":
this._createKeyBtn(
"check_circle",
"keyboard__key--dark",
() => {
this.close();
this._updateValueInTarget();
},
"keyboard__key--wide"
);
break;
default:
this._createKeyBtn();
this.keyElement.textContent =
key.toLowerCase();
this.keyElement
.addEventListener(
"click",
() => {
this.properties.value +=
this.properties.capsLock
? key.toUpperCase()
: key.toLowerCase();
this._updateValueInTarget();
});
break;
}
fragment.appendChild(this.keyElement);
if (insertLineBreak) {
fragment
.appendChild(document.createElement("br"));
}
});
return fragment;
},
_updateValueInTarget() {
this.properties
.keyboardInputs
.forEach((keyboard) => {
keyboard.value =
this.properties.value;
});
},
_toggleCapsLock() {
this.properties.capsLock =
!this.properties.capsLock;
for (let key of this.elements.keys) {
if (key.childElementCount === 0) {
key.textContent =
this.properties.capsLock
? key.textContent.toUpperCase()
: key.textContent.toLowerCase();
}
}
},
open(initialValue, oninput) {
this.properties.value =
initialValue || "";
this.elements.main
.classList
.remove("keyboard--hidden");
},
close() {
this.properties.value =
this.properties.value;
this.elements.main
.classList.add("keyboard--hidden");
},
};
window.addEventListener("DOMContentLoaded", function () {
Keyboard.init();
});