@syncfusion/ej2-inputs
Version:
A package of Essential JS 2 input components such as Textbox, Color-picker, Masked-textbox, Numeric-textbox, Slider, Upload, and Form-validator that is used to get input from the users.
1,055 lines (1,054 loc) • 794 kB
JavaScript
import { isNullOrUndefined, createElement, addClass, attributes, removeClass, formatUnit, remove, detach, classList, closest, Component, getValue, setValue, L10n, getUniqueID, Internationalization, EventHandler, Browser, merge, getNumericObject, Property, Event, NotifyPropertyChanges, extend, ChildProperty, setStyleAttribute, SanitizeHtmlHelper, initializeCSPTemplate, Collection, Complex, Base, onIntlChange, select, selectAll, KeyboardEvents, Ajax, append, Animation, compile, rippleEffect, getInstance } from '@syncfusion/ej2-base';
import { Tooltip, getZindexPartial, createSpinner, showSpinner, hideSpinner, isCollide, Popup } from '@syncfusion/ej2-popups';
import { SplitButton, Deferred, getModel } from '@syncfusion/ej2-splitbuttons';
import { Button } from '@syncfusion/ej2-buttons';
/* eslint-disable valid-jsdoc, jsdoc/require-jsdoc, jsdoc/require-returns, jsdoc/require-param */
const CLASSNAMES = {
RTL: 'e-rtl',
DISABLE: 'e-disabled',
INPUT: 'e-input',
TEXTAREA: 'e-multi-line-input',
INPUTGROUP: 'e-input-group',
FLOATINPUT: 'e-float-input',
FLOATLINE: 'e-float-line',
FLOATTEXT: 'e-float-text',
FLOATTEXTCONTENT: 'e-float-text-content',
CLEARICON: 'e-clear-icon',
CLEARICONHIDE: 'e-clear-icon-hide',
LABELTOP: 'e-label-top',
LABELBOTTOM: 'e-label-bottom',
NOFLOATLABEL: 'e-no-float-label',
INPUTCUSTOMTAG: 'e-input-custom-tag',
FLOATCUSTOMTAG: 'e-float-custom-tag'
};
/**
* Defines the constant attributes for the input element container.
*/
const containerAttributes = ['title', 'style', 'class'];
/**
* Defines the constant focus class for the input element.
*/
const TEXTBOX_FOCUS = 'e-input-focus';
/**
* Base for Input creation through util methods.
*/
// eslint-disable-next-line @typescript-eslint/no-namespace
var Input;
(function (Input) {
let floatType;
let isBindClearAction = true;
/**
* Create a wrapper to input element with multiple span elements and set the basic properties to input based components.
* ```
* E.g : Input.createInput({ element: element, floatLabelType : "Auto", properties: { placeholder: 'Search' } });
* ```
*
*/
function createInput(args, internalCreateElement) {
args.element.__eventHandlers = {};
const makeElement = !isNullOrUndefined(internalCreateElement) ? internalCreateElement : createElement;
let inputObject = { container: null, buttons: [], clearButton: null };
floatType = args.floatLabelType;
isBindClearAction = args.bindClearAction;
if (isNullOrUndefined(args.floatLabelType) || args.floatLabelType === 'Never') {
inputObject.container = createInputContainer(args, CLASSNAMES.INPUTGROUP, CLASSNAMES.INPUTCUSTOMTAG, 'span', makeElement);
args.element.parentNode.insertBefore(inputObject.container, args.element);
addClass([args.element], CLASSNAMES.INPUT);
inputObject.container.appendChild(args.element);
}
else {
createFloatingInput(args, inputObject, makeElement);
}
bindInitialEvent(args);
if (!isNullOrUndefined(args.properties) && !isNullOrUndefined(args.properties.showClearButton) &&
args.properties.showClearButton) {
setClearButton(args.properties.showClearButton, args.element, inputObject, true, makeElement);
inputObject.clearButton.setAttribute('role', 'button');
if (inputObject.container.classList.contains(CLASSNAMES.FLOATINPUT)) {
addClass([inputObject.container], CLASSNAMES.INPUTGROUP);
}
}
if (!isNullOrUndefined(args.buttons)) {
for (let i = 0; i < args.buttons.length; i++) {
inputObject.buttons.push(appendSpan(args.buttons[i], inputObject.container, makeElement));
}
}
if (!isNullOrUndefined(args.element) && args.element.tagName === 'TEXTAREA') {
addClass([inputObject.container], CLASSNAMES.TEXTAREA);
}
validateInputType(inputObject.container, args.element);
inputObject = setPropertyValue(args, inputObject);
createSpanElement(inputObject.container, makeElement);
return inputObject;
}
Input.createInput = createInput;
function bindFocusEventHandler(args) {
const parent = getParentNode(args.element);
if (parent.classList.contains('e-input-group') || parent.classList.contains('e-outline') || parent.classList.contains('e-filled')) {
parent.classList.add('e-input-focus');
}
if (args.floatLabelType !== 'Never') {
setTimeout(() => {
Input.calculateWidth(args.element, parent);
}, 80);
}
}
function bindBlurEventHandler(args) {
const parent = getParentNode(args.element);
if (parent.classList.contains('e-input-group') || parent.classList.contains('e-outline') || parent.classList.contains('e-filled')) {
parent.classList.remove('e-input-focus');
}
if (args.floatLabelType !== 'Never') {
setTimeout(() => {
Input.calculateWidth(args.element, parent);
}, 80);
}
}
function bindInputEventHandler(args) {
checkInputValue(args.floatLabelType, args.element);
}
function bindInitialEvent(args) {
checkInputValue(args.floatLabelType, args.element);
const focusHandler = () => bindFocusEventHandler(args);
const blurHandler = () => bindBlurEventHandler(args);
const inputHandler = () => bindInputEventHandler(args);
args.element.addEventListener('focus', focusHandler);
args.element.addEventListener('blur', blurHandler);
args.element.addEventListener('input', inputHandler);
args.element.__eventHandlers['inputFocusHandler'] = { focusHandler };
args.element.__eventHandlers['inputBlurHandler'] = { blurHandler };
args.element.__eventHandlers['inputHandler'] = { inputHandler };
}
Input.bindInitialEvent = bindInitialEvent;
function unbindInitialEvent(args) {
if (!isNullOrUndefined(args.element)) {
if (!isNullOrUndefined(args.element.__eventHandlers)) {
if (!isNullOrUndefined(args.element.__eventHandlers['inputFocusHandler'])
&& !isNullOrUndefined(args.element.__eventHandlers['inputBlurHandler'])
&& !isNullOrUndefined(args.element.__eventHandlers['inputHandler'])) {
const focusHandler = args.element.__eventHandlers['inputFocusHandler'].focusHandler;
const blurHandler = args.element.__eventHandlers['inputBlurHandler'].blurHandler;
const inputHandler = args.element.__eventHandlers['inputHandler'].inputHandler;
args.element.removeEventListener('focus', focusHandler);
args.element.removeEventListener('blur', blurHandler);
args.element.removeEventListener('input', inputHandler);
// Clean up stored bound functions
delete args.element.__eventHandlers['inputFocusHandler'];
delete args.element.__eventHandlers['inputBlurHandler'];
delete args.element.__eventHandlers['inputHandler'];
}
}
}
}
function checkInputValue(floatLabelType, inputElement) {
const inputValue = inputElement.value;
const inputParent = inputElement.parentElement;
const grandParent = inputParent && inputParent.parentElement;
if (inputValue !== '' && !isNullOrUndefined(inputValue)) {
if (inputParent && inputParent.classList.contains('e-input-group')) {
inputParent.classList.add('e-valid-input');
}
else if (grandParent && grandParent.classList.contains('e-input-group')) {
grandParent.classList.add('e-valid-input');
}
}
else if (floatLabelType !== 'Always') {
if (inputParent && inputParent.classList.contains('e-input-group')) {
inputParent.classList.remove('e-valid-input');
}
else if (grandParent && grandParent.classList.contains('e-input-group')) {
grandParent.classList.remove('e-valid-input');
}
}
}
function _focusFn() {
const label = getParentNode(this).getElementsByClassName('e-float-text')[0];
if (!isNullOrUndefined(label)) {
addClass([label], CLASSNAMES.LABELTOP);
if (label.classList.contains(CLASSNAMES.LABELBOTTOM)) {
removeClass([label], CLASSNAMES.LABELBOTTOM);
}
}
}
function _blurFn() {
const parent = getParentNode(this);
if ((parent.getElementsByTagName('textarea')[0]) ? parent.getElementsByTagName('textarea')[0].value === '' :
parent.getElementsByTagName('input')[0].value === '') {
const label = parent.getElementsByClassName('e-float-text')[0];
if (!isNullOrUndefined(label)) {
if (label.classList.contains(CLASSNAMES.LABELTOP)) {
removeClass([label], CLASSNAMES.LABELTOP);
}
addClass([label], CLASSNAMES.LABELBOTTOM);
}
}
}
function wireFloatingEvents(element) {
element.addEventListener('focus', _focusFn);
element.addEventListener('blur', _blurFn);
}
Input.wireFloatingEvents = wireFloatingEvents;
function unwireFloatingEvents(element) {
if (!isNullOrUndefined(element)) {
element.removeEventListener('focus', _focusFn);
element.removeEventListener('blur', _blurFn);
}
}
function inputEventHandler(args) {
validateLabel(args.element, args.floatLabelType);
}
function blurEventHandler(args) {
validateLabel(args.element, args.floatLabelType);
}
function createFloatingInput(args, inputObject, internalCreateElement) {
const makeElement = !isNullOrUndefined(internalCreateElement) ? internalCreateElement : createElement;
if (args.floatLabelType === 'Auto') {
wireFloatingEvents(args.element);
}
if (isNullOrUndefined(inputObject.container)) {
inputObject.container = createInputContainer(args, CLASSNAMES.FLOATINPUT, CLASSNAMES.FLOATCUSTOMTAG, 'div', makeElement);
inputObject.container.classList.add(CLASSNAMES.INPUTGROUP);
if (args.element.parentNode) {
args.element.parentNode.insertBefore(inputObject.container, args.element);
}
}
else {
if (!isNullOrUndefined(args.customTag)) {
inputObject.container.classList.add(CLASSNAMES.FLOATCUSTOMTAG);
}
inputObject.container.classList.add(CLASSNAMES.FLOATINPUT);
}
const floatLinelement = makeElement('span', { className: CLASSNAMES.FLOATLINE });
const floatLabelElement = makeElement('label', { className: CLASSNAMES.FLOATTEXT });
if (!isNullOrUndefined(args.element.id) && args.element.id !== '') {
floatLabelElement.id = 'label_' + args.element.id.replace(/ /g, '_');
attributes(args.element, { 'aria-labelledby': floatLabelElement.id });
}
if (!isNullOrUndefined(args.element.placeholder) && args.element.placeholder !== '') {
floatLabelElement.innerText = encodePlaceHolder(args.element.placeholder);
args.element.removeAttribute('placeholder');
}
if (!isNullOrUndefined(args.properties) && !isNullOrUndefined(args.properties.placeholder) &&
args.properties.placeholder !== '') {
floatLabelElement.innerText = encodePlaceHolder(args.properties.placeholder);
}
if (!floatLabelElement.innerText) {
inputObject.container.classList.add(CLASSNAMES.NOFLOATLABEL);
}
if (inputObject.container.classList.contains('e-float-icon-left')) {
const inputWrap = inputObject.container.querySelector('.e-input-in-wrap');
inputWrap.appendChild(args.element);
inputWrap.appendChild(floatLinelement);
inputWrap.appendChild(floatLabelElement);
}
else {
inputObject.container.appendChild(args.element);
inputObject.container.appendChild(floatLinelement);
inputObject.container.appendChild(floatLabelElement);
}
updateLabelState(args.element.value, floatLabelElement);
if (args.floatLabelType === 'Always') {
if (floatLabelElement.classList.contains(CLASSNAMES.LABELBOTTOM)) {
removeClass([floatLabelElement], CLASSNAMES.LABELBOTTOM);
}
addClass([floatLabelElement], CLASSNAMES.LABELTOP);
}
if (args.floatLabelType === 'Auto') {
const inputFloatHandler = () => inputEventHandler(args);
const blurFloatHandler = () => blurEventHandler(args);
// Add event listeners using the defined functions
args.element.addEventListener('input', inputFloatHandler);
args.element.addEventListener('blur', blurFloatHandler);
// Store the event handler functions to remove them later
args.element.__eventHandlers['floatInputHandler'] = { inputFloatHandler };
args.element.__eventHandlers['floatBlurHandler'] = { blurFloatHandler };
}
else {
unWireFloatLabelEvents(args);
}
if (!isNullOrUndefined(args.element.getAttribute('id'))) {
floatLabelElement.setAttribute('for', args.element.getAttribute('id'));
}
}
function unWireFloatLabelEvents(args) {
if (!isNullOrUndefined(args.element) &&
!isNullOrUndefined(args.element.__eventHandlers)
&& !isNullOrUndefined(args.element.__eventHandlers['floatInputHandler'])
&& !isNullOrUndefined(args.element.__eventHandlers['floatBlurHandler'])) {
const inputFloatHandler = args.element.__eventHandlers['floatInputHandler'].inputFloatHandler;
const blurFloatHandler = args.element.__eventHandlers['floatBlurHandler'].blurFloatHandler;
// Remove the event listeners using the defined functions
args.element.removeEventListener('input', inputFloatHandler);
args.element.removeEventListener('blur', blurFloatHandler);
// Clean up stored event handler functions
delete args.element.__eventHandlers['floatInputHandler'];
delete args.element.__eventHandlers['floatBlurHandler'];
}
}
function checkFloatLabelType(type, container) {
if (type === 'Always' && container.classList.contains('e-outline')) {
container.classList.add('e-valid-input');
}
}
function setPropertyValue(args, inputObject) {
if (!isNullOrUndefined(args.properties)) {
for (const prop of Object.keys(args.properties)) {
switch (prop) {
case 'cssClass':
setCssClass(args.properties.cssClass, [inputObject.container]);
checkFloatLabelType(args.floatLabelType, inputObject.container);
break;
case 'enabled':
setEnabled(args.properties.enabled, args.element, args.floatLabelType, inputObject.container);
break;
case 'enableRtl':
setEnableRtl(args.properties.enableRtl, [inputObject.container]);
break;
case 'placeholder':
setPlaceholder(args.properties.placeholder, args.element);
break;
case 'readonly':
setReadonly(args.properties.readonly, args.element);
break;
}
}
}
return inputObject;
}
function updateIconState(value, button, readonly) {
if (!isNullOrUndefined(button)) {
if (value && !readonly) {
removeClass([button], CLASSNAMES.CLEARICONHIDE);
}
else {
addClass([button], CLASSNAMES.CLEARICONHIDE);
}
}
}
function updateLabelState(value, label, element = null) {
if (value) {
addClass([label], CLASSNAMES.LABELTOP);
if (label.classList.contains(CLASSNAMES.LABELBOTTOM)) {
removeClass([label], CLASSNAMES.LABELBOTTOM);
}
}
else {
const isNotFocused = element != null ? element !== document.activeElement : true;
if (isNotFocused) {
if (label.classList.contains(CLASSNAMES.LABELTOP)) {
removeClass([label], CLASSNAMES.LABELTOP);
}
addClass([label], CLASSNAMES.LABELBOTTOM);
}
}
}
function getParentNode(element) {
let parentNode = isNullOrUndefined(element.parentNode) ? element
: element.parentNode;
if (parentNode && parentNode.classList.contains('e-input-in-wrap')) {
parentNode = parentNode.parentNode;
}
return parentNode;
}
/**
* To create clear button.
*/
function createClearButton(element, inputObject, initial, internalCreateElement) {
const makeElement = !isNullOrUndefined(internalCreateElement) ? internalCreateElement : createElement;
const button = makeElement('span', { className: CLASSNAMES.CLEARICON });
const container = inputObject.container;
if (!isNullOrUndefined(initial)) {
container.appendChild(button);
}
else {
const baseElement = inputObject.container.classList.contains(CLASSNAMES.FLOATINPUT) ?
inputObject.container.querySelector('.' + CLASSNAMES.FLOATTEXT) : element;
baseElement.insertAdjacentElement('afterend', button);
}
addClass([button], CLASSNAMES.CLEARICONHIDE);
wireClearBtnEvents(element, button);
button.setAttribute('aria-label', 'close');
return button;
}
function clickHandler(event, element, button) {
if (!(element.classList.contains(CLASSNAMES.DISABLE) || element.readOnly)) {
event.preventDefault();
if (element !== document.activeElement) {
element.focus();
}
element.value = '';
addClass([button], CLASSNAMES.CLEARICONHIDE);
}
}
function inputHandler(element, button) {
updateIconState(element.value, button);
}
function focusHandler(element, button) {
updateIconState(element.value, button, element.readOnly);
}
function blurHandler(element, button) {
setTimeout(() => {
if (!isNullOrUndefined(button)) {
addClass([button], CLASSNAMES.CLEARICONHIDE);
button = !isNullOrUndefined(element) && element.classList.contains('e-combobox') ? null : button;
}
}, 200);
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function wireClearBtnEvents(element, button, container) {
if (isBindClearAction === undefined || isBindClearAction) {
const clickHandlerEvent = (e) => clickHandler(e, element, button);
button.addEventListener('click', clickHandlerEvent);
element.__eventHandlers['clearClickHandler'] = { clickHandlerEvent };
}
const inputHandlerEvent = () => inputHandler(element, button);
const focusHandlerEvent = () => focusHandler(element, button);
const blurHandlerEvent = () => blurHandler(element, button);
element.addEventListener('input', inputHandlerEvent);
element.addEventListener('focus', focusHandlerEvent);
element.addEventListener('blur', blurHandlerEvent);
// Store the bound functions to remove them later
element.__eventHandlers['clearInputHandler'] = { inputHandlerEvent };
element.__eventHandlers['clearFocusHandler'] = { focusHandlerEvent };
element.__eventHandlers['clearBlurHandler'] = { blurHandlerEvent };
}
Input.wireClearBtnEvents = wireClearBtnEvents;
function unWireClearBtnEvents(element, button) {
if (!isNullOrUndefined(element) &&
!isNullOrUndefined(element.__eventHandlers)) {
if (!isNullOrUndefined(element.__eventHandlers['clearClickHandler'])) {
const clickHandlerEvent = element.__eventHandlers['clearClickHandler'].clickHandlerEvent;
if (isBindClearAction === undefined || isBindClearAction) {
if (!isNullOrUndefined(button)) {
button.removeEventListener('click', clickHandlerEvent);
}
}
delete element.__eventHandlers['clearClickHandler'];
}
if (!isNullOrUndefined(element.__eventHandlers['clearInputHandler'])
&& !isNullOrUndefined(element.__eventHandlers['clearFocusHandler'])
&& !isNullOrUndefined(element.__eventHandlers['clearBlurHandler'])) {
const inputHandlerEvent = element.__eventHandlers['clearInputHandler'].inputHandlerEvent;
const focusHandlerEvent = element.__eventHandlers['clearFocusHandler'].focusHandlerEvent;
const blurHandlerEvent = element.__eventHandlers['clearBlurHandler'].blurHandlerEvent;
element.removeEventListener('input', inputHandlerEvent);
element.removeEventListener('focus', focusHandlerEvent);
element.removeEventListener('blur', blurHandlerEvent);
// Clean up stored Event functions
delete element.__eventHandlers['clearInputHandler'];
delete element.__eventHandlers['clearFocusHandler'];
delete element.__eventHandlers['clearBlurHandler'];
}
}
}
function destroy(args, button = null) {
unbindInitialEvent(args);
if (args.floatLabelType === 'Auto') {
unWireFloatLabelEvents(args);
}
if (args.properties.showClearButton) {
unWireClearBtnEvents(args.element, button);
}
if (!isNullOrUndefined(args.buttons)) {
_internalRipple(false, null, args.buttons);
}
unwireFloatingEvents(args.element);
if (!isNullOrUndefined(args.element)) {
delete args.element.__eventHandlers;
if (args.element.classList.contains(CLASSNAMES.INPUT)) {
args.element.classList.remove(CLASSNAMES.INPUT);
}
}
}
Input.destroy = destroy;
function validateLabel(element, floatLabelType) {
const parent = getParentNode(element);
if (parent.classList.contains(CLASSNAMES.FLOATINPUT) && floatLabelType === 'Auto') {
const label = getParentNode(element).getElementsByClassName('e-float-text')[0];
updateLabelState(element.value, label, element);
}
}
/**
* To create input box contianer.
*/
function createInputContainer(args, className, tagClass, tag, internalCreateElement) {
const makeElement = !isNullOrUndefined(internalCreateElement) ? internalCreateElement : createElement;
let container;
if (!isNullOrUndefined(args.customTag)) {
container = makeElement(args.customTag, { className: className });
container.classList.add(tagClass);
}
else {
container = makeElement(tag, { className: className });
}
container.classList.add('e-control-wrapper');
return container;
}
function encodePlaceHolder(placeholder) {
let result = '';
if (!isNullOrUndefined(placeholder) && placeholder !== '') {
const spanEle = document.createElement('span');
spanEle.innerHTML = '<input placeholder="' + placeholder + '"/>';
const hiddenInput = (spanEle.children[0]);
result = hiddenInput.placeholder;
}
return result;
}
/**
* Sets the value to the input element.
* ```
* E.g : Input.setValue('content', element, "Auto", true );
* ```
*
* @param {string} value - Specify the value of the input element.
* @param {HTMLInputElement | HTMLTextAreaElement} element - The element on which the specified value is updated.
* @param {string} floatLabelType - Specify the float label type of the input element.
* @param {boolean} clearButton - Boolean value to specify whether the clear icon is enabled / disabled on the input.
*/
function setValue(value, element, floatLabelType, clearButton) {
element.value = value;
if (floatLabelType !== 'Never') {
calculateWidth(element, element.parentElement);
}
if ((!isNullOrUndefined(floatLabelType)) && floatLabelType === 'Auto') {
validateLabel(element, floatLabelType);
}
if (!isNullOrUndefined(clearButton) && clearButton) {
const parentElement = getParentNode(element);
if (!isNullOrUndefined(parentElement)) {
const button = parentElement.getElementsByClassName(CLASSNAMES.CLEARICON)[0];
if (!isNullOrUndefined(button)) {
if (element.value && !isNullOrUndefined(parentElement) && parentElement.classList.contains('e-input-focus')) {
removeClass([button], CLASSNAMES.CLEARICONHIDE);
}
else {
addClass([button], CLASSNAMES.CLEARICONHIDE);
}
}
}
}
checkInputValue(floatLabelType, element);
}
Input.setValue = setValue;
/**
* Sets the single or multiple cssClass to wrapper of input element.
* ```
* E.g : Input.setCssClass('e-custom-class', [element]);
* ```
*
* @param {string} cssClass - Css class names which are needed to add.
* @param {Element[] | NodeList} elements - The elements which are needed to add / remove classes.
* @param {string} oldClass
* - Css class names which are needed to remove. If old classes are need to remove, can give this optional parameter.
*/
function setCssClass(cssClass, elements, oldClass) {
if (!isNullOrUndefined(oldClass) && oldClass !== '') {
removeClass(elements, oldClass.split(' '));
}
if (!isNullOrUndefined(cssClass) && cssClass !== '') {
addClass(elements, cssClass.split(' '));
}
}
Input.setCssClass = setCssClass;
/**
* Set the width to the placeholder when it overflows on the button such as spinbutton, clearbutton, icon etc
* ```
* E.g : Input.calculateWidth(element, container);
* ```
*
* @param {any} element - Input element which is need to add.
* @param {HTMLElement} container - The parent element which is need to get the label span to calculate width
*/
function calculateWidth(element, container, moduleName) {
if (moduleName !== 'multiselect' && !_isElementVisible(element)) {
return;
}
const elementWidth = moduleName === 'multiselect' ? element : element.clientWidth - parseInt(getComputedStyle(element, null).getPropertyValue('padding-left'), 10);
if (!isNullOrUndefined(container) && !isNullOrUndefined(container.getElementsByClassName('e-float-text-content')[0])) {
if (container.getElementsByClassName('e-float-text-content')[0].classList.contains('e-float-text-overflow')) {
container.getElementsByClassName('e-float-text-content')[0].classList.remove('e-float-text-overflow');
}
if (elementWidth < container.getElementsByClassName('e-float-text-content')[0].clientWidth || elementWidth === container.getElementsByClassName('e-float-text-content')[0].clientWidth) {
container.getElementsByClassName('e-float-text-content')[0].classList.add('e-float-text-overflow');
}
}
}
Input.calculateWidth = calculateWidth;
/**
* Set the width to the wrapper of input element.
* ```
* E.g : Input.setWidth('200px', container);
* ```
*
* @param {number | string} width - Width value which is need to add.
* @param {HTMLElement} container - The element on which the width is need to add.
*/
function setWidth(width, container) {
if (typeof width === 'number') {
container.style.width = formatUnit(width);
}
else if (typeof width === 'string') {
container.style.width = (width.match(/px|%|em/)) ? (width) : (formatUnit(width));
}
calculateWidth(container.firstChild, container);
}
Input.setWidth = setWidth;
/**
* Set the placeholder attribute to the input element.
* ```
* E.g : Input.setPlaceholder('Search here', element);
* ```
*
* @param {string} placeholder - Placeholder value which is need to add.
* @param {HTMLInputElement | HTMLTextAreaElement} element - The element on which the placeholder is need to add.
*/
function setPlaceholder(placeholder, element) {
placeholder = encodePlaceHolder(placeholder);
const parentElement = getParentNode(element);
if (parentElement.classList.contains(CLASSNAMES.FLOATINPUT)) {
if (!isNullOrUndefined(placeholder) && placeholder !== '') {
const floatTextContent = parentElement.getElementsByClassName('e-float-text-content')[0];
if (floatTextContent && floatTextContent.children[0]) {
floatTextContent.children[0].textContent = placeholder;
}
else {
parentElement.getElementsByClassName(CLASSNAMES.FLOATTEXT)[0].textContent = placeholder;
}
parentElement.classList.remove(CLASSNAMES.NOFLOATLABEL);
element.removeAttribute('placeholder');
}
else {
parentElement.classList.add(CLASSNAMES.NOFLOATLABEL);
const floatTextContent = parentElement.getElementsByClassName('e-float-text-content')[0];
if (floatTextContent) {
floatTextContent.children[0].textContent = '';
}
else {
parentElement.getElementsByClassName(CLASSNAMES.FLOATTEXT)[0].textContent = '';
}
}
}
else {
if (!isNullOrUndefined(placeholder) && placeholder !== '') {
attributes(element, { 'placeholder': placeholder });
}
else {
element.removeAttribute('placeholder');
}
}
}
Input.setPlaceholder = setPlaceholder;
/**
* Set the read only attribute to the input element
* ```
* E.g : Input.setReadonly(true, element);
* ```
*
* @param {boolean} isReadonly
* - Boolean value to specify whether to set read only. Setting "True" value enables read only.
* @param {HTMLInputElement | HTMLTextAreaElement} element
* - The element which is need to enable read only.
*/
function setReadonly(isReadonly, element, floatLabelType) {
if (isReadonly) {
attributes(element, { readonly: '' });
}
else {
element.removeAttribute('readonly');
}
if (!isNullOrUndefined(floatLabelType)) {
validateLabel(element, floatLabelType);
}
}
Input.setReadonly = setReadonly;
/**
* Displays the element direction from right to left when its enabled.
* ```
* E.g : Input.setEnableRtl(true, [inputObj.container]);
* ```
*
* @param {boolean} isRtl
* - Boolean value to specify whether to set RTL. Setting "True" value enables the RTL mode.
* @param {Element[] | NodeList} elements
* - The elements that are needed to enable/disable RTL.
*/
function setEnableRtl(isRtl, elements) {
if (isRtl) {
addClass(elements, CLASSNAMES.RTL);
}
else {
removeClass(elements, CLASSNAMES.RTL);
}
}
Input.setEnableRtl = setEnableRtl;
/**
* Enables or disables the given input element.
* ```
* E.g : Input.setEnabled(false, element);
* ```
*
* @param {boolean} isEnable
* - Boolean value to specify whether to enable or disable.
* @param {HTMLInputElement | HTMLTextAreaElement} element
* - Element to be enabled or disabled.
*/
function setEnabled(isEnable, element, floatLabelType, inputContainer) {
const disabledAttrs = { 'disabled': '', 'aria-disabled': 'true' };
const considerWrapper = isNullOrUndefined(inputContainer) ? false : true;
if (isEnable) {
element.classList.remove(CLASSNAMES.DISABLE);
removeAttributes(disabledAttrs, element);
if (considerWrapper) {
removeClass([inputContainer], CLASSNAMES.DISABLE);
}
}
else {
element.classList.add(CLASSNAMES.DISABLE);
addAttributes(disabledAttrs, element);
if (considerWrapper) {
addClass([inputContainer], CLASSNAMES.DISABLE);
}
}
if (!isNullOrUndefined(floatLabelType)) {
validateLabel(element, floatLabelType);
}
}
Input.setEnabled = setEnabled;
function setClearButton(isClear, element, inputObject, initial, internalCreateElement) {
const makeElement = !isNullOrUndefined(internalCreateElement) ? internalCreateElement : createElement;
if (isClear) {
inputObject.clearButton = createClearButton(element, inputObject, initial, makeElement);
}
else {
remove(inputObject.clearButton);
inputObject.clearButton = null;
}
}
Input.setClearButton = setClearButton;
/**
* Removing the multiple attributes from the given element such as "disabled","id" , etc.
* ```
* E.g : Input.removeAttributes({ 'disabled': 'disabled', 'aria-disabled': 'true' }, element);
* ```
*
* @param {string} attrs
* - Array of attributes which are need to removed from the element.
* @param {HTMLInputElement | HTMLElement} element
* - Element on which the attributes are needed to be removed.
*/
function removeAttributes(attrs, element) {
for (const key of Object.keys(attrs)) {
const parentElement = getParentNode(element);
if (key === 'disabled') {
element.classList.remove(CLASSNAMES.DISABLE);
}
if (key === 'disabled' && parentElement.classList.contains(CLASSNAMES.INPUTGROUP)) {
parentElement.classList.remove(CLASSNAMES.DISABLE);
}
if (key === 'placeholder' && parentElement.classList.contains(CLASSNAMES.FLOATINPUT)) {
parentElement.getElementsByClassName(CLASSNAMES.FLOATTEXT)[0].textContent = '';
}
else {
element.removeAttribute(key);
}
}
}
Input.removeAttributes = removeAttributes;
/**
* Adding the multiple attributes to the given element such as "disabled","id" , etc.
* ```
* E.g : Input.addAttributes({ 'id': 'inputpopup' }, element);
* ```
*
* @param {string} attrs
* - Array of attributes which is added to element.
* @param {HTMLInputElement | HTMLElement} element
* - Element on which the attributes are needed to be added.
*/
function addAttributes(attrs, element) {
for (const key of Object.keys(attrs)) {
const parentElement = getParentNode(element);
if (key === 'disabled') {
element.classList.add(CLASSNAMES.DISABLE);
}
if (key === 'disabled' && parentElement.classList.contains(CLASSNAMES.INPUTGROUP)) {
parentElement.classList.add(CLASSNAMES.DISABLE);
}
if (key === 'placeholder' && parentElement.classList.contains(CLASSNAMES.FLOATINPUT)) {
parentElement.getElementsByClassName(CLASSNAMES.FLOATTEXT)[0].textContent = attrs[`${key}`];
}
else {
element.setAttribute(key, attrs[`${key}`]);
}
}
}
Input.addAttributes = addAttributes;
function removeFloating(input) {
const container = input.container;
if (!isNullOrUndefined(container) && container.classList.contains(CLASSNAMES.FLOATINPUT)) {
const inputEle = container.querySelector('textarea') ? container.querySelector('textarea') :
container.querySelector('input');
const placeholder = container.querySelector('.' + CLASSNAMES.FLOATTEXT).textContent;
const clearButton = container.querySelector('.e-clear-icon') !== null;
detach(container.querySelector('.' + CLASSNAMES.FLOATLINE));
detach(container.querySelector('.' + CLASSNAMES.FLOATTEXT));
classList(container, [CLASSNAMES.INPUTGROUP], [CLASSNAMES.FLOATINPUT]);
unwireFloatingEvents(inputEle);
attributes(inputEle, { 'placeholder': placeholder });
inputEle.classList.add(CLASSNAMES.INPUT);
if (!clearButton && inputEle.tagName === 'INPUT') {
inputEle.removeAttribute('required');
}
}
}
Input.removeFloating = removeFloating;
function addFloating(input, type, placeholder, internalCreateElement) {
const makeElement = !isNullOrUndefined(internalCreateElement) ? internalCreateElement : createElement;
const container = closest(input, '.' + CLASSNAMES.INPUTGROUP);
floatType = type;
let customTag = container.tagName;
customTag = customTag !== 'DIV' && customTag !== 'SPAN' ? customTag : null;
const args = { element: input, floatLabelType: type,
customTag: customTag, properties: { placeholder: placeholder } };
if (type !== 'Never') {
let iconEle = container.querySelector('.e-clear-icon');
const inputObj = { container: container };
input.classList.remove(CLASSNAMES.INPUT);
createFloatingInput(args, inputObj, makeElement);
createSpanElement(inputObj.container, makeElement);
calculateWidth(args.element, inputObj.container);
const isPrependIcon = container.classList.contains('e-float-icon-left');
if (isNullOrUndefined(iconEle)) {
if (isPrependIcon) {
const inputWrap = container.querySelector('.e-input-in-wrap');
iconEle = inputWrap.querySelector('.e-input-group-icon');
}
else {
iconEle = container.querySelector('.e-input-group-icon');
}
}
if (isNullOrUndefined(iconEle)) {
if (isPrependIcon) {
iconEle = container.querySelector('.e-input-group-icon');
}
}
else {
const floatLine = container.querySelector('.' + CLASSNAMES.FLOATLINE);
const floatText = container.querySelector('.' + CLASSNAMES.FLOATTEXT);
const wrapper = isPrependIcon ? container.querySelector('.e-input-in-wrap') : container;
wrapper.insertBefore(input, iconEle);
wrapper.insertBefore(floatLine, iconEle);
wrapper.insertBefore(floatText, iconEle);
}
}
else {
unWireFloatLabelEvents(args);
}
checkFloatLabelType(type, input.parentElement);
}
Input.addFloating = addFloating;
/**
* Create the span inside the label and add the label text into the span textcontent
* ```
* E.g : Input.createSpanElement(inputObject, makeElement);
* ```
*
* @param {Element} inputObject
* - Element which is need to get the label
* @param {createElementParams} makeElement
* - Element which is need to create the span
*/
function createSpanElement(inputObject, makeElement) {
if (inputObject.classList.contains('e-outline') && inputObject.getElementsByClassName('e-float-text')[0]) {
const labelSpanElement = makeElement('span', { className: CLASSNAMES.FLOATTEXTCONTENT });
labelSpanElement.innerHTML = inputObject.getElementsByClassName('e-float-text')[0].innerHTML;
inputObject.getElementsByClassName('e-float-text')[0].innerHTML = '';
inputObject.getElementsByClassName('e-float-text')[0].appendChild(labelSpanElement);
}
}
Input.createSpanElement = createSpanElement;
/**
* Enable or Disable the ripple effect on the icons inside the Input. Ripple effect is only applicable for material theme.
* ```
* E.g : Input.setRipple(true, [inputObjects]);
* ```
*
* @param {boolean} isRipple
* - Boolean value to specify whether to enable the ripple effect.
* @param {InputObject[]} inputObj
* - Specify the collection of input objects.
*/
function setRipple(isRipple, inputObj) {
for (let i = 0; i < inputObj.length; i++) {
_internalRipple(isRipple, inputObj[parseInt(i.toString(), 10)].container);
}
}
Input.setRipple = setRipple;
function _internalRipple(isRipple, container, button) {
const argsButton = [];
argsButton.push(button);
const buttons = isNullOrUndefined(button) ?
container.querySelectorAll('.e-input-group-icon') : argsButton;
if (isRipple && buttons.length > 0) {
for (let index = 0; index < buttons.length; index++) {
buttons[parseInt(index.toString(), 10)].addEventListener('mousedown', _onMouseDownRipple, false);
buttons[parseInt(index.toString(), 10)].addEventListener('mouseup', _onMouseUpRipple, false);
}
}
else if (buttons.length > 0) {
for (let index = 0; index < buttons.length; index++) {
buttons[parseInt(index.toString(), 10)].removeEventListener('mousedown', _onMouseDownRipple, this);
buttons[parseInt(index.toString(), 10)].removeEventListener('mouseup', _onMouseUpRipple, this);
}
}
}
function _onMouseRipple(container, button) {
if (!container.classList.contains('e-disabled') && !container.querySelector('input').readOnly) {
button.classList.add('e-input-btn-ripple');
}
}
function _isElementVisible(element) {
if (!element) {
return false;
}
// Check if the element or any of its parents are hidden using display: none
let currentElement = element;
while (currentElement && currentElement !== document.body) {
const style = window.getComputedStyle(currentElement);
if (style.display === 'none') {
return false;
}
currentElement = currentElement.parentElement;
}
// If none of the elements have display: none, the element is considered visible
return true;
}
function _onMouseDownRipple() {
const ele = this;
let parentEle = this.parentElement;
while (!parentEle.classList.contains('e-input-group')) {
parentEle = parentEle.parentElement;
}
_onMouseRipple(parentEle, ele);
}
function _onMouseUpRipple() {
const ele = this;
setTimeout(() => {
ele.classList.remove('e-input-btn-ripple');
}, 500);
}
function createIconEle(iconClass, makeElement) {
const button = makeElement('span', { className: iconClass });
button.classList.add('e-input-group-icon');
return button;
}
/**
* Creates a new span element with the given icons added and append it in container element.
* ```
* E.g : Input.addIcon('append', 'e-icon-spin', inputObj.container, inputElement);
* ```
*
* @param {string} position - Specify the icon placement on the input.Possible values are append and prepend.
* @param {string | string[]} icons - Icon classes which are need to add to the span element which is going to created.
* Span element acts as icon or button element for input.
* @param {HTMLElement} container - The container on which created span element is going to append.
* @param {HTMLElement} input - The inputElement on which created span element is going to prepend.
*/
function addIcon(position, icons, container, input, internalCreate) {
const result = typeof (icons) === 'string' ? icons.split(',')
: icons;
if (position.toLowerCase() === 'append') {
for (const icon of result) {
appendSpan(icon, container, internalCreate);
}
}
else {
for (const icon of result) {
prependSpan(icon, container, input, internalCreate);
}
}
if (container.getElementsByClassName('e-input-group-icon')[0] && container.getElementsByClassName('e-float-text-overflow')[0]) {
container.getElementsByClassName('e-float-text-overflow')[0].classList.add('e-icon');
}
}
Input.addIcon = addIcon;
/**
* Creates a new span element with the given icons added and prepend it in input element.
* ```
* E.g : Input.prependSpan('e-icon-spin', inputObj.container, inputElement);
* ```
*
* @param {string} iconClass - Icon classes which are need to add to the span element which is going to created.
* Span element acts as icon or button element for input.
* @param {HTMLElement} container - The container on which created span element is going to append.
* @param {HTMLElement} inputElement - The inputElement on which created span element is going to prepend.
*/
function prependSpan(iconClass, container, inputElement, internalCreateElement) {
const makeElement = !isNullOrUndefined(internalCreateElement) ? internalCreateElement : createElement;
const button = createIconEle(iconClass, makeElement);
container.classList.add('e-float-icon-left');
let innerWrapper = container.querySelector('.e-input-in-wrap');
if (isNullOrUndefined(innerWrapper)) {
innerWrapper = makeElement('span', { className: 'e-input-in-wrap' });
inputElement.parentNode.insertBefore(innerWrapper, inputElement);
const result = container.querySelectorAll(inputElement.tagName + ' ~ *');
innerWrapper.appendChild(inputElement);
for (let i = 0; i < result.length; i++) {
const element = result[parseInt(i.toString(), 10)];
const parentElement = innerWrapper.parentElement;
if (!(element.classList.contains('e-float-line')) || (!(parentElement && parentElement.classList.contains('e-filled')) && parentElement)) {
innerWrapper.appendChild(element);
}
}
}
innerWrapper.parentNode.insertBefore(button, innerWrapper);
_internalRipple(true, container, button);
return button;
}
Input.prependSpan = prependSpan;
/**
* Creates a new span element with the given icons added and append it in container element.
* ```
* E.g : Input.appendSpan('e-icon-spin', inputObj.container);
* ```
*
* @param {string} iconClass - Icon classes which are need to add to the span element which is going to created.
* Span element acts as icon or button element for input.
* @param {HTMLElement} container - The container on which created span element is going to append.
*/
function appendSpan(iconClass, container, internalCreateElement) {
const makeElement = !isNullOrUndefined(internalCreateElement) ? internalCreateElement : createElement;
const button = createIconEle(iconClass, makeElement);
const wrap = (container.classList.contains('e-float-icon-left')) ? container.querySelector('.e-input-in-wrap') :
container;
wrap.appendChild(button);
_internalRipple(true, container, button);
return button;
}
Input.appendSpan = appendSpan;
function validateInputType(containerElement, input) {
if (input.type === 'hidden') {
containerElement.classList.add('e-hidden');
}
else if (containerElement.classList.contains('e-hidden')) {
containerElement.classList.remove('e-hidden');
}
}
Input.validateInputType = validateInputType;
function updateHTMLAttributesToElement(htmlAttributes, element) {
if (!isNullOrUndefined(htmlAttributes)) {
for (const key of Object.keys(htmlAttributes)) {
if (containerAttributes.indexOf(key) < 0) {
element.setAttribute(key, htmlAttributes[`${key}`]);
}
}
}
}
Input.updateHTMLAttributesToElement = updateHTMLAttributesToElement;
function updateCssClass(newClass, oldClass, container) {
setCssClass(getInputValidClassList(newClass), [container], getInputValidClassList(oldClass));
}
Input.updateCssClass = updateCssClass;
function getInputValidClassList(inputClassName) {
let result = inputClassName;
if (!isNullOrUndefined(inputC