vladislavaSim пре 1 година
родитељ
комит
0aeda70bcd
39 измењених фајлова са 3274 додато и 0 уклоњено
  1. 29 0
      JavaScriptHomeWorks/HW1/index.html
  2. 31 0
      JavaScriptHomeWorks/HW1/index.js
  3. 23 0
      JavaScriptHomeWorks/HW10/index.html
  4. 139 0
      JavaScriptHomeWorks/HW10/main.js
  5. 19 0
      JavaScriptHomeWorks/HW11/index.html
  6. 111 0
      JavaScriptHomeWorks/HW11/main.js
  7. 22 0
      JavaScriptHomeWorks/HW12/index.html
  8. 69 0
      JavaScriptHomeWorks/HW12/main.js
  9. 49 0
      JavaScriptHomeWorks/HW13/index.html
  10. 88 0
      JavaScriptHomeWorks/HW13/main.js
  11. 44 0
      JavaScriptHomeWorks/HW14/index.html
  12. 92 0
      JavaScriptHomeWorks/HW14/main.js
  13. 13 0
      JavaScriptHomeWorks/HW15/index.html
  14. 81 0
      JavaScriptHomeWorks/HW15/main.js
  15. 10 0
      JavaScriptHomeWorks/HW2/index.html
  16. 147 0
      JavaScriptHomeWorks/HW2/main.js
  17. 10 0
      JavaScriptHomeWorks/HW3/index.html
  18. 250 0
      JavaScriptHomeWorks/HW3/main.js
  19. 10 0
      JavaScriptHomeWorks/HW4/index.html
  20. 201 0
      JavaScriptHomeWorks/HW4/main.js
  21. 17 0
      JavaScriptHomeWorks/HW5/index.html
  22. 131 0
      JavaScriptHomeWorks/HW5/main.js
  23. 10 0
      JavaScriptHomeWorks/HW6/index.html
  24. 84 0
      JavaScriptHomeWorks/HW6/main.js
  25. 20 0
      JavaScriptHomeWorks/HW7/index.html
  26. 53 0
      JavaScriptHomeWorks/HW7/main.js
  27. 10 0
      JavaScriptHomeWorks/HW8/index.html
  28. 118 0
      JavaScriptHomeWorks/HW8/main.js
  29. 10 0
      JavaScriptHomeWorks/HW9/index.html
  30. 62 0
      JavaScriptHomeWorks/HW9/main.js
  31. BIN
      JavaScriptHomeWorks/JsModule/Loading_icon.gif
  32. 132 0
      JavaScriptHomeWorks/JsModule/index.html
  33. 715 0
      JavaScriptHomeWorks/JsModule/index.js
  34. 53 0
      JavaScriptHomeWorks/painter/index.html
  35. 311 0
      JavaScriptHomeWorks/painter/main.js
  36. BIN
      JavaScriptHomeWorks/tuner/13x.png
  37. BIN
      JavaScriptHomeWorks/tuner/bbno$xdiamondPistols-help herself.mp3
  38. 35 0
      JavaScriptHomeWorks/tuner/index.html
  39. 75 0
      JavaScriptHomeWorks/tuner/index.js

+ 29 - 0
JavaScriptHomeWorks/HW1/index.html

@@ -0,0 +1,29 @@
+<!DOCTYPE html>
+<html lang="en">
+    <head>
+        <meta charset="UTF-8">
+        <title>HW1</title>
+        <style>
+            #message {
+                width: 120px;
+                font-size: 18px;
+            }
+            .success-message {
+                background-color: palegreen;
+            }
+            .fail-message {
+                background-color: #ff6b6b;
+            }
+        </style>
+    </head>
+    <body>
+        <div>
+            <form>
+                <input type="text" id="login" placeholder="login">
+                <input type="text" id="password" placeholder="password">
+                <button id="login-btn">Log in</button>
+            </form>
+        </div>
+    <script src="index.js"></script>
+    </body>
+</html>

+ 31 - 0
JavaScriptHomeWorks/HW1/index.js

@@ -0,0 +1,31 @@
+let cigarettesPerDay = +prompt('How many cigarettes do you smoke per day?');
+let onePackPrice = +prompt('How much does one pack cost?')
+
+let cigarettesPerMonth = cigarettesPerDay * 30;
+let packsPerMonth = cigarettesPerMonth / 20;
+
+let totalPricePerMonth = packsPerMonth * onePackPrice;
+alert(`You spend ${totalPricePerMonth} for cigarettes every month. Aren\'t you surprised?`)
+
+var credentials = {
+    login: 'admin',
+    password: 'qwerty',
+};
+
+let login = document.querySelector('#login');
+let password = document.querySelector('#password');
+let loginBtn = document.querySelector('#login-btn');
+let message = document.createElement('div');
+message.id = 'message'
+
+loginBtn.addEventListener('click', (e) => {
+    e.preventDefault()
+    if(login.value === credentials.login && password.value === credentials.password) {
+        message.innerHTML = 'Successful login'
+        message.className = 'success-message'
+    } else {
+        message.innerHTML = 'Data is wrong!'
+        message.className = 'fail-message'
+    }
+    document.body.append(message)
+});

+ 23 - 0
JavaScriptHomeWorks/HW10/index.html

@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW10</title>
+    <style>
+        #loginForm {
+            display: flex;
+            flex-direction: column;
+            align-items: start;
+        }
+    </style>
+</head>
+
+<body>
+<div>
+    <form id="loginForm">
+
+    </form>
+</div>
+<script src="main.js"></script>
+</body>
+</html>

+ 139 - 0
JavaScriptHomeWorks/HW10/main.js

@@ -0,0 +1,139 @@
+function Password(parent, open) {
+    let value = ''
+    let pass = document.createElement('input')
+    pass.placeholder = 'enter password'
+    let showPassBox = document.createElement('div')
+    let check = document.createElement('input')
+    check.type = 'checkbox'
+    check.name = 'password'
+    let label = document.createElement('label')
+    label.for = 'password'
+    label.innerText = 'Show password'
+    showPassBox.append(check, label)
+    parent.append(pass, showPassBox)
+    check.onchange = () => {
+        this.setOpen(check.checked)
+    }
+    pass.oninput = () => {
+        if (typeof this.onChange === "function") {
+            this.onChange(this.getValue());
+        }
+    };
+    this.getValue = function () {
+        return pass.value
+    }
+    this.setValue = function(value) {
+        pass.value = value
+    }
+    this.getOpen = function () {
+        return open
+    }
+    this.setOpen = function(newOpen) {
+        open = newOpen
+        pass.type = open ? 'text' : 'password'
+        check.checked = open
+        if(typeof this.onOpenChange === 'function') {
+            this.onOpenChange(open)
+        }
+    }
+    this.setOpen(open)
+    this.onChange = () => {
+        button.disabled = !(p.getValue() === p2.getValue())
+    }
+
+}
+
+
+
+// let p = new Password(document.body, false)
+//
+// p.onChange = data => console.log(data)
+// p.onOpenChange = open => console.log(open)
+//
+// p.setValue('qwerty')
+// console.log(p.getValue())
+
+// p.setOpen(false)
+// console.log(p.getOpen())
+
+function Login(parent) {
+    let input = document.createElement('input')
+    input.placeholder = 'enter login'
+    let button = document.createElement('button')
+    button.innerText = 'log in'
+    parent.appendChild(input)
+    let password = new Password(parent, false)
+    password.placeholder = 'enter password'
+    button.disabled = true
+    parent.appendChild(button)
+
+    parent.onchange = function () {
+        console.log(password.getValue())
+        button.disabled = !(input.value !== '' && password.getValue() !== '')
+    }
+}
+let newLogin = new Login(loginForm)
+console.log(newLogin)
+
+
+let p = new Password(document.body, true)
+let p2 = new Password(document.body, true)
+let button = document.createElement('button')
+button.innerText = 'log in'
+button.disabled = true
+
+
+
+
+
+document.body.append(button)
+
+
+
+
+
+
+
+
+
+
+
+// let $login = document.createElement('input');
+// let $password = document.createElement('input')
+// let $loginBtn = document.createElement('button')
+// $loginBtn.innerText = 'Log In'
+// let loginForm = document.querySelector('#loginForm')
+// loginForm.append($login, $password, $loginBtn)
+// let login = new Password(document.body, true)
+// let password = new Password(document.body, false)
+// let btn = new Password(document.body, false)
+//
+// login.setValue('anonymous');
+// password.setValue('123456');
+// login.value && password.value !== '' ? btn.setOpen(true) : btn.setOpen(false)
+// function LoginForm(login, password){
+//     this.login = login
+//     this.password = password
+//     this.btn = false
+//
+//     this.getLogin = function () {
+//         return this.login
+//     }
+//     this.setLogin = function (value) {
+//         return this.login = value
+//     }
+//     this.getPassword = function () {
+//         return this.password
+//     }
+//     this.setPassword = function (value) {
+//         return this.password = value
+//     }
+//     this.setBtn = function () {
+//         this.login.value && this.password.value ? this.btn = true : this.btn = false
+//     }
+// }
+
+// let newLogin = new LoginForm('admin', '11111');
+// console.log(newLogin.login.value)
+// console.log(newLogin)
+

+ 19 - 0
JavaScriptHomeWorks/HW11/index.html

@@ -0,0 +1,19 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW11</title>
+    <style>
+        body {
+            font-size: 20px;
+        }
+        td {
+            border: 1px solid black;
+            padding: 4px;
+        }
+    </style>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 111 - 0
JavaScriptHomeWorks/HW11/main.js

@@ -0,0 +1,111 @@
+function createStore(reducer){
+    let state = reducer(undefined, {})
+    let callbacks = []
+    const getState = () => state
+    const dispatch = (action) => {
+        const newState = reducer(state, action)
+        if(newState !== state) {
+            state = newState
+        }
+        for(let cb of callbacks) {
+            cb()
+        }
+    }
+
+    const subscribe = (callback) => (callbacks.push(callback),
+        () => callbacks = callbacks.filter(c => c !== callback))
+    return {
+        getState,
+        dispatch,
+        subscribe
+    }
+}
+
+function reducer(state, {type, item, number, price}){ //объект action деструктуризируется на три переменных
+    if (!state){ //начальная уборка в ларьке:
+        return {
+            items :
+                [
+                     {
+                        name: 'beer',
+                        price: 35,
+                        number: 100
+                     },
+                    {
+                        name: 'chips',
+                        price: 50,
+                        number: 100
+                    },
+                    {
+                        name: 'cigarettes',
+                        price: 45,
+                        number: 100
+                    },
+                    {
+                        name: 'gum',
+                        price: 15,
+                        number: 100
+                    }
+                ],
+            money: 0
+        }
+    }
+    if (type === 'BUY'){ //если тип action - КУПИТЬ, то:
+        console.log(state.items)
+        return {
+            ...state, //берем все что было из ассортимента
+
+            items: state.items.filter(i => i.name === item), //и уменьшаем то, что покупается на количество
+            money: state.money += state.items.filter(i => i.price === price)
+        }
+    }
+    return state //если мы не поняли, что от нас просят в `action` - оставляем все как есть
+}
+
+const store = createStore(reducer)
+// console.log(store.getState())
+
+let $select = document.createElement('select')
+let $table = document.createElement('table');
+let $num = document.createElement('input')
+$num.type = 'number'
+let btn = document.createElement('button')
+$num.min = '1';
+console.log(store.getState().items)
+let money = document.createElement('div')
+for(let item of store.getState().items) {
+    let $tr = document.createElement('tr')
+    let $td = document.createElement('td')
+    let $td2 = document.createElement('td')
+    let $td3 = document.createElement('td')
+    $td.innerText = item.name
+    $td2.innerText = item.price
+    $td3.innerText = item.number
+    let $option = document.createElement('option')
+    $option.innerHTML = item.name
+    $select.append($option)
+    btn.innerHTML = 'buy'
+    $tr.append($td, $td2, $td3)
+    $table.append($tr)
+    btn.onclick = (e) => {
+        // console.log(store.getState().items, item)
+        // console.log(item.number - +$num.value >= 0 )
+            if(item.number - +$num.value >= 0 ) {
+                // console.log(+$num.value, item.number)
+                let [selected] = store.getState().items.filter(i => i.name === $select.value)
+                selected.number = item.number - +$num.value
+                // console.log(selected.number)
+                if(item.number > 0) {
+                    console.log(store.getState())
+                    store.dispatch({type: 'BUY', item: selected.name, number: item.number - +$num.value})
+                    console.log(store.getState())
+                }
+            }
+
+    }
+    console.log(store.getState())
+    store.subscribe(() => money.innerHTML = `Cashbox: ${+store.getState().money}`)
+    store.subscribe(() => $td3.innerHTML = `${item.number}`)
+    document.body.append($select, $num, btn, $table)
+}
+document.body.appendChild(money)

