From 250e1c394185420346cebcda01e924cf56c15e66 Mon Sep 17 00:00:00 2001 From: nxn Date: Wed, 25 May 2022 02:18:48 +0300 Subject: [PATCH 1/3] home work 3 --- Lesson3/css/style.css | 38 +++++++++++++++++- Lesson3/index.html | 5 ++- Lesson3/js/main.js | 93 +++++++++++++++++++++++++++++++++++++------ 3 files changed, 122 insertions(+), 14 deletions(-) diff --git a/Lesson3/css/style.css b/Lesson3/css/style.css index b2c5c40..f7236b0 100644 --- a/Lesson3/css/style.css +++ b/Lesson3/css/style.css @@ -16,6 +16,27 @@ button{ text-transform: uppercase; font-weight: bold; } +.active{ + display: block!important; +} +.cart{ + position:relative; + width:500px; + display:flex; + justify-content:right; +} +.cart-block{ + display: none; + position: absolute; + z-index: 1; + width: 65%; + height: auto; + left: 0; + top: 0px; + background: #fff; + color: #000; + padding: 25px; +} .btn-cart{ background-color: #fafafa; padding: 10px 20px; @@ -39,7 +60,7 @@ button{ grid-template-columns: repeat(auto-fit, 200px); grid-template-rows: 1fr; padding: 40px 80px; - justify-content: space-between; + justify-content: left; } p { margin: 0 0 5px 0; @@ -74,4 +95,19 @@ img { background-color: transparent; border-color: #2f2a2d; color: #2f2a2d; +} +.delete-btn{ + margin-top: 5px; + background-color: #2f2a2d; + padding: 10px 20px; + border: 1px solid transparent; + color: rgb(238, 142, 142); + border-radius: 5px; + transition: all ease-in-out .4s; + cursor: pointer; +} +.delete-btn:hover{ + background-color: transparent; + border-color: #2f2a2d; + color: #a54242; } \ No newline at end of file diff --git a/Lesson3/index.html b/Lesson3/index.html index c9c796e..de7d94d 100644 --- a/Lesson3/index.html +++ b/Lesson3/index.html @@ -9,7 +9,10 @@
- +
+ +
+
diff --git a/Lesson3/js/main.js b/Lesson3/js/main.js index 3dc1148..7fbf51f 100644 --- a/Lesson3/js/main.js +++ b/Lesson3/js/main.js @@ -1,6 +1,6 @@ const API = 'https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses'; -let getRequest = (url, cb) => { // не fetch +/*let getRequest = (url, cb) => { // не fetch let xhr = new XMLHttpRequest(); xhr.open('GET', url, true); xhr.onreadystatechange = () => { @@ -13,13 +13,48 @@ let getRequest = (url, cb) => { // не fetch } }; xhr.send(); -}; +};*/ +let getRequest = (url) => { + return new Promise((resolve, reject)=>{ + const xhr = new XMLHttpRequest(); + xhr.open("GET", url, true); + xhr.onreadystatechange = () => { + if (xhr.readyState === 4) { + if (xhr.status !== 200) { + console.log('Error'); + reject(xhr.responseText); + } else { + console.log('ok'); + resolve(xhr.responseText); + } + } + }; + xhr.send(); + }); +} + +let addEventToBtn = (className, container, req) => { + container.addEventListener('click', (e) => { + console.log(req); + if(e.target.classList.contains(className)){ + console.log(e.target); + getRequest(`${API}/${req}`); + } + }); +} class ProductList { - constructor(container = '.products') { + constructor( + container = '.products', + textBtn = 'купить', + classBtn = 'buy-btn', + req = 'addToBasket.json' + ){ this.container = document.querySelector(container); this._goods = []; this._productsObjects = []; + this.textBtn = textBtn; + this.classBtn = classBtn; // this._fetchGoods(); // this._render(); @@ -28,6 +63,7 @@ class ProductList { this._goods = data; this._render(); console.log(this.getTotalPrice()); + addEventToBtn(classBtn, this.container, req); }); } @@ -52,8 +88,8 @@ class ProductList { _render() { for (const product of this._goods) { - const productObject = new ProductItem(product); - console.log(productObject); + const productObject = new ProductItem(product, this.textBtn, this.classBtn); + //console.log(productObject); this._productsObjects.push(productObject); this.container.insertAdjacentHTML('beforeend', productObject.getHTMLString()); @@ -62,25 +98,58 @@ class ProductList { } class ProductItem { - constructor(product, img = 'https://via.placeholder.com/200x150') { - this.id = product.id; - this.title = product.title; + constructor( + product, + btnText, + classBtn = 'buy-btn', + img = 'https://via.placeholder.com/200x150' + ){ + this.id = product.id_product; + this.title = product.product_name; this.price = product.price; this.img = img; + this.btnText = btnText; + this.classBtn = classBtn; } - getHTMLString() { return `
Some img

${this.title}

${this.price} \u20bd

- +
`; } } -// const cart = new Cart(); -// const list = new ProductList(cart); +class CartList extends ProductList{ + constructor( + container = '.cart-block', + textBtn = 'удалить', + classBtn = 'delete-btn', + req = 'deleteFromBasket.json' + ){ + super(container,textBtn,classBtn,req); + this.getProducts('getBasket.json') + .then((data) => { + this._goods = data; + this._render(); + }); + console.log(this.getTotalPrice()); + console.log(this.classBtn, this.container); + this.open() + } + open(){ + document.querySelector('.btn-cart').addEventListener('click', (e)=>{ + + e.target.nextElementSibling.classList.toggle('active'); + + }); + } + +} + + const list = new ProductList(); +const cartList = new CartList(); From 3a7fb8df214660a8cc32296da16406c2a5cdc762 Mon Sep 17 00:00:00 2001 From: nxn Date: Wed, 1 Jun 2022 03:01:39 +0300 Subject: [PATCH 2/3] home work 4 original --- Lesson4/css/normalize.css | 349 ++++++++++++++++++++++++++++++++++++++ Lesson4/css/style.css | 171 +++++++++++++++++++ Lesson4/index.html | 29 ++++ Lesson4/js/main.js | 273 +++++++++++++++++++++++++++++ 4 files changed, 822 insertions(+) create mode 100644 Lesson4/css/normalize.css create mode 100644 Lesson4/css/style.css create mode 100644 Lesson4/index.html create mode 100644 Lesson4/js/main.js diff --git a/Lesson4/css/normalize.css b/Lesson4/css/normalize.css new file mode 100644 index 0000000..192eb9c --- /dev/null +++ b/Lesson4/css/normalize.css @@ -0,0 +1,349 @@ +/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ + +/* Document + ========================================================================== */ + +/** + * 1. Correct the line height in all browsers. + * 2. Prevent adjustments of font size after orientation changes in iOS. + */ + +html { + line-height: 1.15; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ +} + +/* Sections + ========================================================================== */ + +/** + * Remove the margin in all browsers. + */ + +body { + margin: 0; +} + +/** + * Render the `main` element consistently in IE. + */ + +main { + display: block; +} + +/** + * Correct the font size and margin on `h1` elements within `section` and + * `article` contexts in Chrome, Firefox, and Safari. + */ + +h1 { + font-size: 2em; + margin: 0.67em 0; +} + +/* Grouping content + ========================================================================== */ + +/** + * 1. Add the correct box sizing in Firefox. + * 2. Show the overflow in Edge and IE. + */ + +hr { + box-sizing: content-box; /* 1 */ + height: 0; /* 1 */ + overflow: visible; /* 2 */ +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +pre { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/* Text-level semantics + ========================================================================== */ + +/** + * Remove the gray background on active links in IE 10. + */ + +a { + background-color: transparent; +} + +/** + * 1. Remove the bottom border in Chrome 57- + * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. + */ + +abbr[title] { + border-bottom: none; /* 1 */ + text-decoration: underline; /* 2 */ + text-decoration: underline dotted; /* 2 */ +} + +/** + * Add the correct font weight in Chrome, Edge, and Safari. + */ + +b, +strong { + font-weight: bolder; +} + +/** + * 1. Correct the inheritance and scaling of font size in all browsers. + * 2. Correct the odd `em` font sizing in all browsers. + */ + +code, +kbd, +samp { + font-family: monospace, monospace; /* 1 */ + font-size: 1em; /* 2 */ +} + +/** + * Add the correct font size in all browsers. + */ + +small { + font-size: 80%; +} + +/** + * Prevent `sub` and `sup` elements from affecting the line height in + * all browsers. + */ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* Embedded content + ========================================================================== */ + +/** + * Remove the border on images inside links in IE 10. + */ + +img { + border-style: none; +} + +/* Forms + ========================================================================== */ + +/** + * 1. Change the font styles in all browsers. + * 2. Remove the margin in Firefox and Safari. + */ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-size: 100%; /* 1 */ + line-height: 1.15; /* 1 */ + margin: 0; /* 2 */ +} + +/** + * Show the overflow in IE. + * 1. Show the overflow in Edge. + */ + +button, +input { /* 1 */ + overflow: visible; +} + +/** + * Remove the inheritance of text transform in Edge, Firefox, and IE. + * 1. Remove the inheritance of text transform in Firefox. + */ + +button, +select { /* 1 */ + text-transform: none; +} + +/** + * Correct the inability to style clickable types in iOS and Safari. + */ + +button, +[type="button"], +[type="reset"], +[type="submit"] { + -webkit-appearance: button; +} + +/** + * Remove the inner border and padding in Firefox. + */ + +button::-moz-focus-inner, +[type="button"]::-moz-focus-inner, +[type="reset"]::-moz-focus-inner, +[type="submit"]::-moz-focus-inner { + border-style: none; + padding: 0; +} + +/** + * Restore the focus styles unset by the previous rule. + */ + +button:-moz-focusring, +[type="button"]:-moz-focusring, +[type="reset"]:-moz-focusring, +[type="submit"]:-moz-focusring { + outline: 1px dotted ButtonText; +} + +/** + * Correct the padding in Firefox. + */ + +fieldset { + padding: 0.35em 0.75em 0.625em; +} + +/** + * 1. Correct the text wrapping in Edge and IE. + * 2. Correct the color inheritance from `fieldset` elements in IE. + * 3. Remove the padding so developers are not caught out when they zero out + * `fieldset` elements in all browsers. + */ + +legend { + box-sizing: border-box; /* 1 */ + color: inherit; /* 2 */ + display: table; /* 1 */ + max-width: 100%; /* 1 */ + padding: 0; /* 3 */ + white-space: normal; /* 1 */ +} + +/** + * Add the correct vertical alignment in Chrome, Firefox, and Opera. + */ + +progress { + vertical-align: baseline; +} + +/** + * Remove the default vertical scrollbar in IE 10+. + */ + +textarea { + overflow: auto; +} + +/** + * 1. Add the correct box sizing in IE 10. + * 2. Remove the padding in IE 10. + */ + +[type="checkbox"], +[type="radio"] { + box-sizing: border-box; /* 1 */ + padding: 0; /* 2 */ +} + +/** + * Correct the cursor style of increment and decrement buttons in Chrome. + */ + +[type="number"]::-webkit-inner-spin-button, +[type="number"]::-webkit-outer-spin-button { + height: auto; +} + +/** + * 1. Correct the odd appearance in Chrome and Safari. + * 2. Correct the outline style in Safari. + */ + +[type="search"] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/** + * Remove the inner padding in Chrome and Safari on macOS. + */ + +[type="search"]::-webkit-search-decoration { + -webkit-appearance: none; +} + +/** + * 1. Correct the inability to style clickable types in iOS and Safari. + * 2. Change font properties to `inherit` in Safari. + */ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* Interactive + ========================================================================== */ + +/* + * Add the correct display in Edge, IE 10+, and Firefox. + */ + +details { + display: block; +} + +/* + * Add the correct display in all browsers. + */ + +summary { + display: list-item; +} + +/* Misc + ========================================================================== */ + +/** + * Add the correct display in IE 10+. + */ + +template { + display: none; +} + +/** + * Add the correct display in IE 10. + */ + +[hidden] { + display: none; +} diff --git a/Lesson4/css/style.css b/Lesson4/css/style.css new file mode 100644 index 0000000..801db80 --- /dev/null +++ b/Lesson4/css/style.css @@ -0,0 +1,171 @@ +body{ + font-family: 'SF Pro Display', sans-serif; +} +header{ + display: flex; + background-color: #2f2a2d; + justify-content: space-between; + color: #fafafa; + padding: 30px 80px; +} +button:focus{ + outline: none; +} +.logo{ + + text-transform: uppercase; + font-weight: bold; +} +.btn-cart{ + background-color: #fafafa; + padding: 10px 20px; + border: 1px solid transparent; + color: #2f2a2d; + border-radius: 5px; + transition: all ease-in-out .4s; + cursor: pointer; +} +.btn-cart:hover{ + background-color: transparent; + border-color: #fafafa; + color: #fafafa; +} +.btn-cart, .logo{ + align-self: center; +} +/*.products {*/ +/*display: flex;*/ +/*justify-content: space-between;*/ +/*flex-wrap: wrap;*/ +/*padding: 40px 80px;*/ +/*}*/ +.products{ + column-gap: 30px; + display: grid; + grid-template-columns: repeat(auto-fit, 200px); + grid-template-rows: 1fr; + padding: 40px 80px; + justify-content: space-between; +} +p { + margin: 0 0 5px 0; +} +.product-item{ + display: flex; + flex-direction: column; + width: 200px; + border-radius: 5px; + overflow: hidden; + margin: 20px 0; +} +img { + max-width: 100%; + height: auto +} +.desc { + border: 1px solid #c0c0c040; + padding: 15px +} +.cart{ + position: relative; +} +.cart-block{ + box-shadow: 0 0 5px rgba(0, 0, 0, 0.62); + border-radius: 5px; + box-sizing: border-box; + right: 0; + top: 130%; + position: absolute; + background-color: white; + padding: 20px; + color: black; + width: 300px; +} + +.invisible{ + display: none; +} +.cart-block:before{ + content: ''; + width: 0; + height: 0; + position: absolute; + top: -10px; + right: 35px; + border-left: 10px solid transparent; + border-right: 10px solid transparent; + border-bottom: 10px solid white; +} + +.buy-btn, .del-btn{ + margin-top: 5px; + background-color: #2f2a2d; + padding: 5px 15px; + border: 1px solid transparent; + color: #fafafa; + border-radius: 5px; + transition: all ease-in-out .4s; + cursor: pointer; +} +.buy-btn:hover, .del-btn:hover{ + background-color: #fafafa; + color: #2f2a2d; + border: 1px solid #2f2a2d; +} +.cart-item { + display: flex; + justify-content: space-between; +} +.cart-item:not(:last-child){ + margin-bottom: 20px; +} +.product-bio{ + display: flex; +} +.cart-item img{ + align-self: flex-start; + margin-right: 15px; +} +.product-single-price{ + color: #474747; + font-size: 0.5em; +} +.product-price{ + margin-left: 30px; +} +.product-desc{ + max-width: 150px; +} +.product-quantity { + margin-top: 15px; + font-size: 0.75em; +} +.right-block{ + text-align: right; +} +.btn-search { + background-color: transparent; + border: none; + color: #fafafa; + font-size: 1.2em; + position: absolute; + bottom: 5px; + right: 0; +} +.search-form{ + position: relative; + margin-right: 50px; + display: inline-block; +} +.search-field:focus{ + outline: none; +} +.search-field { + box-sizing: border-box; + width: 200px; + color: #fafafa; + padding: 10px; + background-color: transparent; + border: none; + border-bottom: 2px solid #fafafa; +} diff --git a/Lesson4/index.html b/Lesson4/index.html new file mode 100644 index 0000000..a25e2a4 --- /dev/null +++ b/Lesson4/index.html @@ -0,0 +1,29 @@ + + + + + Интернет-магазин + + + + +
+ +
+
+ + +
+ + +
+
+
+
+
+ + + + diff --git a/Lesson4/js/main.js b/Lesson4/js/main.js new file mode 100644 index 0000000..5a11e0c --- /dev/null +++ b/Lesson4/js/main.js @@ -0,0 +1,273 @@ +const API = 'https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses'; + +// Переведено на промисы +// let getRequest = (url) => { +// return new Promise((resolve, reject) => { +// let xhr = new XMLHttpRequest(); +// xhr.open("GET", url, true); +// xhr.onreadystatechange = () => { +// if(xhr.readyState === 4){ +// if(xhr.status !== 200){ +// reject('Error'); +// } else { +// resolve(xhr.responseText); +// } +// } +// }; +// xhr.send(); +// }) +// }; + +/** + * Описываем базовые классы + */ +class List { + constructor(url, container, list = listContext){ + this.container = container; + this.list = list; // словарь для классов строка 213 + this.url = url; + this.goods = []; + this.allProducts = []; + this.filtered = []; // отфильтрованные товары + this._init(); + } + + /** + * получение данных с сервера + * @param url + * @returns {Promise} + */ + getJson(url){ + return fetch(url ? url : `${API + this.url}`) + .then(result => result.json()) + .catch(error => { + console.log(error); + }) + } + + /** + * обработка полученных данных + * @param data + */ + handleData(data){ + this.goods = data; + this.render(); + } + + /** + * подсчет стоимости всех товаров + * @returns {*|number} + */ + calcSum(){ + return this.allProducts.reduce((accum, item) => accum + item.price * item.quantity, 0); + } + + render(){ + const block = document.querySelector(this.container); + for (let product of this.goods){ + console.log(this.constructor.name); + const productObj = new this.list[this.constructor.name](product); + + // альтернативаня реализация без словаря + // let productObj = null; + // if (this.constructor.name === 'ProductsList') productObj = new ProductItem(product); + // if (this.constructor.name === 'Cart') productObj = new CartItem(product); + // if (!productObj) return; + + console.log(productObj); + this.allProducts.push(productObj); + block.insertAdjacentHTML('beforeend', productObj.render()); + } + } + + /** + * метод поиска товаров + * @param value - поисковый запрос + */ + filter(value){ + const regexp = new RegExp(value, 'i'); + this.filtered = this.allProducts.filter(product => regexp.test(product.product_name)); + this.allProducts.forEach(el => { + const block = document.querySelector(`.product-item[data-id="${el.id_product}"]`); + if(!this.filtered.includes(el)){ + block.classList.add('invisible'); + } else { + block.classList.remove('invisible'); + } + }) + } + _init(){ + return undefined; + } +} + +class Item{ + constructor(el, img = 'https://via.placeholder.com/200x150'){ + this.product_name = el.product_name; + this.price = el.price; + this.id_product = el.id_product; + this.img = img; + } + + render(){ + return ``; + } +} + +/** + * Наследуемся от базовых классов + */ +class ProductsList extends List{ + constructor(cart, container = '.products', url = "/catalogData.json"){ + super(url, container); + this.cart = cart; + this.getJson() + .then(data => this.handleData(data)); + } + + _init(){ + document.querySelector(this.container).addEventListener('click', e => { + if(e.target.classList.contains('buy-btn')){ + this.cart.addProduct(e.target); + } + }); + document.querySelector('.search-form').addEventListener('submit', e => { + e.preventDefault(); + this.filter(document.querySelector('.search-field').value) + }) + } +} + +class ProductItem extends Item{ + render() { + return `
+ Some img +
+

${this.product_name}

+

${this.price} ₽

+ +
+
`; + } +} + +class Cart extends List{ + constructor(container = ".cart-block", url = "/getBasket.json"){ + super(url, container); + this.getJson() + .then(data => { + this.handleData(data.contents); + }); + } + + /** + * добавление товара + * @param element + */ + addProduct(element){ + this.getJson(`${API}/addToBasket.json`) + .then(data => { + if(data.result === 1){ + let productId = +element.dataset['id']; + let find = this.allProducts.find(product => product.id_product === productId); + if(find){ + find.quantity++; + this._updateCart(find); + } else { + let product = { + id_product: productId, + price: +element.dataset['price'], + product_name: element.dataset['name'], + quantity: 1 + }; + // goods - это своего рода "опорный" массив, отражающий список товаров, которые нужно отрендерить. + // При добавлении нового товара, нас интересует только он один. + this.goods = [product]; + // далее вызывая метод render, мы добавим в allProducts только его, тем самым избегая лишнего перерендера. + this.render(); + } + } else { + alert('Error'); + } + }) + } + + /** + * удаление товара + * @param element + */ + removeProduct(element){ + this.getJson(`${API}/deleteFromBasket.json`) + .then(data => { + if(data.result === 1){ + let productId = +element.dataset['id']; + let find = this.allProducts.find(product => product.id_product === productId); + if(find.quantity > 1){ // если товара > 1, то уменьшаем количество на 1 + find.quantity--; + this._updateCart(find); + } else { // удаляем + this.allProducts.splice(this.allProducts.indexOf(find), 1); + document.querySelector(`.cart-item[data-id="${productId}"]`).remove(); + } + } else { + alert('Error'); + } + }) + } + + /** + * обновляем данные корзины + * @param product + * @private + */ + _updateCart(product){ + let block = document.querySelector(`.cart-item[data-id="${product.id_product}"]`); + block.querySelector('.product-quantity').textContent = `Количество: ${product.quantity}`; + block.querySelector('.product-price').textContent = `${product.quantity * product.price} ₽`; + } + _init(){ + document.querySelector('.btn-cart').addEventListener('click', () => { + document.querySelector(this.container).classList.toggle('invisible'); + }); + document.querySelector(this.container).addEventListener('click', e => { + if(e.target.classList.contains('del-btn')){ + this.removeProduct(e.target); + } + }) + } + +} + +class CartItem extends Item{ + constructor(el, img = 'https://via.placeholder.com/50x100'){ + super(el, img); + this.quantity = el.quantity; + } + render(){ + return `
+
+ Some image +
+

${this.product_name}

+

Количество: ${this.quantity}

+

${this.price} за ед.

+
+
+
+

${this.quantity*this.price} ₽

+ +
+
` + } +} + +const listContext = { + ProductsList: ProductItem, + Cart: CartItem +}; + +let cart = new Cart(); +let products = new ProductsList(cart); From cd495cb2c212ece29f604bc0eea01fce4165fa40 Mon Sep 17 00:00:00 2001 From: nxnwebdev <94235054+nxnwebdev@users.noreply.github.com> Date: Wed, 1 Jun 2022 03:21:29 +0300 Subject: [PATCH 3/3] Delete Lesson4 directory --- Lesson4/css/normalize.css | 349 -------------------------------------- Lesson4/css/style.css | 171 ------------------- Lesson4/index.html | 29 ---- Lesson4/js/main.js | 273 ----------------------------- 4 files changed, 822 deletions(-) delete mode 100644 Lesson4/css/normalize.css delete mode 100644 Lesson4/css/style.css delete mode 100644 Lesson4/index.html delete mode 100644 Lesson4/js/main.js diff --git a/Lesson4/css/normalize.css b/Lesson4/css/normalize.css deleted file mode 100644 index 192eb9c..0000000 --- a/Lesson4/css/normalize.css +++ /dev/null @@ -1,349 +0,0 @@ -/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ - -/* Document - ========================================================================== */ - -/** - * 1. Correct the line height in all browsers. - * 2. Prevent adjustments of font size after orientation changes in iOS. - */ - -html { - line-height: 1.15; /* 1 */ - -webkit-text-size-adjust: 100%; /* 2 */ -} - -/* Sections - ========================================================================== */ - -/** - * Remove the margin in all browsers. - */ - -body { - margin: 0; -} - -/** - * Render the `main` element consistently in IE. - */ - -main { - display: block; -} - -/** - * Correct the font size and margin on `h1` elements within `section` and - * `article` contexts in Chrome, Firefox, and Safari. - */ - -h1 { - font-size: 2em; - margin: 0.67em 0; -} - -/* Grouping content - ========================================================================== */ - -/** - * 1. Add the correct box sizing in Firefox. - * 2. Show the overflow in Edge and IE. - */ - -hr { - box-sizing: content-box; /* 1 */ - height: 0; /* 1 */ - overflow: visible; /* 2 */ -} - -/** - * 1. Correct the inheritance and scaling of font size in all browsers. - * 2. Correct the odd `em` font sizing in all browsers. - */ - -pre { - font-family: monospace, monospace; /* 1 */ - font-size: 1em; /* 2 */ -} - -/* Text-level semantics - ========================================================================== */ - -/** - * Remove the gray background on active links in IE 10. - */ - -a { - background-color: transparent; -} - -/** - * 1. Remove the bottom border in Chrome 57- - * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. - */ - -abbr[title] { - border-bottom: none; /* 1 */ - text-decoration: underline; /* 2 */ - text-decoration: underline dotted; /* 2 */ -} - -/** - * Add the correct font weight in Chrome, Edge, and Safari. - */ - -b, -strong { - font-weight: bolder; -} - -/** - * 1. Correct the inheritance and scaling of font size in all browsers. - * 2. Correct the odd `em` font sizing in all browsers. - */ - -code, -kbd, -samp { - font-family: monospace, monospace; /* 1 */ - font-size: 1em; /* 2 */ -} - -/** - * Add the correct font size in all browsers. - */ - -small { - font-size: 80%; -} - -/** - * Prevent `sub` and `sup` elements from affecting the line height in - * all browsers. - */ - -sub, -sup { - font-size: 75%; - line-height: 0; - position: relative; - vertical-align: baseline; -} - -sub { - bottom: -0.25em; -} - -sup { - top: -0.5em; -} - -/* Embedded content - ========================================================================== */ - -/** - * Remove the border on images inside links in IE 10. - */ - -img { - border-style: none; -} - -/* Forms - ========================================================================== */ - -/** - * 1. Change the font styles in all browsers. - * 2. Remove the margin in Firefox and Safari. - */ - -button, -input, -optgroup, -select, -textarea { - font-family: inherit; /* 1 */ - font-size: 100%; /* 1 */ - line-height: 1.15; /* 1 */ - margin: 0; /* 2 */ -} - -/** - * Show the overflow in IE. - * 1. Show the overflow in Edge. - */ - -button, -input { /* 1 */ - overflow: visible; -} - -/** - * Remove the inheritance of text transform in Edge, Firefox, and IE. - * 1. Remove the inheritance of text transform in Firefox. - */ - -button, -select { /* 1 */ - text-transform: none; -} - -/** - * Correct the inability to style clickable types in iOS and Safari. - */ - -button, -[type="button"], -[type="reset"], -[type="submit"] { - -webkit-appearance: button; -} - -/** - * Remove the inner border and padding in Firefox. - */ - -button::-moz-focus-inner, -[type="button"]::-moz-focus-inner, -[type="reset"]::-moz-focus-inner, -[type="submit"]::-moz-focus-inner { - border-style: none; - padding: 0; -} - -/** - * Restore the focus styles unset by the previous rule. - */ - -button:-moz-focusring, -[type="button"]:-moz-focusring, -[type="reset"]:-moz-focusring, -[type="submit"]:-moz-focusring { - outline: 1px dotted ButtonText; -} - -/** - * Correct the padding in Firefox. - */ - -fieldset { - padding: 0.35em 0.75em 0.625em; -} - -/** - * 1. Correct the text wrapping in Edge and IE. - * 2. Correct the color inheritance from `fieldset` elements in IE. - * 3. Remove the padding so developers are not caught out when they zero out - * `fieldset` elements in all browsers. - */ - -legend { - box-sizing: border-box; /* 1 */ - color: inherit; /* 2 */ - display: table; /* 1 */ - max-width: 100%; /* 1 */ - padding: 0; /* 3 */ - white-space: normal; /* 1 */ -} - -/** - * Add the correct vertical alignment in Chrome, Firefox, and Opera. - */ - -progress { - vertical-align: baseline; -} - -/** - * Remove the default vertical scrollbar in IE 10+. - */ - -textarea { - overflow: auto; -} - -/** - * 1. Add the correct box sizing in IE 10. - * 2. Remove the padding in IE 10. - */ - -[type="checkbox"], -[type="radio"] { - box-sizing: border-box; /* 1 */ - padding: 0; /* 2 */ -} - -/** - * Correct the cursor style of increment and decrement buttons in Chrome. - */ - -[type="number"]::-webkit-inner-spin-button, -[type="number"]::-webkit-outer-spin-button { - height: auto; -} - -/** - * 1. Correct the odd appearance in Chrome and Safari. - * 2. Correct the outline style in Safari. - */ - -[type="search"] { - -webkit-appearance: textfield; /* 1 */ - outline-offset: -2px; /* 2 */ -} - -/** - * Remove the inner padding in Chrome and Safari on macOS. - */ - -[type="search"]::-webkit-search-decoration { - -webkit-appearance: none; -} - -/** - * 1. Correct the inability to style clickable types in iOS and Safari. - * 2. Change font properties to `inherit` in Safari. - */ - -::-webkit-file-upload-button { - -webkit-appearance: button; /* 1 */ - font: inherit; /* 2 */ -} - -/* Interactive - ========================================================================== */ - -/* - * Add the correct display in Edge, IE 10+, and Firefox. - */ - -details { - display: block; -} - -/* - * Add the correct display in all browsers. - */ - -summary { - display: list-item; -} - -/* Misc - ========================================================================== */ - -/** - * Add the correct display in IE 10+. - */ - -template { - display: none; -} - -/** - * Add the correct display in IE 10. - */ - -[hidden] { - display: none; -} diff --git a/Lesson4/css/style.css b/Lesson4/css/style.css deleted file mode 100644 index 801db80..0000000 --- a/Lesson4/css/style.css +++ /dev/null @@ -1,171 +0,0 @@ -body{ - font-family: 'SF Pro Display', sans-serif; -} -header{ - display: flex; - background-color: #2f2a2d; - justify-content: space-between; - color: #fafafa; - padding: 30px 80px; -} -button:focus{ - outline: none; -} -.logo{ - - text-transform: uppercase; - font-weight: bold; -} -.btn-cart{ - background-color: #fafafa; - padding: 10px 20px; - border: 1px solid transparent; - color: #2f2a2d; - border-radius: 5px; - transition: all ease-in-out .4s; - cursor: pointer; -} -.btn-cart:hover{ - background-color: transparent; - border-color: #fafafa; - color: #fafafa; -} -.btn-cart, .logo{ - align-self: center; -} -/*.products {*/ -/*display: flex;*/ -/*justify-content: space-between;*/ -/*flex-wrap: wrap;*/ -/*padding: 40px 80px;*/ -/*}*/ -.products{ - column-gap: 30px; - display: grid; - grid-template-columns: repeat(auto-fit, 200px); - grid-template-rows: 1fr; - padding: 40px 80px; - justify-content: space-between; -} -p { - margin: 0 0 5px 0; -} -.product-item{ - display: flex; - flex-direction: column; - width: 200px; - border-radius: 5px; - overflow: hidden; - margin: 20px 0; -} -img { - max-width: 100%; - height: auto -} -.desc { - border: 1px solid #c0c0c040; - padding: 15px -} -.cart{ - position: relative; -} -.cart-block{ - box-shadow: 0 0 5px rgba(0, 0, 0, 0.62); - border-radius: 5px; - box-sizing: border-box; - right: 0; - top: 130%; - position: absolute; - background-color: white; - padding: 20px; - color: black; - width: 300px; -} - -.invisible{ - display: none; -} -.cart-block:before{ - content: ''; - width: 0; - height: 0; - position: absolute; - top: -10px; - right: 35px; - border-left: 10px solid transparent; - border-right: 10px solid transparent; - border-bottom: 10px solid white; -} - -.buy-btn, .del-btn{ - margin-top: 5px; - background-color: #2f2a2d; - padding: 5px 15px; - border: 1px solid transparent; - color: #fafafa; - border-radius: 5px; - transition: all ease-in-out .4s; - cursor: pointer; -} -.buy-btn:hover, .del-btn:hover{ - background-color: #fafafa; - color: #2f2a2d; - border: 1px solid #2f2a2d; -} -.cart-item { - display: flex; - justify-content: space-between; -} -.cart-item:not(:last-child){ - margin-bottom: 20px; -} -.product-bio{ - display: flex; -} -.cart-item img{ - align-self: flex-start; - margin-right: 15px; -} -.product-single-price{ - color: #474747; - font-size: 0.5em; -} -.product-price{ - margin-left: 30px; -} -.product-desc{ - max-width: 150px; -} -.product-quantity { - margin-top: 15px; - font-size: 0.75em; -} -.right-block{ - text-align: right; -} -.btn-search { - background-color: transparent; - border: none; - color: #fafafa; - font-size: 1.2em; - position: absolute; - bottom: 5px; - right: 0; -} -.search-form{ - position: relative; - margin-right: 50px; - display: inline-block; -} -.search-field:focus{ - outline: none; -} -.search-field { - box-sizing: border-box; - width: 200px; - color: #fafafa; - padding: 10px; - background-color: transparent; - border: none; - border-bottom: 2px solid #fafafa; -} diff --git a/Lesson4/index.html b/Lesson4/index.html deleted file mode 100644 index a25e2a4..0000000 --- a/Lesson4/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - Интернет-магазин - - - - -
- -
-
- - -
- - -
-
-
-
-
- - - - diff --git a/Lesson4/js/main.js b/Lesson4/js/main.js deleted file mode 100644 index 5a11e0c..0000000 --- a/Lesson4/js/main.js +++ /dev/null @@ -1,273 +0,0 @@ -const API = 'https://raw.githubusercontent.com/GeekBrainsTutorial/online-store-api/master/responses'; - -// Переведено на промисы -// let getRequest = (url) => { -// return new Promise((resolve, reject) => { -// let xhr = new XMLHttpRequest(); -// xhr.open("GET", url, true); -// xhr.onreadystatechange = () => { -// if(xhr.readyState === 4){ -// if(xhr.status !== 200){ -// reject('Error'); -// } else { -// resolve(xhr.responseText); -// } -// } -// }; -// xhr.send(); -// }) -// }; - -/** - * Описываем базовые классы - */ -class List { - constructor(url, container, list = listContext){ - this.container = container; - this.list = list; // словарь для классов строка 213 - this.url = url; - this.goods = []; - this.allProducts = []; - this.filtered = []; // отфильтрованные товары - this._init(); - } - - /** - * получение данных с сервера - * @param url - * @returns {Promise} - */ - getJson(url){ - return fetch(url ? url : `${API + this.url}`) - .then(result => result.json()) - .catch(error => { - console.log(error); - }) - } - - /** - * обработка полученных данных - * @param data - */ - handleData(data){ - this.goods = data; - this.render(); - } - - /** - * подсчет стоимости всех товаров - * @returns {*|number} - */ - calcSum(){ - return this.allProducts.reduce((accum, item) => accum + item.price * item.quantity, 0); - } - - render(){ - const block = document.querySelector(this.container); - for (let product of this.goods){ - console.log(this.constructor.name); - const productObj = new this.list[this.constructor.name](product); - - // альтернативаня реализация без словаря - // let productObj = null; - // if (this.constructor.name === 'ProductsList') productObj = new ProductItem(product); - // if (this.constructor.name === 'Cart') productObj = new CartItem(product); - // if (!productObj) return; - - console.log(productObj); - this.allProducts.push(productObj); - block.insertAdjacentHTML('beforeend', productObj.render()); - } - } - - /** - * метод поиска товаров - * @param value - поисковый запрос - */ - filter(value){ - const regexp = new RegExp(value, 'i'); - this.filtered = this.allProducts.filter(product => regexp.test(product.product_name)); - this.allProducts.forEach(el => { - const block = document.querySelector(`.product-item[data-id="${el.id_product}"]`); - if(!this.filtered.includes(el)){ - block.classList.add('invisible'); - } else { - block.classList.remove('invisible'); - } - }) - } - _init(){ - return undefined; - } -} - -class Item{ - constructor(el, img = 'https://via.placeholder.com/200x150'){ - this.product_name = el.product_name; - this.price = el.price; - this.id_product = el.id_product; - this.img = img; - } - - render(){ - return ``; - } -} - -/** - * Наследуемся от базовых классов - */ -class ProductsList extends List{ - constructor(cart, container = '.products', url = "/catalogData.json"){ - super(url, container); - this.cart = cart; - this.getJson() - .then(data => this.handleData(data)); - } - - _init(){ - document.querySelector(this.container).addEventListener('click', e => { - if(e.target.classList.contains('buy-btn')){ - this.cart.addProduct(e.target); - } - }); - document.querySelector('.search-form').addEventListener('submit', e => { - e.preventDefault(); - this.filter(document.querySelector('.search-field').value) - }) - } -} - -class ProductItem extends Item{ - render() { - return `
- Some img -
-

${this.product_name}

-

${this.price} ₽

- -
-
`; - } -} - -class Cart extends List{ - constructor(container = ".cart-block", url = "/getBasket.json"){ - super(url, container); - this.getJson() - .then(data => { - this.handleData(data.contents); - }); - } - - /** - * добавление товара - * @param element - */ - addProduct(element){ - this.getJson(`${API}/addToBasket.json`) - .then(data => { - if(data.result === 1){ - let productId = +element.dataset['id']; - let find = this.allProducts.find(product => product.id_product === productId); - if(find){ - find.quantity++; - this._updateCart(find); - } else { - let product = { - id_product: productId, - price: +element.dataset['price'], - product_name: element.dataset['name'], - quantity: 1 - }; - // goods - это своего рода "опорный" массив, отражающий список товаров, которые нужно отрендерить. - // При добавлении нового товара, нас интересует только он один. - this.goods = [product]; - // далее вызывая метод render, мы добавим в allProducts только его, тем самым избегая лишнего перерендера. - this.render(); - } - } else { - alert('Error'); - } - }) - } - - /** - * удаление товара - * @param element - */ - removeProduct(element){ - this.getJson(`${API}/deleteFromBasket.json`) - .then(data => { - if(data.result === 1){ - let productId = +element.dataset['id']; - let find = this.allProducts.find(product => product.id_product === productId); - if(find.quantity > 1){ // если товара > 1, то уменьшаем количество на 1 - find.quantity--; - this._updateCart(find); - } else { // удаляем - this.allProducts.splice(this.allProducts.indexOf(find), 1); - document.querySelector(`.cart-item[data-id="${productId}"]`).remove(); - } - } else { - alert('Error'); - } - }) - } - - /** - * обновляем данные корзины - * @param product - * @private - */ - _updateCart(product){ - let block = document.querySelector(`.cart-item[data-id="${product.id_product}"]`); - block.querySelector('.product-quantity').textContent = `Количество: ${product.quantity}`; - block.querySelector('.product-price').textContent = `${product.quantity * product.price} ₽`; - } - _init(){ - document.querySelector('.btn-cart').addEventListener('click', () => { - document.querySelector(this.container).classList.toggle('invisible'); - }); - document.querySelector(this.container).addEventListener('click', e => { - if(e.target.classList.contains('del-btn')){ - this.removeProduct(e.target); - } - }) - } - -} - -class CartItem extends Item{ - constructor(el, img = 'https://via.placeholder.com/50x100'){ - super(el, img); - this.quantity = el.quantity; - } - render(){ - return `
-
- Some image -
-

${this.product_name}

-

Количество: ${this.quantity}

-

${this.price} за ед.

-
-
-
-

${this.quantity*this.price} ₽

- -
-
` - } -} - -const listContext = { - ProductsList: ProductItem, - Cart: CartItem -}; - -let cart = new Cart(); -let products = new ProductsList(cart);