refactor reactive submit button JS utility
This commit is contained in:
parent
8a33c7df34
commit
2c04f6f670
@ -1075,8 +1075,8 @@ siteLayout' headingOverride widget = do
|
|||||||
-- addScript $ StaticR js_utils_asyncTableFilter_js
|
-- addScript $ StaticR js_utils_asyncTableFilter_js
|
||||||
-- addScript $ StaticR js_utils_checkAll_js
|
-- addScript $ StaticR js_utils_checkAll_js
|
||||||
-- addScript $ StaticR js_utils_httpClient_js
|
-- addScript $ StaticR js_utils_httpClient_js
|
||||||
-- addScript $ StaticR js_utils_form_js
|
|
||||||
-- JavaScript utils
|
-- JavaScript utils
|
||||||
|
addScript $ StaticR js_utils_form_js
|
||||||
addScript $ StaticR js_utils_inputs_js
|
addScript $ StaticR js_utils_inputs_js
|
||||||
addScript $ StaticR js_utils_modal_js
|
addScript $ StaticR js_utils_modal_js
|
||||||
addScript $ StaticR js_utils_poc_js
|
addScript $ StaticR js_utils_poc_js
|
||||||
|
|||||||
@ -3,25 +3,15 @@
|
|||||||
|
|
||||||
window.utils = window.utils || {};
|
window.utils = window.utils || {};
|
||||||
|
|
||||||
|
var formUtilities = [];
|
||||||
|
|
||||||
var JS_INITIALIZED = 'js-form-initialized';
|
var JS_INITIALIZED = 'js-form-initialized';
|
||||||
var SUBMIT_BUTTON_SELECTOR = '[type="submit"]:not([formnovalidate])';
|
|
||||||
var AUTOSUBMIT_BUTTON_SELECTOR = '[type="submit"][data-autosubmit]';
|
var AUTOSUBMIT_BUTTON_SELECTOR = '[type="submit"][data-autosubmit]';
|
||||||
var AJAX_SUBMIT_FLAG = 'ajaxSubmit';
|
var AJAX_SUBMIT_FLAG = 'ajaxSubmit';
|
||||||
|
|
||||||
var FORM_GROUP_CLASS = 'form-group';
|
var FORM_GROUP_CLASS = 'form-group';
|
||||||
var FORM_GROUP_WITH_ERRORS_CLASS = 'form-group--has-error';
|
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) {
|
window.utils.form = function(form, options) {
|
||||||
options = 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) {
|
* Reactive Submit Button Utility
|
||||||
var button = form.querySelector(SUBMIT_BUTTON_SELECTOR);
|
* disables a forms LAST sumit button as long as the required inputs are invalid
|
||||||
var requireds = Array.from(form.querySelectorAll('[required]'));
|
* (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)) {
|
var REACTIVE_SUBMIT_BUTTON_UTIL_NAME = 'reactiveSubmitButton';
|
||||||
return false;
|
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) {
|
function setupInputs() {
|
||||||
return false;
|
requiredInputs.forEach(function(el) {
|
||||||
}
|
var checkbox = el.getAttribute('type') === 'checkbox';
|
||||||
|
var eventType = checkbox ? 'change' : 'input';
|
||||||
if (typeof button.dataset.formnorequired !== 'undefined' && button.dataset.formnorequired !== null) {
|
el.addEventListener(eventType, function() {
|
||||||
button.addEventListener('click', function() {
|
updateButtonState();
|
||||||
form.submit();
|
});
|
||||||
});
|
});
|
||||||
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() {
|
function updateButtonState() {
|
||||||
if (formValidator(requireds) === true) {
|
if (inputsValid()) {
|
||||||
button.removeAttribute('disabled');
|
submitButton.removeAttribute('disabled');
|
||||||
} else {
|
} else {
|
||||||
button.setAttribute('disabled', 'true');
|
console.log('setting disabled', { submitButton });
|
||||||
|
submitButton.setAttribute('disabled', 'true');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
function inputsValid() {
|
||||||
scope: form,
|
var done = true;
|
||||||
destroy: function() {},
|
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) {
|
window.utils.interactiveFieldset = function(form, options) {
|
||||||
options = options || {};
|
options = options || {};
|
||||||
var fieldSets = options.fieldSets;
|
var fieldSets = options.fieldSets;
|
||||||
@ -199,4 +258,10 @@
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// register the collected form utilities
|
||||||
|
if (UtilRegistry) {
|
||||||
|
formUtilities.forEach(UtilRegistry.register);
|
||||||
|
}
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
|||||||
Reference in New Issue
Block a user