+ 22 - 0
JavaScriptHomeWorks/HW12/index.html

@@ -0,0 +1,22 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW12</title>
+    <style>
+        body {
+            font-size: 20px;
+        }
+        td {
+            border: 1px solid black;
+            padding: 4px;
+        }
+        button {
+            background-color: #C4C4C4;
+        }
+    </style>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 69 - 0
JavaScriptHomeWorks/HW12/main.js

@@ -0,0 +1,69 @@
+fetch('https://swapi.dev/api/people/1/')
+    .then(res => res.json())
+    .then(luke => renderTable(document.body, luke))
+
+function renderTable(parent, obj) {
+    let $table = document.createElement('table')
+    for(let key in obj) {
+        let $tr = document.createElement('tr')
+        let $td = document.createElement('td')
+        let $td2 = document.createElement('td')
+        if(Array.isArray(obj[key])) {
+            for(let item of obj[key]) {
+                let newTable = document.createElement('table')
+                let newTr = document.createElement('tr')
+                let newTd = document.createElement('td')
+                linkChecker(item, newTd)
+                newTr.append(newTd)
+                newTable.append(newTr)
+                $td2.append(newTable)
+            }
+        } else {
+            linkChecker(obj[key], $td2)
+        }
+
+        $td.innerHTML = key
+
+        $tr.append($td, $td2)
+        $table.appendChild($tr)
+    }
+    parent.appendChild($table)
+}
+function linkChecker(str, container) {
+    if(typeof str === 'string') {
+        if(str.includes('https://swapi.dev/api/')) {
+            let btn = document.createElement('button')
+            btn.innerHTML = 'Show'
+            btn.onclick = () => {
+                fetch(str).then(r => r.json())
+                    .then(r => renderTable(container, r))
+                    // .then(r => console.log(r))
+            }
+            container.append(btn)
+        } else {
+            container.innerHTML = str
+        }
+    }
+}
+
+function myFetch(url){
+    return new Promise(function (resolve, reject){
+        const xhr = new XMLHttpRequest()
+        xhr.open('get', url)
+        xhr.onload = function () {
+            if (xhr.status >= 200 && xhr.status < 300) {
+                resolve(xhr.response);
+            } else {
+                reject(() => alert('something went wrong'));
+            }
+        xhr.send();
+    }});
+}
+myFetch('https://swapi.dev/api/peope/4/')
+    .then(res => console.log(res))
+
+function delay(ms) {
+    return setTimeout(() => console.log('delay worked'), ms)
+}
+Promise.race([myFetch('https://swapi.dev/api/peope/4/'), delay(300)]).then(val => console.log(val))
+Promise.race([myFetch('https://swapi.dev/api/peope/1/'), delay(200)]).then(val => console.log(val))

+ 49 - 0
JavaScriptHomeWorks/HW13/index.html

@@ -0,0 +1,49 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW13</title>
+    <style>
+
+        .chat-header {
+            text-align: left;
+        }
+        #chat-message {
+            border-radius: 5px;
+            padding: 7px;
+            background-color: #ccc;
+            display: inline-block;
+            margin-left: 5px;
+        }
+        .msg {
+            width: 250px;
+            border: 1px solid grey;
+            padding: 5px 10px;
+            margin: 5px;
+            background: seashell;
+        }
+        p {
+            margin: 5px;
+        }
+        .msg p:first-child {
+            font-size: 20px;
+        }
+    </style>
+</head>
+<body>
+<main class="main">
+<div class="chat">
+    <h1 class="chat-header">Chat</h1>
+    <div id="content" class = "chat-header">
+        <div class="form">
+            Nick : <input type="text" id = 'nick' value="test">
+            Message : <input type="text" id = 'msg'>
+            <button id="sendButton">Отправить</button>
+        </div>
+    </div>
+</div>
+    <div id="msgHolder"></div>
+</main>
+<script src="main.js"></script>
+</body>
+</html>

+ 88 - 0
JavaScriptHomeWorks/HW13/main.js

@@ -0,0 +1,88 @@
+let $nickname = document.querySelector('#nick')
+let sendBtn = document.querySelector('#sendButton');
+let $msg = document.querySelector('#msg')
+let msgHolder = document.querySelector('#msgHolder')
+
+function jsonPost(url, data) {
+    return new Promise((resolve, reject) => {
+        var x = new XMLHttpRequest();
+        x.onerror = () => reject(new Error('jsonPost failed'))
+        x.open("POST", url, true);
+        x.send(JSON.stringify(data))
+
+        x.onreadystatechange = () => {
+            if (x.readyState === XMLHttpRequest.DONE && x.status === 200){
+                resolve(JSON.parse(x.responseText))
+            }
+            else if (x.status !== 200){
+                reject(new Error('status is not 200'))
+            }
+        }
+    })
+}
+
+// function messageDataCreator(message) {
+//     return {
+//         func: 'addMessage',
+//         nick: $nickname.value,
+//         message: message,
+//     }
+// }
+//
+function showMessagesList(arr) {
+    let $container = document.createElement('div')
+    for(let msg of arr) {
+        let $div = document.createElement('div')
+        $div.className = 'msg'
+        let $p1 = document.createElement('p')
+        let $p2 = document.createElement('p')
+        $p1.innerHTML = msg.nick + ':'
+        $p2.innerHTML = msg.message
+        $div.append($p1, $p2)
+        $container.append($div)
+    }
+    msgHolder.prepend($container)
+}
+
+    async function getMessages() {
+        let id = 0;
+        let resp = await jsonPost("http://students.a-level.com.ua:10012", {func: "getMessages", messageId: id})
+        let {data, nextMessageId} = await resp
+        id = nextMessageId
+        let list = data.slice(data.length - 50).reverse()
+        showMessagesList(list)
+        if(nextMessageId > id) {
+            id = nextMessageId
+            showMessagesList(data)
+        }
+    }
+
+    // let interval = setInterval(async () => {
+    //
+    // }, 3000)
+
+
+async function sendMessage(nick, message) {
+    console.log('test')
+        await jsonPost("http://students.a-level.com.ua:10012",
+            {
+                func: 'addMessage',
+                nick: nick,
+                message: message,
+            }
+        )
+    }
+
+sendBtn.onclick = sendAndCheck()
+    async function sendAndCheck() {
+        await getMessages()
+        await sendMessage($nickname.value, $msg.value)
+        $msg.value = ''
+    }
+
+function delay(ms) {
+    return new Promise((resolve) => setTimeout(resolve, ms))
+}
+
+
+

+ 44 - 0
JavaScriptHomeWorks/HW14/index.html

@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW14</title>
+  <style>
+    .trafficLight {
+      width: 150px;
+      height: 350px;
+      display: flex;
+      flex-direction: column;
+      justify-content: space-around;
+      align-items: center;
+      background-color: black;
+    }
+    .trafficLight  div {
+      width: 100px;
+      height: 100px;
+      border-radius: 50%;
+    }
+    .red {
+      background-color: red;
+        opacity: .2;
+    }
+    .yellow {
+      background-color: yellow;
+        opacity: .2;
+    }
+    .green {
+      background-color: green;
+        opacity: .2;
+    }
+  </style>
+</head>
+<body>
+  <div class="trafficLight">
+    <div class="red"></div>
+    <div class="yellow"></div>
+    <div class="green"></div>
+  </div>
+<button class="btn">Button</button>
+  <script src="main.js"></script>
+</body>
+</html>

+ 92 - 0
JavaScriptHomeWorks/HW14/main.js

@@ -0,0 +1,92 @@
+const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))
+
+const red = document.querySelector('.red')
+const yellow = document.querySelector('.yellow')
+const green = document.querySelector('.green')
+let col = red
+
+// async function trafficLight(){
+//     while (true){
+//         changeLight(green)
+//         await delay(3000)
+//         changeLight(yellow)
+//         await delay(2000)
+//         changeLight(red)
+//         await delay(3000)
+//     }
+// }
+// trafficLight().then()
+
+function changeLight(color) {
+    if(col !== color) {
+        col.style.opacity = .2
+        color.style.opacity = 1
+        col = color
+    } else {
+        color.style.opacity = 1
+    }
+}
+
+let btn = document.querySelector('.btn')
+
+function domEventPromise(button, eventName) {
+    return new Promise(res => {
+        button.addEventListener(eventName, (e) => res(e))
+
+        button.removeEventListener(eventName, (e) => res(e))
+    });
+}
+domEventPromise(btn, 'click')
+    .then(e => console.log('event click happens', e))
+
+let stopLightIsActive = true
+async function pedestrianTrafficLight() {
+    while(stopLightIsActive){
+            changeLight(red)
+            await delay(100)
+    }
+}
+pedestrianTrafficLight().then()
+btn.addEventListener('click', async () => {
+    stopLightIsActive = !stopLightIsActive
+        await delay(3000)
+        changeLight(yellow)
+        await delay(1000)
+        changeLight(green)
+        await delay(4000)
+        changeLight(yellow)
+        await delay(1000)
+        changeLight(red)
+})
+
+async function speedtest(getPromise, count, parallel = 1) {
+    let time = performance.now();
+    let promisesArr = [];
+    let initParallel = parallel;
+    for (let i = 0; i < count; i++) {
+        promisesArr.push(getPromise);
+        parallel--;
+        await Promise.all(promisesArr);
+    }
+
+    time = performance.now() - time;
+
+    return {
+        duration: time,
+        querySpeed: count / time,
+        queryDuration: time / count,
+        parallelSpeed: (count / time) * initParallel,
+        parallelDuration: time / (count * initParallel),
+    };
+}
+
+speedtest(() => delay(1000), 10, 10).then((res) =>console.log(res));
+speedtest(
+    () =>
+        fetch("http://swapi.dev/api/people/1").then((res) =>
+            res.json()
+        ),
+    2,
+    2
+).then((v)=>console.log(v))
+

+ 13 - 0
JavaScriptHomeWorks/HW15/index.html

@@ -0,0 +1,13 @@
+<!doctype html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport"
+          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
+    <meta http-equiv="X-UA-Compatible" content="ie=edge">
+    <title>HW15</title>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 81 - 0
JavaScriptHomeWorks/HW15/main.js

