Mitrofanova Natali 2 سال پیش
والد
کامیت
ad64364e62
3فایلهای تغییر یافته به همراه305 افزوده شده و 0 حذف شده
  1. 15 0
      HW10 Scope and Closures (OOP)/index.html
  2. 239 0
      HW10 Scope and Closures (OOP)/script.js
  3. 51 0
      HW10 Scope and Closures (OOP)/style.css

+ 15 - 0
HW10 Scope and Closures (OOP)/index.html

@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link rel="stylesheet" href="style.css">
+    <title>Document</title>
+</head>
+<body>
+    <div id="formContainer"></div>
+
+    <script src="script.js"></script>
+</body>
+</html>

+ 239 - 0
HW10 Scope and Closures (OOP)/script.js

@@ -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/');

+ 51 - 0
HW10 Scope and Closures (OOP)/style.css

@@ -0,0 +1,51 @@
+*{
+    margin: 0;
+}
+.wrapper{
+    display: flex;
+    flex-direction: column;
+    max-width: 400px;
+align-items: center;
+}
+button{
+    align-self: center;
+    width: 100px;
+}
+input, button{
+    margin-bottom: 7px;
+}
+input{
+    margin-right: 10px;
+    width: 200px;
+    box-sizing: border-box;
+}
+.error{
+    color: red;
+    position: absolute;
+    left: 210px;
+    width: 100px;
+}
+
+.stringWrapper{
+    display: flex;
+    position: relative
+}
+
+.mandatory{
+    color: red;
+    position: absolute;
+    left: -10px;
+    top: 4px
+}
+
+.checkBoxWrapper{
+    display: flex;
+    max-width: 200px;
+    justify-content: space-around;
+    position: relative;
+}
+.checkBoxWrapper p {
+    position: relative;
+    top: -3px;
+    left: 30px;
+}