// console.log(new Date()) // function dateToDateTimeLocal(data){ // // получить timeStamp // // offset // // new Date Математика с этим timestamp // // toISOString без последней буквы // // return "2021-12-07" // let timestamp = data.getTime(); // let offsetInMS = data.getTimezoneOffset() * 60 * 1000; // let offsetDate = new Date (timestamp - offsetInMS); // return offsetDate.toISOString().slice(0,-1); // // return (new Date(data.getTime()- data.getTimezoneOffset()*60000)).toISOString().slice(0, -1) // } // console.log(dateToDateTimeLocal(new Date())) function Form(el, data, okCallback, cancelCallback, url){ let formBody = document.createElement('div') formBody.classList.add("wrapper"); let okButton = document.createElement('button') okButton.className = "ok"; okButton.innerHTML = 'OK' okButton.disabled = true; let cancelButton = document.createElement('button') cancelButton.innerHTML = 'Cancel' let inputCreators = { String(key, value, oninput){ let stringWrapper = document.createElement("div") stringWrapper.className = "stringWrapper"; let err = document.createElement("p"); err.className = 'error'; let input = document.createElement('input') input.type = 'text' input.placeholder = key[0] === "*" ? key.slice(1) : key; input.value = value.split("").some((item)=>item !== "*") ? value : "" ; input.className = value.split("").every((item)=>item === "*") ? "password" : ""; input.oninput = () => oninput(input, input.value) stringWrapper.appendChild(input); stringWrapper.appendChild(err) if (key[0] === "*"){ const mandatory = document.createElement('p'); mandatory.className = "mandatory"; mandatory.innerText = '*'; stringWrapper.prepend(mandatory) } return stringWrapper }, Array(key, value, oninput){ let stringWrapper = document.createElement("div") stringWrapper.className = "stringWrapper"; let err = document.createElement("p"); err.className = 'error'; let input = document.createElement('input') input.type = 'text' input.placeholder = key[0] === "*" ? key.slice(1) : key; input.value = value; input.oninput = () => oninput(input, input.value) stringWrapper.appendChild(input); stringWrapper.appendChild(err) return stringWrapper }, Boolean(key, value, oninput){ let wrap = document.createElement('div'); wrap.className = 'checkBoxWrapper'; let p = document.createElement('p'); p.innerText = key; let input = document.createElement('input'); input.type = 'checkbox'; input.placeholder = key; input.checked = value; input.onchange = () => oninput(input, input.checked); //label for с input type='checkbox' внутри wrap.appendChild(p) wrap.appendChild(input) return wrap }, Date(key, value, oninput){ let input = document.createElement('input') input.type = 'date'; input.placeholder = key; input.value = value; input.onchange = () => oninput(input, input.value); return input //используйте datetime-local }, //и др. по вкусу, например textarea для длинных строк } for(const [key,value]of Object.entries(data)){ let input = inputCreators[value.constructor.name](key, value, (currentInput, newValue) => { const isValid = this.validators[key] && this.validators[key](newValue, key, data, currentInput); if (isValid === undefined){ data[key] = newValue; } if (currentInput.type === "checkbox"){ data[key] = newValue; } if (key[0] === "*" && newValue.length || isValid=== true){ data[key] = newValue; markInputAsValid(currentInput) } if(isValid && isValid.length > 0 && newValue.length){ markInputAsInValid(currentInput, isValid) } if (!newValue.length && key[0] === "*"){ currentInput.nextSibling.innerText = "Necessary field"; currentInput.style.backgroundColor = "pink"; } if (data['*password'] && (!data['*password'].length || data['*password'].split("").every((item)=>item === "*"))){ } if((key === "*password" || key === "*repeatePassword") && data["*password"].length && isValid===true){ const passwordsArray = Array.from(document.querySelectorAll('.password')); passwordsArray.forEach((item)=>{ markInputAsValid(item); }) } else { if ((key === "*password" || key === "*repeatePassword") && data["*password"].length && isValid !== true){ const passwordsArray = Array.from(document.querySelectorAll('.password')); markInputAsValid(passwordsArray[0]) markInputAsInValid(passwordsArray[1], isValid) } } checkAllFormValidation(formBody); }); formBody.appendChild(input); } if (typeof okCallback === 'function'){ formBody.appendChild(okButton); okButton.onclick = (e) => { console.log(data); this.savedData = this.data; // console.log(this) url ? localStorage.setItem(url, JSON.stringify(this.savedData)) : localStorage.setItem('defaultForm', this.savedData); console.log(JSON.parse(localStorage.getItem(url))); this.okCallback(this.data) } } if (typeof cancelCallback === 'function'){ formBody.appendChild(cancelButton); cancelButton.onclick = () => { this.data = {...this.savedData}; Array.from(formBody.querySelectorAll('input')).forEach(input => { input.value = this.savedData[input.placeholder] ? this.savedData[input.placeholder] : this.savedData[`*${input.placeholder}`]; input.value = input.value.split('').every(char => char === "*") ? "" : input.value; if(input.type === 'checkbox'){ input.checked = input.value; } }) cancelCallback(this.savedData); okButton.disabled = true; } } el.appendChild(formBody) this.okCallback = okCallback this.cancelCallback = cancelCallback this.data = data this.validators = {} this.savedData = {...data} this.url = url } let form = new Form(formContainer, { '*name': 'Anakin', surname: 'Skywalker', '*password': '******', '*repeatePassword': '******', married: true, birthday: new Date((new Date).getTime() - 86400000 * 30*365) }, (data) => console.log(data),(data) => console.log(data) ) form.validators.surname = validateName; form.validators['*name'] = validateName; form.validators['*password'] = validatePassword; form.validators['*repeatePassword'] = validatePassword; function validateName(value, key, data, input){ return value.length > 2 && value[0].toUpperCase() == value[0] && !value.includes(' ') ? true : 'Wrong name'; } function validatePassword(value, key, data, input){ const passwordsArray = Array.from(document.querySelectorAll('.password')); return (passwordsArray[0].value === passwordsArray[1].value && passwordsArray[0].value.length > 4 ) ? true : "Password should be similar and 5 or more characters" } function markInputAsValid(currentInput){ currentInput.style.backgroundColor = ""; currentInput.nextSibling.innerText = ''; } function markInputAsInValid(currentInput, isValid){ currentInput.style.backgroundColor = "red"; currentInput.nextSibling.innerText = isValid; } function checkAllFormValidation(wrapper){ const errors = Array.from(wrapper.querySelectorAll('.error')); const okButton = wrapper.querySelector('.ok'); const isFormValidated = errors.every(error => { return error.innerText === ''; }) const mandatory = Array.from(wrapper.querySelectorAll('.mandatory')); const isFormFilled = mandatory.every(mandatoryItem => { return mandatoryItem.nextSibling.value.length; }) okButton.disabled = !isFormValidated || !isFormFilled; } function createFormFromApi(url){ if (localStorage[url]){ new Form(formContainer, JSON.parse(localStorage[url]), (data) => console.log(data),(data) => console.log(data), url) } else { fetch(url) .then(res => res.json()) .then(character => { new Form(formContainer, character, (data) => console.log(data),(data) => console.log(data), url) }) } } createFormFromApi('https://swapi.dev/api/people/1/'); createFormFromApi('https://swapi.dev/api/people/2/');