@@ -0,0 +1,81 @@
+let gql = (url, query, variables={}) =>
+    fetch(url, {
+        method: 'POST',
+        headers:{
+            Accept: 'application/json',
+            "Content-Type": 'application/json'
+        },
+        body: JSON.stringify({query, variables})
+    }).then(res => res.json())
+
+// используя функцию gql, понаделать функций с параметрами для разных запросов: категории, категория по id с товарами, товар по id с картинками и описанием, логин, регистрация.
+//     например:
+let idd = 123456
+// `\\"_id\\":\\"${id}\\"`
+console.log(JSON.parse("[{\"_id\":\"123456\"}]"))
+const url = 'http://shop-roles.node.ed.asmer.org.ua/graphql'
+const gqlCategoriesList = () => {
+    return gql(url, `query cats{
+    CategoryFind(query: "[{}]"){
+    _id, name,
+  }
+}`, {}
+    )
+}
+
+const gqlRegister = (login, password) => {
+    return gql(url, `mutation register($login: String, $password: String){
+    UserUpsert(user: {login: $login, password: $password}){
+        _id, login, createdAt
+    }
+}`, {login, password})
+}
+
+const gqlLogin = (login, password) =>
+    gql(url,
+        `query login($login:String, $password: String){
+                login(login:$login, password: $password)
+        }`, {login, password})
+
+const gqlCategories = () => {
+    return gql(url,
+        ` query categories{
+                            CategoryFind(query:"[{}]"){
+                            _id name goods {
+                                _id
+                                name
+                                price
+                                description
+                                }
+                          }
+                     }`
+        );
+}
+const productSearchById = (id) => {
+    let jsn = JSON.stringify({_id: id})
+    return gql(
+        url,
+        `query searchById{
+        GoodFind(query: ${JSON.stringify(`[${jsn}]`)}){
+            name description images {
+                _id
+                createdAt
+                text
+                url
+                originalFileName
+            }
+        }
+    }`,
+    );
+};
+
+(async function callAll() {
+    console.log(await gqlCategoriesList());
+    console.log(await gqlRegister("Vlada Simonova", "123456"));
+    console.log(await gqlLogin("Vlada Simonova", "123456"));
+    console.log(await gqlCategories());
+    console.log(await productSearchById("62c9472cb74e1f5f2ec1a0d3"));
+})();
+
+
+

+ 10 - 0
JavaScriptHomeWorks/HW2/index.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW2</title>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 147 - 0
JavaScriptHomeWorks/HW2/main.js

@@ -0,0 +1,147 @@
+var a = 5;
+var b, c;
+
+b = (a * 5);
+b = (c = b/2);
+
+b = a *= 5;
+b = c = b / 2;
+
+console.log(b)
+
+for(let i = 0 i < 10 i++) {
+    console.log(i)
+}
+
+const num1 = 110 num2 = num1 + 54
+
+const obj = {}
+(function () { })()
+let x = (5; + 10)
+console.log(x)
+
+let age1 = prompt('how old are you?');
+alert(`you were born in ${2022 - age1}`)
+// (0 °C × 9/5) + 32 = 32 °F
+let celsius = prompt('Enter the temperature in ℃')
+alert(`${celsius * 1.8 + 32} fahrenheit`);
+
+let num1 = prompt('enter the number to divide')
+let num2 = prompt('enter another number')
+alert(Math.floor(num1 / num2));
+
+let number = +prompt('enter the number');
+
+if(!isNaN(number)) {
+    console.log('it\'s a number')
+    if(number % 2 === 0) {
+        console.log('the number is even')
+    } else {
+        console.log('the number is odd')
+    }
+} else {
+    console.log('It\'s not a number!')
+}
+
+let name = prompt('What\'s your name?')
+alert(`Hello, ${name}!`)
+
+let str = prompt('Enter message')
+
+if(str.includes('shit')) {
+    console.log('Hey, it\'s inappropriate')
+}
+
+let isSpeakingSpanish = confirm('Do you speak Spanish?')
+isSpeakingSpanish ? console.log('Hola, amigo!') : console.log('So let\'s learn it!')
+
+let isMan = confirm('Are you a man?')
+let isMarried = confirm('Are you married?')
+let hasChildren = confirm('Do you have children?')
+
+
+let question = confirm('are you a woman?');
+let isWoman = question;
+console.log(isWoman);
+if(isWoman) {
+ alert('you`re a woman')
+ } else {
+ alert('you`re a man');
+}
+
+let shoppingCart = ['avocado', 'milk', 'lemon', 'cheese', 'tea'];
+const answers = [isMan, isMarried, hasChildren, isWoman]
+
+let numbers = [1, 2, 5, 4, 5];
+
+numbers.splice(2, 1,numbers[0] + numbers[1])
+
+console.log(numbers)
+
+let array = ['he', 'l', 'lo']
+array.join('');
+
+let dog = {
+    gender: 'male',
+    breed: 'chihuahua',
+    name: 'Ronnie',
+    age: 6,
+    ['favorite food']: ['cheese', 'meat', 'tomatoes'],
+    hasChildren: false
+}
+
+dog["favorite food"].push('egg yolk')
+
+let age = +prompt("Сколько вам лет?","");
+
+if(age < 0) {
+    alert('возраст не может быть отрицательным')
+} else if (age < 18) {
+    alert("школьник");
+} else if (age > 18 && age < 30) {
+    alert("молодежь");
+} else if (age > 30 && age < 45) {
+    alert("зрелость");
+} else if (age > 45 && age < 60){
+    alert("закат");
+} else if (age > 60){
+    alert("как пенсия?");
+} else {
+    alert("то ли киборг, то ли KERNESS");
+}
+let size = +prompt('введите размер обуви дял конвертации в UK')
+switch (size) {
+    case 35:
+        alert(3.5);
+        break;
+    case 36:
+        alert(4);
+        break;
+    case 37:
+        alert(5);
+        break;
+    case 38:
+        alert(6);
+        break;
+    case 39:
+        alert(6.5);
+        break;
+    case 40:
+        alert(7);
+        break;
+    default:
+        alert('something went wrong')
+}
+isWoman ? alert('you`re a woman') : alert('you`re a man');
+
+
+let flatNumber = +prompt('Введите номер квартиры')
+let flatsPerFloor = +prompt('Сколько квартир на этаже?')
+let porchesPerHouse = +prompt('Сколько подъездов в доме?')
+let floorsPerHouse = +prompt('Сколько этажей в доме?')
+
+let flatsPerEntrance = flatsPerFloor * floorsPerHouse;
+let entrance = Math.floor((flatNumber - 1) / flatsPerEntrance + 1)
+let floor = Math.floor((flatNumber - 1) % flatsPerEntrance / flatsPerFloor + 1)
+
+alert(`Flat No.${flatNumber} is on floor ${floor}, entrance ${entrance}`)

+ 10 - 0
JavaScriptHomeWorks/HW3/index.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW3</title>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 250 - 0
JavaScriptHomeWorks/HW3/main.js

@@ -0,0 +1,250 @@
+let task = prompt('enter task name').toLowerCase();
+
+switch (task) {
+    case 'switch: sizes':
+        let size = +prompt('введите размер обуви дял конвертации в UK')
+        switch (size) {
+            case 35:
+                alert(3.5);
+                break;
+            case 36:
+                alert(4);
+                break;
+            case 37:
+                alert(5);
+                break;
+            case 38:
+                alert(6);
+                break;
+            case 39:
+                alert(6.5);
+                break;
+            case 40:
+                alert(7);
+                break;
+            default:
+                alert('something went wrong')
+        }
+        break;
+
+    case 'switch: if':
+        let color = prompt("Введите цвет","");
+        if(color === "red") {
+            document.write("<div style='background-color: red;'>красный</div>")
+        } else if(color === "black") {
+            document.write("<div style='background-color: black; color: white;'>черный</div>")
+        } else if(color === "blue") {
+            document.write("<div style='background-color: blue;'>синий</div>")
+        } else if(color === "green") {
+            document.write("<div style='background-color: green;'>зеленый</div>")
+        } else {
+            document.write("<div style='background-color: gray;'>Я не понял</div>")
+        }
+        break;
+
+    case 'prompt: or':
+        let age1 = prompt('how old are you?');
+        if(age1 === '' || age1 === null) {
+            alert('something is wrong...')
+        } else {
+            alert(`you were born in ${2022 - age1}`)
+        }
+        break;
+
+    case 'confirm: or this days':
+        let question1 = confirm('Шоппинг?') || alert(' Ты - бяка!');
+        break;
+
+    case 'confirm: if this days':
+        let question2 = confirm('Шоппинг?');
+        if(!question2) {
+            alert(' Ты - бяка!')
+        }
+        break;
+
+    case 'triple prompt':
+        let surname = prompt('Enter surname')
+        let name = prompt('Enter name')
+        let patronymic = prompt('Enter patronymic')
+
+        alert(`${surname} ${name} ${patronymic}`)
+        break;
+
+    case 'default: or':
+        let enteredName = prompt('enter your name');
+        let enteredSurname = prompt('enter your surname');
+
+        enteredName = enteredName || 'Ivan';
+        enteredSurname = enteredSurname || 'Ivanov';
+        break;
+
+    case 'default: if':
+        let enteredName2 = prompt('enter your name');
+        let enteredSurname2 = prompt('enter your surname');
+        if(!enteredSurname2) {
+            enteredSurname2 = 'Ivanov'
+        }
+        if(!enteredName2) {
+            enteredName2 = 'Ivan'
+        }
+        break;
+
+    case 'login and password':
+        const adminName = 'admin';
+        const adminPassword = 'qwerty';
+        let login = prompt('Login: ');
+
+        if(adminName === login) {
+            let password = prompt('Password: ');
+            if(adminPassword === password) {
+                alert('Success!')
+            } else {
+                alert('password is incorrect')
+            }
+        } else {
+            alert('login is incorrect')
+        }
+        break;
+
+    case 'currency calc':
+        let currency1 = prompt('USD or EUR?')
+        let rate1;
+        switch (currency1) {
+            case 'usd':
+                rate1 = 34.67
+                break;
+            case 'eur':
+                rate1 = 37.38
+                break;
+            default:
+                rate1 = 0;
+        }
+        let uah = +prompt('enter UAH to convert');
+        alert(`${(uah / rate1).toFixed(2)} ${currency1}`)
+        break;
+
+    case 'currency calc: improved':
+        let currency2 = prompt('USD or EUR?').toLowerCase();
+        let rate2;
+        switch (currency2) {
+            case 'usd':
+                rate2 = 34.67
+                break;
+            case 'eur':
+                rate2 = 37.38
+                break;
+            default:
+                rate2 = 0;
+        }
+        let uah1 = +prompt('enter UAH to convert');
+        alert(`${(uah1 / rate2).toFixed(2)} ${currency2}`)
+        break;
+
+    case 'currency calc: two rates':
+        let currency3 = prompt('Do you want to use USD or EUR?').toLowerCase()
+        let rate3;
+        let buyRate1 = confirm('Do you want to buy currency?')
+        switch (currency3) {
+            case 'usd':
+                buyRate1 ? rate3 = 36.28 : rate3 = 34.67
+                break;
+            case 'eur':
+                buyRate1 ? rate3 = 41.77 : rate3 = 37.38
+                break;
+            default:
+                alert('error');
+        }
+        let uah2 = +prompt('enter UAH to convert');
+        alert(`${(uah2 / rate3).toFixed(2)} ${currency3}`)
+        break;
+
+    case 'currency calc: if':
+        let currency4 = prompt('Do you want to use USD or EUR?').toLowerCase()
+        if(currency4 === 'usd' || currency4 === 'eur') {
+            let uah4 = +prompt('enter UAH to convert');
+            let rate4;
+            let buyRate2 = confirm('Do you want to buy currency?')
+            if (currency4 === 'usd') {
+                buyRate2 ? rate4 = 36.28 : rate4 = 34.67
+            } else if (currency4 === 'eur') {
+                buyRate2 ? rate4 = 41.77 : rate4 = 37.38
+            } else {
+                alert('error')
+            }
+            alert(`${(uah4 / rate4).toFixed(2)} ${currency4}`)
+        }
+        break;
+
+    case 'scissors':
+
+        let usersTurn = prompt('Rock, paper or scissors?').toLowerCase();
+        let turns = ['rock', 'paper', 'scissors'];
+        const randomIndex  = Math.floor(Math.random() * 3)
+        let computersTurn = turns[randomIndex]
+        console.log(computersTurn)
+
+        if(usersTurn === computersTurn) {
+            alert('It\'s a tie!')
+        } else if(usersTurn === 'paper' && computersTurn === 'scissors') {
+            alert('computer won');
+        } else if(usersTurn === 'scissors' && computersTurn === 'rock') {
+            alert('computer won');
+        } else if(usersTurn === 'rock' && computersTurn === 'paper') {
+            alert('computer won')
+        } else if(computersTurn === 'paper' && usersTurn === 'scissors') {
+            alert('you won');
+        } else if(computersTurn === 'scissors' && usersTurn === 'rock') {
+            alert('you won');
+        } else if(computersTurn === 'rock' && usersTurn === 'paper') {
+            alert('you won')
+        } else {
+            alert('error')
+        }
+        break;
+
+    case 'задание на синий пояс':
+        let ratios = {
+            usdToBuy: 36.28,
+            eurToBuy: 41.77,
+            usdToSell: 34.67,
+            eurToSell: 37.38
+        }
+        let currency5 = prompt('Do you want to use USD or EUR?').toLowerCase()
+        if(currency5 === 'usd' || currency5 === 'eur') {
+            let rate;
+            let uah = +prompt('enter UAH to convert');
+            let buyRate = confirm('Do you want to buy currency?')
+            if (currency5 === 'usd') {
+                rate = buyRate ? ratios["usdToBuy"] : ratios["usdToSell"]
+            } else if (currency5 === 'eur') {
+                rate = buyRate ? ratios["eurToBuy"] : ratios["eurToSell"]
+            } else {
+                alert('error')
+            }
+            alert(`${(uah / rate).toFixed(2)} ${currency5}`)
+        }
+        break;
+
+    case 'real data':
+        let currency = prompt('Enter the currency name to convert (e.g. USD)').toUpperCase()
+            let uah3 = +prompt('enter UAH to convert');
+            fetch('https://open.er-api.com/v6/latest/' + currency)
+                .then(res => res.json())
+                .then(data => {
+                    alert(`${(uah3 / data.rates.UAH).toFixed(2)} ${currency}`)
+                })
+        break;
+
+    case 'задание на черный пояс':
+        let usersTurn1 = prompt('Rock, paper or scissors?').toLowerCase();
+        let turns1 = ['rock', 'paper', 'scissors'];
+        const randomIndex1  = Math.floor(Math.random() * 3)
+        let computersTurn1 = turns1[randomIndex1]
+        console.log(computersTurn1)
+        let compWin = usersTurn1 === 'paper' && computersTurn1 === 'scissors' || usersTurn1 === 'scissors' && computersTurn1 === 'rock' || usersTurn1 === 'rock' && computersTurn1 === 'paper';
+        let userWin = computersTurn1 === 'paper' && usersTurn1 === 'scissors' || computersTurn1 === 'scissors' && usersTurn1 === 'rock' || computersTurn1 === 'rock' && usersTurn1 === 'paper';
+        let tie = usersTurn1 === computersTurn1 && alert('It\'s a tie!')
+        let victory = compWin && alert('computer won') || userWin && alert('you won');
+        break;
+};
+

