outsystems-ui
Version:
OutSystems UI Framework
112 lines (97 loc) • 4.24 kB
text/typescript
// eslint-disable-next-line @typescript-eslint/no-unused-vars
namespace OSFramework.OSUI.Helper {
export abstract class InvalidInputs {
// Method to check if exists invalid inputs
private static _checkInvalidInputs(element: HTMLElement, isSmooth: boolean, elementParentClass: string): void {
const notValidClassess = [
Constants.Dot + GlobalEnum.CssClassElements.InputNotValid,
Constants.Dot + Providers.OSUI.Datepicker.Flatpickr.Enum.CSSSelectors.DatepickerNotValid,
Constants.Dot + Patterns.Dropdown.ServerSide.Enum.CssClass.NotValid,
Constants.Dot + Providers.OSUI.Dropdown.VirtualSelect.Enum.CssClass.NotValid,
];
// Arrange the class names list for selector
const joinClassNames = [notValidClassess].join(Constants.Comma);
// Get the first invalid input element
const invalidInput = element.querySelectorAll(joinClassNames)[0] as HTMLElement;
// Check if exists a invalid input, based on provided class
if (invalidInput) {
const inputVisible = window.getComputedStyle(invalidInput).display !== GlobalEnum.CssProperties.None;
// Check if element exists and is visible on DOM
if (inputVisible) {
// If True, call scroll to element method to given element
this._scrollToInvalidInput(invalidInput, isSmooth, elementParentClass);
} else {
// Check if closest element contains ID
Helper.AsyncInvocation(() => {
this._searchElementId(invalidInput, isSmooth, elementParentClass);
});
}
}
}
// Method to call Utils API > ScrollToElement
private static _scrollToInvalidInput(
element: HTMLElement,
isSmooth: boolean,
elementParentClass: string
): void {
const browser = OSFramework.OSUI.Helper.DeviceInfo.GetBrowser();
OutSystems.OSUI.Utils.ScrollToElement(element.id, isSmooth, 0, elementParentClass);
// Set the element focus directly because the event scrollend isn't supported by safari or iOS
if (browser === GlobalEnum.Browser.safari || OSFramework.OSUI.Helper.DeviceInfo.IsIos) {
if (isSmooth) {
console.warn(
'Due to the unsupported scrollend event on Safari/iOS, the smooth transition is disabled and the invalid input will be focused directly.'
);
}
element.focus();
} else {
// Set the scrollable element to add the ScrollEnd event
const activeScreenElement = Helper.Dom.ClassSelector(
document.body,
GlobalEnum.CssClassElements.ActiveScreen
);
// Set the temporary function for event of ScrollEnd, to focus on element after the scroll occur
const focusOnScrollEnd = () => {
element.focus();
activeScreenElement.removeEventListener(GlobalEnum.HTMLEvent.ScrollEnd, focusOnScrollEnd);
};
// Add event on scrollable element, to focus on target element
activeScreenElement.addEventListener(GlobalEnum.HTMLEvent.ScrollEnd, focusOnScrollEnd);
}
}
// Method that will search for the closest element with ID to valid the invalid inputs
private static _searchElementId(element: HTMLElement, isSmooth: boolean, elementParentClass: string): void {
const elementToSearch = element.parentElement;
if (elementToSearch.id !== Constants.EmptyString) {
this._scrollToInvalidInput(elementToSearch, isSmooth, elementParentClass);
} else {
this._searchElementId(elementToSearch, isSmooth, elementParentClass);
}
}
/**
* Function used to check if an element, body or elementId, contains invalid inputs
*
* @static
* @param {string} elementId
* @param {boolean} isSmooth
* @return {*} {string}
* @memberof InvalidInputs
*/
public static FocusFirstInvalidInput(elementId: string, isSmooth: boolean, elementParentClass: string): string {
const result = OutSystems.OSUI.Utils.CreateApiResponse({
errorCode: OutSystems.OSUI.ErrorCodes.Utilities.FailGetInvalidInput,
callback: () => {
let element: HTMLElement = document.body;
if (elementId !== Constants.EmptyString) {
element = Helper.Dom.GetElementById(elementId);
}
// Wait for invalid classes injection by platform to each input
Helper.AsyncInvocation(() => {
this._checkInvalidInputs(element, isSmooth, elementParentClass);
});
},
});
return result;
}
}
}