1090 lines
23 KiB
JavaScript
1090 lines
23 KiB
JavaScript
import './css/app-ui.css';
|
|
|
|
import { Ut } from '../utils/Ut';
|
|
import { El } from '../utils/dom';
|
|
import { Boot } from './Boot';
|
|
import { Cancelable } from '../widgets/cancelable/Cancelable';
|
|
import { DatePicker } from '../widgets/date-picker/DatePicker';
|
|
import { TwoDatePicker } from '../widgets/two-datepicker/TwoDatepicker';
|
|
import { IntervalPicker } from '../widgets/interval-picker/IntervalPicker';
|
|
import { Uploader } from '../widgets/uploader/Uploader';
|
|
import { PinBox } from '../widgets/pin-box/PinBox';
|
|
|
|
export class Render {
|
|
|
|
/**
|
|
* Make Card Element
|
|
*/
|
|
static makeCardElement(node, parent) {
|
|
|
|
node.outline = Ut.isSet(node.outline) ? node.outline : 1;
|
|
|
|
let card = El('div', { className: 'sp-card' });
|
|
|
|
if (node.name) {
|
|
card.className += ' card-' + node.name;
|
|
}
|
|
|
|
if (node.cls) {
|
|
card.dxAddClass(node.cls);
|
|
}
|
|
|
|
let content = card;
|
|
|
|
if (node.outline == 1) {
|
|
content = card.appendChild( El('div', { className: 'content-card' }) );
|
|
}
|
|
|
|
if (node.children && node.children.tabmenu) {
|
|
|
|
let tabMenu = content.appendChild(El('div', { className: 'tab-menu' }));
|
|
|
|
let active = false;
|
|
|
|
Ut.each(Ut.objVal(node.children.tabmenu)?.children?.item, dataItem => {
|
|
|
|
if (!dataItem.text) {
|
|
return;
|
|
}
|
|
|
|
let item = tabMenu.appendChild(El('a', {},
|
|
El('i', { className: 'fa' + (dataItem['icon-type'] || 's') + ' fa-'+ dataItem.icon }),
|
|
El('span', {}, dataItem.text)
|
|
));
|
|
|
|
if (dataItem.id) {
|
|
item.dataset.id = dataItem.id;
|
|
}
|
|
|
|
if (!active) {
|
|
item.classList.add('active');
|
|
}
|
|
|
|
active = true;
|
|
});
|
|
|
|
tabMenu.dxOn('click', 'a', (_, t) => {
|
|
|
|
t.dxSiblings('.active', itm => itm.classList.remove('active') );
|
|
t.classList.add('active');
|
|
|
|
content?.dxFind('[data-group]:not(.hide)')?.dxFadeOut(_ => content?.dxFind('[data-group="'+ t.dataset.id +'"]')?.dxFadeIn());
|
|
});
|
|
}
|
|
|
|
if (node.title || node.descr || node?.children?.toolbar) {
|
|
|
|
const topBarInner = content.appendChild(El('div', { className: 'top-bar' }))
|
|
.appendChild(El('div', { className: 'top-bar-inner'}) );
|
|
|
|
if (node.title || node.descr) {
|
|
|
|
const titleWrapper = topBarInner.appendChild(El('div', { className: 'title-wrapper' }));
|
|
|
|
node.title && titleWrapper.append( El('h2', { className: 'title' }, Ut.tplString(node.title, node.template) ));
|
|
node.descr && titleWrapper.append( El('p', { className: 'descr' }, Ut.tplString(node.descr, node.template)) );
|
|
}
|
|
|
|
if (node?.children?.toolbar) {
|
|
Render.makeUiElements(
|
|
Ut.objVal(node.children.toolbar).children,
|
|
topBarInner.appendChild(
|
|
El('div', { className: 'ml10 flex v-center no-shrink' })
|
|
)
|
|
);
|
|
}
|
|
}
|
|
|
|
let container = (node['hide-content'] == 1)
|
|
? content
|
|
: content.appendChild(El('div', { className: 'container' }));
|
|
|
|
if (parent) {
|
|
parent.append(card);
|
|
}
|
|
|
|
if (node.children) {
|
|
Render.makeUiElements(node.children, container, node.template);
|
|
}
|
|
|
|
container.dxFind('[data-group]', (el, i) => i && el.classList.add('hide'));
|
|
|
|
return card;
|
|
}
|
|
|
|
/**
|
|
* Make Block Element
|
|
*/
|
|
static makeBlockElement(node, parent) {
|
|
|
|
let block = El('div', { className: 'sp-block block-'+ node.name });
|
|
|
|
if (node.cls) {
|
|
block.className += ' ' + node.cls;
|
|
}
|
|
|
|
if (node.id) {
|
|
block.id = node.id;
|
|
}
|
|
|
|
if (node.title) {
|
|
block.dataset.title = Ut.tplString(node.title, node.template);
|
|
}
|
|
|
|
if (node.descr) {
|
|
block.dataset.descr = Ut.tplString(node.descr, node.template);
|
|
}
|
|
|
|
if (node.type) {
|
|
block.dataset.type = node.type;
|
|
}
|
|
|
|
if (node.label) {
|
|
block.textContent = Ut.tplString(node.label, node.template);
|
|
}
|
|
|
|
if (node.group) {
|
|
block.dataset.group = node.group;
|
|
}
|
|
|
|
if (parent) {
|
|
parent.append(block);
|
|
}
|
|
|
|
if (node.children) {
|
|
Render.makeUiElements(node.children, block, node.template);
|
|
}
|
|
|
|
return block;
|
|
}
|
|
|
|
/**
|
|
* Make Form Element
|
|
*/
|
|
static makeFormElement(node, parent) {
|
|
|
|
let form = El('form', {
|
|
novalidate: true,
|
|
className: 'sp-form form-'+ node.name + (node.cls ? ' ' + node.cls : ''),
|
|
autocomplete: 'off',
|
|
method: 'post'
|
|
});
|
|
|
|
if (node.title) {
|
|
form.dataset.title = Ut.tplString(node.title, node.template);
|
|
}
|
|
|
|
if (node.group) {
|
|
form.dataset.group = node.group;
|
|
}
|
|
|
|
if (parent) {
|
|
parent.append(form);
|
|
}
|
|
|
|
if (node.children) {
|
|
Render.makeUiElements(node.children, form, node.template);
|
|
}
|
|
|
|
return form;
|
|
}
|
|
|
|
/**
|
|
* Make List Element
|
|
*/
|
|
static makeListElement(node, parent) {
|
|
|
|
let list = El('ul', { className: 'sp-list list-'+ node.name + (node.cls ? ' ' + node.cls : ''),
|
|
id: node.id || null
|
|
});
|
|
|
|
if (node.group) {
|
|
list.dataset.group = node.group;
|
|
}
|
|
|
|
if (node.children && node.children.item) {
|
|
|
|
Ut.each (node.children.item, (item, action) => {
|
|
|
|
let itm = El('li', {
|
|
className: 'item-'+ (item.type || 'text') + (item.type == 'link' ? ' cmd-' : ' item-') + action + (item.cls ? ' ' + item.cls : ''),
|
|
'data-id': item.id || null,
|
|
});
|
|
|
|
if (item.icon) {
|
|
let icon = item.icon.split(' ');
|
|
itm.append(El('i', { className: 'fa-'+ (icon[1] || 'solid') +' fa-'+ icon[0] }) );
|
|
}
|
|
|
|
if (item.label) {
|
|
itm.append(El('span', { className: 'item-label' }, Ut.tplString(item.label, node.template) ));
|
|
}
|
|
|
|
list.append(itm);
|
|
});
|
|
|
|
if (parent) {
|
|
parent.append(list);
|
|
}
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
/**
|
|
* Make Title Element
|
|
*/
|
|
static makeTitleElement(node, parent) {
|
|
|
|
let blockTitle = El('div', { className: 'sp-title mb'+ (node.mb || 30) +' title-'+ node.name });
|
|
|
|
if (node.mt) {
|
|
blockTitle.classList.add('mt' + node.mt);
|
|
}
|
|
|
|
if (node.cls) {
|
|
blockTitle.classList.add(node.cls);
|
|
}
|
|
|
|
if (node.icon) {
|
|
blockTitle.appendChild(El('i', { className: 'fa' + (field['icon-type'] || 's') + ' fa-'+ field.icon }) );
|
|
}
|
|
|
|
let title = blockTitle.appendChild(El('h2', { className: 'text-semibold fz' + (node.size || 22) }));
|
|
|
|
if (node.label) {
|
|
title.textContent = Ut.tplString(node.label, node.template);
|
|
}
|
|
|
|
if (parent) {
|
|
parent.append(blockTitle);
|
|
}
|
|
|
|
return blockTitle;
|
|
}
|
|
|
|
/**
|
|
* Make Caption Element
|
|
*/
|
|
static makeCaptionElement(node, parent) {
|
|
|
|
let blockTitle = El('div', { className: 'sp-caption mb'+ (node.mb || 30) +' caption-'+ node.name });
|
|
|
|
if (node.mt) {
|
|
blockTitle.classList.add('mt' + node.mt);
|
|
}
|
|
|
|
if (node.cls) {
|
|
blockTitle.classList.add(node.cls);
|
|
}
|
|
|
|
if (node.icon) {
|
|
blockTitle.appendChild(El('i', { className: 'fa' + (field['icon-type'] || 's') + ' fa-'+ field.icon }) );
|
|
}
|
|
|
|
let title = blockTitle.appendChild(El('h3', { className: 'text-medium fz' + (node.size || 18) }));
|
|
|
|
if (node.label) {
|
|
title.textContent = Ut.tplString(node.label, node.template);
|
|
}
|
|
|
|
if (parent) {
|
|
parent.append(blockTitle);
|
|
}
|
|
|
|
return blockTitle;
|
|
}
|
|
|
|
/**
|
|
* Make Info Element
|
|
*/
|
|
static makeInfoElement(field, parent) {
|
|
|
|
let labelWrapper = El('div', { className: 'form-field field-info' });
|
|
|
|
if (field.name) {
|
|
labelWrapper.dataset.name = field.name;
|
|
}
|
|
|
|
if (field.color) {
|
|
labelWrapper.className += ' color-' + field.color;
|
|
}
|
|
|
|
if (field.cls) {
|
|
labelWrapper.className += ' ' + field.cls;
|
|
}
|
|
|
|
if (field.icon) {
|
|
labelWrapper.append( El('i', { className: 'fa' + (field['icon-type'] || 's') + ' fa-'+ field.icon + ' ic-info fz' + (field['icon-size'] || 32) + ' color-' + (field['icon-color'] || 'black') }) );
|
|
}
|
|
|
|
let group = El('div');
|
|
|
|
if (field.label) {
|
|
group.append(El('label', { className: 'label-name' }, Ut.tplString(field.label, field.template)));
|
|
}
|
|
|
|
let labelValue = El('div', { className: 'label-value' });
|
|
|
|
if (field.wrap) {
|
|
labelValue.className += ' text-wrap';
|
|
}
|
|
|
|
if (field.id) {
|
|
labelValue.id = field.id;
|
|
}
|
|
|
|
if (field.value) {
|
|
labelValue.textContent = field.value;
|
|
}
|
|
|
|
group.append(labelValue);
|
|
|
|
labelWrapper.append(group);
|
|
|
|
if (parent) {
|
|
parent.append(labelWrapper);
|
|
}
|
|
|
|
return labelWrapper;
|
|
}
|
|
|
|
/**
|
|
* Make Link Element
|
|
*/
|
|
static makeLinkElement(node, parent) {
|
|
|
|
let elem = El('a', { className: 'link' });
|
|
|
|
if (node.name) {
|
|
elem.className += ' link-' + node.name;
|
|
}
|
|
|
|
if (node.href) {
|
|
node.href = node.href;
|
|
}
|
|
|
|
if (node.target) {
|
|
node.target = node.target;
|
|
}
|
|
|
|
if (node.icon) {
|
|
elem.prepend(El('i', { className: 'fa' + (node['icon-type'] || 's') + ' fa-'+ node.icon }) );
|
|
}
|
|
|
|
if (node.label) {
|
|
elem.append(Ut.tplString(node.label, node.template));
|
|
}
|
|
else {
|
|
elem.className += ' no-text';
|
|
}
|
|
|
|
if (node.size) {
|
|
elem.className += ' fz' + node.size;
|
|
}
|
|
|
|
if (node.color) {
|
|
elem.className += ' color-' + node.color;
|
|
}
|
|
|
|
if (node.tooltip) {
|
|
|
|
elem.dataset.tooltip = node.tooltip;
|
|
|
|
if (node['tooltip-color']) {
|
|
elem.className += ' tooltip-color-' + node['tooltip-color'];
|
|
}
|
|
}
|
|
|
|
if (node.cls) {
|
|
elem.className += ' ' + node.cls;
|
|
}
|
|
|
|
if (parent) {
|
|
parent.append(elem);
|
|
}
|
|
|
|
return elem;
|
|
}
|
|
|
|
/**
|
|
* Make Card Menu
|
|
*/
|
|
static makeCardMenu(node, parent) {
|
|
|
|
let cardMenu = El('div', { className: 'sp-card-menu' });
|
|
|
|
if (node?.children?.item) {
|
|
|
|
Ut.each (node.children.item, item => {
|
|
|
|
if (!item.title) {
|
|
return;
|
|
}
|
|
|
|
const menuItem = cardMenu.appendChild( El('a', { className: 'card-menu-item' },
|
|
El('div', { className: 'card-icon-wrapper' },
|
|
El('i', { className: 'fa' + (item['icon-type'] || 's') + ' fa-'+ (item.icon || 'cog') + ' fz' + (item['icon-size'] || 36) })
|
|
),
|
|
El('div', { className: 'card-menu-title' }, item.title)
|
|
) );
|
|
|
|
if (item.id) {
|
|
menuItem.dataset.id = item.id;
|
|
}
|
|
|
|
if (item.init) {
|
|
menuItem.dataset.init = item.init;
|
|
}
|
|
|
|
if (item.descr) {
|
|
menuItem.append(El('div', { className: 'card-menu-descr' }, item.descr));
|
|
}
|
|
|
|
cardMenu.append(menuItem);
|
|
});
|
|
}
|
|
|
|
if (parent) {
|
|
parent.append(cardMenu);
|
|
}
|
|
|
|
return cardMenu;
|
|
}
|
|
|
|
/**
|
|
* Make Button Element
|
|
*/
|
|
static makeButtonElement(node, parent) {
|
|
|
|
let elem = El('button', { type: node.type || 'button' });
|
|
|
|
if (node.disabled) {
|
|
elem.disabled = true;
|
|
}
|
|
|
|
elem.className = 'sp-button';
|
|
|
|
if (node.color) {
|
|
elem.className += ' ui-color-' + node.color;
|
|
}
|
|
|
|
if (!node.label && node.icon) {
|
|
elem.className += ' icon-only';
|
|
}
|
|
|
|
if (node.cls) {
|
|
elem.className += ' ' + node.cls;
|
|
}
|
|
|
|
if (node.id) {
|
|
elem.id = node.id;
|
|
}
|
|
|
|
if (node.init) {
|
|
elem.dataset.init = node.init;
|
|
}
|
|
|
|
if (node.label) {
|
|
elem.append( El('span', {}, Ut.tplString(node.label, node.template) ) );
|
|
}
|
|
|
|
if (node.icon) {
|
|
elem.append( El('i', { className: 'icon-' + (node['icon-align'] || 'left') + ' fa' + (node['icon-type'] || 's') + ' fa-' + node.icon + ' fz' + (node['icon-size'] || 14) + ' color-' + (node['icon-color'] || 'white') }) );
|
|
}
|
|
|
|
if (node.tooltip) {
|
|
|
|
elem.dataset.tooltip = node.tooltip;
|
|
|
|
if (node['tooltip-color']) {
|
|
elem.className += ' tooltip-color-' + node['tooltip-color'];
|
|
}
|
|
}
|
|
|
|
if (parent) {
|
|
parent.append(elem);
|
|
}
|
|
|
|
return elem;
|
|
}
|
|
|
|
/**
|
|
* Set Input Default Attrs
|
|
*/
|
|
static setInputAttr(input, field) {
|
|
|
|
Ut.each(field, (val, key) => {
|
|
|
|
if (key == 'readonly') {
|
|
key = 'readOnly';
|
|
val = Boolean(val);
|
|
}
|
|
|
|
if (field.maxlength) {
|
|
key = 'maxLength';
|
|
val = Boolean(val);
|
|
}
|
|
|
|
if (key === 'required' || key === 'disabled') {
|
|
val = Boolean(val);
|
|
}
|
|
|
|
if (input.constructor.prototype) {
|
|
|
|
if (key === 'type' || key === 'value') {
|
|
return;
|
|
}
|
|
|
|
if (key === 'dataid') {
|
|
input.dataset.id = field.dataid;
|
|
return;
|
|
}
|
|
|
|
input[ key ] = val;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Make Field Wrapper
|
|
*/
|
|
static makeFieldWrapper(field, parent) {
|
|
|
|
let wrapper = El('div', { className: 'form-field field-' + field.type });
|
|
|
|
if (field.name) {
|
|
wrapper.className += ' field-' + field.name;
|
|
}
|
|
|
|
if (field.cls) {
|
|
wrapper.className += ' ' + field.cls;
|
|
}
|
|
|
|
if (field.label) {
|
|
wrapper.append( El('label', { className: 'field-label' }, Ut.tplString(field.label, field.template)) );
|
|
}
|
|
|
|
let inputWrapper = null;
|
|
|
|
if (field.type === 'text' || field.type === 'number' || field.type === 'password' || field.type === 'select') {
|
|
|
|
inputWrapper = El('div', { className: 'input-wrapper' });
|
|
|
|
wrapper.append(inputWrapper);
|
|
|
|
if (field.icon) {
|
|
|
|
let icon;
|
|
|
|
if (field['icon-tooltip'] || field['icon-action']) {
|
|
|
|
icon = El('a', { className: 'icon-' + (field['icon-align'] || 'left') },
|
|
El('i', { className: 'fa' + (field['icon-type'] || 's') + ' fa-' + field.icon + ' fz' + (field['icon-size'] || 14) + ' color-' + (field['icon-color'] || 'black') })
|
|
);
|
|
}
|
|
else {
|
|
icon = El('i', { className: 'icon-' + (field['icon-align'] || 'left') + ' fa' + (field['icon-type'] || 's') + ' fa-' + field.icon + ' fz' + (field['icon-size'] || 14) + ' color-' + (field['icon-color'] || 'black') });
|
|
}
|
|
|
|
if (field['icon-tooltip']) {
|
|
icon.dataset.tooltip = field['icon-tooltip'];
|
|
icon.className += ' tooltip-color-' + (field['icon-color'] || black);
|
|
}
|
|
|
|
if (field['icon-display'] == 0 ) {
|
|
icon.className += ' hide';
|
|
}
|
|
|
|
if (field['icon-cls']) {
|
|
icon.className += ' ' + field['icon-cls'];
|
|
}
|
|
|
|
inputWrapper.append( icon );
|
|
}
|
|
}
|
|
|
|
if (parent) {
|
|
parent.append(wrapper);
|
|
}
|
|
|
|
return inputWrapper || wrapper;
|
|
}
|
|
|
|
/**
|
|
* Make Input Element
|
|
*/
|
|
static makeInputElement(field, parent) {
|
|
|
|
const input = El('input', { type: field.type, className: 'sp-form-control' });
|
|
|
|
if (field.value) {
|
|
input.value = field.value;
|
|
}
|
|
|
|
if (field.type !== 'hidden' && field.placeholder) {
|
|
input.placeholder = field.placeholder;
|
|
}
|
|
|
|
if (field.type !== 'hidden' && field.autocomplete) {
|
|
input.setAttribute('autocomplete', field.autocomplete || 'off');
|
|
}
|
|
|
|
Render.setInputAttr(input, field);
|
|
|
|
Render.makeFieldWrapper(field, parent).append(input);
|
|
|
|
if (field.cancelable === '1') {
|
|
new Cancelable(input);
|
|
}
|
|
|
|
if (field['max-chars']) {
|
|
input.Counter({ limit: field['max-chars'] });
|
|
}
|
|
|
|
return input;
|
|
}
|
|
|
|
/**
|
|
* Make Textarea Element
|
|
*/
|
|
static makeTextareaElement(field, parent) {
|
|
|
|
let textarea = El('textarea', { className: 'sp-form-control' });
|
|
|
|
if (field.rows) {
|
|
textarea.setAttribute('rows', field.rows);
|
|
}
|
|
|
|
if (field.placeholder) {
|
|
textarea.placeholder = field.placeholder;
|
|
}
|
|
|
|
Render.setInputAttr(textarea, field);
|
|
|
|
if (field.autoexpand == '1') {
|
|
textarea.AutoExpand({ minRows: field['min-rows'] });
|
|
}
|
|
|
|
if (field['max-chars']) {
|
|
textarea.Counter({ limit: field['max-chars'] });
|
|
}
|
|
|
|
Render.makeFieldWrapper(field, parent).append(textarea);
|
|
|
|
return textarea;
|
|
}
|
|
|
|
/**
|
|
* Make DatePicker Element
|
|
*/
|
|
static makeDatePickerElement(field, parent) {
|
|
|
|
const input = Render.makeInputElement({... field, ... { type: 'text' }}, parent);
|
|
|
|
new DatePicker(input, {
|
|
style: field.style || 'normal',
|
|
disabled: field.disabled || false,
|
|
multiple: field.multiple || false,
|
|
setTime: field['set-time'] || false,
|
|
locales: field.locales || 'ro-RO',
|
|
dateFormat : field['date-format'] || 'dd-mm-yyyy',
|
|
valueFormat : field['value-format'] || 'dd-mm-yyyy',
|
|
datesSep : field['dates-sep'] || ' / ',
|
|
valuesSep : field['values-sep'] || '&'
|
|
});
|
|
|
|
return input;
|
|
}
|
|
|
|
/**
|
|
* Make TwoDatePicker Element
|
|
*/
|
|
static makeTwoDatePickerElement(field, parent) {
|
|
|
|
const input = Render.makeInputElement({... field, ... { type: 'text' }}, parent);
|
|
|
|
new TwoDatePicker(input, {
|
|
style: field.style || 'normal',
|
|
disabled: field.disabled || false,
|
|
locales: field.locales || 'ro-RO',
|
|
});
|
|
|
|
return input;
|
|
}
|
|
|
|
/**
|
|
* Make IntervalPicker Element
|
|
*/
|
|
static makeIntervalPickerElement(field, parent) {
|
|
|
|
const input = Render.makeInputElement({... field, ... { type: 'text' }}, parent);
|
|
|
|
new IntervalPicker(input, {
|
|
style : field.style || 'normal',
|
|
disabled : field.disabled || false,
|
|
locales : field.locales || 'ro-RO',
|
|
dateFormat : field['date-format'] || 'dd-mm-yyyy',
|
|
valueFormat : field['value-format'] || 'dd-mm-yyyy'
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Make Input Color Element
|
|
*/
|
|
static makeInputColorElement(field, parent) {
|
|
|
|
const input = El('input', { type: 'color' });
|
|
|
|
let elem = El('div', { className: 'input-color-wrapper' }, input);
|
|
|
|
Render.setInputAttr(input, field);
|
|
|
|
Render.makeFieldWrapper(field, parent).append(elem);
|
|
|
|
return input;
|
|
}
|
|
|
|
/**
|
|
* Make Input File
|
|
*/
|
|
static makeInputFileElement(field, parent, opts) {
|
|
|
|
const input = El('input', { type: 'file' });
|
|
|
|
Render.setInputAttr(input, field);
|
|
|
|
Render.makeFieldWrapper(field, parent).append(input);
|
|
|
|
new Uploader(input, opts?.vars?.id ? { id: opts.vars.id } : {});
|
|
|
|
return input;
|
|
}
|
|
|
|
/**
|
|
* Make Default Input Element
|
|
*/
|
|
static makeDefaultInputElement(field, parent) {
|
|
|
|
const input = El('input', { type: field.type, className: 'sp-form-control' });
|
|
|
|
Render.setInputAttr(input, field);
|
|
|
|
if (Ut.isSet(field.value)) {
|
|
input.value = field.value;
|
|
}
|
|
|
|
return Render.makeFieldWrapper(field, parent).appendChild(input);
|
|
}
|
|
|
|
/**
|
|
* Make Select Element
|
|
*/
|
|
static makeSelectElement(field, parent) {
|
|
|
|
let elem = El('select', { className: 'sp-form-control' });
|
|
|
|
if (field.multiple === '1') {
|
|
elem.multiple = true;
|
|
}
|
|
|
|
if (field.option) {
|
|
|
|
Ut.each (field.option, (text, val) => elem.append(new Option(text, val, val == field.value)) );
|
|
|
|
if (field.value) {
|
|
elem.value = field.value;
|
|
}
|
|
}
|
|
|
|
Render.setInputAttr(elem, field);
|
|
|
|
Render.makeFieldWrapper(field, parent).append(elem);
|
|
|
|
return elem;
|
|
}
|
|
|
|
/**
|
|
* Make Radio Element
|
|
*/
|
|
static makeRadioElement(field, parent) {
|
|
|
|
if (!field.option) {
|
|
return false;
|
|
}
|
|
|
|
let elem = El('div', { className: 'sp-control ' + field.type +'-control' });
|
|
|
|
Ut.each (field.option, (text, val) => {
|
|
|
|
const input = El('input', { type: field.type });
|
|
|
|
Render.setInputAttr(input, field);
|
|
|
|
if (field.value) {
|
|
input.checked = (val == field.value);
|
|
}
|
|
|
|
input.value = val;
|
|
|
|
let label = El('label', {}, input, El('span', { className: 'ctrl-indicator' }), text);
|
|
|
|
label.className = 'radio-label';
|
|
|
|
if (field.xcls) {
|
|
label.className += ' ' + field.xcls;
|
|
}
|
|
|
|
elem.append(label);
|
|
|
|
if (field.group == '1' && field.type == 'checkbox') {
|
|
input.SelectBox();
|
|
}
|
|
|
|
});
|
|
|
|
Render.makeFieldWrapper(field, parent).append(elem);
|
|
|
|
return elem;
|
|
}
|
|
|
|
/**
|
|
* Make Radio Box Element
|
|
*/
|
|
static makeRadioBoxElement(field, parent) {
|
|
|
|
if (!field.option) {
|
|
return false;
|
|
}
|
|
|
|
let colors = [],
|
|
i = 0;
|
|
|
|
if (field.color) {
|
|
colors = field.color.split(',').map(function(color) {
|
|
return color.trim();
|
|
});
|
|
}
|
|
|
|
let elem = El('div', { className: 'sp-radio-box' });
|
|
|
|
Ut.each (field.option, (text, val) => {
|
|
|
|
let label = El('label');
|
|
|
|
label.className = 'radiobox-label';
|
|
|
|
if (field.xcls) {
|
|
label.className += ' ' + field.xcls;
|
|
}
|
|
|
|
const input = El('input', { type: 'radio' });
|
|
|
|
Render.setInputAttr(input, field);
|
|
|
|
input.value = val;
|
|
|
|
input.checked = (val == field.value);
|
|
|
|
label.append(input);
|
|
|
|
let indicator = El('span', { className: 'ctrl-indicator label-color-'+ (colors[i] ? colors[i] : 'default') });
|
|
|
|
indicator.textContent = text;
|
|
|
|
label.append(indicator);
|
|
|
|
elem.append(label);
|
|
|
|
i++;
|
|
|
|
});
|
|
|
|
Render.makeFieldWrapper(field, parent).append(elem);
|
|
|
|
return elem;
|
|
}
|
|
|
|
/**
|
|
* Make Number Picker Element
|
|
*/
|
|
static makeNumPickerElement(field, parent) {
|
|
|
|
const input = El('input', { name: field.name, type: 'hidden' });
|
|
|
|
if (field.id) {
|
|
input.id = field.id;
|
|
}
|
|
|
|
if (Ut.isSet(field.value)) {
|
|
input.value = field.value;
|
|
}
|
|
|
|
Render.makeFieldWrapper(field, parent).append(input);
|
|
|
|
input.NumberPicker({
|
|
minVal: field.min,
|
|
maxVal: field.max
|
|
});
|
|
|
|
return input;
|
|
}
|
|
|
|
/**
|
|
* Make Radio Box Element
|
|
*/
|
|
static makePinBoxElement(field, parent) {
|
|
|
|
const input = El('input', {
|
|
type: 'hidden',
|
|
name: field.name
|
|
});
|
|
|
|
Render.makeFieldWrapper(field, parent).append(input);
|
|
|
|
new PinBox(input, { digits: field.digits || 6 });
|
|
|
|
return input;
|
|
}
|
|
|
|
/**
|
|
* Make Hidden Element
|
|
*/
|
|
static makeHiddenElement(field, parent) {
|
|
|
|
if (field.label) {
|
|
return Render.makeInputElement(field, parent);
|
|
}
|
|
|
|
const input = parent.appendChild(El('input', { type: 'hidden' }));
|
|
|
|
Ut.each(field, (val, key) => (key in HTMLInputElement.prototype) && (input[ key ] = val))
|
|
|
|
return input;
|
|
}
|
|
|
|
/**
|
|
* Make Element
|
|
*/
|
|
static makeElement(props, parent, opts) {
|
|
|
|
switch (props._type) {
|
|
case 'card': return Render.makeCardElement(props, parent);
|
|
case 'block': return Render.makeBlockElement(props, parent);
|
|
case 'form': return Render.makeFormElement(props, parent);
|
|
case 'field': return Render.makeFormControl(props, parent, opts);
|
|
case 'list': return Render.makeListElement(props, parent);
|
|
case 'title': return Render.makeTitleElement(props, parent);
|
|
case 'caption': return Render.makeCaptionElement(props, parent);
|
|
case 'link': return Render.makeLinkElement(props, parent);
|
|
case 'button': case 'submit': return Render.makeButtonElement(props, parent);
|
|
case 'info': return Render.makeInfoElement(props, parent);
|
|
case 'cardmenu': return Render.makeCardMenu(props, parent);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Make Form Control
|
|
*/
|
|
static makeFormControl(field, parent, opts) {
|
|
|
|
if (!field.type || !field.name) { // Field type && field name are required
|
|
return false;
|
|
}
|
|
|
|
switch (field.type) {
|
|
case 'text': return Render.makeInputElement(field, parent);
|
|
case 'password': return Render.makeDefaultInputElement(field, parent);
|
|
case 'textarea': return Render.makeTextareaElement(field, parent);
|
|
case 'number': return Render.makeDefaultInputElement(field, parent);
|
|
case 'range': return Render.makeDefaultInputElement(field, parent);
|
|
case 'color': return Render.makeInputColorElement(field, parent);
|
|
case 'datepicker': return Render.makeDatePickerElement(field, parent);
|
|
case 'twodatepicker': return Render.makeTwoDatePickerElement(field, parent);
|
|
case 'intervalpicker': return Render.makeIntervalPickerElement(field, parent);
|
|
case 'file': return Render.makeInputFileElement(field, parent, opts);
|
|
case 'select': return Render.makeSelectElement(field, parent);
|
|
case 'radio': case 'checkbox': return Render.makeRadioElement(field, parent);
|
|
case 'radiobox': return Render.makeRadioBoxElement(field, parent);
|
|
case 'numpicker': return Render.makeNumPickerElement(field, parent);
|
|
case 'pinbox': return Render.makePinBoxElement(field, parent);
|
|
case 'hidden': return Render.makeHiddenElement(field, parent);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Make UI Elements
|
|
*/
|
|
static makeUiElements(rootNode, parent, template) {
|
|
|
|
if (!rootNode) {
|
|
return;
|
|
}
|
|
|
|
template = template || {};
|
|
|
|
let nodesList = [];
|
|
|
|
Ut.each (rootNode, (node, type) => {
|
|
Ut.each(node, (prop, name) => {
|
|
if (typeof prop == 'object') {
|
|
nodesList[prop.order] = prop;
|
|
prop._type = type;
|
|
prop.name = name;
|
|
prop.template = template;
|
|
}
|
|
});
|
|
});
|
|
|
|
// Reiterate
|
|
nodesList.forEach(props => Render.makeElement(props, parent));
|
|
}
|
|
|
|
/**
|
|
* Render UI Component
|
|
*
|
|
* @param string id Component ID
|
|
* @param object template Template Object Vars
|
|
*
|
|
*/
|
|
static make(id, template) {
|
|
|
|
const token = id.split('.');
|
|
|
|
if (token.length != 2) {
|
|
|
|
if (Boot.DEBUG) {
|
|
console.log('Invalid component ID!');
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
let nodeObj = null;
|
|
|
|
if (Boot._section) {
|
|
|
|
let mainNode = Boot.intData?.section[Boot._section[0]];
|
|
nodeObj = mainNode?.children?.[token[0]]?.[token[1]];
|
|
}
|
|
else {
|
|
nodeObj = Boot.intData?.[token[0]]?.[token[1]];
|
|
}
|
|
|
|
if (!nodeObj) {
|
|
|
|
if (Boot.DEBUG) {
|
|
console.log('This component ID doesn\'t exist!');
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
nodeObj._type = token[0];
|
|
nodeObj.name = token[1];
|
|
nodeObj.template = template || {};
|
|
|
|
return Render.makeElement(nodeObj, null, { vars: Boot.vars || {} });
|
|
}
|
|
|
|
} // End Class
|