+ 10 - 0
JavaScriptHomeWorks/HW4/index.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW4</title>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 201 - 0
JavaScriptHomeWorks/HW4/main.js

@@ -0,0 +1,201 @@
+let body = {
+    tagName: 'body',
+    children: [
+        {
+            tagName: 'div',
+            children: [
+                {
+                    tagName: 'span',
+                    innerText: 'Enter a data please:'
+                },
+                {
+                    tagName: 'br'
+                },
+                {
+                    tagName: 'input',
+                    type: 'text',
+                    id: 'name'
+                },
+                {
+                    tagName: 'input',
+                    type: 'text',
+                    id: 'surname'
+                }
+            ]
+        },
+        {
+            tagName: 'div',
+            children: [
+                {
+                    tagName: 'button',
+                    innerText: 'OK',
+                    id: 'ok'
+                },
+                {
+                    tagName: 'button',
+                    innerText: 'Cancel',
+                    id: 'cancel'
+                }
+            ]
+        }
+    ]
+};
+
+console.log(body.children[1].children[1].innerText)
+console.log(body.children[0].children[3].id)
+
+
+var person;
+var notebook = {
+    brand: prompt('Brand:'),
+    type:  prompt('Type:'),
+    model: prompt('Model:'),
+    ram: +prompt('Ram:'),
+    size: +prompt('Size:'),
+    weight: +prompt('Weight:'),
+    resolution: {
+        width: +prompt('Resolution width:'),
+        height: +prompt('Resolution height:'),
+    },
+    owner: person
+};
+
+var phone = {
+    brand: prompt('Brand:'),
+    model: prompt('Model:'),
+    ram: +prompt('Ram:'),
+    color: prompt('Color:'),
+    owner: person
+};
+
+person = {
+    name: prompt('Name:'),
+    surname: prompt('Surname:'),
+    married: confirm('Married?'),
+    smartphone: phone,
+    laptop: notebook
+};
+
+let array1 = []
+array1[0] = prompt('string 1');
+array1[1] = prompt('string 2');
+array1[2] = prompt('string 3');
+
+let confirm1;
+while(!confirm1) {
+    confirm1 = confirm('Are you hungry?');
+    if(confirm1) {
+        break;
+    }
+}
+
+let prompt1;
+let array2 = []
+while(prompt1 !== null) {
+    prompt1 = prompt('Enter something');
+    array2.push(prompt1)
+    if(!prompt1) {
+        break
+    }
+    console.log(array2)
+}
+
+
+let prompt2 = prompt('Enter something');
+let array3 = []
+do {
+    let i = 0;
+    prompt2 ? array3[i++] = prompt2 : null
+    console.log(array3)
+} while(prompt2 !== null)
+
+let i = 0;
+let n;
+while(n !== 5) {
+    i++
+    let n = Math.random() * 5;
+    console.log(n)
+    console.log(i)
+    if(n === 5) {
+        break
+    }
+}
+let end = +prompt('Введите крайнее число прогрессии')
+let sum = 0;
+for(let i = 1; i < 30; i+=3){
+    console.log(i)
+    sum += i
+}
+alert(`Сумма чисел в прогрессии - ${sum}`);
+
+let chessString = '';
+
+for(let i = 0; i < 10; i++) {
+    i % 2 === 0 ? chessString += ' ' : chessString += '#'
+}
+console.log(chessString);
+
+let numbers2 = '';
+
+for(let i = 0; i < 10; i++) {
+    numbers2 += '\n'
+    for(let j = 0; j < 10; j++) {
+        numbers2 += j
+    }
+}
+console.log(numbers2)
+
+let height = 8;
+let width = 10;
+let board = "";
+
+for (let i = 0; i < height; i++) {
+    if(i > 0) board += "\n";
+    for (let j = 0; j < width; j++) {
+        if ((j + i) % 2 === 0){
+            board += ".";
+        } else {
+            board += "#";
+        }
+    }
+}
+
+console.log(board);
+
+let numbers = [];
+for(let i = 0; i < 15; i++) {
+    numbers.push(Math.pow(i, 3));
+}
+
+console.log(numbers)
+
+let multiplyTable = [];
+for(let i = 0; i <= 9; i++) {
+    let nestedArr = []
+    multiplyTable.push(nestedArr)
+    for(let j = 0; j <= 9; j++) {
+        nestedArr.push([j * i])
+    }
+}
+console.log(multiplyTable[5][6])
+
+
+let table = document.createElement('table')
+for(let i = 1; i <= 9; i++) {
+    let tr = document.createElement('tr');
+    for(let j = 1; j <= 9; j++) {
+        let td = document.createElement('td')
+        td.innerHTML = String(j * i)
+        tr.appendChild(td)
+    }
+    table.appendChild(tr)
+}
+
+document.body.appendChild(table)
+
+
+
+
+
+
+

+ 17 - 0
JavaScriptHomeWorks/HW5/index.html

@@ -0,0 +1,17 @@
+<!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">
+    <title>HW5</title>
+    <style>
+        tr:nth-child(odd) {
+            background-color: aquamarine;
+        }
+    </style>
+</head>
+<body>
+<script src='main.js'></script>  
+</body>
+</html>

+ 131 - 0
JavaScriptHomeWorks/HW5/main.js

@@ -0,0 +1,131 @@
+let a = {
+    name: 'Olga',
+    surname: 'Kosareva'
+}
+let b = {
+    name: 'Elena',
+    surname: 'Krasnik'
+}
+let c = {
+    name: 'Leonid',
+    surname: 'Onoprienko'
+}
+
+a.age = 42;
+b.fatherName = 'Igorevna'
+c.sex = 'male'
+
+
+let arrofPersons = [a, b, c, {name: 'Anatoly', surname: 'Petrenko', age: 30}]
+
+for(let i = 0; i < arrofPersons.length; i++) {
+    console.log(arrofPersons[i]);
+}
+
+for(let person of arrofPersons) {
+    console.log(person.surname + ' ' + person.name);
+}
+
+for(let i = 0; i < arrofPersons.length; i++) {
+   for (let key in arrofPersons[i]) {
+        console.log(arrofPersons[i][key]);
+    }
+}
+
+for(let obj of arrofPersons) {
+    if(obj.name && obj.surname) {
+        obj.fullName = obj.name + ' ' + obj.surname
+    }
+ }
+console.log(arrofPersons);
+
+JSON.stringify(arrofPersons);
+
+
+// let str = "<table border='1'>"
+// arrofPersons.map(person => {
+//     str += `<tr><td>${person.name}</td><td>${person.surname}</td></tr>`
+// })
+// str += '</table>'
+// document.write(str)
+
+
+let str = "<table border='1'>"
+arrofPersons.map(person => {
+    str += `<tr>`
+    Object.values(person).map(value => str += `<td>${value}</td>`)
+    str += `</tr>`
+})
+str += '</table>'
+document.write(str)
+
+var someTree = {
+    tagName: "table", //html tag
+    subTags: [ //вложенные тэги
+        {
+                    tagName: "tr",
+                    subTags: [
+                        {
+                            tagName: "td",
+                            text: "some text",
+                        },
+                        {
+                            tagName: "td",
+                            text: "some text 2",
+                        }
+                    ]
+        }
+    ],
+    attrs:
+    {
+        border: 1,
+    },
+}
+
+let table = `<${someTree.tagName} ${Object.keys(someTree.attrs)[0]}=${Object.values(someTree.attrs)}>`
+
+for(let subTag of someTree.subTags) {
+    table += `<${subTag.tagName}>`
+    for(let innerTag of subTag.subTags) {
+        table += `<${innerTag.tagName}>${innerTag.text}</${innerTag.tagName}>`
+    }
+}
+table += `</${someTree.tagName}>`
+document.write(table);
+
+let arr = [1,2,3,4,5, "a", "b", "c"]
+
+let [odd1, even1, odd2, even2, odd3, ...letters] = arr
+
+let arr2 = [1, "abc"]
+
+let [number, [s1, s2, s3]] = arr2
+
+let obj = {
+    name: 'Ivan',
+    surname: 'Petrov',
+    children: [
+        {name: 'Maria'},
+        {name: 'Nikolay'}
+    ]
+}
+
+let {
+    children:
+        [{name: name1}, {name: name2}]} = obj
+
+
+let arr3 = [1,2,3,4, 5,6,7,10];
+
+let [first, second, {length = arr3.length}] = arr3
+
+
+
+
+
+
+
+
+
+
+

