|
@@ -0,0 +1,239 @@
|
|
|
+
|
|
|
+// 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/');
|