refactor async form js util
This commit is contained in:
parent
63aef9e362
commit
559fb3fb9d
@ -1071,6 +1071,7 @@ siteLayout' headingOverride widget = do
|
||||
-- addScript $ StaticR js_utils_alerts_js
|
||||
-- addScript $ StaticR js_utils_asidenav_js
|
||||
-- JavaScript utils
|
||||
addScript $ StaticR js_utils_asyncForm_js
|
||||
addScript $ StaticR js_utils_asyncTable_js
|
||||
addScript $ StaticR js_utils_checkAll_js
|
||||
addScript $ StaticR js_utils_form_js
|
||||
|
||||
@ -121,7 +121,7 @@ postAdminTestR = do
|
||||
let emailWidget' = wrapForm emailWidget def
|
||||
{ formAction = Just . SomeRoute $ AdminTestR
|
||||
, formEncoding = emailEnctype
|
||||
, formAttrs = [("data-ajax-submit", "")]
|
||||
, formAttrs = [("uw-async-form", "")]
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -261,7 +261,7 @@ postHelpR = do
|
||||
let form = wrapForm formWidget def
|
||||
{ formAction = Just $ SomeRoute HelpR
|
||||
, formEncoding = formEnctype
|
||||
, formAttrs = [ ("data-ajax-submit", "") | isModal ]
|
||||
, formAttrs = [ ("uw-async-form", "") | isModal ]
|
||||
}
|
||||
|
||||
formResultModal res HelpR $ \HelpForm{..} -> do
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
.async-form-response {
|
||||
.async-form__response {
|
||||
margin: 20px 0;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@ -7,15 +7,15 @@
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
.async-form-response::before,
|
||||
.async-form-response::after {
|
||||
.async-form__response::before,
|
||||
.async-form__response::after {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
left: 50%;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.async-form-response--success::before {
|
||||
.async-form__response--success::before {
|
||||
content: '';
|
||||
width: 17px;
|
||||
height: 28px;
|
||||
@ -24,7 +24,7 @@
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
}
|
||||
|
||||
.async-form-response--info::before {
|
||||
.async-form__response--info::before {
|
||||
content: '';
|
||||
width: 5px;
|
||||
height: 30px;
|
||||
@ -32,7 +32,7 @@
|
||||
background-color: #777;
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.async-form-response--info::after {
|
||||
.async-form__response--info::after {
|
||||
content: '';
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
@ -40,14 +40,14 @@
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.async-form-response--warning::before {
|
||||
.async-form__response--warning::before {
|
||||
content: '';
|
||||
width: 5px;
|
||||
height: 30px;
|
||||
background-color: rgb(255, 187, 0);
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
.async-form-response--warning::after {
|
||||
.async-form__response--warning::after {
|
||||
content: '';
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
@ -56,14 +56,14 @@
|
||||
transform: translateX(-50%);
|
||||
}
|
||||
|
||||
.async-form-response--error::before {
|
||||
.async-form__response--error::before {
|
||||
content: '';
|
||||
width: 5px;
|
||||
height: 40px;
|
||||
background-color: #940d0d;
|
||||
transform: translateX(-50%) rotate(-45deg);
|
||||
}
|
||||
.async-form-response--error::after {
|
||||
.async-form__response--error::after {
|
||||
content: '';
|
||||
width: 5px;
|
||||
height: 40px;
|
||||
@ -71,7 +71,7 @@
|
||||
transform: translateX(-50%) rotate(45deg);
|
||||
}
|
||||
|
||||
.async-form-loading {
|
||||
.async-form--loading {
|
||||
opacity: 0.1;
|
||||
transition: opacity 800ms ease-out;
|
||||
pointer-events: none;
|
||||
|
||||
@ -1,33 +1,62 @@
|
||||
(function collonadeClosure() {
|
||||
'use strict';
|
||||
|
||||
window.utils = window.utils || {};
|
||||
/**
|
||||
*
|
||||
* 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='...'>
|
||||
* ...
|
||||
*/
|
||||
|
||||
var ASYNC_FORM_RESPONSE_CLASS = 'async-form-response';
|
||||
var ASYNC_FORM_LOADING_CLASS = 'async-form-loading';
|
||||
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 DEFAULT_FAILURE_MESSAGE = 'The response we received from the server did not match what we expected. Please let us know this happened via the help widget in the top navigation.';
|
||||
var ASYNC_FORM_DEFAULT_FAILURE_MESSAGE = 'The response we received from the server did not match what we expected. Please let us know this happened via the help widget in the top navigation.';
|
||||
|
||||
window.utils.asyncForm = function(formElement, options) {
|
||||
|
||||
options = options || {};
|
||||
var asyncFormUtil = function(element) {
|
||||
|
||||
var lastRequestTimestamp = 0;
|
||||
|
||||
function setup() {
|
||||
formElement.addEventListener('submit', submitHandler);
|
||||
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 = formElement.parentElement;
|
||||
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, formElement);
|
||||
formElement.remove();
|
||||
parentElement.insertBefore(responseElement, element);
|
||||
element.remove();
|
||||
}, delay);
|
||||
}
|
||||
|
||||
@ -43,12 +72,12 @@
|
||||
function submitHandler(event) {
|
||||
event.preventDefault();
|
||||
|
||||
formElement.classList.add(ASYNC_FORM_LOADING_CLASS)
|
||||
element.classList.add(ASYNC_FORM_LOADING_CLASS)
|
||||
lastRequestTimestamp = Date.now();
|
||||
|
||||
var url = formElement.getAttribute('action');
|
||||
var url = element.getAttribute('action');
|
||||
var headers = { };
|
||||
var body = new FormData(formElement);
|
||||
var body = new FormData(element);
|
||||
|
||||
if (options && options.headers) {
|
||||
Object.keys(options.headers).forEach(function(headerKey) {
|
||||
@ -66,21 +95,24 @@
|
||||
}).then(function(response) {
|
||||
processResponse(response[0]);
|
||||
}).catch(function(error) {
|
||||
var failureMessage = DEFAULT_FAILURE_MESSAGE;
|
||||
var failureMessage = ASYNC_FORM_DEFAULT_FAILURE_MESSAGE;
|
||||
if (options.i18n && options.i18n.asyncFormFailure) {
|
||||
failureMessage = options.i18n.asyncFormFailure;
|
||||
}
|
||||
processResponse({ content: failureMessage });
|
||||
|
||||
formElement.classList.remove(ASYNC_FORM_LOADING_CLASS);
|
||||
element.classList.remove(ASYNC_FORM_LOADING_CLASS);
|
||||
});
|
||||
}
|
||||
|
||||
setup();
|
||||
|
||||
return {
|
||||
scope: formElement,
|
||||
destroy: function() {},
|
||||
};
|
||||
return init();
|
||||
};
|
||||
|
||||
if (UtilRegistry) {
|
||||
UtilRegistry.register({
|
||||
name: ASYNC_FORM_UTIL_NAME,
|
||||
selector: ASYNC_FORM_UTIL_SELECTOR,
|
||||
setup: asyncFormUtil
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user