+ 10 - 0
JavaScriptHomeWorks/HW6/index.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW6</title>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 84 - 0
JavaScriptHomeWorks/HW6/main.js

@@ -0,0 +1,84 @@
+function a(text) {
+    alert(text)
+}
+
+function cube(n) {
+    return Math.pow(n, 3)
+}
+
+function avg2(a, b) {
+    return (a + b) / 2
+}
+
+function sum3(a, b, ...c) {
+    return a + b + +c
+}
+function intRandom(min = 0, max = 10) {
+    return Math.round(Math.random() * (max - min - 1) + min)
+}
+
+// function greetAll(...arguments) {
+//     for(let arg of arguments) {
+//         alert(`Hello, ${arg}!`)
+//     }
+// }
+
+function greetAll(...arguments) {
+    arguments = arguments.map(item => ' ' + item)
+    alert(`Hello, ${arguments}!`)
+
+}
+function sum(...arguments) {
+    let result = 0
+    for(let num of arguments) {
+        result += num
+    }
+    return result
+}
+
+var sample = prompt("Введите название задания")
+
+switch (sample.toLowerCase()){
+    case "a": a('Test prompt')
+        break
+    case "cube": cube(5)
+        break
+    case 'avg2': avg2(55, 17)
+        break
+    case 'sum3': sum3(5, 82, 47)
+        break
+    case 'intRandom': intRandom(1, 105)
+        break
+    case 'greetAll': greetAll('Sonya', 'Kerry', 'Eve')
+        break
+    case 'sum': sum(45, 741, 32, 14)
+        break
+    default:
+        a()
+}
+
+let sampleObj = {
+        a() {
+            a('Test prompt')
+        },
+        cube() {
+            cube(50)
+        },
+        avg2() {
+            avg2(55, 17)
+        },
+        sum3() {
+            sum3(5, 82, 47)
+        },
+        intRandom() {
+            intRandom(1, 50)
+        },
+        greetAll() {
+            greetAll('Sonya', 'Kerry', 'Eve')
+        },
+        sum() {
+            sum(45, 741, 32, 14)
+        },
+    };
+
+console.log(sampleObj[prompt("Введите название задания")]());

+ 20 - 0
JavaScriptHomeWorks/HW7/index.html

@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW7</title>
+    <style>
+        table td {
+            padding: 5px;
+            border: 1px solid grey;
+        }
+    </style>
+</head>
+<body>
+    <input type="number" id="n1">
+    <input type="number" id="n2">
+    <button id="calcBtn">sum</button>
+    <div id="result"></div>
+<script src="main.js"></script>
+</body>
+</html>

+ 53 - 0
JavaScriptHomeWorks/HW7/main.js

@@ -0,0 +1,53 @@
+let $table = document.createElement('table');
+
+function rerenderColor(e, color) {
+    Array.from($table.children).map(item => {
+        Array.from(item.children).filter(item => item.cellIndex === e.target.cellIndex).map(item => item.style.backgroundColor = color)
+    })
+}
+
+for(let i = 1; i < 10; i++) {
+    let $tr = document.createElement('tr')
+
+    for(let j = 1; j < 10; j++) {
+        // $td.addEventListener('mouseover', (e) => rerenderColor(e, 'blue'))
+        // $td.addEventListener('mouseout', (e) => rerenderColor(e, 'transparent'))
+        let $td = document.createElement('td')
+        $td.innerText = String(j * i)
+
+        $td.addEventListener('mouseover', (e) => {
+            rerenderColor(e, 'red')
+
+            $td.style.backgroundColor = 'green'
+        })
+        $td.addEventListener('mouseout', (e) => rerenderColor(e, 'transparent'))
+        $tr.appendChild($td)
+    }
+    $table.appendChild($tr)
+}
+document.body.appendChild($table)
+
+const $n1 = document.querySelector('#n1')
+const $n2 = document.querySelector('#n2')
+const $calcBtn = document.querySelector('#calcBtn')
+const $result = document.querySelector('#result')
+
+const calcSum = () => {
+    return $result.innerText = String(+$n1.value + +$n2.value)
+}
+
+$calcBtn.addEventListener( 'click',  () => {
+    calcSum()
+})
+$n1.onchange = calcSum()
+$n2.onchange = calcSum()
+$calcBtn.onclick = calcSum()
+
+
+
+
+
+
+
+
+

+ 10 - 0
JavaScriptHomeWorks/HW8/index.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW8</title>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 118 - 0
JavaScriptHomeWorks/HW8/main.js

@@ -0,0 +1,118 @@
+//SORT
+
+var persons = [
+    {name: "Иван", age: 17},
+    {name: "Мария", age: 35},
+    {name: "Алексей", age: 73},
+    {name: "Яков", age: 12},
+]
+
+function sort(arr, type, bool = true) {
+    return arr.sort((a, b) => {
+        let res;
+        if (bool) {
+            console.log('true')
+            res = a[type] > b[type] ? 1 : -1;
+        } else {
+            console.log('false')
+            res = a[type] < b[[type]] ? 1 : -1;
+        }
+        return res
+    })
+}
+console.log(sort(persons, 'name', false))
+
+
+//ARRAY MAP
+let someArr = ["1", {}, null, undefined, "500", 700];
+
+let newArr = someArr.map(item => typeof item === 'string' ? +item : item)
+console.log(newArr)
+
+
+//ARRAY REDUCE
+let reduceArr = ["0", 5, 3, "string", null];
+let reducedArr = reduceArr.filter(item => typeof item === 'number').reduce((acc, curr) => acc *= curr)
+console.log(reducedArr)
+
+
+//OBJECT FILTER
+var phone = {
+    brand: "meizu",
+    model: "m2",
+    ram: 2,
+    color: "black",
+};
+
+function filter(obj, callback) {
+    let filteredObj = {}
+    for(let key in obj) {
+        if (callback(key, obj[key])) {
+            filteredObj = {...filteredObj, [key]: obj[key]}
+        }
+      }
+        return filteredObj
+}
+
+console.log(filter(phone,(key,value) => key === "color" || value === 2))
+
+
+//OBJECT MAP
+function map(obj, callback) {
+    let res = {};
+    for(let key in obj) {
+        res = { ...res, ...callback(key, obj[key]) }
+    }
+    return res
+}
+
+let test = map({name: "Иван", age: 17},function(key,value){
+    var result = {};
+    result[key+"_"] = value + "$";
+    return result;
+})
+console.log(test)
+
+
+//SUM
+function geomProgressionCalc(min, max, step){
+    if (max <= 0) return 0;
+    return geomProgressionCalc(min + step,max -1, step) + min
+}
+
+console.log(geomProgressionCalc(10, 20, 2))
+
+//HTML TREE RECURSION
+let $table = document.createElement('table');
+
+function rerenderColor(e, color) {
+    Array.from($table.children).map(item => {
+        Array.from(item.children).filter(item => item.cellIndex === e.target.cellIndex).map(item => item.style.backgroundColor = color)
+    })
+};
+
+let i = 10;
+function createRow() {
+    i--
+    let $tr = document.createElement('tr')
+
+    let j = 1;
+    function createCell() {
+        j++
+        let $td = document.createElement('td');
+        $td.innerText = String(j * i)
+        $td.addEventListener('mouseover', (e) => {
+            rerenderColor(e, 'red')
+            $td.style.backgroundColor = 'green'
+        })
+        $td.addEventListener('mouseout', (e) => rerenderColor(e, 'transparent'))
+        $tr.appendChild($td)
+        if(j < 9) createCell()
+    }
+    $table.appendChild($tr)
+    createCell()
+    if(i > 1) createRow();
+}
+
+createRow()
+document.body.appendChild($table);

+ 10 - 0
JavaScriptHomeWorks/HW9/index.html

@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="UTF-8">
+    <title>HW9</title>
+</head>
+<body>
+<script src="main.js"></script>
+</body>
+</html>

+ 62 - 0
JavaScriptHomeWorks/HW9/main.js

@@ -0,0 +1,62 @@
+function makeProfileTimer() {
+    let start = performance.now();
+    return function() {
+        let end = performance.now();
+        return end - start
+    };
+}
+
+let timer = makeProfileTimer();
+
+alert("Замеряем время работы этого alert");
+alert(`This code took ${timer()}ms`);
+
+function makeSaver(data){
+    let promptShowed = false;
+    let newData;
+    return () => {
+        if(!promptShowed) {
+            promptShowed = true;
+            return newData = data()
+        }
+    }
+}
+var saver = makeSaver(Math.random)
+var value1 = saver()
+var value2 = saver()
+console.log(value1, value2)
+console.log(value1 === value2 )
+var saver2 = makeSaver(() => console.log('saved function called') || [null, undefined, false, '', 0, Math.random()][Math.ceil(Math.random()*6)])
+var value3 = saver2()
+var value4 = saver2()
+console.log(value3 === value4)
+
+let namePrompt = prompt.bind(window, 'Как тебя зовут?')
+let nameSaver = makeSaver(namePrompt)
+
+alert(`Привет! Prompt еще не было!`)
+alert(`Привет ${nameSaver()}. Только что запустился prompt, первый и последний раз`)
+alert(`Слушай, ${nameSaver()}, го пить пиво. Ведь prompt был только один раз`)
+
+let count = 5;
+function timer2() {
+    console.log(count);
+    const timeout = setTimeout(() => {
+        timer();
+    }, 1000);
+    if (count > 0) {
+        return (() => {
+            return count--;
+        })();
+    }
+    clearTimeout(timeout);
+    if (count === 0) {
+        console.log("поехали!");
+    }
+}
+timer2();
+
+
+
+
+

BIN
JavaScriptHomeWorks/JsModule/Loading_icon.gif


+ 132 - 0
JavaScriptHomeWorks/JsModule/index.html

