diff options
author | itchief <alex.malcev1980@gmail.com> | 2020-10-24 12:58:48 +0300 |
---|---|---|
committer | itchief <alex.malcev1980@gmail.com> | 2020-10-24 12:58:48 +0300 |
commit | 8e1c87f9db670c9a9c327ae335789cc3864121f2 (patch) | |
tree | 958dc509cd5e75e6208cd1136c893de2e2805c86 | |
parent | c1b59068e5d0b7e446a6a82f0508fbb50f47f0fa (diff) |
add js without jquery
-rw-r--r-- | feedback/index.html | 199 | ||||
-rw-r--r-- | feedback/js/process-forms-without-jquery.js | 474 |
2 files changed, 573 insertions, 100 deletions
diff --git a/feedback/index.html b/feedback/index.html index 35bbce8..754d463 100644 --- a/feedback/index.html +++ b/feedback/index.html @@ -9,132 +9,131 @@ <body>
-<div class="container">
- <h1>Форма обратной связи</h1>
-
- <div class="form__wrapper">
- <!-- Форма обратной связи -->
- <form id="feedback-form" action="/feedback/process/process.php" enctype="multipart/form-data" novalidate>
- <div class="form-row">
- <!-- Имя пользователя -->
- <div class="form-group">
- <label for="name" class="control-label">Имя</label>
- <input id="name" type="text" name="name" class="form-control" value="" placeholder="Имя" minlength="2"
- maxlength="30" required="required">
- <div class="invalid-feedback"></div>
+ <div class="container">
+ <h1>Форма обратной связи</h1>
+
+ <div class="form__wrapper">
+ <!-- Форма обратной связи -->
+ <form id="feedback-form" action="/feedback/process/process.php" enctype="multipart/form-data" novalidate>
+ <div class="form-row">
+ <!-- Имя пользователя -->
+ <div class="form-group">
+ <label for="name" class="control-label">Имя</label>
+ <input id="name" type="text" name="name" class="form-control" value="" placeholder="Имя" minlength="2"
+ maxlength="30" required="required">
+ <div class="invalid-feedback"></div>
+ </div>
+ <!-- Email пользователя -->
+ <div class="form-group">
+ <label for="email" class="control-label">Email-адрес</label>
+ <input id="email" type="email" name="email" required="required" class="form-control" value=""
+ placeholder="Email-адрес">
+ <div class="invalid-feedback"></div>
+ </div>
</div>
- <!-- Email пользователя -->
+ <!-- Сообщение пользователя -->
<div class="form-group">
- <label for="email" class="control-label">Email-адрес</label>
- <input id="email" type="email" name="email" required="required" class="form-control" value=""
- placeholder="Email-адрес">
+ <label for="message" class="control-label">Сообщение (не менее 20 символов)</label>
+ <textarea id="message" name="message" class="form-control" rows="3"
+ placeholder="Сообщение (не менее 20 символов)" minlength="20" maxlength="500"
+ required="required"></textarea>
<div class="invalid-feedback"></div>
</div>
- </div>
- <!-- Сообщение пользователя -->
- <div class="form-group">
- <label for="message" class="control-label">Сообщение (не менее 20 символов)</label>
- <textarea id="message" name="message" class="form-control" rows="3"
- placeholder="Сообщение (не менее 20 символов)" minlength="20" maxlength="500"
- required="required"></textarea>
- <div class="invalid-feedback"></div>
- </div>
- <!-- Файлы, для прикрепления к форме -->
- <div class="form-group form-attachments" data-count="5">
- <div class="form-attachments__wrapper">
- <input type="file" name="attachment[]" multiple>
- <div class="form-attachments__items">
- <div class="form-attachments__description">
- <div>Нажмите чтобы добавить файлы к сообщению.</div>
- <div>Можно добавить до 5 файлов с разрешением jpg, jpeg, bmp, gif, png и размером до 512 Кбайт.</div>
+ <!-- Файлы, для прикрепления к форме -->
+ <div class="form-group form-attachments" data-count="5">
+ <div class="form-attachments__wrapper">
+ <input type="file" name="attachment[]" multiple>
+ <div class="form-attachments__items">
+ <div class="form-attachments__description">
+ <div>Нажмите чтобы добавить файлы к сообщению.</div>
+ <div>Можно добавить до 5 файлов с разрешением jpg, jpeg, bmp, gif, png и размером до 512 Кбайт.</div>
+ </div>
</div>
</div>
</div>
- </div>
- <!-- Капча -->
- <div class="form-group form-captcha">
- <img class="form-captcha__image" src="/feedback/captcha/captcha.php" data-src="/feedback/captcha/captcha.php"
- width="132" height="46" alt="Капча">
- <div class="form-captcha__refresh">
- <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="16" height="16">
- <path fill="currentColor"
- d="M440.65 12.57l4 82.77A247.16 247.16 0 0 0 255.83 8C134.73 8 33.91 94.92 12.29 209.82A12 12 0 0 0 24.09 224h49.05a12 12 0 0 0 11.67-9.26 175.91 175.91 0 0 1 317-56.94l-101.46-4.86a12 12 0 0 0-12.57 12v47.41a12 12 0 0 0 12 12H500a12 12 0 0 0 12-12V12a12 12 0 0 0-12-12h-47.37a12 12 0 0 0-11.98 12.57zM255.83 432a175.61 175.61 0 0 1-146-77.8l101.8 4.87a12 12 0 0 0 12.57-12v-47.4a12 12 0 0 0-12-12H12a12 12 0 0 0-12 12V500a12 12 0 0 0 12 12h47.35a12 12 0 0 0 12-12.6l-4.15-82.57A247.17 247.17 0 0 0 255.83 504c121.11 0 221.93-86.92 243.55-201.82a12 12 0 0 0-11.8-14.18h-49.05a12 12 0 0 0-11.67 9.26A175.86 175.86 0 0 1 255.83 432z">
- </path>
- </svg>
- </div>
- <div class="form-group form-captcha__input">
- <label for="captcha" class="control-label d-none">Код, показанный на изображении</label>
- <input type="text" name="captcha" maxlength="6" required="required" id="captcha"
- class="form-control captcha" placeholder="******" autocomplete="off" value="">
- <div class="invalid-feedback"></div>
+ <!-- Капча -->
+ <div class="form-group form-captcha">
+ <img class="form-captcha__image" src="/feedback/captcha/captcha.php" data-src="/feedback/captcha/captcha.php"
+ width="132" height="46" alt="Капча">
+ <div class="form-captcha__refresh">
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="16" height="16">
+ <path fill="currentColor"
+ d="M440.65 12.57l4 82.77A247.16 247.16 0 0 0 255.83 8C134.73 8 33.91 94.92 12.29 209.82A12 12 0 0 0 24.09 224h49.05a12 12 0 0 0 11.67-9.26 175.91 175.91 0 0 1 317-56.94l-101.46-4.86a12 12 0 0 0-12.57 12v47.41a12 12 0 0 0 12 12H500a12 12 0 0 0 12-12V12a12 12 0 0 0-12-12h-47.37a12 12 0 0 0-11.98 12.57zM255.83 432a175.61 175.61 0 0 1-146-77.8l101.8 4.87a12 12 0 0 0 12.57-12v-47.4a12 12 0 0 0-12-12H12a12 12 0 0 0-12 12V500a12 12 0 0 0 12 12h47.35a12 12 0 0 0 12-12.6l-4.15-82.57A247.17 247.17 0 0 0 255.83 504c121.11 0 221.93-86.92 243.55-201.82a12 12 0 0 0-11.8-14.18h-49.05a12 12 0 0 0-11.67 9.26A175.86 175.86 0 0 1 255.83 432z">
+ </path>
+ </svg>
+ </div>
+ <div class="form-group form-captcha__input">
+ <label for="captcha" class="control-label d-none">Код, показанный на изображении</label>
+ <input type="text" name="captcha" maxlength="6" required="required" id="captcha"
+ class="form-control captcha" placeholder="******" autocomplete="off" value="">
+ <div class="invalid-feedback"></div>
+ </div>
</div>
- </div>
- <!-- Пользовательское солашение -->
- <div class="form-group form-agreement">
- <div class="custom-control custom-checkbox">
- <input type="checkbox" name="agree" class="custom-control-input" id="customCheck">
- <label class="custom-control-label" for="customCheck">Нажимая кнопку, я принимаю условия <a
- href="#">Пользовательского соглашения</a> и даю своё согласие на обработку моих персональных данных, в
- соответствии с Федеральным законом от 27.07.2006 года №152-ФЗ «О персональных данных».</label>
+ <!-- Пользовательское солашение -->
+ <div class="form-group form-agreement">
+ <div class="custom-control custom-checkbox">
+ <input type="checkbox" name="agree" class="custom-control-input" id="customCheck">
+ <label class="custom-control-label" for="customCheck">Нажимая кнопку, я принимаю условия <a
+ href="#">Пользовательского соглашения</a> и даю своё согласие на обработку моих персональных данных, в
+ соответствии с Федеральным законом от 27.07.2006 года №152-ФЗ «О персональных данных».</label>
+ </div>
</div>
- </div>
- <!-- Сообщение при ошибке -->
- <div class="form-error d-none">
- Исправьте данные и отправьте форму ещё раз.
- </div>
+ <!-- Сообщение при ошибке -->
+ <div class="form-error d-none">
+ Исправьте данные и отправьте форму ещё раз.
+ </div>
- <!-- Индикация отправки данных формы на сервер -->
- <div class="progress d-none">
- <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
- style="width: 0"></div>
- </div>
+ <!-- Индикация отправки данных формы на сервер -->
+ <div class="progress d-none">
+ <div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"
+ style="width: 0"></div>
+ </div>
- <!-- Кнопка для отправки формы на сервер -->
- <div class="form-submit">
- <button type="submit" disabled>Отправить сообщение</button>
- </div>
+ <!-- Кнопка для отправки формы на сервер -->
+ <div class="form-submit">
+ <button type="submit" disabled>Отправить сообщение</button>
+ </div>
- </form>
+ </form>
- <!-- Сообщение об успешной отправки формы -->
- <div class="form-result-success d-none">
- <div>Форма успешно отправлена. Нажмите на <a href="#" data-target="#feedback-form">ссылку</a>, чтобы отправить ещё
- одно сообщение.
+ <!-- Сообщение об успешной отправки формы -->
+ <div class="form-result-success d-none">
+ <div>Форма успешно отправлена. Нажмите на <a href="#" data-target="#feedback-form">ссылку</a>, чтобы отправить
+ ещё одно сообщение.</div>
</div>
+
</div>
</div>
-</div>
-
-<script src="/feedback/vendors/jquery/jquery-3.4.1.min.js"></script>
-<script src="/feedback/js/process-forms.js"></script>
-<script>
+ <script src="/feedback/vendors/jquery/jquery-3.4.1.min.js"></script>
+ <script src="/feedback/js/process-forms-without-jquery.js"></script>
+ <script>
//после загрузки DOM
$(function () {
- /*
- Параметры указываются в виде:
- {
- ключ: значение;
- ключ: значение;
- ...
- }
- Основные параметры
- selector - селектор формы (по умолчанию '#feedback-form')
- attachmentsMaxFileSize - максимальный размер файла в Кбайтах (по умолчанию 512)
- attachmentsFileExt - допустимые расширения файлов для загрузки (по умолчанию 'jpg','jpeg','bmp','gif','png')
- isUseDefaultSuccessMessage - отображать дефолтное сообщение после отправки
- */
- var form1 = new ProcessForm();
- form1.init();
+ /*
+ Параметры указываются в виде:
+ {
+ ключ: значение;
+ ключ: значение;
+ ...
+ }
+ Основные параметры
+ selector - селектор формы (по умолчанию '#feedback-form')
+ attachmentsMaxFileSize - максимальный размер файла в Кбайтах (по умолчанию 512)
+ attachmentsFileExt - допустимые расширения файлов для загрузки (по умолчанию 'jpg','jpeg','bmp','gif','png')
+ isUseDefaultSuccessMessage - отображать дефолтное сообщение после отправки
+ */
+ var form1 = new ProcessForm();
+ form1.init();
});
-</script>
+ </script>
</body>
-</html>
\ No newline at end of file +</html>
diff --git a/feedback/js/process-forms-without-jquery.js b/feedback/js/process-forms-without-jquery.js new file mode 100644 index 0000000..853c541 --- /dev/null +++ b/feedback/js/process-forms-without-jquery.js @@ -0,0 +1,474 @@ +/*! + * Форма обратной связи (https://github.com/itchief/feedback-form) + * Страница с описанием: https://itchief.ru/lessons/php/feedback-form-for-website + * Copyright 2016-2020 Alexander Maltsev + * Licensed under MIT (https://github.com/itchief/feedback-form/blob/master/LICENSE) + */ + +'use strict'; + +var ProcessForm = function (settings) { + this._settings = { + selector: '#feedback-form', // дефолтный селектор + attachmentsMaxFileSize: 512, // дефолтный максимальный размер файла в Кб + attachmentsFileExt: ['jpg', 'jpeg', 'bmp', 'gif', 'png'], // дефолтные допустимые расширения для файлов + isUseDefaultSuccessMessage: true, // отображать дефолтное сообщение об успешной отправки формы + }; + this._isCaptchaSection = false; // имеется ли в форме блок с капчей + this._isAgreementSection = false; // имеется ли в форме блок с пользовательским соглашением + this._isAttachmentsSection = false; // имеется ли в форме блок для добавления к ней файлов + this._attachmentsIdCounter = 0; // счетчик, хранящий количество добавленных к форме файлов + this._attachmentsMaxItems = 5; // переменная, определяющее максимальное количество файлов, которые можно прикрепить к форме + this._attachmentsItems = []; // переменная, хранящая массив файлов, которые нужно прекрепить к форме + + for (var propName in settings) { + if (settings.hasOwnProperty(propName)) { + this._settings[propName] = settings[propName]; + } + } + this._$form = document.querySelector(this._settings.selector); + // инициализация формы + this._init(); +}; + +// функция для проверки расширения файла +ProcessForm.validateFileExtension = function (filename, validFileExtensions) { + // получаем расширение файла + var fileExtension = filename.slice(((filename.lastIndexOf('.') - 1) >>> 0) + 2); + // если есть расширение, то проверяем соответствует ли оно допустимому + if (fileExtension) { + for (var i = 0; i <= validFileExtensions.length; i++) { + if (validFileExtensions[i] === fileExtension.toLowerCase()) { + return true; + } + } + } + return false; +}; + +// переключение состояния disabled у кнопки submit +ProcessForm.prototype._changeStateSubmit = function (state) { + this._$form.querySelector('[type="submit"]').disabled = state; +}; + +// обновление капчи +ProcessForm.prototype._refreshCaptcha = function () { + var captchaImg = this._$form.querySelector('.form-captcha__image'); + var captchaSrc = captchaImg.getAttribute('data-src'); + var captchaPrefix = captchaSrc.indexOf('?id') !== -1 ? '&rnd=' : '?rnd='; + var captchaNewSrc = captchaSrc + captchaPrefix + new Date().getTime(); + captchaImg.setAttribute('src', captchaNewSrc); +}; + +// изменение состояния элемента формы (success, error, clear) +ProcessForm.prototype._setStateValidaion = function (input, state, message) { + if (state === 'error') { + input.classList.remove('is-valid'); + input.classList.add('is-invalid'); + input.parentElement.querySelector('.invalid-feedback').textContent = message; + } else if (state === 'success') { + input.classList.remove('is-invalid'); + input.classList.add('is-valid'); + } else { + input.classList.remove('is-valid'); + input.classList.remove('is-invalid'); + } +}; + +// валидация формы +ProcessForm.prototype._validateForm = function () { + var valid = true; + var $elements = this._$form.querySelectorAll('input, textarea'); + for (var i = 0; i < $elements.length; i++) { + if ($elements[i].type === 'file' || $elements[i].name === 'agree') { + continue; + } + if ($elements[i].checkValidity()) { + this._setStateValidaion($elements[i], 'success'); + } else { + this._setStateValidaion($elements[i], 'error', $elements[i].validationMessage); + valid = false; + } + } + + // для теста > + if (this._attachmentsItems.length === 0) { + var files = this._attachmentsItems; + for (var i = 0, length = files.length; i < length; i++) { + // проверим размер и расширение файла + if (files[i].file.size > this._settings.attachmentsMaxFileSize * 1024) { + var attach = this._$form.querySelector('.form-attachments__item[data-id="' + i + '"]'); + attach.setAttribute( + 'title', + 'Размер файла больше ' + this._settings.attachmentsMaxFileSize + 'Кб' + ); + attach.classList.add('is-invalid'); + valid = false; + } else if ( + !ProcessForm.validateFileExtension(files[i].file.name, this._settings.attachmentsFileExt) + ) { + var attach = this._$form.querySelector('.form-attachments__item[data-id="' + i + '"]'); + attach.setAttribute('title', 'Тип не соответствует разрешённым'); + attach.classList.add('is-invalid'); + valid = false; + } else { + var attach = this._$form.querySelector('.form-attachments__item[data-id="' + i + '"]'); + if (attach) { + attach.setAttribute('title', ''); + attach.classList.add('is-valid'); + } + } + } + } + return valid; +}; + +ProcessForm.prototype._showForm = function () { + this._$form.querySelector('.form-error').classList.add('d-none'); + var $resultSuccess = this._$form.parentElement.querySelector('.form-result-success'); + $resultSuccess.classList.add('d-none'); + $resultSuccess.classList.remove('d-flex'); + this._$form.reset(); + var $elements = this._$form.querySelectorAll('input, textarea'); + for (var i = 0, length = $elements.length; i < length; i++) { + this._setStateValidaion($elements[i], 'clear'); + } + if (this._isCaptchaSection) { + this._refreshCaptcha(); + } + if (this._isAgreementSection) { + this._changeStateSubmit(true); + } else { + this._changeStateSubmit(false); + } + + // удаление attachment items + var $attachs = this._$form.querySelectorAll('.form-attachments__item'); + if ($attachs.length > 0) { + for (var i = 0, length = $attachs.length; i < length; i++) { + $attachs[i].parentElement.removeChild($attachs[i]); + } + } + + if (this._$form.querySelector('.progress-bar').length) { + var $progressBar = this._$form.querySelector('.progress-bar'); + $progressBar.setAttribute('aria-valuenow', '0'); + $progressBar.style.width = 0; + } +}; + +// переключение disabled для name="attachment[]" +ProcessForm.prototype._disabledAttach = function (state) { + var $attach = this._$form.querySelector('[name="attachment[]"]'); + if ($attach) { + $attach.disabled = state; + } +}; + +// собираем данные для отправки на сервер +ProcessForm.prototype._collectData = function () { + var data; + var $attachs = this._attachmentsItems; + // отключаем добавление данных из name="attachment[]" в FormData + this._disabledAttach(true); + data = new FormData(this._$form); + // включаем доступность name="attachment[]" + this._disabledAttach(false); + // добавляем данные из name="attachment[]" в FormData + for (var i = 0, length = $attachs.length; i < length; i++) { + data.append('attachment[]', $attachs[i].file); + } + return data; +}; + +// отправка формы +ProcessForm.prototype._sendForm = function () { + this._$form.dispatchEvent(new Event('beforeSubmit')); + if (!this._validateForm()) { + if (this._$form.querySelectorAll('.is-invalid').length > 0) { + if (this._$form.querySelectorAll('.is-invalid')[0].classList.contains('file')) { + this._$form.querySelector('input[type="file"]').focus(); + } else { + this._$form.querySelectorAll('.is-invalid')[0].focus(); + } + } + return; + } + + if (!this._$form.querySelector('.form-error').classList.contains('d-none')) { + this._$form.querySelector('.form-error').classList.add('d-none'); + } + + this._changeStateSubmit(true); + + var _this = this; + + var request = new XMLHttpRequest(); + request.onreadystatechange = function () { + if (request.readyState === 0 || request.readyState === 4) { + if (request.status == 200) { + _success(JSON.parse(request.responseText), _this); + } else { + _error(_this); + } + //done(); + } + }; + if (this._$form.querySelector('.progress').classList.contains('d-none')) { + this._$form.querySelector('.progress').classList.remove('d-none'); + } + request.upload.onprogress = function (e) { + // если известно количество байт для пересылки + if (e.lengthComputable) { + // получаем общее количество байт для пересылки + var total = e.total; + // получаем какое количество байт уже отправлено + var loaded = e.loaded; + // определяем процент отправленных данных на сервер + var progress = ((loaded * 100) / total).toFixed(1); + // обновляем состояние прогресс бара Bootstrap + var progressBar = this._$form.querySelector('.progress-bar'); + progressBar.setAttribute('aria-valuenow', progress); + progressBar.style.width = progress + '%'; + //progressBar.querySelector('.sr-only').textContent = progress + '%'; + } + }.bind(this); + + request.open('POST', this._$form.getAttribute('action'), true); + request.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + //request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); + request.send(this._collectData()); + + // при получении успешного ответа от сервера + function _success(data, _this) { + var _this = _this; + + var $progress = _this._$form.querySelector('.progress'); + if ($progress) { + $progress.classList.add('d-none'); + var progressBar = $progress.querySelector('.progress-bar'); + progressBar.setAttribute('aria-valuenow', '0'); + progressBar.style.width = '0'; + //progressBar.querySelector('.sr-only').textContent = '0%'; + } + + // при успешной отправки формы + if (data.result === 'success') { + _this._$form.dispatchEvent(new Event('pf_success')); + if (_this._settings.isUseDefaultSuccessMessage) { + var $resultSuccess = _this._$form.parentElement.querySelector('.form-result-success'); + $resultSuccess.classList.remove('d-none'); + $resultSuccess.classList.add('d-flex'); + } + return; + } + // если произошли ошибки при отправке + _this._$form.querySelector('.form-error').classList.remove('d-none'); + _this._changeStateSubmit(false); + + var attach = _this._$form.querySelector('.form-attachments__item'); + if (attach) { + attach.setAttribute('title', ''); + attach.classList.remove('is-valid'); + attach.classList.remove('is-invalid'); + } + + // выводим ошибки которые прислал сервер + for (var error in data) { + if (!data.hasOwnProperty(error)) { + continue; + } + switch (error) { + case 'captcha': + _this._refreshCaptcha(_this); + var $element = _this._$form.querySelector('[name="' + error + '"]'); + _this._setStateValidaion($element, 'error', data[error]); + break; + case 'attachment': + var attachs = data[error]; + for (let key in attachs) { + var id = _this._attachmentsItems[key].id; + var selector = '.form-attachments__item[data-id="' + id + '"]'; + var $attach = _this._$form.querySelector(selector); + $attach.setAttribute('title', attachs[key]); + $attach.classList.add('is-invalid'); + } + break; + case 'log': + var logs = data[error]; + for (var i = 0, length = logs.length; i < length; i++) { + console.log(logs[i]); + } + break; + default: + var $element = _this._$form.querySelector('[name="' + error + '"]'); + if ($element) { + _this._setStateValidaion($element, 'error', data[error]); + } + } + } + // устанавливаем фокус на не валидный элемент + if (_this._$form.querySelectorAll('.is-invalid').length > 0) { + if (_this._$form.querySelectorAll('.is-invalid')[0].classList.contains('file')) { + _this._$form.querySelector('input[type="file"]').focus(); + } else { + _this._$form.querySelectorAll('.is-invalid')[0].focus(); + } + } + var its = _this._$form.querySelectorAll('.form-attachments__item :not(.is-invalid)'); + for (var i = 0, length = its.lengt; i < length; i++) { + its[i].classList.add('is-valid'); + } + } + + // если не получили успешный ответ от сервера + function _error(_this) { + _this._$form.querySelector('.form-error').classList.remove('d-none'); + } +}; + +// функция для инициализации +ProcessForm.prototype._init = function () { + // устанавливаем значение свойства _isCaptchaSection в завимости от того имеется ли у формы секция с капчей или нет + this._isCaptchaSection = this._$form.querySelectorAll('.form-captcha').length > 0; + // устанавливаем значение свойства _isAgreementSection в завимости от того имеется ли у формы секция с пользовательским соглашением или нет + this._isAgreementSection = this._$form.querySelectorAll('.form-agreement').length > 0; + // устанавливаем значения свойств _isAttachmentsSection и _attachmentsMaxItems в завимости от того имеется ли у формы секция с секцией для добавления к ней файлов + var formAttachments = this._$form.querySelectorAll('.form-attachments'); + if (formAttachments.length) { + this._isAttachmentsSection = true; + if (formAttachments[0].getAttribute('data-count')) { + this._attachmentsMaxItems = +formAttachments[0].getAttribute('data-count'); + } + } + this._setupListener.call(this); +}; + +ProcessForm.prototype._reset = function () { + this._showForm(); +}; + +// устанавливаем обработчики событий +ProcessForm.prototype._setupListener = function () { + var $form = this._$form; + $form.onchange = function (e) { + var $element = e.target; + if ($element.name === 'agree') { + this._changeStateSubmit(!$element.checked); + } + }.bind(this); + $form.onsubmit = function (e) { + var $form = e.target; + if ($form === this._$form) { + e.preventDefault(); + this._sendForm(this); + } + }.bind(this); + // обработка события click + $form.onclick = function (e) { + var $element = e.target; + if ($element.classList.contains('form-captcha__refresh')) { + // при нажатии click на form-captcha__refresh + e.preventDefault(); + this._refreshCaptcha(); + } else if ($element.classList.contains('form-attachments__item-link')) { + // при нажатии click на form-attachments__item-link + var id = +$element.dataset.id; + var $item = $form.querySelector('.form-attachments__item[data-id="' + id + '"]'); + var $attachs = this._attachmentsItems; + for (var i = 0, length = $attachs.length; i < length; i++) { + if ($attachs[i].id === id) { + $attachs.splice(i, 1); + break; + } + } + $item.parentElement.removeChild($item); + } + }.bind(this); + + $form.parentElement.onclick = function (e) { + var $element = e.target; + if ($element.dataset.target === this._settings.selector) { + e.preventDefault(); + this._showForm(); + } + }.bind(this); + + var _this = this; + + // если у формы имеется .form-attachment + if (this._isAttachmentsSection) { + // событие при изменении элемента input с type="file" (name="attachment[]) + _this._$form.addEventListener('change', function (e) { + if (e.target.name !== 'attachment[]') { + return; + } + + var file, fileId, removeLink; + + for (var i = 0, length = e.target.files.length; i < length; i++) { + if (_this._attachmentsItems.length === _this._attachmentsMaxItems) { + e.target.value = ''; + break; + } + fileId = _this._attachmentsIdCounter++; + file = e.target.files[i]; + _this._attachmentsItems.push({ + id: fileId, + file: file, + }); + if (file.type.match(/image.*/)) { + var reader = new FileReader(); + reader.readAsDataURL(file); + (function (file, fileId) { + reader.addEventListener('load', function (e) { + var removeLink = + '<div class="form-attachments__item" data-id="' + + fileId + + '">' + + '<div class="form-attachments__item-wrapper">' + + '<img class="form-attachments__item-image" src="' + + e.target.result + + '" alt="' + + file.name + + '">' + + '<div class="form-attachments__item-name">' + + file.name + + '</div>' + + '<div class="form-attachments__item-size">' + + (file.size / 1024).toFixed(1) + + 'Кб' + + '</div>' + + '<div class="form-attachments__item-link" data-id="' + + fileId + + '">×</div>' + + '</div>' + + '</div>'; + _this._$form.querySelector('.form-attachments__items').innerHTML += removeLink; + }); + })(file, fileId); + continue; + } + removeLink = + '<div class="form-attachments__item" data-id="' + + fileId + + '">' + + '<div class="form-attachments__item-wrapper">' + + '<div class="form-attachments__item-name">' + + file.name + + '</div>' + + '<div class="form-attachments__item-size">' + + (file.size / 1024).toFixed(1) + + 'Кб' + + '</div>' + + '<div class="form-attachments__item-link" data-id="' + + fileId + + '">×</div>' + + '</div>' + + '</div>'; + _this._$form.querySelector('.form-attachments__items').innerHTML += removeLink; + } + e.target.value = null; + }); + } +}; |