refactor reactive submit button JS utility

This commit is contained in:
Felix Hamann 2019-04-07 13:48:58 +02:00
parent 8a33c7df34
commit 2c04f6f670
2 changed files with 109 additions and 44 deletions

View File

@ -1075,8 +1075,8 @@ siteLayout' headingOverride widget = do
-- addScript $ StaticR js_utils_asyncTableFilter_js
-- addScript $ StaticR js_utils_checkAll_js
-- addScript $ StaticR js_utils_httpClient_js
-- addScript $ StaticR js_utils_form_js
-- JavaScript utils
addScript $ StaticR js_utils_form_js
addScript $ StaticR js_utils_inputs_js
addScript $ StaticR js_utils_modal_js
addScript $ StaticR js_utils_poc_js

View File

@ -3,25 +3,15 @@
window.utils = window.utils || {};
var formUtilities = [];
var JS_INITIALIZED = 'js-form-initialized';
var SUBMIT_BUTTON_SELECTOR = '[type="submit"]:not([formnovalidate])';
var AUTOSUBMIT_BUTTON_SELECTOR = '[type="submit"][data-autosubmit]';
var AJAX_SUBMIT_FLAG = 'ajaxSubmit';
var FORM_GROUP_CLASS = 'form-group';
var FORM_GROUP_WITH_ERRORS_CLASS = 'form-group--has-error';
function formValidator(inputs) {
var done = true;
inputs.forEach(function(inp) {
var len = inp.value.trim().length;
if (done && len === 0) {
done = false;
}
});
return done;
}
window.utils.form = function(form, options) {
options = options || {};
@ -77,50 +67,119 @@
};
};
// registers input-listener for each element in <inputs> (array) and
// enables <button> if <formValidator> for these inputs returns true
window.utils.reactiveButton = function(form, options) {
var button = form.querySelector(SUBMIT_BUTTON_SELECTOR);
var requireds = Array.from(form.querySelectorAll('[required]'));
/**
*
* Reactive Submit Button Utility
* disables a forms LAST sumit button as long as the required inputs are invalid
* (only checks if the value of the inputs are not empty)
*
* Attribute: uw-reactive-submit-button
* works only on `form` elements
*
* Params:
* data-formnorequired: string
* If present the submit button will never get disabled
*
* Example usage:
* <form uw-reactive-submit-button>
* <input type="text" required>
* <button type="submit">
* </form>
*/
if (!button || button.matches(AUTOSUBMIT_BUTTON_SELECTOR)) {
return false;
var REACTIVE_SUBMIT_BUTTON_UTIL_NAME = 'reactiveSubmitButton';
var REACTIVE_SUBMIT_BUTTON_UTIL_SELECTOR = 'form';
var REACTIVE_SUBMIT_BUTTON_INITIALIZED_CLASS = 'reactive-submit-button--initialized';
var reactiveButtonUtil = function(element) {
var requiredInputs;
var submitButton;
function init() {
if (!element) {
throw new Error('Reactive Submit Button utility cannot be setup without an element!');
}
if (element.classList.contains(REACTIVE_SUBMIT_BUTTON_INITIALIZED_CLASS)) {
throw new Error('Reactive Submit Button utility already initialized!');
}
// abort if form has param data-formnorequired
if (element.dataset.formnorequired !== undefined) {
throw new Error('Form has formnorequired data attribute. Will skip setup of reactive submit button.');
}
requiredInputs = Array.from(element.querySelectorAll('[required]'));
if (!requiredInputs) {
// abort if form has no required inputs
throw new Error('Submit button has formnorequired data attribute. Will skip setup of reactive submit button.');
}
var submitButtons = Array.from(element.querySelectorAll('[type="submit"]'));
if (!submitButtons) {
throw new Error('Reactive Submit Button utility couldn\'t find any submit buttons!');
}
submitButton = submitButtons.reverse()[0];
// abort if form has param data-formnorequired
if (submitButton.dataset.formnorequired !== undefined) {
return false;
}
setupInputs();
updateButtonState();
element.classList.add(REACTIVE_SUBMIT_BUTTON_INITIALIZED_CLASS);
return {
name: REACTIVE_SUBMIT_BUTTON_UTIL_NAME,
element: element,
destroy: function() {},
};
}
if (requireds.length == 0) {
return false;
}
if (typeof button.dataset.formnorequired !== 'undefined' && button.dataset.formnorequired !== null) {
button.addEventListener('click', function() {
form.submit();
function setupInputs() {
requiredInputs.forEach(function(el) {
var checkbox = el.getAttribute('type') === 'checkbox';
var eventType = checkbox ? 'change' : 'input';
el.addEventListener(eventType, function() {
updateButtonState();
});
});
return false;
}
updateButtonState();
requireds.forEach(function(el) {
var checkbox = el.getAttribute('type') === 'checkbox';
var eventType = checkbox ? 'change' : 'input';
el.addEventListener(eventType, function() {
updateButtonState();
});
});
function updateButtonState() {
if (formValidator(requireds) === true) {
button.removeAttribute('disabled');
if (inputsValid()) {
submitButton.removeAttribute('disabled');
} else {
button.setAttribute('disabled', 'true');
console.log('setting disabled', { submitButton });
submitButton.setAttribute('disabled', 'true');
}
}
return {
scope: form,
destroy: function() {},
};
function inputsValid() {
var done = true;
requiredInputs.forEach(function(inp) {
var len = inp.value.trim().length;
if (done && len === 0) {
done = false;
}
});
return done;
}
return init();
};
formUtilities.push({
name: REACTIVE_SUBMIT_BUTTON_UTIL_NAME,
selector: REACTIVE_SUBMIT_BUTTON_UTIL_SELECTOR,
setup: reactiveButtonUtil,
});
window.utils.interactiveFieldset = function(form, options) {
options = options || {};
var fieldSets = options.fieldSets;
@ -199,4 +258,10 @@
},
};
};
// register the collected form utilities
if (UtilRegistry) {
formUtilities.forEach(UtilRegistry.register);
}
})();