All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.dominokit.domino.ui.forms.ValueBox Maven / Gradle / Ivy
package org.dominokit.domino.ui.forms;
import elemental2.dom.HTMLDivElement;
import elemental2.dom.HTMLElement;
import elemental2.dom.HTMLLabelElement;
import elemental2.dom.Node;
import org.dominokit.domino.ui.grid.flex.FlexItem;
import org.dominokit.domino.ui.grid.flex.FlexLayout;
import org.dominokit.domino.ui.style.Color;
import org.dominokit.domino.ui.utils.*;
import org.jboss.elemento.IsElement;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static org.jboss.elemento.Elements.label;
import static org.jboss.elemento.Elements.span;
public abstract class ValueBox, E extends HTMLElement, V> extends BasicFormElement implements
Focusable, HasPlaceHolder, IsReadOnly, HasChangeHandlers {
public static final String FOCUSED = "focused";
public static final String FLOATING = "floating";
public static final String DISABLED = "disabled";
private DominoElement inputElement;
protected DominoElement fieldGroup = DominoElement.div();
protected DominoElement fieldContainer = DominoElement.div();
protected FlexItem inputContainer = FlexItem.create();
private DominoElement notesContainer = DominoElement.div();
private FlexLayout leftAddOnsContainer = FlexLayout.create();
private FlexLayout rightAddOnsContainer = FlexLayout.create();
private FlexItem helpItem;
private FlexItem countItem;
private FlexItem errorItem;
private FlexItem prefixItem = FlexItem.create();
private FlexItem postFixItem = FlexItem.create();
private DominoElement labelElement;
private DominoElement labelTextElement = DominoElement.of(span());
private Color focusColor = Color.BLUE;
private String placeholder;
private AutoValidator autoValidator;
protected List> changeHandlers = new ArrayList<>();
private final List> onClearHandlers = new ArrayList<>();
private boolean pauseChangeHandlers = false;
private boolean valid = true;
private boolean floating;
private boolean readOnly;
private String prefix;
private String postfix;
private FlexItem mandatoryAddOn;
private boolean validateOnFocusLost = true;
private FieldStyle fieldStyle = DominoFields.INSTANCE.getDefaultFieldsStyle();
private FlexLayout fieldInnerContainer;
private boolean permaFloating = false;
private FlexLayout additionalInfoContainer;
public ValueBox(String type, String label) {
helpItem = FlexItem.create();
countItem = FlexItem.create().hide();
errorItem = FlexItem.create();
labelElement = createLabelElement();
init((T) this);
inputElement = DominoElement.of(createInputElement(type));
inputElement.addEventListener("change", evt -> {
callChangeHandlers();
}
);
inputElement.addEventListener("input", evt -> {
if (isEmpty()) {
showPlaceholder();
}
}
);
layout();
setFocusColor(focusColor);
addFocusListeners();
setLabel(label);
setSpellCheck(true);
fieldStyle.apply(this);
}
public FieldStyle getFieldStyle() {
return fieldStyle;
}
public T setFieldStyle(FieldStyle fieldStyle) {
if (nonNull(fieldStyle)) {
fieldStyle.apply(this);
this.fieldStyle = fieldStyle;
}
return (T) this;
}
private void layout() {
fieldGroup.css("field-group");
fieldContainer
.css("field-cntr");
notesContainer
.css("notes-cntr");
leftAddOnsContainer
.css("field-lft-addons");
rightAddOnsContainer
.css("field-rgt-addons");
prefixItem.css("field-prefix");
postFixItem.css("field-postfix");
linkLabelToField();
fieldInnerContainer = FlexLayout.create();
additionalInfoContainer = FlexLayout.create();
fieldGroup
.appendChild(fieldContainer
.appendChild(fieldInnerContainer
.appendChild(inputContainer
.css("field-input-cntr")
.setFlexGrow(1)
.appendChild(labelElement)
.appendChild(inputElement)
)
.apply(self -> {
mandatoryAddOn = createMandatoryAddOn();
if (nonNull(mandatoryAddOn)) {
self.appendChild(mandatoryAddOn.css("field-mandatory-addon"));
}
})
)
)
.appendChild(notesContainer
.css("field-note")
.appendChild(additionalInfoContainer
.appendChild(helpItem
.css("field-helper")
.setFlexGrow(1)
)
.appendChild(errorItem
.hide()
.css("field-errors")
.setFlexGrow(1)
)
.appendChild(countItem
.css("field-counter")
)
)
);
}
@Override
public T setFixErrorsPosition(boolean fixPosition) {
if (fixPosition) {
errorItem.show();
errorItem.style().setMinHeight("25px");
} else {
errorItem.style().setMinHeight("0px");
}
return super.setFixErrorsPosition(fixPosition);
}
protected void linkLabelToField() {
if (!inputElement.hasAttribute("id")) {
inputElement.setAttribute("id", inputElement.getAttribute(BaseDominoElement.DOMINO_UUID));
}
labelElement.setAttribute("for", inputElement.getAttribute("id"));
}
protected void callChangeHandlers() {
if (!pauseChangeHandlers) {
changeHandlers.forEach(changeHandler -> changeHandler.onValueChanged(getValue()));
}
}
protected DominoElement createLabelElement() {
return DominoElement.of(label().css("field-label"));
}
protected abstract E createInputElement(String type);
private void addFocusListeners() {
inputElement.addEventListener("focus", evt -> doFocus());
inputElement.addEventListener("focusout", evt -> {
doUnfocus();
if (isAutoValidation() && validateOnFocusLost) {
validate();
}
});
labelElement.addEventListener("click", evt -> {
if (!isDisabled()) {
focus();
} else {
evt.stopPropagation();
evt.preventDefault();
}
});
}
public T setFloating(boolean floating) {
if (floating) {
floating();
} else {
nonfloating();
}
return (T) this;
}
public T floating() {
floatLabel();
this.permaFloating = true;
showPlaceholder();
return (T) this;
}
public T nonfloating() {
unfloatLabel();
this.permaFloating = false;
hidePlaceholder();
return (T) this;
}
public boolean isFloating() {
return floating;
}
public FlexItem getMandatoryAddOn() {
return mandatoryAddOn;
}
@Override
public T focus() {
if (!isDisabled()) {
if (!isAttached()) {
ElementUtil.onAttach(getInputElement(), mutationRecord -> {
tryFocus();
});
} else {
tryFocus();
}
}
return (T) this;
}
private void tryFocus() {
getInputElement().element().focus();
doFocus();
}
@Override
public T unfocus() {
if (!isAttached()) {
ElementUtil.onAttach(getInputElement(), mutationRecord -> {
getInputElement().element().blur();
doUnfocus();
});
} else {
getInputElement().element().blur();
doUnfocus();
}
return (T) this;
}
protected void doFocus() {
if (!isDisabled()) {
fieldGroup.style().add(FOCUSED);
floatLabel();
if (valid) {
if (isAddFocusColor()) {
fieldContainer.style().add("fc-" + focusColor.getStyle());
}
setLabelColor(focusColor);
}
showPlaceholder();
}
}
protected boolean isAddFocusColor() {
return true;
}
protected void doUnfocus() {
fieldGroup.style().remove(FOCUSED);
fieldContainer.style().remove("fc-" + focusColor.getStyle(), FOCUSED);
unfloatLabel();
removeLabelColor(focusColor);
hidePlaceholder();
}
@Override
protected void updateLabel(String label) {
if (isNull(labelTextElement)) {
labelTextElement = DominoElement.of(span());
}
labelTextElement.remove();
labelTextElement.setTextContent(label);
getLabelElement().appendChild(labelTextElement);
}
@Override
public DominoElement getLabelTextElement() {
return labelTextElement;
}
public T hideLabelText() {
this.labelTextElement.hide();
return (T) this;
}
public T showLabelText() {
this.labelTextElement.show();
return (T) this;
}
public T setLabelTextVisible(boolean visible) {
this.labelTextElement.toggleDisplay(visible);
return (T) this;
}
@Override
public boolean isFocused() {
return fieldGroup.style().contains(FOCUSED);
}
private void setLabelColor(Color color) {
labelElement.style().add(color.getStyle());
}
private void removeLabelColor(Color color) {
labelElement.style().remove(color.getStyle());
}
@Override
public T enable() {
super.enable();
fieldGroup.style().remove(DISABLED);
return (T) this;
}
@Override
public T disable() {
super.disable();
fieldGroup.style().add(DISABLED);
return (T) this;
}
@Override
public T setLabel(String label) {
super.setLabel(label);
hidePlaceholder();
return (T) this;
}
@Override
public T setPlaceholder(String placeholder) {
this.placeholder = placeholder;
showPlaceholder();
return (T) this;
}
private void showPlaceholder() {
if (placeholder != null && shouldShowPlaceholder()) {
inputElement.setAttribute("placeholder", placeholder);
}
}
private void hidePlaceholder() {
if (placeholder != null && !shouldShowPlaceholder()) {
inputElement.removeAttribute("placeholder");
}
}
private boolean shouldShowPlaceholder() {
return isEmpty() && floating;
}
@Override
public String getPlaceholder() {
return this.placeholder;
}
@Override
public T setFocusColor(Color focusColor) {
removeLabelColor(this.focusColor);
if (isFocused()) {
setLabelColor(focusColor);
}
this.focusColor = focusColor;
return (T) this;
}
@Override
public DominoElement getFieldInputContainer() {
return DominoElement.of(inputContainer);
}
@Override
public DominoElement getFieldContainer() {
return DominoElement.of(fieldContainer);
}
public T addLeftAddOn(FlexItem addon) {
leftAddOnsContainer.appendChild(addon);
if (!leftAddOnsContainer.isAttached()) {
fieldInnerContainer.insertFirst(leftAddOnsContainer);
}
return (T) this;
}
public T addLeftAddOn(IsElement> addon) {
return addLeftAddOn(FlexItem.create().appendChild(addon));
}
public T addLeftAddOn(Node addon) {
return addLeftAddOn(FlexItem.create().appendChild(addon));
}
public T addRightAddOn(FlexItem rightAddon) {
rightAddOnsContainer.appendChild(rightAddon);
if (!rightAddOnsContainer.isAttached()) {
fieldInnerContainer.appendChild(rightAddOnsContainer);
}
return (T) this;
}
public T addRightAddOn(IsElement> addon) {
addRightAddOn(FlexItem.create().appendChild(addon));
return (T) this;
}
public T addRightAddOn(Node addon) {
addRightAddOn(FlexItem.create().appendChild(addon));
return (T) this;
}
public T removeRightAddOn(FlexItem addon) {
return removeRightAddOn(addon.element());
}
public T removeRightAddOn(IsElement> addon) {
return removeRightAddOn(addon.element());
}
public T removeRightAddOn(Node addon) {
return removeAddOn(rightAddOnsContainer, addon);
}
public T removeRightAddOn(int index) {
if (index >= 0 && index < rightAddOnsContainer.childNodes().length) {
return removeAddOn(rightAddOnsContainer, rightAddOnsContainer.childNodes().getAt(index));
}
return (T) this;
}
public T removeLeftAddOn(FlexItem addon) {
return removeLeftAddOn(addon.element());
}
public T removeLeftAddOn(IsElement> addon) {
return removeLeftAddOn(addon.element());
}
public T removeLeftAddOn(Node addon) {
return removeAddOn(leftAddOnsContainer, addon);
}
public T removeLeftAddOn(int index) {
if (index >= 0 && index < leftAddOnsContainer.childNodes().length) {
return removeAddOn(leftAddOnsContainer, leftAddOnsContainer.childNodes().getAt(index));
}
return (T) this;
}
private T removeAddOn(FlexLayout container, Node addon) {
if (container.isAttached() && container.contains(addon)) {
if (container.hasDirectChild(addon)) {
container.removeChild(addon);
} else {
return removeAddOn(container, addon.parentNode);
}
}
return (T) this;
}
public T removeRightAddOns() {
rightAddOnsContainer.clearElement();
return (T) this;
}
public T removeLeftAddOns() {
leftAddOnsContainer.clearElement();
return (T) this;
}
@Override
public DominoElement getInputElement() {
return DominoElement.of(inputElement);
}
@Override
protected DominoElement getHelperContainer() {
return DominoElement.of(helpItem.element());
}
@Override
protected DominoElement getErrorsContainer() {
return DominoElement.of(errorItem.element());
}
@Override
public V getValue() {
return null;
}
@Override
public boolean isEmpty() {
return false;
}
@Override
public String getStringValue() {
return null;
}
@Override
public DominoElement getLabelElement() {
return DominoElement.of(labelElement);
}
@Override
public HTMLElement element() {
return fieldGroup.element();
}
@Override
public T invalidate(String errorMessage) {
this.valid = false;
updateValidationStyles();
return super.invalidate(errorMessage);
}
public T asTableField() {
setTableField(true);
return (T) this;
}
public T setTableField(boolean asTableField) {
if (asTableField) {
css("table-field");
} else {
removeCss("table-field");
}
return (T) this;
}
@Override
public T invalidate(List errorMessages) {
this.valid = false;
updateValidationStyles();
return super.invalidate(errorMessages);
}
private void updateValidationStyles() {
fieldContainer.style().remove("fc-" + focusColor.getStyle());
fieldContainer.style().add("fc-" + Color.RED.getStyle());
removeLabelColor(focusColor);
setLabelColor(Color.RED);
changeLabelFloating();
}
public T pauseFocusValidation() {
this.validateOnFocusLost = false;
return (T) this;
}
public T resumeFocusValidation() {
this.validateOnFocusLost = true;
return (T) this;
}
@Override
public T clearInvalid() {
this.valid = true;
fieldContainer.style().add("fc-" + focusColor.getStyle());
fieldContainer.style().remove("fc-" + Color.RED.getStyle());
removeLabelColor(Color.RED);
if (isFocused()) {
doFocus();
} else {
doUnfocus();
}
changeLabelFloating();
return super.clearInvalid();
}
@Override
public T setAutoValidation(boolean autoValidation) {
if (autoValidation) {
if (autoValidator == null) {
autoValidator = createAutoValidator(this::validate);
}
autoValidator.attach();
} else {
if (nonNull(autoValidator)) {
autoValidator.remove();
}
autoValidator = null;
}
return (T) this;
}
@Override
public boolean isAutoValidation() {
return nonNull(autoValidator);
}
protected abstract AutoValidator createAutoValidator(AutoValidate autoValidate);
@Override
public T clear() {
clearValue();
autoValidate();
onClearHandlers.forEach(handler -> handler.accept((T) ValueBox.this));
return (T) this;
}
@Override
public T value(V value) {
doSetValue(value);
changeLabelFloating();
autoValidate();
callChangeHandlers();
return (T) this;
}
@Override
public T setReadOnly(boolean readOnly) {
this.readOnly = readOnly;
if (readOnly) {
getInputElement().setAttribute(DISABLED, "true");
getInputElement().setAttribute("readonly", "true");
getInputElement().setAttribute(FLOATING, isFloating());
css("readonly");
floating();
} else {
getInputElement().removeAttribute(DISABLED);
getInputElement().removeAttribute("readonly");
removeCss("readonly");
boolean floating;
if (getInputElement().hasAttribute(FLOATING)) {
floating = Boolean.parseBoolean(getInputElement().getAttribute(FLOATING));
} else {
floating = isFloating();
}
setFloating(floating);
changeLabelFloating();
}
return (T) this;
}
@Override
public boolean isReadOnly() {
return readOnly;
}
protected void changeLabelFloating() {
if (!isEmpty() || isFocused())
floatLabel();
else
unfloatLabel();
}
protected void floatLabel() {
if (!floating || permaFloating) {
fieldGroup.style().add(FLOATING);
this.floating = true;
}
}
protected void unfloatLabel() {
if ((floating && !permaFloating) && isEmpty()) {
fieldGroup.style().remove(FLOATING);
this.floating = false;
}
}
protected void autoValidate() {
if (isAutoValidation())
validate();
}
@Override
public T addChangeHandler(ChangeHandler super V> changeHandler) {
changeHandlers.add(changeHandler);
return (T) this;
}
@Override
public T removeChangeHandler(ChangeHandler super V> changeHandler) {
changeHandlers.remove(changeHandler);
return (T) this;
}
public T setPauseChangeHandlers(boolean pauseChangeHandlers) {
this.pauseChangeHandlers = pauseChangeHandlers;
return (T) this;
}
public T pauseChangeHandlers() {
return setPauseChangeHandlers(true);
}
public T resumeChangeHandlers() {
return setPauseChangeHandlers(false);
}
public FlexLayout getLeftAddonContainer() {
return leftAddOnsContainer;
}
public FlexLayout getRightAddonContainer() {
return rightAddOnsContainer;
}
@Override
public boolean hasChangeHandler(ChangeHandler super V> changeHandler) {
return changeHandlers.contains(changeHandler);
}
public T setSpellCheck(boolean spellCheck) {
inputElement.setAttribute("spellcheck", spellCheck);
return (T) this;
}
public T addOnClearHandler(Consumer onClearHandler) {
this.onClearHandlers.add(onClearHandler);
return (T) this;
}
public T removeOnClearHandler(Consumer onClearHandler) {
this.onClearHandlers.remove(onClearHandler);
return (T) this;
}
public List> getOnClearHandlers() {
return new ArrayList<>(onClearHandlers);
}
public T setPrefix(String prefix) {
if (!prefixItem.isAttached()) {
fieldInnerContainer.insertBefore(prefixItem, inputContainer);
}
this.prefixItem.setTextContent(prefix);
this.prefix = prefix;
return (T) this;
}
public String getPrefix() {
return prefix;
}
public T setPostFix(String postfix) {
if (!postFixItem.isAttached()) {
fieldInnerContainer.insertAfter(postFixItem, inputContainer);
}
this.postFixItem.setTextContent(postfix);
this.postfix = postfix;
return (T) this;
}
public DominoElement getFieldGroup() {
return fieldGroup;
}
public FlexItem getInputContainer() {
return inputContainer;
}
public DominoElement getNotesContainer() {
return notesContainer;
}
@Override
public DominoElement getAdditionalInfoContainer() {
return DominoElement.of(additionalInfoContainer);
}
public FlexLayout getLeftAddOnsContainer() {
return leftAddOnsContainer;
}
public FlexLayout getRightAddOnsContainer() {
return rightAddOnsContainer;
}
public FlexItem getHelpItem() {
return helpItem;
}
public FlexItem getCountItem() {
return countItem;
}
public FlexItem getErrorItem() {
return errorItem;
}
public FlexItem getPrefixItem() {
return prefixItem;
}
public FlexItem getPostFixItem() {
return postFixItem;
}
public Color getFocusColor() {
return focusColor;
}
public String getPostfix() {
return postfix;
}
protected abstract void clearValue();
protected abstract void doSetValue(V value);
public T condense() {
removeCss("condensed");
css("condensed");
return (T) this;
}
public T spread() {
removeCss("condensed");
return (T) this;
}
protected FlexItem createMandatoryAddOn() {
return null;
}
public interface AutoValidate {
void apply();
}
public abstract static class AutoValidator {
protected AutoValidate autoValidate;
public AutoValidator(AutoValidate autoValidate) {
this.autoValidate = autoValidate;
}
public abstract void attach();
public abstract void remove();
}
}