views/mdc/assets/js/components/text-fields.js
import {MDCTextField} from '@material/textfield';
import {VBaseComponent, hookupComponents} from './base-component';
import {eventHandlerMixin} from './mixins/event-handler';
import {visibilityObserverMixin} from './mixins/visibility-observer';
import {dirtyableMixin} from './mixins/dirtyable';
const AFTER_INPUT_EVENT = 'after_input';
const AFTER_INPUT_TIMEOUT = 500; // ms
export function initTextFields(e) {
console.debug('\tTextFields');
hookupComponents(e, '.v-text-field', VTextField, MDCTextField);
}
export class VTextField extends dirtyableMixin(
visibilityObserverMixin(
eventHandlerMixin(VBaseComponent))) {
constructor(element, mdcComponent) {
super(element, mdcComponent);
this.input = element.querySelector('input,textarea');
this.input.vComponent = this;
this.afterInputTimeout = null;
this.helperDisplay = this.root.getElementById(`${element.id}-input-helper-text`);
this.origHelperText = this.helperDisplay.innerHTML.trim();
this.recalcWhenVisible(this);
this.input.addEventListener('input', (event) => {
clearTimeout(this.afterInputTimeout);
this.afterInputTimeout = setTimeout(() => {
this.element.dispatchEvent(new Event(AFTER_INPUT_EVENT, {composed: true}));
}, AFTER_INPUT_TIMEOUT);
});
const caseType = element.dataset.case_type;
if (caseType !== 'mixed') {
this.input.addEventListener('keyup', (e) => {
this.forceCase(caseType);
});
}
this.originalValue = this.value();
}
// Called whenever a form is about to be submitted.
// returns true on success
// returns on failure return an error object that can be processed by VErrors:
// { email: ["email must be filled", "email must be from your domain"] }
// { :page: ["must be filled"] }
validate(formData) {
console.debug('TextField validate', formData);
const isValid = this.input.checkValidity();
if (isValid) {
if (this.origHelperText !== '') {
this.helperDisplay.innerHTML = this.origHelperText;
this.helperDisplay.classList.remove('v-hidden', 'mdc-text-field-helper-text--validation-msg');
this.element.classList.remove('mdc-text-field--invalid');
}
else {
this.helperDisplay.classList.add('v-hidden');
}
return true;
}
const message = this.helperDisplay.dataset.validationError ?
this.helperDisplay.dataset.validationError :
this.input.validationMessage;
const errorMessage = {};
errorMessage[this.element.id] = [message];
return errorMessage;
}
// Called to collect data for submission
prepareSubmit(params) {
const optionSelected = this.optionSelected();
if (optionSelected) {
const key = optionSelected.dataset.key;
if (key) {
const name = this.name();
const id = name + '_id';
params.push([id, key]);
console.debug('TextField prepareSubmit added:' + id + '=' + key);
}
}
params.push([this.name(), this.value()]);
}
optionSelected() {
const dataList = this.element.querySelector('datalist');
if (dataList) {
const parentElement = this.input;
// If we find the input inside our list, we submit the form
for (const element of dataList.children) {
if (element.value === parentElement.value) {
return element;
}
}
}
return null;
}
name() {
return this.input.name;
}
value() {
return this.input.value;
}
clear() {
if (this.value() !== '') {
this.setValue(null);
}
}
reset() {
this.input.value = this.originalValue;
}
setValue(value) {
this.input.value = value;
}
isDirty() {
return this.dirtyable
&& this.value().localeCompare(this.originalValue) !== 0;
}
onShow() {
this.mdcComponent.layout();
}
preview(result, acceptsMimeTypes) {
this.setValue(result);
}
// Return true if focus is able to be set, false otherwise
focus() {
if (this.isHidden() || this.input.disabled) return false;
this.input.focus();
return true;
}
isHidden() {
const style = window.getComputedStyle(this.element);
return (style.display === 'none');
}
forceCase(caseType){
if (caseType === 'upper') {
this.input.value = this.input.value.toUpperCase();
} else if (caseType === 'lower') {
this.input.value = this.input.value.toLowerCase();
}
}
}