diff --git a/packages/common/src/filters/compoundInputFilter.ts b/packages/common/src/filters/compoundInputFilter.ts
index d6d57d93e..35896e777 100644
--- a/packages/common/src/filters/compoundInputFilter.ts
+++ b/packages/common/src/filters/compoundInputFilter.ts
@@ -12,7 +12,7 @@ import {
SlickGrid,
} from '../interfaces/index';
import { buildSelectOperator } from './filterUtilities';
-import { emptyElement } from '../services/domUtilities';
+import { createDomElement, emptyElement } from '../services/domUtilities';
import { getTranslationPrefix, mapOperatorToShorthandDesignation, toSentenceCase } from '../services/utilities';
import { BindingEventService } from '../services/bindingEvent.service';
import { TranslaterService } from '../services/translater.service';
@@ -177,11 +177,11 @@ export class CompoundInputFilter implements Filter {
placeholder = this.columnFilter.placeholder;
}
- const inputElm = document.createElement('input');
- inputElm.type = this._inputType || 'text';
- inputElm.className = `form-control compound-input filter-${columnId}`;
- inputElm.autocomplete = 'off';
- inputElm.placeholder = placeholder;
+ const inputElm = createDomElement('input', {
+ type: this._inputType || 'text',
+ autocomplete: 'off', placeholder,
+ className: `form-control compound-input filter-${columnId}`,
+ });
inputElm.setAttribute('role', 'presentation');
inputElm.setAttribute('aria-label', this.columnFilter?.ariaLabel ?? `${toSentenceCase(columnId + '')} Search Filter`);
@@ -247,16 +247,11 @@ export class CompoundInputFilter implements Filter {
// create the DOM Select dropdown for the Operator
this._selectOperatorElm = buildSelectOperator(this.getOperatorOptionValues(), this.gridOptions);
this._filterInputElm = this.buildInputElement();
- const emptySpanElm = document.createElement('span');
+ const emptySpanElm = createDomElement('span');
- const filterContainerElm = document.createElement('div');
- filterContainerElm.className = `form-group search-filter filter-${columnId}`;
-
- const containerInputGroupElm = document.createElement('div');
- containerInputGroupElm.className = 'input-group';
-
- const operatorInputGroupAddonElm = document.createElement('div');
- operatorInputGroupAddonElm.className = 'input-group-addon input-group-prepend operator';
+ const filterContainerElm = createDomElement('div', { className: `form-group search-filter filter-${columnId}` });
+ const containerInputGroupElm = createDomElement('div', { className: 'input-group' });
+ const operatorInputGroupAddonElm = createDomElement('div', { className: 'input-group-addon input-group-prepend operator' });
/* the DOM element final structure will be
diff --git a/packages/common/src/filters/compoundSliderFilter.ts b/packages/common/src/filters/compoundSliderFilter.ts
index 981b34db6..ee6f00a09 100644
--- a/packages/common/src/filters/compoundSliderFilter.ts
+++ b/packages/common/src/filters/compoundSliderFilter.ts
@@ -12,7 +12,7 @@ import {
import { Constants } from '../constants';
import { OperatorString, OperatorType, SearchTerm } from '../enums/index';
import { buildSelectOperator } from './filterUtilities';
-import { emptyElement } from '../services/domUtilities';
+import { createDomElement, emptyElement } from '../services/domUtilities';
import { getTranslationPrefix, hasData, mapOperatorToShorthandDesignation, toSentenceCase } from '../services/utilities';
import { BindingEventService } from '../services/bindingEvent.service';
import { TranslaterService } from '../services/translater.service';
@@ -254,27 +254,20 @@ export class CompoundSliderFilter implements Filter {
// create the DOM Select dropdown for the Operator
this.selectOperatorElm = buildSelectOperator(this.getOperatorOptionValues(), this.gridOptions);
- const spanPrependElm = document.createElement('span');
- spanPrependElm.className = 'input-group-addon input-group-prepend operator';
+ const spanPrependElm = createDomElement('span', { className: 'input-group-addon input-group-prepend operator' });
spanPrependElm.appendChild(this.selectOperatorElm);
// create the DOM element
- this.filterInputElm = document.createElement('input');
- this.filterInputElm.type = 'range';
- this.filterInputElm.className = `form-control slider-filter-input range compound-slider ${this._elementRangeInputId}`;
- this.filterInputElm.defaultValue = defaultValue;
- this.filterInputElm.value = searchTermInput;
- this.filterInputElm.min = `${minValue}`;
- this.filterInputElm.max = `${maxValue}`;
- this.filterInputElm.step = `${step}`;
- this.filterInputElm.name = this._elementRangeInputId;
+ this.filterInputElm = createDomElement('input', {
+ type: 'range', name: this._elementRangeInputId,
+ className: `form-control slider-filter-input range compound-slider ${this._elementRangeInputId}`,
+ defaultValue, value: searchTermInput,
+ min: `${minValue}`, max: `${maxValue}`, step: `${step}`,
+ });
this.filterInputElm.setAttribute('aria-label', this.columnFilter?.ariaLabel ?? `${toSentenceCase(columnId + '')} Search Filter`);
- this.divContainerFilterElm = document.createElement('div');
- this.divContainerFilterElm.className = `form-group search-filter slider-container filter-${columnId}`;
-
- this.containerInputGroupElm = document.createElement('div');
- this.containerInputGroupElm.className = `input-group search-filter filter-${columnId}`;
+ this.divContainerFilterElm = createDomElement('div', { className: `form-group search-filter slider-container filter-${columnId}` });
+ this.containerInputGroupElm = createDomElement('div', { className: `input-group search-filter filter-${columnId}` });
this.containerInputGroupElm.appendChild(spanPrependElm);
this.containerInputGroupElm.appendChild(this.filterInputElm);
this.divContainerFilterElm.appendChild(this.containerInputGroupElm);
@@ -283,12 +276,11 @@ export class CompoundSliderFilter implements Filter {
this.containerInputGroupElm.classList.add('input-group');
this.filterInputElm.value = searchTermInput;
- const divGroupAppendElm = document.createElement('div');
- divGroupAppendElm.className = 'input-group-addon input-group-append slider-value';
-
- this.filterNumberElm = document.createElement('span');
- this.filterNumberElm.className = `input-group-text ${this._elementRangeOutputId}`;
- this.filterNumberElm.textContent = searchTermInput;
+ const divGroupAppendElm = createDomElement('div', { className: 'input-group-addon input-group-append slider-value' });
+ this.filterNumberElm = createDomElement('span', {
+ className: `input-group-text ${this._elementRangeOutputId}`,
+ textContent: searchTermInput
+ });
divGroupAppendElm.appendChild(this.filterNumberElm);
this.containerInputGroupElm.appendChild(divGroupAppendElm);
}
diff --git a/packages/common/src/filters/dateRangeFilter.ts b/packages/common/src/filters/dateRangeFilter.ts
index 51f1c9c6c..ad43c3daf 100644
--- a/packages/common/src/filters/dateRangeFilter.ts
+++ b/packages/common/src/filters/dateRangeFilter.ts
@@ -21,7 +21,7 @@ import {
GridOption,
SlickGrid,
} from '../interfaces/index';
-import { destroyObjectDomElementProps, emptyElement, } from '../services/domUtilities';
+import { createDomElement, destroyObjectDomElementProps, emptyElement, } from '../services/domUtilities';
import { mapFlatpickrDateFormatWithFieldType, mapMomentDateFormatWithFieldType } from '../services/utilities';
import { BindingEventService } from '../services/bindingEvent.service';
import { TranslaterService } from '../services/translater.service';
@@ -257,16 +257,10 @@ export class DateRangeFilter implements Filter {
placeholder = this.columnFilter.placeholder;
}
- const filterDivInputElm = document.createElement('div');
- filterDivInputElm.className = `flatpickr search-filter filter-${columnId}`;
-
- const inputElm = document.createElement('input');
- inputElm.type = 'text';
- inputElm.className = 'form-control';
- inputElm.dataset.input = '';
- inputElm.placeholder = placeholder;
-
- filterDivInputElm.appendChild(inputElm);
+ const filterDivInputElm = createDomElement('div', { className: `flatpickr search-filter filter-${columnId}` });
+ filterDivInputElm.appendChild(
+ createDomElement('input', { type: 'text', className: 'form-control', placeholder, dataset: { input: '' } })
+ );
this.flatInstance = flatpickr(filterDivInputElm, this._flatpickrOptions as unknown as Partial);
return filterDivInputElm;
diff --git a/packages/common/src/filters/filterUtilities.ts b/packages/common/src/filters/filterUtilities.ts
index 35dddd389..9b0c7eec2 100644
--- a/packages/common/src/filters/filterUtilities.ts
+++ b/packages/common/src/filters/filterUtilities.ts
@@ -1,7 +1,7 @@
import { OperatorString } from '../enums/operatorString.type';
import { Column, GridOption } from '../interfaces/index';
import { Observable, RxJsFacade, Subject, Subscription } from '../services/rxjsFacade';
-import { htmlEncodedStringWithPadding, sanitizeTextByAvailableSanitizer, } from '../services/domUtilities';
+import { createDomElement, htmlEncodedStringWithPadding, sanitizeTextByAvailableSanitizer, } from '../services/domUtilities';
import { castObservableToPromise, getDescendantProperty, } from '../services/utilities';
/**
@@ -10,14 +10,15 @@ import { castObservableToPromise, getDescendantProperty, } from '../services/uti
* @returns {Object} selectElm - Select Dropdown HTML Element
*/
export function buildSelectOperator(optionValues: Array<{ operator: OperatorString, description: string }>, gridOptions: GridOption): HTMLSelectElement {
- const selectElm = document.createElement('select');
- selectElm.className = 'form-control';
+ const selectElm = createDomElement('select', { className: 'form-control' });
for (const option of optionValues) {
- const selectOption = document.createElement('option');
- selectOption.value = option.operator;
- selectOption.innerHTML = sanitizeTextByAvailableSanitizer(gridOptions, `${htmlEncodedStringWithPadding(option.operator, 3)}${option.description}`);
- selectElm.appendChild(selectOption);
+ selectElm.appendChild(
+ createDomElement('option', {
+ value: option.operator,
+ innerHTML: sanitizeTextByAvailableSanitizer(gridOptions, `${htmlEncodedStringWithPadding(option.operator, 3)}${option.description}`)
+ })
+ );
}
return selectElm;
diff --git a/packages/common/src/filters/inputFilter.ts b/packages/common/src/filters/inputFilter.ts
index b1d3642c5..7e37b9b49 100644
--- a/packages/common/src/filters/inputFilter.ts
+++ b/packages/common/src/filters/inputFilter.ts
@@ -9,7 +9,7 @@ import {
} from '../interfaces/index';
import { OperatorType, OperatorString, SearchTerm } from '../enums/index';
import { BindingEventService } from '../services/bindingEvent.service';
-import { emptyElement, toSentenceCase } from '../services';
+import { createDomElement, emptyElement, toSentenceCase } from '../services';
export class InputFilter implements Filter {
protected _bindEventService: BindingEventService;
@@ -195,16 +195,16 @@ export class InputFilter implements Filter {
placeholder = this.columnFilter.placeholder;
}
- const inputElm = document.createElement('input');
- inputElm.type = this._inputType || 'text';
- inputElm.className = `form-control search-filter filter-${columnId}`;
- inputElm.autocomplete = 'off';
- inputElm.placeholder = placeholder;
+ const inputElm = createDomElement('input', {
+ type: this._inputType || 'text',
+ autocomplete: 'off', placeholder,
+ className: `form-control search-filter filter-${columnId}`,
+ value: (searchTerm ?? '') as string,
+ dataset: { columnid: `${columnId}` }
+ });
inputElm.setAttribute('aria-label', this.columnFilter?.ariaLabel ?? `${toSentenceCase(columnId + '')} Search Filter`);
inputElm.setAttribute('role', 'presentation');
- inputElm.value = (searchTerm ?? '') as string;
- inputElm.dataset.columnid = `${columnId}`;
// if there's a search term, we will add the "filled" class for styling purposes
if (searchTerm) {
diff --git a/packages/common/src/filters/nativeSelectFilter.ts b/packages/common/src/filters/nativeSelectFilter.ts
index 993d42bc2..49dd8cc35 100644
--- a/packages/common/src/filters/nativeSelectFilter.ts
+++ b/packages/common/src/filters/nativeSelectFilter.ts
@@ -8,7 +8,7 @@ import {
SlickGrid,
} from '../interfaces/index';
import { OperatorType, OperatorString, SearchTerm } from '../enums/index';
-import { emptyElement, } from '../services/domUtilities';
+import { createDomElement, emptyElement, } from '../services/domUtilities';
import { toSentenceCase } from '../services/utilities';
import { TranslaterService } from '../services/translater.service';
import { BindingEventService } from '../services/bindingEvent.service';
@@ -146,9 +146,8 @@ export class NativeSelectFilter implements Filter {
*/
buildFilterSelectFromCollection(collection: any[]): HTMLSelectElement {
const columnId = this.columnDef?.id ?? '';
- const selectElm = document.createElement('select');
+ const selectElm = createDomElement('select', { className: `form-control search-filter filter-${columnId}` });
selectElm.setAttribute('aria-label', this.columnFilter?.ariaLabel ?? `${toSentenceCase(columnId + '')} Search Filter`);
- selectElm.className = `form-control search-filter filter-${columnId}`;
const labelName = this.columnFilter.customStructure?.label ?? 'label';
const valueName = this.columnFilter.customStructure?.value ?? 'value';
@@ -157,11 +156,9 @@ export class NativeSelectFilter implements Filter {
// collection could be an Array of Strings OR Objects
if (collection.every(x => typeof x === 'string')) {
for (const option of collection) {
- const selectOption = document.createElement('option');
- selectOption.value = option;
- selectOption.label = option;
- selectOption.textContent = option;
- selectElm.appendChild(selectOption);
+ selectElm.appendChild(
+ createDomElement('option', { value: option, label: option, textContent: option })
+ );
}
} else {
for (const option of collection) {
@@ -172,10 +169,9 @@ export class NativeSelectFilter implements Filter {
const labelKey = option.labelKey || option[labelName];
const textLabel = ((option.labelKey || isEnabledTranslate) && this.translater && this.translater.translate && this.translater.getCurrentLanguage && this.translater.getCurrentLanguage()) ? this.translater.translate(labelKey || ' ') : labelKey;
- const selectOption = document.createElement('option');
- selectOption.value = option[valueName];
- selectOption.textContent = textLabel;
- selectElm.appendChild(selectOption);
+ selectElm.appendChild(
+ createDomElement('option', { value: option[valueName], textContent: textLabel })
+ );
}
}
diff --git a/packages/common/src/filters/sliderFilter.ts b/packages/common/src/filters/sliderFilter.ts
index 5795e135d..cfff81b95 100644
--- a/packages/common/src/filters/sliderFilter.ts
+++ b/packages/common/src/filters/sliderFilter.ts
@@ -7,7 +7,7 @@ import {
FilterCallback,
SlickGrid,
} from './../interfaces/index';
-import { emptyElement, } from '../services/domUtilities';
+import { createDomElement, emptyElement, } from '../services/domUtilities';
import { hasData, toSentenceCase } from '../services/utilities';
import { BindingEventService } from '../services/bindingEvent.service';
@@ -194,31 +194,23 @@ export class SliderFilter implements Filter {
this._currentValue = +searchTermInput;
// create the DOM element
- this.filterInputElm = document.createElement('input');
- this.filterInputElm.type = 'range';
- this.filterInputElm.className = `form-control slider-filter-input range ${this._elementRangeInputId}`;
- this.filterInputElm.defaultValue = defaultValue;
- this.filterInputElm.value = searchTermInput;
- this.filterInputElm.min = `${minValue}`;
- this.filterInputElm.max = `${maxValue}`;
- this.filterInputElm.step = `${step}`;
- this.filterInputElm.name = this._elementRangeInputId;
+ this.filterInputElm = createDomElement('input', {
+ type: 'range', name: this._elementRangeInputId,
+ className: `form-control slider-filter-input range ${this._elementRangeInputId}`,
+ defaultValue, value: searchTermInput,
+ min: `${minValue}`, max: `${maxValue}`, step: `${step}`,
+ });
this.filterInputElm.setAttribute('aria-label', this.columnFilter?.ariaLabel ?? `${toSentenceCase(columnId + '')} Search Filter`);
- this.divContainerFilterElm = document.createElement('div');
- this.divContainerFilterElm.className = `search-filter slider-container filter-${columnId}`;
+ this.divContainerFilterElm = createDomElement('div', { className: `search-filter slider-container filter-${columnId}` });
this.divContainerFilterElm.appendChild(this.filterInputElm);
if (!this.filterParams.hideSliderNumber) {
this.divContainerFilterElm.classList.add('input-group');
this.filterInputElm.value = searchTermInput;
- const divGroupAppendElm = document.createElement('div');
- divGroupAppendElm.className = 'input-group-addon input-group-append slider-value';
-
- this.filterNumberElm = document.createElement('span');
- this.filterNumberElm.className = `input-group-text ${this._elementRangeOutputId}`;
- this.filterNumberElm.textContent = searchTermInput;
+ const divGroupAppendElm = createDomElement('div', { className: 'input-group-addon input-group-append slider-value' });
+ this.filterNumberElm = createDomElement('span', { className: `input-group-text ${this._elementRangeOutputId}`, textContent: searchTermInput });
divGroupAppendElm.appendChild(this.filterNumberElm);
this.divContainerFilterElm.appendChild(divGroupAppendElm);
}
diff --git a/packages/common/src/interfaces/slickEventHandler.interface.ts b/packages/common/src/interfaces/slickEventHandler.interface.ts
index b7662821e..5bec376f3 100644
--- a/packages/common/src/interfaces/slickEventHandler.interface.ts
+++ b/packages/common/src/interfaces/slickEventHandler.interface.ts
@@ -1,18 +1,6 @@
import { SlickEvent, SlickEventData } from './index';
-/**
- * TypeScript Helper to get the Generic Type T of the SlickEvent
- * for example GetType> will return { columnDef: Column }
- */
-/* eslint-disable @typescript-eslint/indent */
-// disable eslint indent rule until this issue is fixed: https://github.com/typescript-eslint/typescript-eslint/issues/1824
-export type GetSlickEventType =
- T extends (infer U)[] ? U :
- T extends (...args: any[]) => infer U ? U :
- T extends SlickEvent ? U : T;
-/* eslint-enable @typescript-eslint/indent */
-
-type Handler = (e: SlickEventData, data: H) => void
+type Handler = (e: SlickEventData, data: H) => void;
export interface SlickEventHandler {
/** Subscribe to a SlickGrid Event and execute its handler callback */
diff --git a/packages/common/src/services/__tests__/utilities.spec.ts b/packages/common/src/services/__tests__/utilities.spec.ts
index 424ad563e..0d03cc9ac 100644
--- a/packages/common/src/services/__tests__/utilities.spec.ts
+++ b/packages/common/src/services/__tests__/utilities.spec.ts
@@ -1,3 +1,4 @@
+import 'jest-extended';
import { of } from 'rxjs';
import { FieldType, OperatorType } from '../../enums/index';
@@ -9,6 +10,7 @@ import {
addWhiteSpaces,
arrayRemoveItemByIndex,
cancellablePromise,
+ CancelledException,
castObservableToPromise,
flattenToParentChildArray,
unflattenParentChildArrayToTree,
@@ -29,6 +31,7 @@ import {
mapOperatorByFieldType,
mapOperatorToShorthandDesignation,
mapOperatorType,
+ mergeDeep,
parseBoolean,
parseUtcDate,
removeAccentFromText,
@@ -42,7 +45,6 @@ import {
unsubscribeAll,
uniqueArray,
uniqueObjectArray,
- CancelledException,
} from '../utilities';
describe('Service/Utilies', () => {
@@ -1200,6 +1202,32 @@ describe('Service/Utilies', () => {
});
});
+ describe('mergeDeep method', () => {
+ it('should have undefined object when input object is also undefined', () => {
+ const inputObj = undefined;
+ mergeDeep(inputObj, { firstName: 'John' });
+ expect(inputObj).toEqual(undefined);
+ });
+
+ it('should provide empty object as input and expect output object to include 2nd object', () => {
+ const inputObj = {};
+ mergeDeep(inputObj, { firstName: 'John' });
+ expect(inputObj).toEqual({ firstName: 'John' });
+ });
+
+ it('should provide filled object and return same object when 2nd object is also an object', () => {
+ const inputObj = { firstName: 'Jane' };
+ mergeDeep(inputObj, { firstName: { name: 'John' } });
+ expect(inputObj).toEqual({ firstName: 'Jane' });
+ });
+
+ it('should provide input object with undefined property and expect output object to return merged object from 2nd object when that one is filled', () => {
+ const inputObj = { firstName: undefined };
+ mergeDeep(inputObj, { firstName: {} });
+ expect(inputObj).toEqual({ firstName: {} });
+ });
+ });
+
describe('parseBoolean method', () => {
it('should return false when input value is not parseable to a boolean', () => {
const output = parseBoolean('abc');
diff --git a/packages/common/src/services/domUtilities.ts b/packages/common/src/services/domUtilities.ts
index d6fee9af6..ae614afb5 100644
--- a/packages/common/src/services/domUtilities.ts
+++ b/packages/common/src/services/domUtilities.ts
@@ -1,9 +1,10 @@
import * as DOMPurify_ from 'dompurify';
const DOMPurify = DOMPurify_; // patch to fix rollup to work
-import { SearchTerm } from '../enums/index';
+import { InferType, SearchTerm } from '../enums/index';
import { Column, GridOption, HtmlElementPosition, SelectOption, SlickGrid, } from '../interfaces/index';
import { TranslaterService } from './translater.service';
+import { mergeDeep } from './utilities';
/**
* Create the HTML DOM Element for a Select Editor or Filter, this is specific to these 2 types only and the unit tests are directly under them
@@ -155,6 +156,22 @@ export function calculateAvailableSpace(element: HTMLElement): { top: number; bo
return { top, bottom, left, right };
}
+/** Create a DOM Element with any optional attributes or properties */
+export function createDomElement(tagName: T, elementOptions?: { [P in K]: InferType }): HTMLElementTagNameMap[T] {
+ const elm = document.createElement(tagName);
+
+ if (elementOptions) {
+ Object.keys(elementOptions).forEach((elmOptionKey) => {
+ const elmValue = (elementOptions as any)[elmOptionKey];
+ if (typeof elmValue === 'object') {
+ mergeDeep(elm[elmOptionKey as K], elmValue);
+ } else {
+ elm[elmOptionKey as K] = (elementOptions as any)[elmOptionKey];
+ }
+ });
+ }
+ return elm;
+}
/**
* Loop through all properties of an object and nullify any properties that are instanceof HTMLElement,
diff --git a/packages/common/src/services/groupingAndColspan.service.ts b/packages/common/src/services/groupingAndColspan.service.ts
index 91ce2d5a5..0ca65972c 100644
--- a/packages/common/src/services/groupingAndColspan.service.ts
+++ b/packages/common/src/services/groupingAndColspan.service.ts
@@ -10,7 +10,7 @@ import {
} from './../interfaces/index';
import { ExtensionUtility } from '../extensions/extensionUtility';
import { PubSubService } from './pubSub.service';
-import { emptyElement } from './domUtilities';
+import { createDomElement, emptyElement } from './domUtilities';
// using external non-typed js libraries
declare const Slick: SlickNamespace;
@@ -154,13 +154,10 @@ export class GroupingAndColspanService {
}
} else {
widthTotal = colDef.width || 0;
- headerElm = document.createElement('div');
- headerElm.className = `ui-state-default slick-header-column ${isFrozenGrid ? 'frozen' : ''}`;
+ headerElm = createDomElement('div', { className: `ui-state-default slick-header-column ${isFrozenGrid ? 'frozen' : ''}` });
headerElm.style.width = `${widthTotal - headerColumnWidthDiff}px`;
- const spanColumnNameElm = document.createElement('span');
- spanColumnNameElm.className = 'slick-column-name';
- spanColumnNameElm.textContent = colDef.columnGroup || '';
+ const spanColumnNameElm = createDomElement('span', { className: 'slick-column-name', textContent: colDef.columnGroup || '' });
headerElm.appendChild(spanColumnNameElm);
preHeaderPanel.appendChild(headerElm);
diff --git a/packages/common/src/services/utilities.ts b/packages/common/src/services/utilities.ts
index 7c4e0ef84..6c184c3bc 100644
--- a/packages/common/src/services/utilities.ts
+++ b/packages/common/src/services/utilities.ts
@@ -279,6 +279,15 @@ export function isEmptyObject(obj: any): boolean {
return Object.entries(obj).length === 0;
}
+/**
+ * Simple object check.
+ * @param item
+ * @returns {boolean}
+ */
+export function isObject(item: any) {
+ return (item && typeof item === 'object' && !Array.isArray(item));
+}
+
/**
* @deprecated use `findItemInTreeStructure()` instead. Find an item from a hierarchical (tree) view structure (a parent that can have children array which themseleves can children and so on)
* @param treeArray
@@ -826,6 +835,33 @@ export function mapOperatorByFieldType(fieldType: typeof FieldType[keyof typeof
return map;
}
+/**
+ * Deep merge two objects.
+ * @param {*} target
+ * @param {*} ...sources
+ */
+export function mergeDeep(target: any, ...sources: any[]): any {
+ if (!sources.length) {
+ return target;
+ }
+ const source = sources.shift();
+
+ if (isObject(target) && isObject(source)) {
+ for (const key in source) {
+ if (isObject(source[key])) {
+ if (!target[key]) {
+ Object.assign(target, { [key]: {} });
+ }
+ mergeDeep(target[key], source[key]);
+ } else {
+ Object.assign(target, { [key]: source[key] });
+ }
+ }
+ }
+
+ return mergeDeep(target, ...sources);
+}
+
/**
* Takes an object and allow to provide a property key to omit from the original object
* @param {Object} obj - input object
diff --git a/packages/composite-editor-component/src/slick-composite-editor.component.ts b/packages/composite-editor-component/src/slick-composite-editor.component.ts
index 78db2255f..d95cefde1 100644
--- a/packages/composite-editor-component/src/slick-composite-editor.component.ts
+++ b/packages/composite-editor-component/src/slick-composite-editor.component.ts
@@ -10,6 +10,7 @@ import {
CompositeEditorOption,
Constants,
ContainerService,
+ createDomElement,
CurrentRowSelection,
deepCopy,
DOMEvent,
@@ -359,55 +360,45 @@ export class SlickCompositeEditorComponent implements ExternalResource {
const parsedHeaderTitle = headerTitle.replace(/\{\{(.*?)\}\}/g, (_match, group) => getDescendantProperty(dataContext, group));
const layoutColCount = viewColumnLayout === 'auto' ? this.autoCalculateLayoutColumnCount(modalColumns.length) : viewColumnLayout;
- this._modalElm = document.createElement('div');
- this._modalElm.className = `slick-editor-modal ${gridUid}`;
-
- const modalContentElm = document.createElement('div');
- modalContentElm.className = 'slick-editor-modal-content';
+ this._modalElm = createDomElement('div', { className: `slick-editor-modal ${gridUid}` });
+ const modalContentElm = createDomElement('div', { className: 'slick-editor-modal-content' });
if (viewColumnLayout > 1 || (viewColumnLayout === 'auto' && layoutColCount > 1)) {
const splitClassName = layoutColCount === 2 ? 'split-view' : 'triple-split-view';
modalContentElm.classList.add(splitClassName);
}
- const modalHeaderTitleElm = document.createElement('div');
- modalHeaderTitleElm.className = 'slick-editor-modal-title';
- modalHeaderTitleElm.innerHTML = sanitizeTextByAvailableSanitizer(this.gridOptions, parsedHeaderTitle);
-
- const modalCloseButtonElm = document.createElement('button');
- modalCloseButtonElm.type = 'button';
- modalCloseButtonElm.textContent = '×';
- modalCloseButtonElm.className = 'close';
- modalCloseButtonElm.dataset.action = 'close';
+ const modalHeaderTitleElm = createDomElement('div', {
+ className: 'slick-editor-modal-title',
+ innerHTML: sanitizeTextByAvailableSanitizer(this.gridOptions, parsedHeaderTitle),
+ });
+ const modalCloseButtonElm = createDomElement('button', { type: 'button', textContent: '×', className: 'close', dataset: { action: 'close' } });
modalCloseButtonElm.setAttribute('aria-label', 'Close');
if (this._options.showCloseButtonOutside) {
modalHeaderTitleElm?.classList?.add('outside');
modalCloseButtonElm?.classList?.add('outside');
}
- const modalHeaderElm = document.createElement('div');
- modalHeaderElm.className = 'slick-editor-modal-header';
+ const modalHeaderElm = createDomElement('div', { className: 'slick-editor-modal-header' });
modalHeaderElm.setAttribute('aria-label', 'Close');
modalHeaderElm.appendChild(modalHeaderTitleElm);
modalHeaderElm.appendChild(modalCloseButtonElm);
- const modalBodyElm = document.createElement('div');
- modalBodyElm.className = 'slick-editor-modal-body';
+ const modalBodyElm = createDomElement('div', { className: 'slick-editor-modal-body' });
- this._modalBodyTopValidationElm = document.createElement('div');
- this._modalBodyTopValidationElm.className = 'validation-summary';
+ this._modalBodyTopValidationElm = createDomElement('div', { className: 'validation-summary' });
this._modalBodyTopValidationElm.style.display = 'none';
modalBodyElm.appendChild(this._modalBodyTopValidationElm);
- const modalFooterElm = document.createElement('div');
- modalFooterElm.className = 'slick-editor-modal-footer';
+ const modalFooterElm = createDomElement('div', { className: 'slick-editor-modal-footer' });
- const modalCancelButtonElm = document.createElement('button');
- modalCancelButtonElm.type = 'button';
- modalCancelButtonElm.className = 'btn btn-cancel btn-default btn-sm';
- modalCancelButtonElm.dataset.action = 'cancel';
+ const modalCancelButtonElm = createDomElement('button', {
+ type: 'button',
+ className: 'btn btn-cancel btn-default btn-sm',
+ textContent: this.getLabelText('cancelButton', 'TEXT_CANCEL', 'Cancel'),
+ dataset: { action: 'cancel' },
+ });
modalCancelButtonElm.setAttribute('aria-label', this.getLabelText('cancelButton', 'TEXT_CANCEL', 'Cancel'));
- modalCancelButtonElm.textContent = this.getLabelText('cancelButton', 'TEXT_CANCEL', 'Cancel');
let leftFooterText = '';
let saveButtonText = '';
@@ -429,20 +420,18 @@ export class SlickCompositeEditorComponent implements ExternalResource {
saveButtonText = this.getLabelText('saveButton', 'TEXT_SAVE', 'Save');
}
- const selectionCounterElm = document.createElement('div');
- selectionCounterElm.className = 'footer-status-text';
- selectionCounterElm.textContent = leftFooterText;
-
- this._modalSaveButtonElm = document.createElement('button');
- this._modalSaveButtonElm.type = 'button';
- this._modalSaveButtonElm.className = 'btn btn-save btn-primary btn-sm';
- this._modalSaveButtonElm.dataset.action = (modalType === 'create' || modalType === 'edit') ? 'save' : modalType;
- this._modalSaveButtonElm.dataset.ariaLabel = saveButtonText;
- this._modalSaveButtonElm.textContent = saveButtonText;
+ const selectionCounterElm = createDomElement('div', { className: 'footer-status-text', textContent: leftFooterText });
+ this._modalSaveButtonElm = createDomElement('button', {
+ type: 'button', className: 'btn btn-save btn-primary btn-sm',
+ textContent: saveButtonText,
+ dataset: {
+ action: (modalType === 'create' || modalType === 'edit') ? 'save' : modalType,
+ ariaLabel: saveButtonText
+ }
+ });
this._modalSaveButtonElm.setAttribute('aria-label', saveButtonText);
- const footerContainerElm = document.createElement('div');
- footerContainerElm.className = 'footer-buttons';
+ const footerContainerElm = createDomElement('div', { className: 'footer-buttons' });
if (modalType === 'mass-update' || modalType === 'mass-selection') {
modalFooterElm.appendChild(selectionCounterElm);
@@ -458,8 +447,7 @@ export class SlickCompositeEditorComponent implements ExternalResource {
for (const columnDef of modalColumns) {
if (columnDef.editor) {
- const itemContainer = document.createElement('div');
- itemContainer.className = `item-details-container editor-${columnDef.id}`;
+ const itemContainer = createDomElement('div', { className: `item-details-container editor-${columnDef.id}` });
if (layoutColCount === 1) {
itemContainer.classList.add('slick-col-medium-12');
@@ -467,16 +455,15 @@ export class SlickCompositeEditorComponent implements ExternalResource {
itemContainer.classList.add('slick-col-medium-6', `slick-col-xlarge-${12 / layoutColCount}`);
}
- const templateItemLabelElm = document.createElement('div');
- templateItemLabelElm.className = `item-details-label editor-${columnDef.id}`;
- templateItemLabelElm.textContent = this.getColumnLabel(columnDef) || 'n/a';
-
- const templateItemEditorElm = document.createElement('div');
- templateItemEditorElm.className = 'item-details-editor-container slick-cell';
- templateItemEditorElm.dataset.editorid = `${columnDef.id}`;
-
- const templateItemValidationElm = document.createElement('div');
- templateItemValidationElm.className = `item-details-validation editor-${columnDef.id}`;
+ const templateItemLabelElm = createDomElement('div', {
+ className: `item-details-label editor-${columnDef.id}`,
+ textContent: this.getColumnLabel(columnDef) || 'n/a'
+ });
+ const templateItemEditorElm = createDomElement('div', {
+ className: 'item-details-editor-container slick-cell',
+ dataset: { editorid: `${columnDef.id}` },
+ });
+ const templateItemValidationElm = createDomElement('div', { className: `item-details-validation editor-${columnDef.id}` });
// optionally add a reset button beside each editor
if (this._options?.showResetButtonOnEachEditor) {
@@ -643,11 +630,11 @@ export class SlickCompositeEditorComponent implements ExternalResource {
* @returns {Object} - html button
*/
protected createEditorResetButtonElement(columnId: string): HTMLButtonElement {
- const resetButtonElm = document.createElement('button');
- resetButtonElm.type = 'button';
- resetButtonElm.name = columnId;
- resetButtonElm.title = this._options?.labels?.resetFormButton ?? 'Reset Form Input';
- resetButtonElm.className = 'btn btn-xs btn-editor-reset';
+ const resetButtonElm = createDomElement('button', {
+ type: 'button', name: columnId,
+ title: this._options?.labels?.resetFormButton ?? 'Reset Form Input',
+ className: 'btn btn-xs btn-editor-reset'
+ });
resetButtonElm.setAttribute('aria-label', 'Reset');
if (this._options?.resetEditorButtonCssClass) {
@@ -666,15 +653,9 @@ export class SlickCompositeEditorComponent implements ExternalResource {
* @returns {Object} - html button
*/
protected createFormResetButtonElement(): HTMLDivElement {
- const resetButtonContainerElm = document.createElement('div');
- resetButtonContainerElm.className = 'reset-container';
-
- const resetButtonElm = document.createElement('button');
- resetButtonElm.type = 'button';
- resetButtonElm.className = 'btn btn-sm reset-form';
-
- const resetIconSpanElm = document.createElement('span');
- resetIconSpanElm.className = this._options?.resetFormButtonIconCssClass ?? '';
+ const resetButtonContainerElm = createDomElement('div', { className: 'reset-container' });
+ const resetButtonElm = createDomElement('button', { type: 'button', className: 'btn btn-sm reset-form' });
+ const resetIconSpanElm = createDomElement('span', { className: this._options?.resetFormButtonIconCssClass ?? '' });
resetButtonElm.appendChild(resetIconSpanElm);
resetButtonElm.appendChild(document.createTextNode(' Reset Form'));
resetButtonContainerElm.appendChild(resetButtonElm);
diff --git a/packages/custom-footer-component/src/slick-footer.component.ts b/packages/custom-footer-component/src/slick-footer.component.ts
index 2fb14cbe7..24bc8293e 100644
--- a/packages/custom-footer-component/src/slick-footer.component.ts
+++ b/packages/custom-footer-component/src/slick-footer.component.ts
@@ -3,6 +3,7 @@ const moment = (moment_ as any)['default'] || moment_; // patch to fix rollup "m
import {
Constants,
+ createDomElement,
CustomFooterOption,
GridOption,
Locale,
@@ -169,19 +170,17 @@ export class SlickFooterComponent {
/** Create the Footer Container */
protected createFooterContainer(gridParentContainerElm: HTMLElement) {
- const footerElm = document.createElement('div');
- footerElm.className = `slick-custom-footer ${this.gridUid}`;
+ const footerElm = createDomElement('div', { className: `slick-custom-footer ${this.gridUid}` });
footerElm.style.width = '100%';
footerElm.style.height = `${this.customFooterOptions.footerHeight || 20}px`;
- const leftFooterElm = document.createElement('div');
- leftFooterElm.className = `left-footer ${this.customFooterOptions.leftContainerClass}`;
- leftFooterElm.innerHTML = sanitizeTextByAvailableSanitizer(this.gridOptions, this.customFooterOptions.leftFooterText || '');
-
- const rightFooterElm = this.createFooterRightContainer();
-
- footerElm.appendChild(leftFooterElm);
- footerElm.appendChild(rightFooterElm);
+ footerElm.appendChild(
+ createDomElement('div', {
+ className: `left-footer ${this.customFooterOptions.leftContainerClass}`,
+ innerHTML: sanitizeTextByAvailableSanitizer(this.gridOptions, this.customFooterOptions.leftFooterText || '')
+ })
+ );
+ footerElm.appendChild(this.createFooterRightContainer());
this._footerElement = footerElm;
if (gridParentContainerElm?.appendChild && this._footerElement) {
@@ -191,15 +190,13 @@ export class SlickFooterComponent {
/** Create the Right Section Footer */
protected createFooterRightContainer(): HTMLDivElement {
- const rightFooterElm = document.createElement('div');
- rightFooterElm.className = `right-footer ${this.customFooterOptions.rightContainerClass || ''}`;
+ const rightFooterElm = createDomElement('div', { className: `right-footer ${this.customFooterOptions.rightContainerClass || ''}` });
if (!this._isRightFooterOriginallyEmpty) {
rightFooterElm.innerHTML = sanitizeTextByAvailableSanitizer(this.gridOptions, this.customFooterOptions.rightFooterText || '');
} else if (!this.customFooterOptions.hideMetrics) {
rightFooterElm.classList.add('metrics');
- const lastUpdateElm = document.createElement('span');
- lastUpdateElm.className = 'timestamp';
+ const lastUpdateElm = createDomElement('span', { className: 'timestamp' });
if (!this.customFooterOptions.hideLastUpdateTimestamp) {
const footerLastUpdateElm = this.createFooterLastUpdate();
@@ -208,41 +205,32 @@ export class SlickFooterComponent {
}
}
- const itemCountElm = document.createElement('span');
- itemCountElm.className = 'item-count';
- itemCountElm.textContent = `${this.metrics?.itemCount ?? '0'}`;
-
// last update elements
rightFooterElm.appendChild(lastUpdateElm);
- rightFooterElm.appendChild(itemCountElm);
+ rightFooterElm.appendChild(
+ createDomElement('span', { className: 'item-count', textContent: `${this.metrics?.itemCount ?? '0'}` })
+ );
// total count element (unless hidden)
if (!this.customFooterOptions.hideTotalItemCount) {
// add carriage return which will add a space before the span
rightFooterElm.appendChild(document.createTextNode('\r\n'));
-
- const textOfElm = document.createElement('span');
- textOfElm.className = 'text-of';
- textOfElm.textContent = ` ${this.customFooterOptions.metricTexts?.of ?? 'of'} `;
- rightFooterElm.appendChild(textOfElm);
+ rightFooterElm.appendChild(
+ createDomElement('span', { className: 'text-of', textContent: ` ${this.customFooterOptions.metricTexts?.of ?? 'of'} ` })
+ );
// add another carriage return which will add a space after the span
rightFooterElm.appendChild(document.createTextNode('\r\n'));
-
- const totalCountElm = document.createElement('span');
- totalCountElm.className = 'total-count';
- totalCountElm.textContent = `${this.metrics?.totalItemCount ?? '0'}`;
-
- rightFooterElm.appendChild(totalCountElm);
+ rightFooterElm.appendChild(
+ createDomElement('span', { className: 'total-count', textContent: `${this.metrics?.totalItemCount ?? '0'}` })
+ );
}
// add carriage return which will add a space before the span
rightFooterElm.appendChild(document.createTextNode('\r\n'));
-
- const textItemsElm = document.createElement('span');
- textItemsElm.className = 'text-items';
- textItemsElm.textContent = ` ${this.customFooterOptions.metricTexts?.items ?? 'items'} `;
- rightFooterElm.appendChild(textItemsElm);
+ rightFooterElm.appendChild(
+ createDomElement('span', { className: 'text-items', textContent: ` ${this.customFooterOptions.metricTexts?.items ?? 'items'} ` })
+ );
}
return rightFooterElm;
@@ -253,24 +241,17 @@ export class SlickFooterComponent {
// get translated text & last timestamp
const lastUpdateText = this.customFooterOptions?.metricTexts?.lastUpdate ?? 'Last Update';
const lastUpdateTimestamp = moment(this.metrics?.endTime).format(this.customFooterOptions.dateFormat);
+ const lastUpdateContainerElm = createDomElement('span');
- const lastUpdateElm = document.createElement('span');
- lastUpdateElm.className = 'text-last-update';
- lastUpdateElm.textContent = lastUpdateText;
-
- const lastUpdateTimestampElm = document.createElement('span');
- lastUpdateTimestampElm.className = 'last-update-timestamp';
- lastUpdateTimestampElm.textContent = lastUpdateTimestamp;
-
- const separatorElm = document.createElement('span');
- separatorElm.className = 'separator';
- separatorElm.textContent = ` ${this.customFooterOptions.metricSeparator || ''} `;
-
- const lastUpdateContainerElm = document.createElement('span');
- lastUpdateContainerElm.appendChild(lastUpdateElm);
+ lastUpdateContainerElm.appendChild(
+ createDomElement('span', { className: 'text-last-update', textContent: lastUpdateText }));
lastUpdateContainerElm.appendChild(document.createTextNode('\r\n'));
- lastUpdateContainerElm.appendChild(lastUpdateTimestampElm);
- lastUpdateContainerElm.appendChild(separatorElm);
+ lastUpdateContainerElm.appendChild(
+ createDomElement('span', { className: 'last-update-timestamp', textContent: lastUpdateTimestamp })
+ );
+ lastUpdateContainerElm.appendChild(
+ createDomElement('span', { className: 'separator', textContent: ` ${this.customFooterOptions.metricSeparator || ''} ` })
+ );
return lastUpdateContainerElm;
}
diff --git a/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts b/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts
index 605a5b065..67370c58b 100644
--- a/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts
+++ b/packages/custom-tooltip-plugin/src/slickCustomTooltip.ts
@@ -5,6 +5,7 @@ import {
CancelledException,
Column,
ContainerService,
+ createDomElement,
CustomTooltipOption,
findFirstElementAttribute,
Formatter,
@@ -300,8 +301,7 @@ export class SlickCustomTooltip {
* also clear the "title" attribute from the grid div text content so that it won't show also as a 2nd browser tooltip
*/
protected renderRegularTooltip(formatterOrText: Formatter | string | undefined, cell: { row: number; cell: number; }, value: any, columnDef: Column, item: any) {
- const tmpDiv = document.createElement('div');
- tmpDiv.innerHTML = this.parseFormatterAndSanitize(formatterOrText, cell, value, columnDef, item);
+ const tmpDiv = createDomElement('div', { innerHTML: this.parseFormatterAndSanitize(formatterOrText, cell, value, columnDef, item) });
let tooltipText = columnDef?.toolTip ?? '';
let tmpTitleElm: HTMLDivElement | null | undefined;
@@ -338,8 +338,7 @@ export class SlickCustomTooltip {
protected renderTooltipFormatter(formatter: Formatter | string | undefined, cell: { row: number; cell: number; }, value: any, columnDef: Column, item: unknown, tooltipText?: string, inputTitleElm?: Element | null) {
// create the tooltip DOM element with the text returned by the Formatter
- this._tooltipElm = document.createElement('div');
- this._tooltipElm.className = this.className;
+ this._tooltipElm = createDomElement('div', { className: this.className });
this._tooltipElm.classList.add(this.gridUid);
this._tooltipElm.classList.add('l' + cell.cell);
this._tooltipElm.classList.add('r' + cell.cell);
diff --git a/packages/pagination-component/src/slick-pagination.component.ts b/packages/pagination-component/src/slick-pagination.component.ts
index 0a0f3ce22..899e8ebc2 100644
--- a/packages/pagination-component/src/slick-pagination.component.ts
+++ b/packages/pagination-component/src/slick-pagination.component.ts
@@ -1,5 +1,6 @@
import {
Constants,
+ createDomElement,
getTranslationPrefix,
GridOption,
Locale,
@@ -134,8 +135,7 @@ export class SlickPaginationComponent {
renderPagination(gridParentContainerElm: HTMLElement) {
const paginationElm = this.createPaginationContainer();
- const divNavContainerElm = document.createElement('div');
- divNavContainerElm.className = 'slick-pagination-nav';
+ const divNavContainerElm = createDomElement('div', { className: 'slick-pagination-nav' });
const leftNavigationElm = this.createPageNavigation('Page navigation', [
{ liClass: 'page-item seek-first', aClass: 'page-link icon-seek-first', ariaLabel: 'First Page' },
{ liClass: 'page-item seek-prev', aClass: 'page-link icon-seek-prev', ariaLabel: 'Previous Page' },
@@ -169,10 +169,9 @@ export class SlickPaginationComponent {
const selectElm = document.querySelector(`.${this.gridUid} .items-per-page`);
if (selectElm && Array.isArray(this.availablePageSizes)) {
for (const option of this.availablePageSizes) {
- const opt = document.createElement('option');
- opt.value = `${option}`;
- opt.text = `${option}`;
- selectElm.appendChild(opt);
+ selectElm.appendChild(
+ createDomElement('option', { value: `${option}`, text: `${option}` })
+ );
}
}
}
@@ -256,13 +255,10 @@ export class SlickPaginationComponent {
/** Create the Pagination Container */
protected createPaginationContainer() {
- const paginationContainerElm = document.createElement('div');
- paginationContainerElm.className = `slick-pagination-container ${this.gridUid} pager`;
- paginationContainerElm.id = 'pager';
+ const paginationContainerElm = createDomElement('div', { id: 'pager', className: `slick-pagination-container ${this.gridUid} pager` });
paginationContainerElm.style.width = '100%';
- const paginationElm = document.createElement('div');
- paginationElm.className = 'slick-pagination';
+ const paginationElm = createDomElement('div', { className: 'slick-pagination' });
paginationContainerElm.appendChild(paginationElm);
this._paginationElement = paginationContainerElm; // keep internal ref
@@ -270,16 +266,12 @@ export class SlickPaginationComponent {
}
protected createPageNavigation(navAriaLabel: string, liElements: Array<{ liClass: string, aClass: string, ariaLabel: string }>) {
- const navElm = document.createElement('nav');
- navElm.ariaLabel = navAriaLabel;
- const ulElm = document.createElement('ul');
- ulElm.className = 'pagination';
+ const navElm = createDomElement('nav', { ariaLabel: navAriaLabel });
+ const ulElm = createDomElement('ul', { className: 'pagination' });
for (const li of liElements) {
- const liElm = document.createElement('li');
- liElm.className = li.liClass;
- const aElm = document.createElement('a');
- aElm.className = li.aClass;
+ const liElm = createDomElement('li', { className: li.liClass });
+ const aElm = createDomElement('a', { className: li.aClass });
aElm.setAttribute('aria-label', li.ariaLabel);
liElm.appendChild(aElm);
ulElm.appendChild(liElm);
@@ -290,24 +282,16 @@ export class SlickPaginationComponent {
}
protected createPageNumberSection() {
- const divElm = document.createElement('div');
- divElm.className = 'slick-page-number';
- const spanTextPageElm = document.createElement('span');
- spanTextPageElm.className = 'text-page';
- spanTextPageElm.textContent = 'Page';
- const input = document.createElement('input');
- input.type = 'text';
- input.className = 'form-control page-number';
- input.dataset.test = 'page-number-input';
+ const divElm = createDomElement('div', { className: 'slick-page-number' });
+ const spanTextPageElm = createDomElement('span', { className: 'text-page', textContent: 'Page' });
+ const input = createDomElement('input', {
+ type: 'text', className: 'form-control page-number',
+ value: '1', size: 1,
+ dataset: { test: 'page-number-input' },
+ });
input.setAttribute('aria-label', 'Page Number');
- input.value = '1';
- input.size = 1;
- const spanTextOfElm = document.createElement('span');
- spanTextOfElm.className = 'text-of';
- spanTextOfElm.textContent = 'of';
- const spanPageCountElm = document.createElement('span');
- spanPageCountElm.className = 'page-count';
- spanPageCountElm.dataset.test = 'page-count';
+ const spanTextOfElm = createDomElement('span', { className: 'text-of', textContent: 'of' });
+ const spanPageCountElm = createDomElement('span', { className: 'page-count', dataset: { test: 'page-count' } });
divElm.appendChild(spanTextPageElm);
divElm.appendChild(document.createTextNode(' '));
divElm.appendChild(input);
@@ -320,38 +304,20 @@ export class SlickPaginationComponent {
}
protected createPaginationSettingsSection() {
- const spanContainerElm = document.createElement('span');
- spanContainerElm.className = 'slick-pagination-settings';
- const selectElm = document.createElement('select');
- selectElm.id = 'items-per-page-label';
- selectElm.className = 'items-per-page';
+ const spanContainerElm = createDomElement('span', { className: 'slick-pagination-settings' });
+ const selectElm = createDomElement('select', { id: 'items-per-page-label', className: 'items-per-page' });
selectElm.setAttribute('aria-label', 'Items per Page Select');
- const spanItemPerPageElm = document.createElement('span');
- spanItemPerPageElm.className = 'text-item-per-page';
- spanItemPerPageElm.textContent = 'items per page';
- const spanPaginationCount = document.createElement('span');
- spanPaginationCount.className = 'slick-pagination-count';
- const spanInfoFromToElm = document.createElement('span');
- spanInfoFromToElm.className = 'page-info-from-to';
- const spanItemFromElm = document.createElement('span');
- spanItemFromElm.className = 'item-from';
- spanItemFromElm.dataset.test = 'item-from';
+ const spanItemPerPageElm = createDomElement('span', { className: 'text-item-per-page', textContent: 'items per page' });
+ const spanPaginationCount = createDomElement('span', { className: 'slick-pagination-count' });
+ const spanInfoFromToElm = createDomElement('span', { className: 'page-info-from-to' });
+ const spanItemFromElm = createDomElement('span', { className: 'item-from', dataset: { test: 'item-from' } });
spanItemFromElm.setAttribute('aria-label', 'Page Item From');
- const spanItemToElm = document.createElement('span');
- spanItemToElm.className = 'item-to';
- spanItemToElm.dataset.test = 'item-to';
+ const spanItemToElm = createDomElement('span', { className: 'item-to', dataset: { test: 'item-to' } });
spanItemToElm.setAttribute('aria-label', 'Page Item To');
- const spanOfElm = document.createElement('span');
- spanOfElm.className = 'text-of';
- spanOfElm.textContent = 'of';
- const spanInfoTotalElm = document.createElement('span');
- spanInfoTotalElm.className = 'page-info-total-items';
- const spanTotalItem = document.createElement('span');
- spanTotalItem.className = 'total-items';
- spanTotalItem.dataset.test = 'total-items';
- const spanTextItemsElm = document.createElement('span');
- spanTextItemsElm.className = 'text-items';
- spanTextItemsElm.textContent = 'items';
+ const spanOfElm = createDomElement('span', { className: 'text-of', textContent: 'of' });
+ const spanInfoTotalElm = createDomElement('span', { className: 'page-info-total-items' });
+ const spanTotalItem = createDomElement('span', { className: 'total-items', dataset: { test: 'total-items' } });
+ const spanTextItemsElm = createDomElement('span', { className: 'text-items', textContent: 'items' });
spanContainerElm.appendChild(selectElm);
spanContainerElm.appendChild(document.createTextNode(' '));