fradrive/static/js/utils/asyncForm.js

127 lines
3.7 KiB
JavaScript

(function collonadeClosure() {
'use strict';
/**
*
* Async Form Utility
* prevents form submissions from reloading the page but instead firing an AJAX request
*
* Attribute: uw-async-form
* (works only on <form> elements)
*
* Example usage:
* <form uw-async-form method='POST' action='...'>
* ...
*
* Internationalization:
* This utility expects the following translations to be available:
* asyncFormFailure: text that gets shown if an async form request fails
* example: "Oops. Something went wrong."
*/
var ASYNC_FORM_UTIL_NAME = 'asyncForm';
var ASYNC_FORM_UTIL_SELECTOR = 'form[uw-async-form]';
var ASYNC_FORM_INITIALIZED_CLASS = 'check-all--initialized';
var ASYNC_FORM_RESPONSE_CLASS = 'async-form__response';
var ASYNC_FORM_LOADING_CLASS = 'async-form--loading';
var ASYNC_FORM_MIN_DELAY = 600;
var MODAL_SELECTOR = '.modal';
var MODAL_HEADER_KEY = 'Is-Modal';
var MODAL_HEADER_VALUE = 'True';
var asyncFormUtil = function(element) {
var lastRequestTimestamp = 0;
function init() {
if (!element) {
throw new Error('Async Form Utility cannot be setup without an element!');
}
if (element.classList.contains(ASYNC_FORM_INITIALIZED_CLASS)) {
return false;
}
element.addEventListener('submit', submitHandler);
element.classList.add(ASYNC_FORM_INITIALIZED_CLASS);
return {
name: ASYNC_FORM_UTIL_NAME,
element: element,
destroy: function() {},
};
}
function processResponse(response) {
var responseElement = makeResponseElement(response.content, response.status);
var parentElement = element.parentElement;
// make sure there is a delay between click and response
var delay = Math.max(0, ASYNC_FORM_MIN_DELAY + lastRequestTimestamp - Date.now());
setTimeout(function() {
parentElement.insertBefore(responseElement, element);
element.remove();
}, delay);
}
function makeResponseElement(content, status) {
var 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;
}
function submitHandler(event) {
event.preventDefault();
if (!HttpClient) {
throw new Error('HttpClient not found! Can\'t fetch submit form asynchronously!');
}
element.classList.add(ASYNC_FORM_LOADING_CLASS)
lastRequestTimestamp = Date.now();
var url = element.getAttribute('action');
var headers = { };
var body = new FormData(element);
var isModal = element.closest(MODAL_SELECTOR);
if (!!isModal) {
headers[MODAL_HEADER_KEY] = MODAL_HEADER_VALUE;
}
HttpClient.post(url, headers, body)
.then(function(response) {
if (response.headers.get("content-type").indexOf("application/json") !== -1) {// checking response header
return response.json();
} else {
throw new TypeError('Unexpected Content-Type. Expected Content-Type: "application/json". Requested URL:' + url + '"');
}
}).then(function(response) {
processResponse(response[0]);
}).catch(function(error) {
var failureMessage = I18n.get('asyncFormFailure');
processResponse({ content: failureMessage });
element.classList.remove(ASYNC_FORM_LOADING_CLASS);
});
}
return init();
};
if (UtilRegistry) {
UtilRegistry.register({
name: ASYNC_FORM_UTIL_NAME,
selector: ASYNC_FORM_UTIL_SELECTOR,
setup: asyncFormUtil
});
}
})();