import { Utility } from '../../core/utility'; import { Datepicker } from '../form/datepicker'; import './async-form.scss'; const ASYNC_FORM_INITIALIZED_CLASS = 'check-all--initialized'; const ASYNC_FORM_RESPONSE_CLASS = 'async-form__response'; const ASYNC_FORM_LOADING_CLASS = 'async-form--loading'; const ASYNC_FORM_MIN_DELAY = 600; const MODAL_SELECTOR = '.modal'; const MODAL_HEADER_KEY = 'Is-Modal'; const MODAL_HEADER_VALUE = 'True'; @Utility({ selector: 'form[uw-async-form]', }) export class AsyncForm { _lastRequestTimestamp = 0; _element; _app; constructor(element, app) { if (!element) { throw new Error('Async Form Utility cannot be setup without an element!'); } this._element = element; this._app = app; if (this._element.classList.contains(ASYNC_FORM_INITIALIZED_CLASS)) { return false; } this._element.addEventListener('submit', this._submitHandler); this._element.classList.add(ASYNC_FORM_INITIALIZED_CLASS); } destroy() { // TODO } _processResponse(response) { const responseElement = this._makeResponseElement(response.content, response.status); const parentElement = this._element.parentElement; // make sure there is a delay between click and response const delay = Math.max(0, ASYNC_FORM_MIN_DELAY + this._lastRequestTimestamp - Date.now()); setTimeout(() => { parentElement.insertBefore(responseElement, this._element); this._element.remove(); }, delay); } _makeResponseElement(content, status) { const responseElement = document.createElement('div'); status = status || 'info'; responseElement.classList.add(ASYNC_FORM_RESPONSE_CLASS); responseElement.classList.add(ASYNC_FORM_RESPONSE_CLASS + '--' + status); responseElement.innerHTML = content; return responseElement; } _submitHandler = (event) => { event.preventDefault(); this._element.classList.add(ASYNC_FORM_LOADING_CLASS); this._lastRequestTimestamp = Date.now(); const url = this._element.getAttribute('action'); const headers = { }; // create new FormData and format any date values const body = Datepicker.unformatAll(this._element, new FormData(this._element)); const isModal = this._element.closest(MODAL_SELECTOR); if (isModal) { headers[MODAL_HEADER_KEY] = MODAL_HEADER_VALUE; } this._app.httpClient.post({ url: url, headers: headers, body: body, }).then( (response) => response.json() ).then( (response) => this._processResponse(response[0]) ).catch(() => { const failureMessage = this._app.i18n.get('asyncFormFailure'); this._processResponse({ content: failureMessage }); this._element.classList.remove(ASYNC_FORM_LOADING_CLASS); }); } }