feat(mass-input): automatic add before submit
This commit is contained in:
parent
7018196bc7
commit
7540a4fe5f
@ -1,3 +1,5 @@
|
|||||||
|
/* global global:writable */
|
||||||
|
|
||||||
import { Utility } from '../../core/utility';
|
import { Utility } from '../../core/utility';
|
||||||
import { Datepicker } from '../form/datepicker';
|
import { Datepicker } from '../form/datepicker';
|
||||||
import './mass-input.sass';
|
import './mass-input.sass';
|
||||||
@ -7,6 +9,11 @@ const MASS_INPUT_ADD_CELL_SELECTOR = '.massinput__cell--add';
|
|||||||
const MASS_INPUT_SUBMIT_BUTTON_CLASS = 'massinput__submit-button';
|
const MASS_INPUT_SUBMIT_BUTTON_CLASS = 'massinput__submit-button';
|
||||||
const MASS_INPUT_INITIALIZED_CLASS = 'mass-input--initialized';
|
const MASS_INPUT_INITIALIZED_CLASS = 'mass-input--initialized';
|
||||||
|
|
||||||
|
const MASS_INPUT_ADD_CHANGE_FIELD_SELECTOR = 'select, input[type=radio]';
|
||||||
|
|
||||||
|
// const MASS_INPUT_SAFETY_SUBMITTED_CLASS = 'massinput--safety-submitted';
|
||||||
|
// const MASS_INPUT_SAFETY_SUBMITTED_TIMEOUT = 1000;
|
||||||
|
|
||||||
@Utility({
|
@Utility({
|
||||||
selector: '[uw-mass-input]',
|
selector: '[uw-mass-input]',
|
||||||
})
|
})
|
||||||
@ -14,11 +21,14 @@ export class MassInput {
|
|||||||
|
|
||||||
_element;
|
_element;
|
||||||
_app;
|
_app;
|
||||||
|
_global;
|
||||||
|
|
||||||
_massInputId;
|
_massInputId;
|
||||||
_massInputFormSubmitHandler;
|
_massInputFormSubmitHandler;
|
||||||
_massInputForm;
|
_massInputForm;
|
||||||
|
|
||||||
|
_changedAdd = new Array();
|
||||||
|
|
||||||
constructor(element, app) {
|
constructor(element, app) {
|
||||||
if (!element) {
|
if (!element) {
|
||||||
throw new Error('Mass Input utility cannot be setup without an element!');
|
throw new Error('Mass Input utility cannot be setup without an element!');
|
||||||
@ -27,6 +37,14 @@ export class MassInput {
|
|||||||
this._element = element;
|
this._element = element;
|
||||||
this._app = app;
|
this._app = app;
|
||||||
|
|
||||||
|
if (global !== undefined)
|
||||||
|
this._global = global;
|
||||||
|
else if (window !== undefined)
|
||||||
|
this._global = window;
|
||||||
|
else
|
||||||
|
throw new Error('Cannot setup Mass Input utility without window or global');
|
||||||
|
|
||||||
|
|
||||||
if (this._element.classList.contains(MASS_INPUT_INITIALIZED_CLASS)) {
|
if (this._element.classList.contains(MASS_INPUT_INITIALIZED_CLASS)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -47,8 +65,10 @@ export class MassInput {
|
|||||||
this._setupSubmitButton(button);
|
this._setupSubmitButton(button);
|
||||||
});
|
});
|
||||||
|
|
||||||
this._massInputForm.addEventListener('submit', this._massInputFormSubmitHandler);
|
this._massInputForm.addEventListener('submit', this._massInputFormSubmitHandler.bind(this));
|
||||||
this._massInputForm.addEventListener('keypress', this._keypressHandler);
|
this._massInputForm.addEventListener('keypress', this._keypressHandler.bind(this));
|
||||||
|
|
||||||
|
Array.from(this._element.querySelectorAll(MASS_INPUT_ADD_CELL_SELECTOR)).forEach(this._setupChangedHandlers.bind(this));
|
||||||
|
|
||||||
// mark initialized
|
// mark initialized
|
||||||
this._element.classList.add(MASS_INPUT_INITIALIZED_CLASS);
|
this._element.classList.add(MASS_INPUT_INITIALIZED_CLASS);
|
||||||
@ -58,6 +78,26 @@ export class MassInput {
|
|||||||
this._reset();
|
this._reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_setupChangedHandlers(addCell) {
|
||||||
|
Array.from(addCell.querySelectorAll(MASS_INPUT_ADD_CHANGE_FIELD_SELECTOR)).forEach(inputElem => {
|
||||||
|
if (inputElem.closest('[uw-mass-input]') !== this._element)
|
||||||
|
return;
|
||||||
|
|
||||||
|
inputElem.addEventListener('change', () => { this._changedAdd.push(addCell); });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_unsafeAddCells() {
|
||||||
|
let changedAdd = this._changedAdd;
|
||||||
|
|
||||||
|
Array.from(this._element.querySelectorAll(MASS_INPUT_ADD_CELL_SELECTOR)).forEach(addCell => addCell.querySelectorAll('input:not([type=checkbox]):not([type=radio])').forEach(inputElem => {
|
||||||
|
if (inputElem.closest('[uw-mass-input]') === this._element && inputElem.value !== '')
|
||||||
|
changedAdd.push(addCell);
|
||||||
|
}));
|
||||||
|
|
||||||
|
return changedAdd;
|
||||||
|
}
|
||||||
|
|
||||||
_makeSubmitHandler() {
|
_makeSubmitHandler() {
|
||||||
const method = this._massInputForm.getAttribute('method') || 'POST';
|
const method = this._massInputForm.getAttribute('method') || 'POST';
|
||||||
const url = this._massInputForm.getAttribute('action') || window.location.href;
|
const url = this._massInputForm.getAttribute('action') || window.location.href;
|
||||||
@ -69,31 +109,58 @@ export class MassInput {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (event) => {
|
return (event) => {
|
||||||
let activeElement;
|
let submitButton;
|
||||||
|
let isAddCell;
|
||||||
|
|
||||||
|
let isMassInputSubmit = (() => {
|
||||||
|
let activeElement;
|
||||||
|
|
||||||
// check if event occured from either a mass input add/delete button or
|
// check if event occured from either a mass input add/delete button or
|
||||||
// from inside one of massinput's inputs (i.e. a child is focused/active)
|
// from inside one of massinput's inputs (i.e. a child is focused/active)
|
||||||
activeElement = this._element.querySelector(':focus, :active');
|
activeElement = this._element.querySelector(':focus, :active');
|
||||||
|
|
||||||
if (!activeElement) {
|
if (!activeElement) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find the according massinput cell thats hosts the element that triggered the submit
|
||||||
|
const massInputCell = activeElement.closest(MASS_INPUT_CELL_SELECTOR);
|
||||||
|
if (!massInputCell) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
submitButton = massInputCell.querySelector('.' + MASS_INPUT_SUBMIT_BUTTON_CLASS);
|
||||||
|
if (!submitButton) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
isAddCell = massInputCell.matches(MASS_INPUT_ADD_CELL_SELECTOR);
|
||||||
|
const submitButtonIsActive = submitButton.matches(':focus, :active');
|
||||||
|
// if the cell is not an add cell the active element must at least be the cells submit button
|
||||||
|
if (!isAddCell && !submitButtonIsActive) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
})();
|
||||||
|
|
||||||
|
let unsafeAddCells = this._unsafeAddCells();
|
||||||
|
|
||||||
|
if (unsafeAddCells.length > 0 && !isMassInputSubmit) {
|
||||||
|
let addButtons = Array.from(unsafeAddCells[0].querySelectorAll('.' + MASS_INPUT_SUBMIT_BUTTON_CLASS)).filter(addButton => addButton.closest('[uw-mass-input]') === this._element);
|
||||||
|
|
||||||
|
if (addButtons.length > 0) {
|
||||||
|
submitButton = addButtons[0];
|
||||||
|
isMassInputSubmit = true;
|
||||||
|
isAddCell = false;
|
||||||
|
|
||||||
|
this._element.scrollIntoView();
|
||||||
|
// this._element.classList.add(MASS_INPUT_SAFETY_SUBMITTED_CLASS);
|
||||||
|
// this._global.setTimeout(() => { this._element.classList.remove(MASS_INPUT_SAFETY_SUBMITTED_CLASS) }, MASS_INPUT_SAFETY_SUBMITTED_TIMEOUT)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// find the according massinput cell thats hosts the element that triggered the submit
|
if (!isMassInputSubmit) {
|
||||||
const massInputCell = activeElement.closest(MASS_INPUT_CELL_SELECTOR);
|
|
||||||
if (!massInputCell) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const submitButton = massInputCell.querySelector('.' + MASS_INPUT_SUBMIT_BUTTON_CLASS);
|
|
||||||
if (!submitButton) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const isAddCell = massInputCell.matches(MASS_INPUT_ADD_CELL_SELECTOR);
|
|
||||||
const submitButtonIsActive = submitButton.matches(':focus, :active');
|
|
||||||
// if the cell is not an add cell the active element must at least be the cells submit button
|
|
||||||
if (!isAddCell && !submitButtonIsActive) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
@use "../../app" as *
|
||||||
|
|
||||||
.massinput-list__wrapper, .massinput-list__cell
|
.massinput-list__wrapper, .massinput-list__cell
|
||||||
display: grid
|
display: grid
|
||||||
grid: auto / auto 50px
|
grid: auto / auto 50px
|
||||||
@ -12,3 +14,14 @@
|
|||||||
|
|
||||||
.massinput-list__cell
|
.massinput-list__cell
|
||||||
grid-column: 1 / 3
|
grid-column: 1 / 3
|
||||||
|
|
||||||
|
/* .massinput--safety-submitted
|
||||||
|
/* animation: massinput--safety-submitted linear 1s
|
||||||
|
|
||||||
|
/* @keyframes massinput--safety-submitted
|
||||||
|
/* 0%
|
||||||
|
/* background-color: rgba(252, 153, 0, 0)
|
||||||
|
/* 50%
|
||||||
|
/* background-color: rgba(252, 153, 0, 0.8)
|
||||||
|
/* 100%
|
||||||
|
/* background-color: rgba(252, 153, 0, 0)
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user