From dadced9a3c9d11ccafdba1e8bdfdf72d990437c6 Mon Sep 17 00:00:00 2001 From: Maxim Stogniy Date: Sun, 17 May 2020 22:24:31 +1200 Subject: [PATCH] Add contacts modal validation and modal message --- src/components/contacts.pug | 21 +++-- src/main.js | 3 +- src/scripts/contacts.js | 112 +++++++++++++++++++++++++++ src/styles/blocks/error-tooltip.pcss | 26 +++++++ src/styles/blocks/form.pcss | 14 +++- src/styles/blocks/modal.pcss | 44 +++++++++++ src/styles/blocks/slider-btn.pcss | 5 ++ src/styles/variables.json | 3 +- 8 files changed, 218 insertions(+), 10 deletions(-) create mode 100644 src/scripts/contacts.js create mode 100644 src/styles/blocks/error-tooltip.pcss create mode 100644 src/styles/blocks/modal.pcss diff --git a/src/components/contacts.pug b/src/components/contacts.pug index 10a4a73..43bf798 100644 --- a/src/components/contacts.pug +++ b/src/components/contacts.pug @@ -2,13 +2,13 @@ section.contacts(id="contacts") .container.contacts__container h2.section__title.contacts__title Связаться со мной .contacts__form - form + form(novalidate)#contacts__form .form__container .form__row - var fields = [ - ["Введите ваше имя", "Иванов Иван", "user"], - ["Введите ваш email", "example@mail.com", "envelope"] + ["Введите ваше имя", "Иванов Иван", "user-empty", "text"], + ["Введите ваш email", "example@mail.com", "envelope", "email"] ] each field in fields label.form__block @@ -16,14 +16,23 @@ section.contacts(id="contacts") .form__block-wrap +icon(field[2],'form__block-icon') .form__block-field - input(placeholder=field[1]).form__block-input + input(type=field[3] placeholder=field[1] required).form__block-input + .error-tooltip .form__row.form__row--more-margin label.form__block .form__block-label Сообщение к письму .form__block-wrap.form__block-wrap--align-top +icon('message','form__block-icon') .form__block-field - textarea(placeholder="Требуется ваша помощь в создании сайта. \nИнтересуют сроки и цена вопроса" rows="3").form__block-input.form__block-textarea + textarea(required minlength="15" placeholder="Требуется ваша помощь в создании сайта. \nИнтересуют сроки и цена вопроса" rows="3").form__block-input.form__block-textarea + .error-tooltip .form__row .form__buttons - button(type="submit").custom-btn Отправить \ No newline at end of file + button(type="submit" id="contacts__form-submit").custom-btn Отправить + + script(type="template" id="modalTemplate") + .modal + .modal__container + .modal__content + .modal__content-text Письмо отправлено + button(type=button)#modal__close.custom-btn Закрыть \ No newline at end of file diff --git a/src/main.js b/src/main.js index 2da8888..daa4f5a 100644 --- a/src/main.js +++ b/src/main.js @@ -7,4 +7,5 @@ import "./scripts/skills"; import "./scripts/works"; import "./scripts/reviews"; import "./scripts/parallax"; -import "./scripts/nav"; \ No newline at end of file +import "./scripts/nav"; +import "./scripts/contacts"; \ No newline at end of file diff --git a/src/scripts/contacts.js b/src/scripts/contacts.js new file mode 100644 index 0000000..b32021c --- /dev/null +++ b/src/scripts/contacts.js @@ -0,0 +1,112 @@ +const submitBtn = document.querySelector("#contacts__form-submit") +const form = document.querySelector("#contacts__form") +let formInValid + +( () => { + Array.from(form.elements).forEach(elem => { + if (elem.type === "submit") return + elem.addEventListener("input", () => { + if (formInValid) { + validateElem(elem) + } + }) + }) +})() + +function switchScroll () { + document.body.classList.toggle('body--scroll-block') +} + + +function formValidate (form) { + formInValid = Array.from(form.elements).some(elem => !elem.checkValidity()) +} +submitBtn.addEventListener("click", (e) => { + e.preventDefault() + formValidate(form) + if (formInValid) { + Array.from(form.elements).forEach(elem => { + if (elem.type === "submit") return + validateElem(elem) + }) + } else { + const template = document.querySelector("#modalTemplate").innerHTML; + const modal = createModal(template); + modal.open(); + } +}) + +function validateElem(elem) { + if (!elem.checkValidity()) { + showError(elem) + } else { + hideError(elem) + } +} + +function showError (elem) { + let errorText = '' + const parent = elem.closest('.form__block') + const tooltip = parent.querySelector('.error-tooltip') + parent.classList.add('error') + if (elem.value.length === 0) { + errorText = "Поле не должно быть пустым" + } else { + switch (elem.type) { + case 'email': + errorText = "Введите корректный e-mail" + break + case 'textarea': + errorText = "Введите не менее 15 символов" + break + } + } + + tooltip.innerText = errorText + tooltip.classList.add("error-tooltip--showed") +} + +function emptyForm (form) { + form.reset() +} + +function hideError (elem) { + const parent = elem.closest('.form__block') + const tooltip = parent.querySelector('.error-tooltip') + parent.classList.remove('error') + tooltip.innerText = '' + tooltip.classList.remove("error-tooltip--showed") +} + +function createModal(template) { + const fragment = document.createElement('div'); + + fragment.innerHTML = template; + + const modalElement = fragment.querySelector(".modal"); + const closeElement = fragment.querySelector("#modal__close"); + + modalElement.addEventListener("click", e => { + if (e.target === modalElement) { + closeElement.click(e); + + } + }); + + closeElement.addEventListener("click", (e) => { + e.preventDefault() + document.querySelector('.contacts').removeChild(modalElement); + switchScroll() + emptyForm(form) + }); + + return { + open() { + document.querySelector('.contacts').appendChild(modalElement); + switchScroll() + }, + close() { + closeElement.click(); + } + }; +} \ No newline at end of file diff --git a/src/styles/blocks/error-tooltip.pcss b/src/styles/blocks/error-tooltip.pcss new file mode 100644 index 0000000..1998df8 --- /dev/null +++ b/src/styles/blocks/error-tooltip.pcss @@ -0,0 +1,26 @@ +.error-tooltip { + opacity: 0; + position: absolute; + left: 5%; + font-size: 14px; + line-height: 44px; + color: #fff; + background-color: $errors-color; + padding: 0 20px; + z-index: 9999; + user-select: none; + + &:after { + content: ''; + position: absolute; + bottom: 100%; + left: 50%; + transform: translateX(-50%); + border: 6px solid transparent; + border-bottom: 6px solid $errors-color; + } + + &--showed { + opacity: 1; + } +} \ No newline at end of file diff --git a/src/styles/blocks/form.pcss b/src/styles/blocks/form.pcss index d9d468f..3badc59 100644 --- a/src/styles/blocks/form.pcss +++ b/src/styles/blocks/form.pcss @@ -27,10 +27,12 @@ .form__block { flex: 1; margin-right: 90px; - border-bottom: 1px solid currentColor; + border-bottom: 2px solid currentColor; + position: relative; &:hover, - &:focus { + &:focus, + &:focus-within { border-color: $main; .form__block-icon { @@ -43,6 +45,14 @@ margin-right: 0; } + &.error { + border-color: #fb0000; + + .form__block-icon { + fill: #fb0000; + opacity: 1; + } + } @include tablets { margin-right: 20px; diff --git a/src/styles/blocks/modal.pcss b/src/styles/blocks/modal.pcss new file mode 100644 index 0000000..7ebf30b --- /dev/null +++ b/src/styles/blocks/modal.pcss @@ -0,0 +1,44 @@ +.modal { + display: flex; + position: fixed; + width: 100%; + height: 100%; + bottom: 0; + + &:before { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: block; + content: ""; + background-color: #2d3c4e; + opacity: .9; + } +} + +.modal__container { + display: flex; + justify-content: center; + align-items: center; + flex: 1; + z-index: 10; +} + +.modal__content { + background-color: $white; + width: 565px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + padding: 50px; +} + +.modal__content-text { + margin-bottom: 30px; + font-weight: 500; + font-size: 36px; + text-align: center; +} \ No newline at end of file diff --git a/src/styles/blocks/slider-btn.pcss b/src/styles/blocks/slider-btn.pcss index de1d91c..b07621f 100644 --- a/src/styles/blocks/slider-btn.pcss +++ b/src/styles/blocks/slider-btn.pcss @@ -5,6 +5,11 @@ padding: 0; border: none; + &:disabled { + cursor: unset; + opacity: .3; + } + &:enabled { &:hover { background-color: #5500f2; diff --git a/src/styles/variables.json b/src/styles/variables.json index 7b8cbbf..d7b0a54 100644 --- a/src/styles/variables.json +++ b/src/styles/variables.json @@ -20,5 +20,6 @@ "href": "#586ed3", "white": "#fff", "tag": "#859ec2", - "admin-font": "#414c63" + "admin-font": "#414c63", + "errors-color": "#cd1515" }