Skip to content

Commit

Permalink
refactor: add new createDomElement utility
Browse files Browse the repository at this point in the history
- makes it simpler to create & add options to a created DOM element, it also does proper inference
  • Loading branch information
ghiscoding committed Nov 12, 2021
1 parent 5d81644 commit ec8e46a
Show file tree
Hide file tree
Showing 37 changed files with 473 additions and 579 deletions.
12 changes: 6 additions & 6 deletions packages/common/src/editors/checkboxEditor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Constants } from './../constants';
import { Column, ColumnEditor, CompositeEditorOption, Editor, EditorArguments, EditorValidator, EditorValidationResult, GridOption, SlickGrid, SlickNamespace } from './../interfaces/index';
import { createDomElement } from '../services/domUtilities';
import { getDescendantProperty, setDeepValue, toSentenceCase } from '../services/utilities';
import { BindingEventService } from '../services/bindingEvent.service';

Expand Down Expand Up @@ -67,17 +68,16 @@ export class CheckboxEditor implements Editor {

init(): void {
const columnId = this.columnDef?.id ?? '';
const title = this.columnEditor?.title ?? '';
const compositeEditorOptions = this.args.compositeEditorOptions;

this._checkboxContainerElm = document.createElement('div');
this._checkboxContainerElm.className = `checkbox-editor-container editor-${columnId}`;

this._input = document.createElement('input');
this._input.className = `editor-checkbox editor-${columnId}`;
this._input.title = title;
this._input.type = 'checkbox';
this._input.value = 'true';
this._input = createDomElement('input', {
type: 'checkbox', value: 'true',
className: `editor-checkbox editor-${columnId}`,
title: this.columnEditor?.title ?? '',
});
this._input.setAttribute('aria-label', this.columnEditor?.ariaLabel ?? `${toSentenceCase(columnId + '')} Checkbox Editor`);

const cellContainer = this.args?.container;
Expand Down
29 changes: 10 additions & 19 deletions packages/common/src/editors/dateEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
SlickNamespace,
} from './../interfaces/index';
import {
createDomElement,
destroyObjectDomElementProps,
emptyElement,
} from '../services/domUtilities';
Expand Down Expand Up @@ -121,8 +122,6 @@ export class DateEditor implements Editor {
if (this.args && this.columnDef) {
const compositeEditorOptions = this.args.compositeEditorOptions;
const columnId = this.columnDef?.id ?? '';
const placeholder = this.columnEditor?.placeholder ?? '';
const title = this.columnEditor && this.columnEditor.title || '';
const gridOptions = (this.args.grid.getOptions() || {}) as GridOption;
this.defaultDate = (this.args.item) ? this.args.item[this.columnDef.field] : null;
const inputFormat = mapFlatpickrDateFormatWithFieldType(this.columnEditor.type || this.columnDef.type || FieldType.dateUtc);
Expand Down Expand Up @@ -158,23 +157,15 @@ export class DateEditor implements Editor {
this._pickerMergedOptions.altInputClass = 'flatpickr-alt-input form-control';
}

this._editorInputGroupElm = document.createElement('div');
this._editorInputGroupElm.className = 'flatpickr input-group';

const closeButtonGroupElm = document.createElement('span');
closeButtonGroupElm.className = 'input-group-btn input-group-append';
closeButtonGroupElm.dataset.clear = '';

this._closeButtonElm = document.createElement('button');
this._closeButtonElm.type = 'button';
this._closeButtonElm.className = 'btn btn-default icon-clear';

this._inputElm = document.createElement('input');
this._inputElm.dataset.input = '';
this._inputElm.dataset.defaultdate = this.defaultDate;
this._inputElm.className = inputCssClasses.replace(/\./g, ' ');
this._inputElm.placeholder = placeholder;
this._inputElm.title = title;
this._editorInputGroupElm = createDomElement('div', { className: 'flatpickr input-group' });
const closeButtonGroupElm = createDomElement('span', { className: 'input-group-btn input-group-append', dataset: { clear: '' } });
this._closeButtonElm = createDomElement('button', { type: 'button', className: 'btn btn-default icon-clear' });
this._inputElm = createDomElement('input', {
placeholder: this.columnEditor?.placeholder ?? '',
title: this.columnEditor && this.columnEditor.title || '',
className: inputCssClasses.replace(/\./g, ' '),
dataset: { input: '', defaultdate: this.defaultDate }
});

this._editorInputGroupElm.appendChild(this._inputElm);

Expand Down
21 changes: 12 additions & 9 deletions packages/common/src/editors/dualInputEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
import { getDescendantProperty, setDeepValue, toSentenceCase } from '../services/utilities';
import { floatValidator, integerValidator, textValidator } from '../editorValidators';
import { BindingEventService } from '../services/bindingEvent.service';
import { createDomElement } from '../services/domUtilities';

// using external non-typed js libraries
declare const Slick: SlickNamespace;
Expand Down Expand Up @@ -187,20 +188,22 @@ export class DualInputEditor implements Editor {
fieldType = 'number';
}

const input = document.createElement('input') as HTMLInputElement;
input.id = `item-${itemId}-${position}`;
input.className = `dual-editor-text editor-${columnId} ${position.replace(/input/gi, '')}`;
const input = createDomElement('input', {
type: fieldType || 'text',
id: `item-${itemId}-${position}`,
className: `dual-editor-text editor-${columnId} ${position.replace(/input/gi, '')}`,
autocomplete: 'off',
placeholder: editorSideParams.placeholder || '',
title: editorSideParams.title || '',
});
input.setAttribute('role', 'presentation');
input.setAttribute('aria-label', this.columnEditor?.ariaLabel ?? `${toSentenceCase(columnId + '')} Input Editor`);

if (fieldType === 'readonly') {
// when the custom type is defined as readonly, we'll make a readonly text input
input.readOnly = true;
fieldType = 'text';
}
input.type = fieldType || 'text';
input.setAttribute('role', 'presentation');
input.setAttribute('aria-label', this.columnEditor?.ariaLabel ?? `${toSentenceCase(columnId + '')} Input Editor`);
input.autocomplete = 'off';
input.placeholder = editorSideParams.placeholder || '';
input.title = editorSideParams.title || '';
if (fieldType === 'number') {
input.step = this.getInputDecimalSteps(position);
}
Expand Down
18 changes: 8 additions & 10 deletions packages/common/src/editors/floatEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { KeyCode } from '../enums/index';
import { EditorArguments, EditorValidationResult } from '../interfaces/index';
import { floatValidator } from '../editorValidators/floatValidator';
import { InputEditor } from './inputEditor';
import { createDomElement } from '../services/domUtilities';
import { getDescendantProperty, toSentenceCase } from '../services/utilities';

const DEFAULT_DECIMAL_PLACES = 0;
Expand All @@ -15,19 +16,16 @@ export class FloatEditor extends InputEditor {
init() {
if (this.columnDef && this.columnEditor && this.args) {
const columnId = this.columnDef?.id ?? '';
const placeholder = this.columnEditor?.placeholder ?? '';
const title = this.columnEditor?.title ?? '';
const inputStep = (this.columnEditor.valueStep !== undefined) ? this.columnEditor.valueStep : this.getInputDecimalSteps();
const compositeEditorOptions = this.args.compositeEditorOptions;

this._input = document.createElement('input') as HTMLInputElement;
this._input.className = `editor-text editor-${columnId}`;
this._input.type = 'number';
this._input = createDomElement('input', {
type: 'number', autocomplete: 'off',
className: `editor-text editor-${columnId}`,
placeholder: this.columnEditor?.placeholder ?? '',
title: this.columnEditor?.title ?? '',
step: `${(this.columnEditor.valueStep !== undefined) ? this.columnEditor.valueStep : this.getInputDecimalSteps()}`,
});
this._input.setAttribute('role', 'presentation');
this._input.autocomplete = 'off';
this._input.placeholder = placeholder;
this._input.title = title;
this._input.step = `${inputStep}`;
this._input.setAttribute('aria-label', this.columnEditor?.ariaLabel ?? `${toSentenceCase(columnId + '')} Number Editor`);
const cellContainer = this.args.container;
if (cellContainer && typeof cellContainer.appendChild === 'function') {
Expand Down
16 changes: 8 additions & 8 deletions packages/common/src/editors/inputEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Column, ColumnEditor, CompositeEditorOption, Editor, EditorArguments, E
import { getDescendantProperty, setDeepValue, toSentenceCase } from '../services/utilities';
import { textValidator } from '../editorValidators/textValidator';
import { BindingEventService } from '../services/bindingEvent.service';
import { createDomElement } from '../services/domUtilities';

// using external non-typed js libraries
declare const Slick: SlickNamespace;
Expand Down Expand Up @@ -81,17 +82,16 @@ export class InputEditor implements Editor {

init() {
const columnId = this.columnDef?.id ?? '';
const placeholder = this.columnEditor?.placeholder ?? '';
const title = this.columnEditor?.title ?? '';
const compositeEditorOptions = this.args.compositeEditorOptions;

this._input = document.createElement('input') as HTMLInputElement;
this._input.className = `editor-text editor-${columnId}`;
this._input.type = this._inputType || 'text';
this._input = createDomElement('input', {
type: this._inputType || 'text',
autocomplete: 'off',
placeholder: this.columnEditor?.placeholder ?? '',
title: this.columnEditor?.title ?? '',
className: `editor-text editor-${columnId}`,
});
this._input.setAttribute('role', 'presentation');
this._input.autocomplete = 'off';
this._input.placeholder = placeholder;
this._input.title = title;
this._input.setAttribute('aria-label', this.columnEditor?.ariaLabel ?? `${toSentenceCase(columnId + '')} Input Editor`);
const cellContainer = this.args.container;
if (cellContainer && typeof cellContainer.appendChild === 'function') {
Expand Down
18 changes: 8 additions & 10 deletions packages/common/src/editors/integerEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { KeyCode } from '../enums/index';
import { EditorArguments, EditorValidationResult } from '../interfaces/index';
import { integerValidator } from '../editorValidators/integerValidator';
import { InputEditor } from './inputEditor';
import { createDomElement } from '../services/domUtilities';
import { getDescendantProperty, toSentenceCase } from '../services/utilities';

export class IntegerEditor extends InputEditor {
Expand All @@ -13,19 +14,16 @@ export class IntegerEditor extends InputEditor {
init() {
if (this.columnDef && this.columnEditor && this.args) {
const columnId = this.columnDef?.id ?? '';
const placeholder = this.columnEditor?.placeholder ?? '';
const title = this.columnEditor?.title ?? '';
const inputStep = (this.columnEditor.valueStep !== undefined) ? this.columnEditor.valueStep : '1';
const compositeEditorOptions = this.args.compositeEditorOptions;

this._input = document.createElement('input') as HTMLInputElement;
this._input.className = `editor-text editor-${columnId}`;
this._input.type = 'number';
this._input = createDomElement('input', {
type: 'number', autocomplete: 'off',
placeholder: this.columnEditor?.placeholder ?? '',
title: this.columnEditor?.title ?? '',
step: `${(this.columnEditor.valueStep !== undefined) ? this.columnEditor.valueStep : '1'}`,
className: `editor-text editor-${columnId}`,
});
this._input.setAttribute('role', 'presentation');
this._input.autocomplete = 'off';
this._input.placeholder = placeholder;
this._input.title = title;
this._input.step = `${inputStep}`;
this._input.setAttribute('aria-label', this.columnEditor?.ariaLabel ?? `${toSentenceCase(columnId + '')} Slider Editor`);
const cellContainer = this.args.container;
if (cellContainer && typeof cellContainer.appendChild === 'function') {
Expand Down
53 changes: 19 additions & 34 deletions packages/common/src/editors/longTextEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
SlickGrid,
SlickNamespace,
} from '../interfaces/index';
import { getHtmlElementOffset, } from '../services/domUtilities';
import { createDomElement, getHtmlElementOffset, } from '../services/domUtilities';
import { getDescendantProperty, getTranslationPrefix, setDeepValue, toSentenceCase, } from '../services/utilities';
import { BindingEventService } from '../services/bindingEvent.service';
import { TranslaterService } from '../services/translater.service';
Expand Down Expand Up @@ -119,57 +119,42 @@ export class LongTextEditor implements Editor {

const compositeEditorOptions = this.args.compositeEditorOptions;
const columnId = this.columnDef?.id ?? '';
const placeholder = this.columnEditor?.placeholder ?? '';
const title = this.columnEditor?.title ?? '';
const maxLength = this.columnEditor?.maxLength;
const textAreaCols = this.editorOptions?.cols ?? 40;
const textAreaRows = this.editorOptions?.rows ?? 4;

const containerElm = compositeEditorOptions ? this.args.container : document.body;
this._wrapperElm = document.createElement('div');
this._wrapperElm.className = `slick-large-editor-text editor-${columnId}`;
this._wrapperElm = createDomElement('div', { className: `slick-large-editor-text editor-${columnId}` });
this._wrapperElm.style.position = compositeEditorOptions ? 'relative' : 'absolute';
containerElm.appendChild(this._wrapperElm);

this._textareaElm = document.createElement('textarea');
this._textareaElm.cols = textAreaCols;
// use textarea row if defined but don't go over 3 rows with composite editor modal
this._textareaElm.rows = (compositeEditorOptions && textAreaRows > 3) ? 3 : textAreaRows;
this._textareaElm.placeholder = placeholder;
this._textareaElm.title = title;
this._textareaElm = createDomElement('textarea', {
cols: this.editorOptions?.cols ?? 40,
rows: (compositeEditorOptions && textAreaRows > 3) ? 3 : textAreaRows,
placeholder: this.columnEditor?.placeholder ?? '',
title: this.columnEditor?.title ?? '',
});
this._textareaElm.setAttribute('aria-label', this.columnEditor?.ariaLabel ?? `${toSentenceCase(columnId + '')} Text Editor`);
this._wrapperElm.appendChild(this._textareaElm);

const editorFooterElm = document.createElement('div');
editorFooterElm.className = 'editor-footer';

const countContainerElm = document.createElement('span');
countContainerElm.className = 'counter';

this._currentLengthElm = document.createElement('span');
this._currentLengthElm.className = 'text-length';
this._currentLengthElm.textContent = '0';
const editorFooterElm = createDomElement('div', { className: 'editor-footer' });
const countContainerElm = createDomElement('span', { className: 'counter' });
this._currentLengthElm = createDomElement('span', { className: 'text-length', textContent: '0' });
countContainerElm.appendChild(this._currentLengthElm);

if (maxLength !== undefined) {
const maxLengthSeparatorElm = document.createElement('span');
maxLengthSeparatorElm.className = 'separator';
maxLengthSeparatorElm.textContent = '/';
const maxLengthElm = document.createElement('span');
maxLengthElm.className = 'max-length';
maxLengthElm.textContent = `${maxLength}`;
countContainerElm.appendChild(maxLengthSeparatorElm);
countContainerElm.appendChild(maxLengthElm);
countContainerElm.appendChild(
createDomElement('span', { className: 'separator', textContent: '/' })
);
countContainerElm.appendChild(
createDomElement('span', { className: 'max-length', textContent: `${maxLength}` })
);
}
editorFooterElm.appendChild(countContainerElm);

if (!compositeEditorOptions) {
const cancelBtnElm = document.createElement('button');
cancelBtnElm.className = 'btn btn-cancel btn-default btn-xs';
cancelBtnElm.textContent = cancelText;
const saveBtnElm = document.createElement('button');
saveBtnElm.className = 'btn btn-save btn-primary btn-xs';
saveBtnElm.textContent = saveText;
const cancelBtnElm = createDomElement('button', { className: 'btn btn-cancel btn-default btn-xs', textContent: cancelText });
const saveBtnElm = createDomElement('button', { className: 'btn btn-save btn-primary btn-xs', textContent: saveText });
editorFooterElm.appendChild(cancelBtnElm);
editorFooterElm.appendChild(saveBtnElm);
this._bindEventService.bind(cancelBtnElm, 'click', this.cancel.bind(this) as EventListener);
Expand Down
32 changes: 12 additions & 20 deletions packages/common/src/editors/sliderEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Column, ColumnEditor, CompositeEditorOption, Editor, EditorArguments, E
import { getDescendantProperty, setDeepValue, toSentenceCase } from '../services/utilities';
import { sliderValidator } from '../editorValidators/sliderValidator';
import { BindingEventService } from '../services/bindingEvent.service';
import { createDomElement } from '../services/domUtilities';

const DEFAULT_MIN_VALUE = 0;
const DEFAULT_MAX_VALUE = 100;
Expand Down Expand Up @@ -305,36 +306,27 @@ export class SliderEditor implements Editor {
const minValue = this.columnEditor.hasOwnProperty('minValue') ? this.columnEditor.minValue : DEFAULT_MIN_VALUE;
const maxValue = this.columnEditor.hasOwnProperty('maxValue') ? this.columnEditor.maxValue : DEFAULT_MAX_VALUE;
const defaultValue = this.editorParams.hasOwnProperty('sliderStartValue') ? this.editorParams.sliderStartValue : minValue;
const step = this.columnEditor.hasOwnProperty('valueStep') ? this.columnEditor.valueStep : DEFAULT_STEP;
this._defaultValue = defaultValue;

const inputElm = document.createElement('input');
inputElm.name = this._elementRangeInputId;
inputElm.title = title;
inputElm.type = 'range';
inputElm.defaultValue = defaultValue;
inputElm.value = defaultValue;
inputElm.min = `${minValue}`;
inputElm.max = `${maxValue}`;
inputElm.step = `${step}`;
inputElm.className = `form-control slider-editor-input editor-${columnId} range ${this._elementRangeInputId}`;
const inputElm = createDomElement('input', {
type: 'range', name: this._elementRangeInputId, title,
defaultValue, value: defaultValue, min: `${minValue}`, max: `${maxValue}`,
step: `${this.columnEditor.hasOwnProperty('valueStep') ? this.columnEditor.valueStep : DEFAULT_STEP}`,
className: `form-control slider-editor-input editor-${columnId} range ${this._elementRangeInputId}`,
});
inputElm.setAttribute('aria-label', this.columnEditor?.ariaLabel ?? `${toSentenceCase(columnId + '')} Slider Editor`);

const divContainerElm = document.createElement('div');
divContainerElm.className = 'slider-container slider-editor';
const divContainerElm = createDomElement('div', { className: 'slider-container slider-editor' });
divContainerElm.appendChild(inputElm);

if (!this.editorParams.hideSliderNumber) {
divContainerElm.classList.add('input-group');

// <div class="input-group-addon input-group-append slider-value"><span class="input-group-text ${this._elementRangeOutputId}">${defaultValue}</span></div>
const spanGroupElm = document.createElement('span');
spanGroupElm.className = `input-group-text ${this._elementRangeOutputId}`;
spanGroupElm.textContent = `${defaultValue}`;

const divGroupAddonElm = document.createElement('div');
divGroupAddonElm.className = 'input-group-addon input-group-append slider-value';
divGroupAddonElm.appendChild(spanGroupElm);
const divGroupAddonElm = createDomElement('div', { className: 'input-group-addon input-group-append slider-value' });
divGroupAddonElm.appendChild(
createDomElement('span', { className: `input-group-text ${this._elementRangeOutputId}`, textContent: `${defaultValue}` })
);
divContainerElm.appendChild(divGroupAddonElm);
}

Expand Down
1 change: 1 addition & 0 deletions packages/common/src/enums/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './filterMultiplePassType.enum';
export * from './filterMultiplePassTypeString.type';
export * from './gridAutosizeColsMode.enum';
export * from './gridStateType.enum';
export * from './infer.type';
export * from './keyCode.enum';
export * from './operatorString.type';
export * from './operatorType.enum';
Expand Down
1 change: 1 addition & 0 deletions packages/common/src/enums/infer.type.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type InferType<T> = T extends infer R ? R : any;
Loading

0 comments on commit ec8e46a

Please sign in to comment.