@@ -0,0 +1,132 @@
+<!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">
+  <title>Module Shop</title>
+  <style>
+    body {
+      font-family: system-ui;
+      padding: 0;
+    }
+    header {
+      height: 50px;
+      display: flex;
+      align-items: center;
+      justify-content: space-around;
+    }
+    header a {
+      margin: 5px 10px;
+      border: 1px solid grey;
+      padding: 5px 10px;
+    }
+    a {
+      text-decoration: none;
+      color: black;
+      padding: 5px 10px;
+      transition-property: transform, border-radius;
+      transition-duration: .5s;
+    }
+    .cat {
+      color: grey;
+    }
+    img {
+      max-width: 150px;
+    }
+    #userBox {
+      display: flex;
+      align-items: baseline;
+      flex-direction: row-reverse;
+    }
+
+    #authBox {
+      display: flex;
+      min-width: 150px;
+      justify-content: space-between;
+    }
+    aside {
+      display: flex;
+      flex-direction: column;
+      margin-right: 150px;
+    }
+    aside > a {
+      margin-bottom: 15px;
+    }
+
+    #mainContainer {
+      display: flex;
+    }
+    button, .loginBtn  {
+      margin: 5px 10px;
+      border: 1px solid #FB8F1D;
+      padding: 5px 10px;
+      background-color: sandybrown;
+      color: white;
+      font-size: 16px;
+      font-family: system-ui;
+    }
+    .showMore, #userBox > a {
+      margin: 5px 10px;
+      border: 1px solid #FB8F1D;
+      padding: 5px 10px;
+    }
+    a:hover {
+      transform: translateY(5px);
+      box-shadow: 0 0 11px sandybrown;
+      border-radius: 8px;
+      animation-delay: .5s;
+    }
+    .card {
+      padding: 15px 20px;
+      margin: 35px;
+      border: 1px solid lightgrey;
+      border-radius: 20px;
+      display: flex;
+      transition-property: transform;
+      transition-duration: .5s;
+      width: 400px;
+      justify-content: space-between;
+    }
+    .card:hover {
+      transform: translateX(10px);
+    }
+    button:hover {
+      color: #FB8F1D;
+      background-color: white;
+      box-shadow: 0 0 11px sandybrown;
+    }
+
+  </style>
+</head>
+
+<body>
+
+  <header>
+
+    <a href="">Main</a>
+      <a id="cartIcon" href="#/cart">
+        Cart
+        <span id="cartCounter"></span>
+      </a>
+      <div id="userBox"></div>
+    <div id="authBox"></div>
+    </div>
+  </header>
+
+
+  <div id='mainContainer'>
+    <aside id='aside'>
+    </aside>
+
+    <main id='main'>
+      <h3>Welcome to our shop! Let's find something for you :)</h3>
+    </main>
+
+  </div>
+
+</div>
+  <script src='index.js'></script>
+</body>
+
+</html>

+ 715 - 0
JavaScriptHomeWorks/JsModule/index.js

