// Control, крутилки регулировки RGB и Audio function Control( el, { value = 0, min = 0, max = 100, minAngle = 0, maxAngle = 360, wheelSpeed = 0.1, step = 1, } = {} ) { const img = document.createElement("img"); img.src = "wheel.png"; el.append(img); const ratio = (maxAngle - minAngle) / (max - min); const getAngle = () => (value - min) * ratio + minAngle; this.setValue = (newValue) => { if (newValue > max) { newValue = max; } if (newValue < min) { newValue = min; } value = newValue; img.style.transform = `rotate(${getAngle()}deg)`; if (this.onchange && typeof this.onchange === "function") { this.onchange(value); } }; this.getValue = () => value; img.onmousewheel = (e) => { const { deltaY } = e; const newValue = value + deltaY * wheelSpeed; this.setValue(newValue); e.preventDefault(); }; img.onclick = (e) => { const { width } = img; const { layerX } = e; if (layerX > width / 2) { this.setValue(value + step); } else { this.setValue(value - step); } }; const toDeg = (rad) => ((rad * 180) / Math.PI + 360 + 90) % 360; let prevMouseAngle = null; img.onmousedown = (e) => { const y = e.layerY - img.height / 2; const x = e.layerX - img.width / 2; prevMouseAngle = toDeg(Math.atan2(y, x)); e.preventDefault(); }; img.onmousemove = (e) => { if (prevMouseAngle === null) return; const y = e.layerY - img.height / 2; const x = e.layerX - img.width / 2; let currentMouseAngle = toDeg(Math.atan2(y, x)); let moveAngleDiff = currentMouseAngle - prevMouseAngle; this.setValue(value + moveAngleDiff / ratio); prevMouseAngle = currentMouseAngle; }; img.ommouseout = img.onmouseup = () => { prevMouseAngle = null; }; this.setValue(value); } function changeVolume() { let control = document.querySelector("#myPlayer"); let volumeValue = volumeControl.getValue() * 0.01; control.volume = volumeValue; } const volumeControl = new Control(container1, { min: 0, max: 100 }); volumeControl.onchange = changeVolume; function setRGB() { let color = document.querySelector("#colorChange"); let redValue = red.getValue(); let greenValue = green.getValue(); let blueValue = blue.getValue(); color.style.backgroundColor = "rgb(" + redValue + "," + greenValue + "," + blueValue + ")"; } const red = new Control(container2, { min: 0, max: 255 }); red.onchange = setRGB; const green = new Control(container2, { min: 0, max: 255 }); green.onchange = setRGB; const blue = new Control(container2, { min: 0, max: 255 }); blue.onchange = setRGB; // ДЗ: Functional OOP // Password function Password(parent = document.body, open = false) { let passInput = document.createElement("input"); let check = document.createElement("input"); check.type = "checkbox"; check.id = "showhide"; check.checked = open; parent.append(check); passInput.type = check.checked ? "text" : "password"; parent.append(passInput); // get input value this.getValue = () => passInput.value; // set input value this.setValue = (newValue) => { passInput.value = newValue; }; // read the openness of the text in the input field this.getOpen = () => check.checked; // set the openness of the text in the input field this.setOpen = () => check.checked ? (passInput.type = "text") : (passInput.type = "password"); // sending text out passInput.oninput = () => { if (this.onChange && typeof this.onChange === "function") { this.onChange(this.getValue()); } }; // triggered by changing the password open state check.oninput = () => { this.getOpen() ? this.setOpen(true) : this.setOpen(false); if (typeof this.onOpenChange === "function") { this.onOpenChange(this.getOpen()); } if (this.onOpenChange && typeof this.onOpenChange === "function") { this.onOpenChange(this.getOpen()); } }; } let p = new Password(container3, true); p.onChange = (data) => console.log(data); p.onOpenChange = (open) => console.log(open); p.setValue("qwertyasd"); console.log(p.getValue()); p.setOpen(false); console.log(p.getOpen()); // LoginForm function LoginForm(parent = formContainer, disabled = true) { const login = document.createElement("input"); const loginBtn = document.createElement("button"); login.type = "text"; loginBtn.disabled = disabled; loginBtn.innerText = "Login"; this.getValue = () => login.value; this.setValue = (newValue) => (login.value = newValue); this.getOpen = () => loginBtn.disabled; this.setOpen = (check) => (loginBtn.disabled = check); login.oninput = () => this.onChange(); parent.append(login); parent.append(loginBtn); } let loginForm = new LoginForm(formContainer, true); let password = new Password(formContainer, true); function check() { loginForm.getValue() !== "" && password.getValue() !== "" ? loginForm.setOpen(false) : password.setOpen(true); } loginForm.onChange = check; password.onChange = check; // Password Verify function passChange() { const secondPassword = document.createElement("input"); password.onOpenChange = (check) => { if (!check) { secondPassword.type = password.setOpen(); secondPassword.value = password.getValue(); secondPassword.checked = password.getOpen(); formContainer.append(secondPassword); } else { secondPassword.remove(); } }; } passChange(); // Form function Form(el = sFormContainer, data, okCallback, cancelCallback) { let initState = data; let flags = {}; for (let key in data) { key[0] !== "*" ? (flags[key] = true) : (flags[key.slice(1)] = false); } let formBody = document.createElement("div"); formBody.id = "formBody"; let table = document.createElement("table"); table.setAttribute("border", "1"); formBody.append(table); let buttons = document.createElement("div"); let okButton = document.createElement("button"); okButton.innerHTML = "OK"; okButton.disabled = true; let cancelButton = document.createElement("button"); cancelButton.innerHTML = "Cancel"; this.validators = {}; let inputCreators = { String(key, value, oninput) { let input = document.createElement("input"); input.type = /[*]/g.test(value) ? "password" : "text"; input.value = /[*]/g.test(value) ? "" : value; input.placeholder = key[0] === "*" ? key.slice(1) : key; input.oninput = () => oninput(input.value); return input; }, Boolean(key, value, oninput) { let input = document.createElement("input"); input.type = "checkbox"; input.checked = value; input.oninput = () => oninput(input.checked); return input; }, Date(key, value, oninput) { let input = document.createElement("input"); input.type = "datetime-local"; input.value = new Date(value - new Date().getTimezoneOffset() * 60 * 1000) .toISOString() .slice(0, -1); input.oninput = () => oninput(new Date(input.value)); return input; }, Number(key, value, oninput) { let input = document.createElement("input"); input.type = "number"; input.placeholder = key[0] === "*" ? key.slice(1) : key; input.value = value; input.oninput = () => oninput(input.value); return input; }, }; let flagsArray = []; for (let [key, value] of Object.entries(data)) { const tr = document.createElement("tr"); const th = document.createElement("th"); th.innerHTML = key[0] === "*" ? `${key[0]} ${key.slice(1)}` : key; const td = document.createElement("td"); const error = document.createElement("span"); error.style.color = "red"; const input = inputCreators[value.constructor.name]( key, value, (valueInput) => { value = valueInput; } ); td.append(input); tr.append(th); tr.append(td); if (key[0] === "*" && value === "") { flags[key.slice(1)] = false; error.innerText = `Required ${key.slice(1)} field is not filled`; td.append(error); } if (key[0] === "*" && value.length > 0) { flags[key.slice(1)] = true; } flagsArray = Object.values(flags); function checkButtons(callback, nameCallback, flags) { if (typeof callback === "function") { if (nameCallback === "okCallback") { buttons.appendChild(okButton); formBody.appendChild(buttons); if (flags.some((e) => e === false)) { okButton.disabled = true; } else { okButton.disabled = false; callback(data); okButton.onclick = (e) => { callback(e); }; } } if (nameCallback === "cancelCallback") { buttons.appendChild(cancelButton); formBody.appendChild(buttons); cancelButton.onclick = () => { formBody.remove(); buttons.remove(); Form( sFormContainer, initState, () => console.log("ok"), () => console.log("cancel") ); callback(); }; } } } checkButtons(okCallback, "okCallback", flagsArray); checkButtons(cancelCallback, "cancelCallback", flagsArray); input.onchange = () => { let keyCheck = key[0] === "*" ? key.slice(1) : key; if ( Object.keys(this.validators).length !== 0 && keyCheck in this.validators ) { let check = this.validators[keyCheck](value, key, data, input); if (check) { flags[keyCheck] = true; input.style.border = ""; error.innerText = ""; } else { flags[keyCheck] = false; input.style.border = "1px solid red"; error.innerText = `Invalid ${keyCheck} entered or a required field is missing`; } td.append(error); tr.append(td); flagsArray = Object.values(flags); } checkButtons(okCallback, "okCallback", flagsArray); checkButtons(cancelCallback, "cancelCallback", flagsArray); }; table.append(tr); } el.appendChild(formBody); el.appendChild(buttons); this.okCallback = okCallback; this.cancelCallback = cancelCallback; this.data = data; } let form = new Form( sFormContainer, { "*name": "Anakin", "*surname": "Skywalker", "*password": "****************", married: true, birthday: new Date(new Date().getTime() - 86400000 * 30 * 365), }, () => console.log("ok"), () => console.log("cancel") ); form.okCallback = () => console.log("ok2"); form.cancelCallback = () => console.log("cancel2"); form.validators.name = (value, key, data, input) => { if (key[0] === "*") { if ( value.length > 3 && value[0].toUpperCase() === value[0] && !value.includes(" ") ) { return true; } else { return false; } } else { return true; } }; form.validators.surname = (value, key, data, input) => { if (key[0] === "*") { if ( value.length > 3 && value[0].toUpperCase() === value[0] && !value.includes(" ") ) { return true; } else { return false; } } else { return true; } }; form.validators.password = (value, key, data, input) => { if (key[0] === "*") { if (value.length > 7 && !value.includes(" ")) { return true; } else { return false; } } else { return true; } };