2019-03-14 20:52:01 +00:00
|
|
|
import $ from 'jquery';
|
2021-02-14 18:09:20 +00:00
|
|
|
import { memoize, throttle } from 'lodash';
|
2022-03-04 18:20:01 +00:00
|
|
|
import createEventHub from '~/helpers/event_hub_factory';
|
2018-10-15 13:36:19 +00:00
|
|
|
|
|
|
|
class DirtySubmitForm {
|
|
|
|
constructor(form) {
|
|
|
|
this.form = form;
|
|
|
|
this.dirtyInputs = [];
|
|
|
|
this.isDisabled = true;
|
2022-03-04 18:20:01 +00:00
|
|
|
this.events = createEventHub();
|
2018-10-15 13:36:19 +00:00
|
|
|
|
|
|
|
this.init();
|
|
|
|
}
|
|
|
|
|
|
|
|
init() {
|
|
|
|
this.inputs = this.form.querySelectorAll('input, textarea, select');
|
|
|
|
this.submits = this.form.querySelectorAll('input[type=submit], button[type=submit]');
|
|
|
|
|
|
|
|
this.inputs.forEach(DirtySubmitForm.initInput);
|
|
|
|
this.toggleSubmission();
|
|
|
|
|
|
|
|
this.registerListeners();
|
|
|
|
}
|
|
|
|
|
|
|
|
registerListeners() {
|
2020-03-31 06:07:50 +00:00
|
|
|
const getThrottledHandlerForInput = memoize(() =>
|
2020-12-23 21:10:24 +00:00
|
|
|
throttle((event) => this.updateDirtyInput(event), DirtySubmitForm.THROTTLE_DURATION),
|
2018-10-15 13:36:19 +00:00
|
|
|
);
|
2019-05-17 17:05:15 +00:00
|
|
|
|
2020-12-23 21:10:24 +00:00
|
|
|
const throttledUpdateDirtyInput = (event) => {
|
2019-05-17 17:05:15 +00:00
|
|
|
const throttledHandler = getThrottledHandlerForInput(event.target.name);
|
|
|
|
throttledHandler(event);
|
|
|
|
};
|
|
|
|
|
2018-10-15 13:36:19 +00:00
|
|
|
this.form.addEventListener('input', throttledUpdateDirtyInput);
|
2018-11-14 19:51:39 +00:00
|
|
|
this.form.addEventListener('change', throttledUpdateDirtyInput);
|
2019-03-14 20:52:01 +00:00
|
|
|
$(this.form).on('change.select2', throttledUpdateDirtyInput);
|
2020-12-23 21:10:24 +00:00
|
|
|
this.form.addEventListener('submit', (event) => this.formSubmit(event));
|
2018-10-15 13:36:19 +00:00
|
|
|
}
|
|
|
|
|
2022-03-04 18:20:01 +00:00
|
|
|
addInputsListener(callback) {
|
|
|
|
this.events.$on('input', callback);
|
|
|
|
}
|
|
|
|
|
|
|
|
removeInputsListener(callback) {
|
|
|
|
this.events.$off('input', callback);
|
|
|
|
}
|
|
|
|
|
2018-10-15 13:36:19 +00:00
|
|
|
updateDirtyInput(event) {
|
2018-11-14 19:51:39 +00:00
|
|
|
const { target } = event;
|
2018-10-15 13:36:19 +00:00
|
|
|
|
2018-11-14 19:51:39 +00:00
|
|
|
if (!target.dataset.isDirtySubmitInput) return;
|
2018-10-15 13:36:19 +00:00
|
|
|
|
2022-03-04 18:20:01 +00:00
|
|
|
this.events.$emit('input', event);
|
|
|
|
|
2018-11-14 19:51:39 +00:00
|
|
|
this.updateDirtyInputs(target);
|
2018-10-15 13:36:19 +00:00
|
|
|
this.toggleSubmission();
|
|
|
|
}
|
|
|
|
|
|
|
|
updateDirtyInputs(input) {
|
|
|
|
const { name } = input;
|
|
|
|
const isDirty =
|
|
|
|
input.dataset.dirtySubmitOriginalValue !== DirtySubmitForm.inputCurrentValue(input);
|
|
|
|
const indexOfInputName = this.dirtyInputs.indexOf(name);
|
|
|
|
const isExisting = indexOfInputName !== -1;
|
|
|
|
|
|
|
|
if (isDirty && !isExisting) this.dirtyInputs.push(name);
|
|
|
|
if (!isDirty && isExisting) this.dirtyInputs.splice(indexOfInputName, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
toggleSubmission() {
|
|
|
|
this.isDisabled = this.dirtyInputs.length === 0;
|
2020-12-23 21:10:24 +00:00
|
|
|
this.submits.forEach((element) => {
|
2018-10-15 13:36:19 +00:00
|
|
|
element.disabled = this.isDisabled;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
formSubmit(event) {
|
|
|
|
if (this.isDisabled) {
|
|
|
|
event.preventDefault();
|
|
|
|
event.stopImmediatePropagation();
|
|
|
|
}
|
|
|
|
|
|
|
|
return !this.isDisabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
static initInput(element) {
|
2018-11-06 08:48:03 +00:00
|
|
|
element.dataset.isDirtySubmitInput = true;
|
2018-10-15 13:36:19 +00:00
|
|
|
element.dataset.dirtySubmitOriginalValue = DirtySubmitForm.inputCurrentValue(element);
|
|
|
|
}
|
|
|
|
|
|
|
|
static isInputCheckable(input) {
|
|
|
|
return input.type === 'checkbox' || input.type === 'radio';
|
|
|
|
}
|
|
|
|
|
|
|
|
static inputCurrentValue(input) {
|
|
|
|
return DirtySubmitForm.isInputCheckable(input) ? input.checked.toString() : input.value;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DirtySubmitForm.THROTTLE_DURATION = 500;
|
|
|
|
|
|
|
|
export default DirtySubmitForm;
|