@@ -0,0 +1,715 @@
+
+function createStore(reducer){
+    let state       = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
+    let cbs         = []                     //массив подписчиков
+
+    const getState  = () => state            //функция, возвращающая переменную из замыкания
+    const subscribe = cb => (cbs.push(cb),   //запоминаем подписчиков в массиве
+        () => cbs = cbs.filter(c => c !== cb)) //возвращаем функцию unsubscribe, которая удаляет подписчика из списка
+
+    const dispatch  = action => {
+        if (typeof action === 'function'){ //если action - не объект, а функция
+            return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
+        }
+        const newState = reducer(state, action) //пробуем запустить редьюсер
+        if (newState !== state){ //проверяем, смог ли редьюсер обработать action
+            state = newState //если смог, то обновляем state
+            for (let cb of cbs)  cb() //и запускаем подписчиков
+        }
+    }
+
+    return {
+        getState, //добавление функции getState в результирующий объект
+        dispatch,
+        subscribe //добавление subscribe в объект
+    }
+}
+
+function combineReducers(reducers) {
+    return (state={}, action) => {
+        const newState = {}
+        // перебрать все редьюсеры
+        if (reducers) {
+            for (const [reducerName, reducer] of Object.entries(reducers)) {
+                const newSubState = reducer(state[reducerName], action)
+                if (newSubState !== state[reducerName]) {
+                    newState[reducerName] = newSubState
+                }
+            }
+            // если newState не пустой, то вернуть стейт в
+            if (Object.keys(newState).length !== 0) {
+                return {...state, ...newState}
+            } else {
+                return state
+            }
+        }
+
+    }
+}
+
+const combinedReducer = combineReducers({promise: promiseReducer, auth: authReducer, cart: cartReducer})
+const store = createStore(combinedReducer)
+
+store.subscribe(() => console.log(store.getState()))
+
+
+
+function jwtDecode(token){
+    try {
+        return JSON.parse(atob(token.split('.')[1]))
+    }
+    catch(e){
+    }
+}
+
+function authReducer(state, {type, token}) {
+    if (!state) {
+        if (localStorage.authToken) {
+            token = localStorage.authToken
+            type = 'AUTH_LOGIN'
+        } else {
+            return {}
+        }
+    }
+    if (type === 'AUTH_LOGIN') {
+        let payload = jwtDecode(token)
+        if (typeof payload === 'object') {
+            localStorage.authToken = token
+            return {
+                ...state,
+                token,
+                payload
+            }
+        } else {
+            return state
+        }
+    }
+    if (type === 'AUTH_LOGOUT') {
+        delete localStorage.authToken
+        location.reload()
+        return {}
+    }
+    return state
+}
+
+const actionAuthLogin = (token) => ({type: 'AUTH_LOGIN', token})
+const actionAuthLogout = () => ({type: 'AUTH_LOGOUT'})
+
+
+
+function cartReducer (state={}, {type, good={}, count=1}) {
+
+    if (Object.keys(state).length === 0 && localStorage.cart) {
+        let currCart = JSON.parse(localStorage.cart)
+        if (currCart && Object.keys(currCart).length !== 0) {
+            state = currCart
+        }
+    }
+
+    const {_id} = good
+
+    const types = {
+        CART_ADD() {
+            count = +count
+            if (!count) {
+                return state
+            }
+            let newState = {
+                ...state,
+                [_id]: {good, count: (count + (state[_id]?.count || 0)) < 1 ? 1 : count + (state[_id]?.count || 0)}
+            }
+            localStorage.cart = JSON.stringify(newState)
+            return newState
+        },
+        CART_CHANGE() {
+            count = +count
+            if (!count) {
+                return state
+            }
+            let newState = {
+                ...state,
+                [_id]: {good, count: count < 0 ? 0 : count}
+            }
+            localStorage.cart = JSON.stringify(newState)
+            return newState
+        },
+        CART_REMOVE() {
+            let { [_id]: removed, ...newState }  = state
+            localStorage.cart = JSON.stringify(newState)
+            return newState
+        },
+        CART_CLEAR() {
+            localStorage.cart = JSON.stringify({})
+            return {}
+        },
+    }
+    if (type in types) {
+        return types[type]()
+    }
+    return state
+}
+
+const actionCartAdd = (good, count) => ({type: 'CART_ADD', good, count})
+const actionCartChange = (good, count) => ({type: 'CART_CHANGE', good, count})
+const actionCartRemove = (good) => ({type: 'CART_REMOVE', good})
+const actionCartClear = () => ({type: 'CART_CLEAR'})
+
+
+function promiseReducer(state={}, {type, status, payload, error, name}) {
+    if (!state) {
+        return {}
+    }
+    if (type === 'PROMISE') {
+        return {
+            ...state,
+            [name]: {
+                status: status,
+                payload : payload,
+                error: error,
+            }
+        }
+    }
+    return state
+}
+
+const actionPending = (name) => ({type: 'PROMISE', status: 'PENDING', name})
+const actionResolved = (name, payload) => ({type: 'PROMISE', status: 'RESOLVED', name, payload})
+const actionRejected = (name, error) => ({type: 'PROMISE', status: 'REJECTED', name, error})
+
+
+const actionPromise = (name, promise) => (
+    async (dispatch) => {
+        dispatch(actionPending(name))
+        try {
+            let data = await promise
+            dispatch(actionResolved(name, data))
+            return data
+        }
+        catch(error){
+            dispatch(actionRejected(name, error))
+        }
+    }
+)
+
+const getGQL = url => (
+    async (query, variables={}) => {
+        let obj = await fetch(url, {
+            method: 'POST',
+            headers: {
+                "Content-Type": "application/json",
+                ...(localStorage.authToken ? {Authorization: "Bearer " + localStorage.authToken} : {})
+            },
+            body: JSON.stringify({ query, variables })
+        })
+        let a = await obj.json()
+        if (!a.data && a.errors) {
+            throw new Error(JSON.stringify(a.errors))
+        } else {
+            return a.data[Object.keys(a.data)[0]]
+        }
+    }
+)
+
+const backURL = 'http://shop-roles.node.ed.asmer.org.ua/'
+const gql = getGQL(backURL + 'graphql');
+
+
+
+const actionOrder = () => (
+    async (dispatch, getState) => {
+        let {cart} = getState()
+
+        const orderGoods = Object.entries(cart)
+            .map(([_id, {good, count}]) => ({good: {_id}, count}))
+
+        let result = await dispatch(actionPromise('order', gql(`
+                  mutation newOrder($order:OrderInput){
+                    OrderUpsert(order:$order)
+                      { _id total}
+                  }
+          `, {order: {orderGoods}})))
+        if (result?._id) {
+            dispatch(actionCartClear())
+        }
+    })
+
+
+
+
+
+const actionLogin = (login, password) => (
+    actionPromise('login', gql(`query log($login: String, $password: String) {
+        login(login: $login, password: $password)
+    }`, {login, password}))
+)
+
+const actionFullLogin = (login, password) => (
+    async (dispatch) => {
+        let token = await dispatch(actionLogin(login, password))
+        if (token) {
+            dispatch(actionAuthLogin(token))
+            location.hash = '#/category'
+        } else {
+            showErrorMessage('please, enter correct login and password', main)
+        }
+    }
+)
+
+
+const actionRegister = (login, password) => (
+    actionPromise('register', gql(`mutation reg($user:UserInput) {
+        UserUpsert(user:$user) {
+        _id 
+        }
+    }
+    `, {user: {login, password}})
+    )
+)
+
+const actionFullRegister = (login, password) => (
+    async (dispatch) => {
+        let registerId = await dispatch(actionRegister(login, password))
+
+        if (registerId) {
+            dispatch(actionFullLogin(login, password))
+        }
+    }
+)
+
+
+
+const actionRootCats = () => (
+    actionPromise('rootCats', gql(`query {
+        CategoryFind(query: "[{\\"parent\\":null}]"){
+            _id name
+        }
+    }`))
+)
+
+const actionCatById = (_id) => (
+    actionPromise('catById', gql(`query catById($q: String){
+        CategoryFindOne(query: $q){
+            _id name goods {
+                _id name price images {
+                    url
+                }
+            }
+            subCategories {
+                _id name 
+            }
+        }
+    }`, {q: JSON.stringify([{_id}])}))
+)
+
+const actionGoodById = (_id) => (
+    actionPromise('goodById', gql(`query goodById($q: String) {
+        GoodFindOne(query: $q) {
+            _id name price description images {
+            url
+            }
+        }
+    }`, {q: JSON.stringify([{_id}])}))
+)
+
+const actionGoodsByUser = (_id) => (
+    actionPromise('goodByUser', gql(`query oUser($query: String) {
+        OrderFind(query:$query){
+        _id orderGoods{
+                price count total good{
+                    _id name categories{
+                    name
+                    }
+                    images {
+                        url
+                    }
+                }
+            } 
+            owner {
+            _id login
+            }
+        }
+    }`,
+        {query: JSON.stringify([{___owner: _id}])}))
+)
+
+store.subscribe(() => {
+    const {promise, auth} = store.getState()
+    const {rootCats} = promise
+
+    if (rootCats?.status === 'PENDING') {
+        aside.innerHTML = `<img src="Loading_icon.gif">`
+    } else {
+        if (rootCats?.payload) {
+            aside.innerHTML = ''
+            authBox.innerHTML = ''
+            const regBtn = document.createElement('a')
+            regBtn.href = '#/register'
+            regBtn.innerText = 'Register'
+            const loginBtn = document.createElement('a')
+            loginBtn.className = 'loginBtn'
+            loginBtn.href = `#/login`
+            loginBtn.innerText = 'Login'
+            const logoutBtn = document.createElement('a')
+            logoutBtn.innerText = 'Logout'
+            auth.token ? authBox.append(logoutBtn) : authBox.append(regBtn, loginBtn)
+
+            logoutBtn.onclick = () => {
+                store.dispatch(actionAuthLogout())
+            }
+            for (const {_id, name} of rootCats?.payload) {
+                const link = document.createElement('a')
+                link.href = `#/category/${_id}`
+                link.innerText = name
+                aside.append(link)
+            }
+        }
+    }
+})
+
+store.dispatch(actionRootCats())
+
+
+function createForm(parent, type, callback) {
+let {auth} = store.getState()
+    let res = `<label for="login${type}">Nick</label>
+            <input id="login${type}" type="text"/>
+            <label for="pass${type}">Password</label>
+            <input id="pass${type}" type="password"/>
+      
+        <button id="btn${type}">${type}</button>
+    </div>`
+    parent.innerHTML = res
+    return () => window[`btn${type}`].onclick = () => {
+        store.dispatch(callback(window[`login${type}`].value, window[`pass${type}`].value))
+    }
+}
+
+let message = document.createElement('p')
+function showErrorMessage(text, parent) {
+    message.innerHTML = text
+    parent.append(message)
+    }
+
+
+
+const createCartPage = (parent) => {
+    parent.innerHTML = ''
+    const {cart} = store.getState()
+
+    const clearBtn = document.createElement('button')
+    clearBtn.innerText = "clear all"
+    if(Object.keys(cart).length !== 0) {
+        parent.append(clearBtn)
+    }
+    clearBtn.onclick = () => {
+        store.dispatch(actionCartClear())
+    }
+
+    const cartPage  = document.createElement('div')
+    if(Object.keys(cart).length === 0) {
+        showErrorMessage('Hmm... Let`s add something into the cart!', cartPage)
+    }
+    main.append(cartPage)
+
+    let cartCounter = 0
+    for(const item in cart) {
+        const {good} = cart[item]
+        const {count, good: {_id: id, name: name, price: price, images: [{url}]}} = cart[item]
+
+        cartCounter += count*price
+
+        const card = document.createElement('div')
+        card.innerHTML = `
+                        <h4>${name}</h4>
+                        </div>
+                        <img src="${backURL}/${url}" />
+                        <p>amount: </p>                                
+                        `
+
+        const inputGr = document.createElement('div')
+        card.lastElementChild.append(inputGr)
+
+        const minusBtn = document.createElement('button')
+        minusBtn.innerText = '-'
+        inputGr.append(minusBtn)
+        minusBtn.onclick = () => {
+            store.dispatch(actionCartAdd(good, -1))
+        }
+
+        const changeCount = document.createElement('input')
+        changeCount.type = 'number'
+        changeCount.value = count
+        changeCount.setAttribute('min', '1')
+        inputGr.append(changeCount)
+        changeCount.oninput = () => {
+            store.dispatch(actionCartChange(good, changeCount.value))
+        }
+
+        const plusBtn = document.createElement('button')
+        plusBtn.innerText = '+'
+        inputGr.append(plusBtn)
+        plusBtn.onclick = () => {
+            store.dispatch(actionCartAdd(good))
+        }
+
+        const deleteGood = document.createElement('button')
+        deleteGood.innerText = 'remove item'
+        deleteGood.style.display = 'block'
+        card.lastElementChild.append(deleteGood)
+        deleteGood.onclick = () => {
+            store.dispatch(actionCartRemove(good))
+        }
+
+        cartPage.append(card)
+    }
+
+    const total  = document.createElement('h5')
+    total.innerText = `Total: ${cartCounter} UAH`
+
+    const sendOrder = document.createElement('button')
+    sendOrder.innerText = 'Make an order'
+    if(Object.keys(cart).length !== 0) {
+        parent.append(total)
+        parent.append(sendOrder)
+    }
+    const {auth} = store.getState()
+    sendOrder.disabled = !auth.token;
+    sendOrder.onclick = () => {
+        store.dispatch(actionOrder())
+    }
+}
+
+
+
+// location.hash
+window.onhashchange = () => {
+    const [,route, _id] = location.hash.split('/')
+
+    const routes = {
+        category(){
+            store.dispatch(actionCatById(_id))
+        },
+        good(){
+            store.dispatch(actionGoodById(_id))
+        },
+        register(){
+            const registerFunc = createForm(main, 'Register', actionFullRegister)
+            registerFunc()
+        },
+        login(){
+            const loginFunc = createForm(main, 'Login', actionFullLogin)
+            loginFunc()
+        },
+        orders(){
+            store.dispatch(actionGoodsByUser(_id))
+        },
+        cart(){
+            createCartPage(main)
+        }
+    }
+    if (route in routes) {
+        routes[route]()
+    }
+}
+
+
+store.subscribe(() => {
+    const [,route] = location.hash.split('/')
+    if (route === 'cart') {
+        createCartPage(main)
+    }
+})
+
+
+window.onhashchange()
+
+store.subscribe(() => {
+    const {promise} = store.getState()
+    const {catById} = promise
+    const [,route, _id] = location.hash.split('/')
+
+    if (catById?.status === 'PENDING') {
+        main.innerHTML = `<img src="Loading_icon.gif">`
+    } else {
+        if (catById?.payload && route === 'category'){
+            main.innerHTML = ''
+            const catBody  = document.createElement('div')
+            main.append(catBody)
+
+            const {name} = catById.payload;
+            catBody.innerHTML = `<h1>${name}</h1>`
+
+            if (catById.payload.subCategories) {
+                const linkList  = document.createElement('div')
+                catBody.append(linkList)
+
+                for(const {_id, name} of catById.payload.subCategories) {
+                    const link = document.createElement('a')
+                    link.href = `#/category/${_id}`
+                    link.innerText  = name
+                    link.className = 'cat'
+                    catBody.append(link)
+                }
+            if(location.hash === '#/category/') {
+                for(const {_id, name} of catById.payload) {
+                    const link = document.createElement('a')
+                    link.href = `#/category/${_id}`
+                    link.innerText  = name
+                    link.className = 'cat'
+                    catBody.append(link)
+                }
+            }
+            }
+
+            if (catById.payload.goods) {
+                const cardBody  = document.createElement('div')
+                main.append(cardBody)
+                for (const good of catById.payload.goods){
+                    const {_id, name, price, images} = good
+                    const card      = document.createElement('div')
+                    card.className = 'card'
+                    card.innerHTML = `
+                                    <img src="${backURL}/${images[0].url}" />
+                                    <div>
+                                        <h4>${name}</h4>
+                                        <h5>${price} UAH</h5>                                    
+                                        <a href="#/good/${_id}" class="showMore">
+                                            Show more
+                                        </a>
+                                    </div>
+                                    `
+                    const btnCart = document.createElement('button')
+                    btnCart.innerText = 'To cart'
+                    btnCart.onclick = () => {
+                        store.dispatch(actionCartAdd(good))
+                    }
+                    card.lastElementChild.append(btnCart)
+                    cardBody.append(card)
+                }
+            }
+        }
+    }
+})
+
+store.subscribe(() => {
+        const {promise} = store.getState()
+        const {goodById} = promise
+        const [,route, _id] = location.hash.split('/');
+
+        if (goodById?.status === 'PENDING') {
+            main.innerHTML = `<img src="Loading_icon.gif">`
+        } else {
+            if (goodById?.payload && route === 'good') {
+                main.innerHTML = ''
+                const good = goodById.payload
+                const {_id, name, images, price, description} = good
+                const card = document.createElement('div')
+                card.innerHTML = `<h2>${name}</h2>
+                                <img src="${backURL}/${images[0].url}" />
+                                <div>                                    
+                                    <h6>${description}</h6>
+                                    <strong>Цена - ${price} грн</strong>
+                                </div>
+                                `
+                const btnCart = document.createElement('button')
+                btnCart.innerText  = 'Add to cart'
+                btnCart.onclick = () => {
+                    store.dispatch(actionCartAdd(good))
+                }
+                card.append(btnCart)
+                main.append(card);
+            }
+        }
+    }
+)
+
+
+store.subscribe(() => {
+    const {auth} = store.getState()
+    const name = document.createElement('div')
+    name.innerText = `Hello, stranger`
+    const {payload} = auth
+    if (payload?.sub) {
+        userBox.innerHTML = ''
+        const {id, login}  = payload.sub
+        name.innerText = `Hello, ${login}`
+        const myOrders = document.createElement('a')
+        myOrders.innerText = 'My orders'
+        myOrders.href = `#/orders/${id}`
+        userBox.append(myOrders)
+    } else {
+        userBox.innerHTML = ''
+    }
+    userBox.append(name)
+})
+
+
+
+store.subscribe(() => {
+    const {promise} = store.getState()
+    const {goodByUser} = promise
+    const [,route] = location.hash.split('/')
+
+    if (goodByUser?.status === 'PENDING') {
+        main.innerHTML = `<img src="Loading_icon.gif">`
+    } else {
+        if (goodByUser?.payload && route === 'orders'){
+
+            main.innerHTML = ''
+            const cardBody  = document.createElement('div')
+            main.append(cardBody)
+
+            if (goodByUser.payload) {
+                let totalMoney = 0
+
+                for (const order of goodByUser.payload) {
+
+                    if (order.orderGoods) {
+                        for (const {price, count, total, good} of order.orderGoods) {
+                            if (price !== null && count !== null && total !== null && good !== null) {
+                                totalMoney += total
+                                const {_id, name, images} = good
+
+                                const card      = document.createElement('div')
+                                card.innerHTML = `
+                                <img src="${backURL}/${images[0].url}" />
+                                <div>
+                                    <h4>${name}</h4>
+                                    // <h6>
+                                    //     bought: ${count},  ${price} UAH 
+                                    // </h6>  
+                                    <h6>
+                                        Total: ${total} UAH
+                                    </h6>   
+                                    <a href="#/good/${_id}">
+                                        show more
+                                    </a>
+                                </div>
+                                `
+                                cardBody.append(card)
+
+                            }
+                        }
+                    }
+
+                }
+                const totalBlock = document.createElement('h3')
+                totalBlock.innerText = 'Total: ' + totalMoney + ' UAH'
+                main.append(totalBlock)
+            }
+        }
+    }
+})
+
+
+
+store.subscribe(() => {
+    const {cart} = store.getState()
+    let counter = 0;
+
+    for (const key in cart) {
+        counter += cart[key].count
+    }
+    cartCounter.innerText  = counter
+})
+

+ 53 - 0
JavaScriptHomeWorks/painter/index.html

@@ -0,0 +1,53 @@
+<html>
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width">
+  <title>eval</title>
+  <style>
+    * {
+      box-sizing: border-box;
+      margin: 0;
+      padding: 0;
+    }
+
+    body {
+      margin: 0;
+      padding: 0;
+    }
+
+    button{
+      width: 100%;
+      font-size: 2em;
+    }
+    input, button, select{
+      width: 100%;
+      font-size: 2em;
+    }
+
+    table {
+      border: 1px;
+      border-collapse: collapse;
+    }
+
+    td,th {
+      border: 1px solid black;
+    }
+  </style>
+</head>
+<body>
+<canvas id='canvas' width=400 height=400></canvas>
+<button id='undo'>UNDO</button>
+<input type='color' id='color'>
+<select id='tool'>
+  <option value='graffity'>Graffity</option>
+  <option value='circle'>Circle</option>
+  <option value='line'>Line</option>
+  <option value='rectangle'>Rectangle</option>
+  <option value='ellipse'>Ellipse</option>
+  <option value='select'>Select</option>
+</select>
+<input type='number' id='size' value=10>
+<button id='delete'>Delete</button>
+<script src="main.js"></script>
+</body>
+</html>

+ 311 - 0
JavaScriptHomeWorks/painter/main.js

