@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,058 lines (1,055 loc) • 650 kB
JavaScript
import { Ajax, Animation, Base, Browser, ChildProperty, Collection, Complex, Component, Event, EventHandler, Internationalization, KeyboardEvents, L10n, NotifyPropertyChanges, Property, SanitizeHtmlHelper, addClass, append, attributes, classList, closest, compile, createElement, detach, extend, formatUnit, getInstance, getNumericObject, getUniqueID, getValue, isNullOrUndefined, merge, onIntlChange, remove, removeClass, rippleEffect, select, selectAll, setStyleAttribute, setValue } from '@syncfusion/ej2-base';
import { Popup, Tooltip, createSpinner, getZindexPartial, hideSpinner, showSpinner } from '@syncfusion/ej2-popups';
import { Deferred, SplitButton, getModel } from '@syncfusion/ej2-splitbuttons';
/* 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'
};
/**
* 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) {
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 && args.element.tagName !== 'TEXTAREA') {
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) && args.element.tagName !== 'TEXTAREA') {
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);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
return inputObject;
}
Input.createInput = createInput;
function bindInitialEvent(args) {
checkInputValue(args.floatLabelType, args.element);
args.element.addEventListener('focus', function () {
const parent = getParentNode(this);
if (parent.classList.contains('e-input-group') || parent.classList.contains('e-outline')
|| parent.classList.contains('e-filled')) {
parent.classList.add('e-input-focus');
}
setTimeout(() => {
Input.calculateWidth(args.element, parent);
}, 80);
});
args.element.addEventListener('blur', function () {
const parent = getParentNode(this);
if (parent.classList.contains('e-input-group') || parent.classList.contains('e-outline')
|| parent.classList.contains('e-filled')) {
parent.classList.remove('e-input-focus');
}
setTimeout(() => {
Input.calculateWidth(args.element, parent);
}, 80);
});
args.element.addEventListener('input', () => {
checkInputValue(floatType, args.element);
});
}
Input.bindInitialEvent = bindInitialEvent;
function checkInputValue(floatLabelType, inputElement) {
const inputValue = inputElement.value;
if (inputValue !== '' && !isNullOrUndefined(inputValue) && inputElement.parentElement) {
inputElement.parentElement.classList.add('e-valid-input');
}
else if (floatLabelType !== 'Always' && inputElement.parentElement) {
inputElement.parentElement.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) {
element.removeEventListener('focus', _focusFn);
element.removeEventListener('blur', _blurFn);
}
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);
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') {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
args.element.addEventListener('input', (event) => {
updateLabelState(args.element.value, floatLabelElement, args.element);
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
args.element.addEventListener('blur', (event) => {
updateLabelState(args.element.value, floatLabelElement);
});
}
if (!isNullOrUndefined(args.element.getAttribute('id'))) {
floatLabelElement.setAttribute('for', args.element.getAttribute('id'));
}
}
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 (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);
}
if (!isNullOrUndefined(container) &&
container.classList.contains(CLASSNAMES.FLOATINPUT)) {
addClass([container], CLASSNAMES.INPUTGROUP);
}
addClass([button], CLASSNAMES.CLEARICONHIDE);
wireClearBtnEvents(element, button, container);
button.setAttribute('aria-label', 'close');
return button;
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
function wireClearBtnEvents(element, button, container) {
if (isBindClearAction === undefined || isBindClearAction) {
button.addEventListener('click', (event) => {
if (!(element.classList.contains(CLASSNAMES.DISABLE) || element.readOnly)) {
event.preventDefault();
if (element !== document.activeElement) {
element.focus();
}
element.value = '';
addClass([button], CLASSNAMES.CLEARICONHIDE);
}
});
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
element.addEventListener('input', (event) => {
updateIconState(element.value, button);
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
element.addEventListener('focus', (event) => {
updateIconState(element.value, button, element.readOnly);
});
// eslint-disable-next-line @typescript-eslint/no-unused-vars
element.addEventListener('blur', (event) => {
setTimeout(() => {
addClass([button], CLASSNAMES.CLEARICONHIDE);
}, 200);
});
}
Input.wireClearBtnEvents = wireClearBtnEvents;
function destroy() {
}
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$$1(value, element, floatLabelType, clearButton) {
element.value = value;
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$$1;
/**
* 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) {
const elementWidth = moduleName === 'multiselect' ? element : element.clientWidth - parseInt(getComputedStyle(element, null).getPropertyValue('padding-left'), 10);
if (!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 !== '') {
parentElement.getElementsByClassName('e-float-text-content')[0] ? parentElement.getElementsByClassName(CLASSNAMES.FLOATTEXT)[0].children[0].textContent = placeholder : parentElement.getElementsByClassName(CLASSNAMES.FLOATTEXT)[0].textContent = placeholder;
parentElement.classList.remove(CLASSNAMES.NOFLOATLABEL);
element.removeAttribute('placeholder');
}
else {
parentElement.classList.add(CLASSNAMES.NOFLOATLABEL);
parentElement.getElementsByClassName('e-float-text-content')[0] ? parentElement.getElementsByClassName(CLASSNAMES.FLOATTEXT)[0].children[0].textContent = '' : 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': '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;
if (type !== 'Never') {
let customTag = container.tagName;
customTag = customTag !== 'DIV' && customTag !== 'SPAN' ? customTag : null;
const args = { element: input, floatLabelType: type,
customTag: customTag, properties: { placeholder: placeholder } };
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');
}
if (isNullOrUndefined(iconEle)) {
container.classList.remove(CLASSNAMES.INPUTGROUP);
}
}
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);
}
}
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 {InputObject} 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())].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())].addEventListener('mousedown', _onMouseDownRipple, false);
buttons[parseInt(index.toString())].addEventListener('mouseup', _onMouseUpRipple, false);
}
}
else if (buttons.length > 0) {
for (let index = 0; index < buttons.length; index++) {
buttons[parseInt(index.toString())].removeEventListener('mousedown', _onMouseDownRipple, this);
buttons[parseInt(index.toString())].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 _onMouseDownRipple() {
// eslint-disable-next-line @typescript-eslint/no-this-alias
const ele = this;
let parentEle = this.parentElement;
while (!parentEle.classList.contains('e-input-group')) {
parentEle = parentEle.parentElement;
}
_onMouseRipple(parentEle, ele);
}
function _onMouseUpRipple() {
// eslint-disable-next-line @typescript-eslint/no-this-alias
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.
*/
/* eslint-disable @typescript-eslint/indent */
function addIcon(position, icons, container, input, internalCreate) {
/* eslint-enable @typescript-eslint/indent */
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.
*/
/* eslint-disable @typescript-eslint/indent */
function prependSpan(iconClass, container, inputElement, internalCreateElement) {
/* eslint-enable @typescript-eslint/indent */
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++) {
innerWrapper.appendChild(result[parseInt(i.toString())]);
}
}
innerWrapper.parentNode.insertBefore(button, innerWrapper);
if (!container.classList.contains(CLASSNAMES.INPUTGROUP)) {
container.classList.add(CLASSNAMES.INPUTGROUP);
}
_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);
if (!container.classList.contains(CLASSNAMES.INPUTGROUP)) {
container.classList.add(CLASSNAMES.INPUTGROUP);
}
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;
})(Input || (Input = {}));
/* eslint-enable valid-jsdoc, jsdoc/require-jsdoc, jsdoc/require-returns, jsdoc/require-param */
var __decorate = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
const ROOT = 'e-control-wrapper e-numeric';
const SPINICON = 'e-input-group-icon';
const SPINUP = 'e-spin-up';
const SPINDOWN = 'e-spin-down';
const ERROR = 'e-error';
const INCREMENT = 'increment';
const DECREMENT = 'decrement';
const INTREGEXP = new RegExp('^(-)?(\\d*)$');
const DECIMALSEPARATOR = '.';
const COMPONENT = 'e-numerictextbox';
const CONTROL = 'e-control';
const NUMERIC_FOCUS = 'e-input-focus';
const HIDDENELEMENT = 'e-numeric-hidden';
const wrapperAttributes = ['title', 'style', 'class'];
let selectionTimeOut = 0;
/**
* Represents the NumericTextBox component that allows the user to enter only numeric values.
* ```html
* <input type='text' id="numeric"/>
* ```
* ```typescript
* <script>
* var numericObj = new NumericTextBox({ value: 10 });
* numericObj.appendTo("#numeric");
* </script>
* ```
*/
let NumericTextBox = class NumericTextBox extends Component {
/**
*
* @param {NumericTextBoxModel} options - Specifies the NumericTextBox model.
* @param {string | HTMLInputElement} element - Specifies the element to render as component.
* @private
*/
constructor(options, element) {
super(options, element);
this.isVue = false;
this.preventChange = false;
this.isAngular = false;
this.isDynamicChange = false;
this.numericOptions = options;
}
preRender() {
this.isPrevFocused = false;
this.decimalSeparator = '.';
// eslint-disable-next-line no-useless-escape
this.intRegExp = new RegExp('/^(-)?(\d*)$/');
this.isCalled = false;
const ejInstance = getValue('ej2_instances', this.element);
this.cloneElement = this.element.cloneNode(true);
removeClass([this.cloneElement], [CONTROL, COMPONENT, 'e-lib']);
this.angularTagName = null;
this.formEle = closest(this.element, 'form');
if (this.element.tagName === 'EJS-NUMERICTEXTBOX') {
this.angularTagName = this.element.tagName;
const input = this.createElement('input');
let index = 0;
for (index; index < this.element.attributes.length; index++) {
const attributeName = this.element.attributes[index].nodeName;
if (attributeName !== 'id' && attributeName !== 'class') {
input.setAttribute(this.element.attributes[index].nodeName, this.element.attributes[index].nodeValue);
input.innerHTML = this.element.innerHTML;
}
else if (attributeName === 'class') {
input.setAttribute(attributeName, this.element.className.split(' ').filter((item) => item.indexOf('ng-') !== 0).join(' '));
}
}
if (this.element.hasAttribute('name')) {
this.element.removeAttribute('name');
}
this.element.classList.remove('e-control', 'e-numerictextbox');
this.element.appendChild(input);
this.element = input;
setValue('ej2_instances', ejInstance, this.element);
}
attributes(this.element, { 'role': 'spinbutton', 'tabindex': '0', 'autocomplete': 'off' });
const localeText = {
incrementTitle: 'Increment value', decrementTitle: 'Decrement value', placeholder: this.placeholder
};
this.l10n = new L10n('numerictextbox', localeText, this.locale);
if (this.l10n.getConstant('placeholder') !== '') {
this.setProperties({ placeholder: this.placeholder || this.l10n.getConstant('placeholder') }, true);
}
if (!this.element.hasAttribute('id')) {
this.element.setAttribute('id', getUniqueID('numerictextbox'));
}
this.isValidState = true;
this.inputStyle = null;
this.inputName = null;
this.cultureInfo = {};
this.initCultureInfo();
this.initCultureFunc();
this.prevValue = this.value;
this.updateHTMLAttrToElement();
this.checkAttributes(false);
if (this.formEle) {
this.inputEleValue = this.value;
}
this.validateMinMax();
this.validateStep();
if (this.placeholder === null) {
this.updatePlaceholder();
}
}
/**
* To Initialize the control rendering
*
* @returns {void}
* @private
*/
render() {
if (this.element.tagName.toLowerCase() === 'input') {
this.createWrapper();
if (this.showSpinButton) {
this.spinBtnCreation();
}
this.setElementWidth(this.width);
if (!this.container.classList.contains('e-input-group')) {
this.container.classList.add('e-input-group');
}
this.changeValue(this.value === null || isNaN(this.value) ?
null : this.strictMode ? this.trimValue(this.value) : this.value);
this.wireEvents();
if (this.value !== null && !isNaN(this.value)) {
if (this.decimals) {
this.setProperties({ value: this.roundNumber(this.value, this.decimals) }, true);
}
}
if (this.element.getAttribute('value') || this.value) {
this.element.setAttribute('value', this.element.value);
this.hiddenInput.setAttribute('value', this.hiddenInput.value);
}
this.elementPrevValue = this.element.value;
if (this.element.hasAttribute('data-val')) {
this.element.setAttribute('data-val', 'false');
}
if (!isNullOrUndefined(closest(this.element, 'fieldset')) && closest(this.element, 'fieldset').disabled) {
this.enabled = false;
}
this.renderComplete();
}
}
checkAttributes(isDynamic) {
const attributes$$1 = isDynamic ? isNullOrUndefined(this.htmlAttributes) ? [] : Object.keys(this.htmlAttributes) :
['value', 'min', 'max', 'step', 'disabled', 'readonly', 'style', 'name', 'placeholder'];
for (const prop of attributes$$1) {
if (!isNullOrUndefined(this.element.getAttribute(prop))) {
switch (prop) {
case 'disabled':
if ((isNullOrUndefined(this.numericOptions) || (this.numericOptions['enabled'] === undefined)) || isDynamic) {
const enabled = this.element.getAttribute(prop) === 'disabled' || this.element.getAttribute(prop) === ''
|| this.element.getAttribute(prop) === 'true' ? false : true;
this.setProperties({ enabled: enabled }, !isDynamic);
}
break;
case 'readonly':
if ((isNullOrUndefined(this.numericOptions) || (this.numericOptions['readonly'] === undefined)) || isDynamic) {
const readonly = this.element.getAttribute(prop) === 'readonly' || this.element.getAttribute(prop) === ''
|| this.element.getAttribute(prop) === 'true' ? true : false;
this.setProperties({ readonly: readonly }, !isDynamic);
}
break;
case 'placeholder':
if ((isNullOrUndefined(this.numericOptions) || (this.numericOptions['placeholder'] === undefined)) || isDynamic) {
this.setProperties({ placeholder: this.element.placeholder }, !isDynamic);
}
break;
case 'value':
if ((isNullOrUndefined(this.numericOptions) || (this.numericOptions['value'] === undefined)) || isDynamic) {
const setNumber = this.instance.getNumberParser({ format: 'n' })(this.e