fradrive/static/js/utils/form.js
2019-03-03 22:19:53 +01:00

160 lines
4.1 KiB
JavaScript

(function() {
'use strict';
window.utils = window.utils || {};
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';
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) {
if (form.classList.contains(JS_INITIALIZED)) {
return false;
}
var utilInstances = [];
// reactive buttons
utilInstances.push(window.utils.setup('reactiveButton', form));
// conditonal fieldsets
var fieldSets = Array.from(form.querySelectorAll('fieldset[data-conditional-id][data-conditional-value]'));
utilInstances.push(window.utils.setup('interactiveFieldset', form, { fieldSets }));
// hide autoSubmit submit button
utilInstances.push(window.utils.setup('autoSubmit', form, options));
// async form
if (AJAX_SUBMIT_FLAG in form.dataset) {
utilInstances.push(window.utils.setup('asyncForm', form, options));
}
// inputs
utilInstances.push(window.utils.setup('inputs', form, options));
form.classList.add(JS_INITIALIZED);
function destroyUtils() {
utilInstances.forEach(function(utilInstance) {
utilInstance.destroy();
});
}
return {
scope: form,
destroy: destroyUtils,
};
};
// 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]'));
if (!button || button.matches(AUTOSUBMIT_BUTTON_SELECTOR)) {
return false;
}
if (requireds.length == 0) {
return false;
}
if (typeof button.dataset.formnorequired !== 'undefined' && button.dataset.formnorequired !== null) {
button.addEventListener('click', function() {
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() {
if (formValidator(requireds) === true) {
button.removeAttribute('disabled');
} else {
button.setAttribute('disabled', 'true');
}
}
return {
scope: form,
destroy: function() {},
};
};
window.utils.interactiveFieldset = function(form, options) {
options = options || {};
var fieldSets = options.fieldSets;
if (!fieldSets) {
throw new Error('interactiveFieldset must be passed fieldSets via options');
}
var fields = fieldSets.map(function(fs) {
return {
fieldSet: fs,
condId: fs.dataset.conditionalId,
condValue: fs.dataset.conditionalValue,
condEl: form.querySelector('#' + fs.dataset.conditionalId),
};
}).filter(function(field) {
return !!field.condEl;
});
function updateFields() {
fields.forEach(function(field) {
field.fieldSet.classList.toggle('hidden', field.condEl.value !== field.condValue);
});
}
function addEventListeners() {
fields.forEach(function(field) {
field.condEl.addEventListener('input', updateFields)
});
}
if (fieldSets.length) {
addEventListeners();
updateFields();
}
return {
scope: form,
destroy: function() {},
};
};
window.utils.autoSubmit = function(form, options) {
var button = form.querySelector(AUTOSUBMIT_BUTTON_SELECTOR);
if (button) {
button.classList.add('hidden');
}
return {
scope: form,
destroy: function() {},
};
};
})();