@@ -0,0 +1,311 @@
+const canvas = document.getElementById('canvas')
+const ctx    = canvas.getContext('2d')
+const width  = canvas.width;
+const height = canvas.height;
+let current;
+let selection = []
+
+const tools = {
+    graffity: {
+        mousemove(e){
+            (e.buttons & 1) && new Circle(e.clientX, e.clientY, +size.value, color.value)
+        }
+    },
+    circle: {
+        mousedown(e){
+            current = new Circle(e.clientX, e.clientY, 1, color.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.radius = current.distanceTo(e.clientX, e.clientY)
+            Drawable.drawAll()
+        },
+
+        mouseup(e){
+            current = null
+        }
+    },
+    line: {
+        mousedown(e){
+            current = new Line(e.clientX, e.clientY, 0, 0, color.value, +size.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.width = e.clientX - current.x
+            current.height = e.clientY - current.y
+
+            Drawable.drawAll()
+        },
+
+        mouseup(e){
+            current = null
+        }
+    },
+    select: {
+        click(e){
+            console.log(e)
+            let found = Drawable.instances.filter(c => c.in && c.in(e.clientX, e.clientY))
+            if (found.length){
+                if (e.altKey){
+                    selection.push(found.pop())
+                }
+                else {
+                    selection = [found.pop()]
+                }
+            }
+            else {
+                if (!e.altKey) selection = []
+            }
+
+            Drawable.drawAll(selection)
+        },
+        mousedown(e){},
+        mousemove(e){},
+        mouseup(e){},
+    },
+    rectangle: {
+        mousedown(e){
+            current = new Rectangle(e.clientX, e.clientY, 0, 0, color.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.width = e.clientX - current.x
+            current.height = e.clientY - current.y
+
+            Drawable.drawAll()
+        },
+
+        mouseup(e){
+            current = null
+        }
+    },
+    ellipse: {
+        mousedown(e){
+            current = new Ellipse(e.clientX, e.clientY, 0, 0, color.value)
+        },
+        mousemove(e){
+            if (!current) return;
+
+            current.width = e.clientX - current.x
+            current.height = e.clientY - current.y
+
+            Drawable.drawAll()
+        },
+        mouseup(e){
+            current = null
+        }
+    }
+}
+
+function superHandler(evt){
+    let t = tools[tool.value]
+    if (typeof t[evt.type] === 'function')
+        t[evt.type].call(this, evt)
+}
+
+canvas.onmousemove = superHandler
+canvas.onmouseup   = superHandler
+canvas.onmousedown = superHandler
+canvas.onclick = superHandler
+
+function Drawable(){
+    Drawable.addInstance(this);
+}
+
+const distance = (x1, y1, x2, y2) => ((x1-x2)**2 + (y1-y2)**2)**0.5
+
+Drawable.prototype.draw = function(){};
+Drawable.prototype.distanceTo = function(x,y){
+    if (typeof this.x !== 'number' ||
+        typeof this.y !== 'number'){
+        return NaN
+    }
+    return distance(this.x, this.y, x, y)
+};
+Drawable.instances = [];
+Drawable.addInstance = function(item){
+    Drawable.instances.push(item);
+}
+Drawable.drawAll = function(selection=[]){
+    ctx.clearRect(0,0,width,height);
+    Drawable.forAll(item => item.draw())
+    selection.forEach(item  => item.draw(true))
+}
+Drawable.forAll = function(callback){
+    for(var i = 0; i<Drawable.instances.length;i++){
+        callback(Drawable.instances[i])
+    }
+}
+
+class Circle extends Drawable {
+    constructor(x,y,radius, color){
+        super()
+        this.x      = x
+        this.y      = y
+        this.radius = radius
+        this.color  = color
+        this.draw()
+    }
+
+    draw(selected){
+        ctx.beginPath()
+        ctx.arc(this.x, this.y, this.radius, 0, 2 * Math.PI)
+        ctx.closePath()
+        ctx.fillStyle = this.color
+        if (selected){
+            ctx.lineWidth = 2
+            ctx.stroke()
+        }
+        ctx.fill()
+    }
+
+    in(x, y){
+        return this.distanceTo(x, y) < this.radius
+    }
+
+    inBounds(x, y, w, h){
+        return this.x >= x && this.x <= x + w && this.y >= y && this.y <= y + h
+    }
+}
+
+class Line extends Drawable {
+    constructor(x,y, width, height, color, lineWidth){
+        super()
+        this.x      = x
+        this.y      = y
+        this.width  = width
+        this.height = height
+        this.color  = color
+        this.lineWidth  = lineWidth
+        this.draw()
+    }
+    draw(selected){
+        ctx.beginPath()
+        ctx.moveTo(this.x, this.y)
+        ctx.lineTo(this.x + this.width, this.y + this.height)
+        ctx.closePath()
+        ctx.strokeStyle = this.color
+        ctx.lineWidth   = this.lineWidth
+        if (selected){
+            ctx.strokeStyle = '#f0f'
+            ctx.stroke()
+        }
+        ctx.stroke()
+    }
+    in(x, y) {
+        let rotateLine = Math.atan2(this.height, this.width)
+        let rotCursor = Math.atan2(y - this.y, x - this.x)
+        let distanceToPoint = distance(x, y, this.x, this.y)
+        let angleLine = rotCursor - rotateLine
+        let rotateX = Math.cos(angleLine) * distanceToPoint
+        let rotateY = Math.sin(angleLine) * distanceToPoint
+        return rotateX >= 0 && rotateX <= this.length && rotateY <= this.lineWidth/2 && rotateY >= -this.lineWidth/2
+    }
+    get length(){
+        return this.distanceTo(this.x + this.width, this.y + this.height)
+    }
+}
+
+class Rectangle extends Drawable{
+    constructor(x, y, width, height, color){
+        super()
+        this.x      = x
+        this.y      = y
+        this.width  = width
+        this.height = height
+        this.color  = color
+        this.draw()
+    }
+    draw(selected){
+        ctx.beginPath()
+        ctx.moveTo(this.x, this.y)
+        ctx.fillRect(this.x, this.y, this.width, this.height)
+        if (selected){
+            ctx.rect(this.x, this.y, this.width, this.height)
+            ctx.strokeStyle = '#f0f'
+            ctx.stroke()
+        }
+        ctx.fillStyle = this.color
+        ctx.stroke()
+    }
+    in(x, y){
+        return x >= this.x && x <= this.x + this.width && y >= this.y && y <= this.y + this.height
+    }
+}
+
+class Ellipse extends Drawable{
+    #width = 0
+    #height = 0
+    constructor(x, y, width, height, color){
+        super()
+        this.x      = x
+        this.y      = y
+        this.#width  = width
+        this.#height = height
+        this.color  = color
+        this.draw()
+    }
+    draw(selected){
+        ctx.beginPath()
+        ctx.moveTo(this.x, this.y)
+        ctx.ellipse(this.x + this.rx, this.y + this.ry, this.rx, this.ry, 0, 0, 2 * Math.PI)
+        ctx.closePath()
+        if (selected){
+            ctx.lineWidth = 2
+            ctx.fill()
+        }
+        ctx.fillStyle = this.color
+        ctx.fill()
+    }
+
+    in(x, y) {
+        let h = this.x + this.rx
+        let k = this.y + this.ry
+        return Math.pow((x - h), 2)/Math.pow(this.rx, 2) + Math.pow((y - k), 2)/Math.pow(this.ry, 2) <= 1
+    }
+
+    set width(newWidth){
+        if (newWidth < 0){
+            this.#width = -newWidth
+            this.x     += newWidth
+        }
+        else
+            this.#width = newWidth
+    }
+    set height(newHeight){
+        if (newHeight < 0){
+            this.#height = -newHeight
+            this.y      +=  newHeight
+        }
+        else
+            this.#height = newHeight
+    }
+    get width(){
+        return this.#width
+    }
+    get height(){
+        return this.#height
+    }
+    get rx(){
+        return this.#width/2
+    }
+    get ry(){
+        return this.#height/2
+    }
+}
+
+color.onchange = () => {
+    selection.forEach(c => c.color = color.value)
+    Drawable.drawAll(selection)
+}
+undo.onclick = function(){
+    Drawable.instances.pop()
+    Drawable.drawAll()
+}
+document.getElementById('delete').onclick = () =>{
+    Drawable.instances = []
+    Drawable.drawAll()
+}

BIN
JavaScriptHomeWorks/tuner/13x.png


BIN
JavaScriptHomeWorks/tuner/bbno$xdiamondPistols-help herself.mp3


+ 35 - 0
JavaScriptHomeWorks/tuner/index.html

@@ -0,0 +1,35 @@
+<html>
+<head>
+    <meta charset="utf-8" />
+    <meta name="viewport" content="width=device-width" />
+    <title>Tuner</title>
+    <style>
+        #container1 {
+            padding: 40px;
+        }
+        img{
+            width: 100px;
+            height: 100px;
+            margin: 15px;
+        }
+        #colorBox {
+            width: 500px;
+            height: 100px;
+            border: 1px solid black;
+        }
+    </style>
+</head>
+<body>
+<div id='container2'></div>
+
+<div id="colorBox"></div>
+<div class="audioBox">
+    <div id='container1'></div>
+    <p>bbno$ ft Diamond Pistols - Help Yourself</p>
+    <audio class="mySong" autoplay controls>
+        <source src="bbno$xdiamondPistols-help%20herself.mp3" type="audio/mp3">
+    </audio>
+</div>
+<script src='index.js'></script>
+</body>
+</html>

+ 75 - 0
JavaScriptHomeWorks/tuner/index.js

@@ -0,0 +1,75 @@
+function Control(el, {value=50,
+    min=0,
+    max=100,
+    minAngle=-90,
+    maxAngle=90,
+    wheelSpeed=0.1,
+    step=1}={}){
+
+    const img = document.createElement('img')
+    img.src   = '13x.png'
+    el.append(img)
+
+    const ratio    = (maxAngle - minAngle) / (max - min) //цена единицы value в градусах
+    const getAngle = () => (value - min) * ratio + minAngle //подсчитали отступ в единицах, пересчитали в градусы и прибавили к стартовому углу
+
+
+    this.setValue = (newValue) => {
+        if (newValue < min){
+            newValue = min
+        }
+
+        if (newValue > max){
+            newValue = max
+        }
+
+        value = newValue
+
+        if (typeof this.onchange === 'function'){
+            this.onchange(value)
+        }
+
+        img.style.transform = `rotate(${getAngle()}deg)`
+    }
+
+    this.getValue = () => value
+
+    img.onmousewheel = (e) => {
+        const {deltaY} = e
+        //console.log(deltaY)
+        e.preventDefault()
+
+        this.setValue(value + deltaY*wheelSpeed)
+    }
+
+    img.onclick = (e) => {
+        const {layerX} = e
+        console.log(e, layerX)
+        if (layerX > img.width/2)
+            this.setValue(value +step)
+        else
+            this.setValue(value -step)
+    }
+
+    this.setValue(value)
+}
+let $song = document.querySelector('.mySong')
+const volumeControl  = new Control(container1, {max: 1, wheelSpeed: 0.001, value: 75, minAngle: -180})
+volumeControl.onchange = (value => {
+    $song.volume = value
+})
+
+setTimeout(() => volumeControl.setValue(80), 2000)
+
+function setRGB(value, n){
+    colorBox.style.backgroundColor = `rgb(${red.getValue()}, ${green.getValue()}, ${blue.getValue()})`
+}
+
+const red  = new Control(container2, {min: 0, max: 255})
+const green  = new Control(container2, {min: 0, max: 255})
+const blue  = new Control(container2, {min: 0, max: 255})
+const colors = [red, green, blue];
+for(let i = 0; i < colors.length; i++) {
+    colors[i].onchange = value => setRGB(value, i)
+}
+