activator-oce-exporter
Version:
Extract Activator binder and convert it to valid OCE mono pacakge
652 lines (582 loc) • 16.9 kB
JavaScript
import { html } from '@polymer/lit-element';
import { FusionBase } from '../../base';
import { FusionApi } from '../../api';
import { applyMixins, Font, SlideComponent } from '../../mixins';
import { FusionText } from '../text';
import { getPartial, debounce } from '../../utils';
class FusionTableCell extends applyMixins(FusionText, [Font]) {
static get properties() {
const properties = ['width', 'font-size', 'font-family', 'font-weight', 'font-style', 'line-height', 'letter-spacing', 'color', 'background-color'];
const filteredProp = getPartial(FusionText.properties, properties);
return {
...filteredProp,
'padding-top': {
type: String,
fieldType: 'Number',
value: '10px',
},
'padding-bottom': {
type: String,
fieldType: 'Number',
value: '10px',
},
'padding-left': {
type: String,
fieldType: 'Number',
value: '10px',
},
'padding-right': {
type: String,
fieldType: 'Number',
value: '10px',
},
};
}
static get options() {
return {
componentName: 'fusion-table-cell',
componentType: 'static',
componentCategory: 'data',
componentUIName: 'Table Cell',
componentScope: 'standard',
componentDescription: 'Basic table cell component',
componentDomain: 'slide',
isTextEdit: true,
isRootNested: false,
nestedTypes: ['*'],
nestedComponents: ['*'],
defaultTemplate: '<p>Cell text</p>',
resizable: 'e',
draggable: false,
rotatable: false,
sortable: false,
};
}
connectedCallback() {
super.connectedCallback();
this.emitCustomEvent(`${this.constructor.options.componentName}:added`);
}
disconnectedCallback() {
super.disconnectedCallback();
this.emitCustomEvent(`${this.constructor.options.componentName}:removed`);
}
update(changedProps) {
super.update(changedProps);
if (changedProps.has('background-color')) {
this.emitCustomEvent(`${this.constructor.options.componentName}:bg-changed`);
}
}
checkSizes(sizeProps) {
super.checkSizes(sizeProps);
this.triggerEvent();
}
triggerEvent() {
this.emitCustomEvent(`${this.constructor.options.componentName}:resized`);
}
static getStyle() {
const styleRoot = super.getStyle();
return `
${styleRoot}
:host {
position: relative;
height: 100%;
}`;
}
render() {
super.render();
return html`
<style>
${FusionTableCell.getStyle()}
</style>
<div class='content'>
<slot></slot>
</div>
${FusionTableCell.getSystemSlotTemplate()}
`;
}
}
class FusionTable extends applyMixins(FusionBase, [Font, SlideComponent]) {
static get properties() {
return {
...super.properties,
columns: {
type: String,
fieldType: 'Number',
value: '3',
min: 0,
prop: true,
},
rows: {
type: String,
fieldType: 'Number',
value: '3',
min: 0,
prop: true,
},
color: {
type: String,
fieldType: 'ColorPicker',
value: 'rgba(0, 0, 0, 1)',
},
'padding-top': {
type: String,
fieldType: 'Number',
value: '10px',
},
'padding-bottom': {
type: String,
fieldType: 'Number',
value: '10px',
},
'padding-left': {
type: String,
fieldType: 'Number',
value: '10px',
},
'padding-right': {
type: String,
fieldType: 'Number',
value: '10px',
},
'border-color': {
type: String,
fieldType: 'ColorPicker',
value: 'rgba(0, 0, 0, 1)',
},
'background-color': {
type: String,
fieldType: 'ColorPicker',
value: 'rgba(255, 255, 255, 1)',
},
'border-width': {
type: String,
fieldType: 'Number',
value: '1px',
},
'border-radius': {
type: String,
fieldType: 'Number',
value: '0px',
},
};
}
static get options() {
return {
componentName: 'fusion-table',
componentType: 'static',
componentCategory: 'data',
componentUIName: 'Table',
componentScope: 'standard',
componentDescription: 'Basic table component',
componentDomain: 'slide',
isTextEdit: true,
isRootNested: true,
nestedTypes: [],
nestedComponents: [],
defaultTemplate: '',
resizable: false,
draggable: 'xy',
rotatable: true,
sortable: false,
};
}
static getChildComponent(component) {
const { componentName } = component.options;
return {
component,
name: componentName,
events: {
add: `${componentName}:added`,
remove: `${componentName}:removed`,
resize: `${componentName}:resized`,
bgChange: `${componentName}:bg-changed`,
},
};
}
constructor() {
super();
this.cell = FusionTable.getChildComponent(FusionTableCell);
this.prevTableOffsetWidth = 0;
this.generateMissedCells = this.isCellsExist();
this.saveUpdatedColumnCells = debounce((currentCell) => {
this.columnCells.map(cell => FusionApi.saveStyles(`#${cell.id}`, { width: currentCell.width }));
});
}
getExistCells() {
return Array.from(this.getElementsByTagName(this.cell.name));
}
isCellsExist() {
return this.getExistCells().length > 0;
}
connectedCallback() {
super.connectedCallback();
this.addEventListener(this.cell.events.resize, this.cellResizeHandler.bind(this));
this.addEventListener(this.cell.events.add, this.cellAddHandler.bind(this));
}
shouldCellResize(targetCell) {
return this.columnCells.some(item => item.width !== targetCell.width);
}
static getColumnIndex(cell) {
return cell.getAttribute('slot').split('_')[1];
}
getColumnCells(columnIndex, arr = this.getExistCells()) {
return arr
.filter(cell => this.constructor.getColumnIndex(cell) === columnIndex);
}
cellResizeHandler(e) {
const targetCell = e.target;
const columnIndex = this.constructor.getColumnIndex(targetCell);
this.columnCells = this.getColumnCells(columnIndex);
if (this.shouldCellResize(targetCell)) {
this.updateColumnCellsWidth(targetCell);
this.saveUpdatedColumnCells(targetCell);
this.updateColumnTdsWidth(targetCell, columnIndex);
}
}
updateColumnCellsWidth(currentCell) {
this.columnCells.forEach((cell) => { cell.width = currentCell.width; });
}
updateColumnTdsWidth(currentCell, columnIndex) {
[...this.table.querySelectorAll('td')]
.filter(cell => cell.dataset.slot.split('_')[1] === columnIndex)
.forEach((cell) => {
cell.style.setProperty('width', currentCell.width);
});
}
cellAddHandler(e) {
const curItem = e.target;
curItem.addEventListener(this.cell.events.remove, this.cellRemoveHandler.bind(this));
curItem.addEventListener(this.cell.events.bgChange, this.cellBgChangeHandler.bind(this));
}
getTableCell(fusionCell) {
const curCellSlot = fusionCell.slot;
return this.table.querySelector(`[data-slot="${curCellSlot}"]`);
}
cellRemoveHandler(e) {
const curCell = e.target;
const cell = this.getTableCell(curCell);
if (cell) {
const cellSlot = cell.querySelector(`[name="${curCell.slot}"]`);
cellSlot.removeAttribute('name');
cell.removeAttribute('data-slot');
}
}
cellBgChangeHandler(e) {
const fusionCell = e.target;
const cell = this.getTableCell(fusionCell);
if (cell) {
FusionTable.setTableCellBg(cell, fusionCell);
}
}
static setTableCellBg(cell, fusionCell) {
cell.style.background = fusionCell['background-color'];
}
initTable() {
this.table = document.createElement('table');
this.table.appendChild(this.initThead());
this.table.appendChild(this.initTbody());
}
clearTable() {
this.table.innerHTML = '';
this.deleteAllFusionCells();
}
static getSlotKey(rowIndex, cellIndex) {
return `${rowIndex}_${cellIndex}`;
}
static addCellSlot(cell, key) {
const slot = document.createElement('slot');
slot.setAttribute('name', key);
cell.appendChild(slot);
}
addFusionCell(key) {
const { componentName, defaultTemplate } = this.cell.component.options;
const unit = 'px';
FusionApi.createElement(
componentName,
{
width: {
value: `100${unit}`,
},
color: {
value: this.color,
},
'font-size': {
value: this['font-size'],
},
slot: {
value: key,
},
},
defaultTemplate,
this,
`#${this.id}`,
{},
);
}
addCustomCell(cell, rowIndex, cellIndex) {
const key = FusionTable.getSlotKey(rowIndex, cellIndex);
if (this.generateMissedCells) {
this.generateMissedSlots(cell, key);
} else {
FusionTable.setCellSlotAttr(cell, key);
this.addFusionCell(key);
}
}
generateMissedSlots(cell, key) {
const fusionCell = this.getExistCells().find(currentCell => currentCell.slot === key);
if (fusionCell) {
FusionTable.setCellSlotAttr(cell, key);
FusionTable.setTableCellBg(cell, fusionCell);
}
}
static setCellSlotAttr(cell, key) {
cell.setAttribute('data-slot', key);
FusionTable.addCellSlot(cell, key);
}
initThead() {
this.thead = document.createElement('thead');
const row = this.thead.insertRow(0);
this.addRowCells(row, 0);
return this.thead;
}
initTbody() {
this.tbody = document.createElement('tbody');
this.addRows();
return this.tbody;
}
addRows() {
for (let index = 0; index < this.rows - 1; index += 1) {
if (!this.tbody.rows[index]) {
const tr = this.tbody.insertRow(index);
const rowIndex = index + 1;
this.addRowCells(tr, rowIndex);
}
}
}
deleteRows(count) {
const { rows } = this.tbody;
for (let index = 0; index < count; index += 1) {
const rowIndex = rows.length - 1;
const row = rows[rowIndex];
this.tbody.deleteRow(rowIndex);
this.deleteRowFusionCells(row);
}
}
addRowCells(row, rowIndex) {
for (let index = 0; index < parseInt(this.columns, 10); index += 1) {
if (!row.cells[index]) {
const cell = row.insertCell(index);
this.addCustomCell(cell, rowIndex, cell.cellIndex);
}
}
}
deleteRowFusionCells(row) {
const cells = Array.from(row.cells);
cells.forEach((cell) => {
this.deleteFusionCell(cell.dataset.slot);
});
}
addCellsListeners() {
this.getExistCells().forEach((cell) => {
cell.addEventListener(this.cell.events.remove, this.cellRemoveHandler.bind(this));
cell.addEventListener(this.cell.events.bgChange, this.cellBgChangeHandler.bind(this));
});
}
deleteAllFusionCells() {
this.getExistCells().forEach((cell) => {
this.removeChild(cell);
});
}
deleteFusionCell(key) {
const cell = this.getExistCells().find(currentCell => currentCell.slot === key);
this.removeChild(cell);
}
deleteFusionCells(row, count) {
const { cells } = row;
for (let index = 0; index < count; index += 1) {
const cellIndex = cells.length - 1;
const cell = cells[cellIndex];
row.deleteCell(cellIndex);
this.deleteFusionCell(cell.dataset.slot);
}
}
addCells(parent) {
const rows = Array.from(parent.rows);
rows.forEach((row) => {
this.addRowCells(row, row.rowIndex);
});
}
addColumns() {
this.addCells(this.thead);
this.addCells(this.tbody);
}
deleteCells(parent, count) {
const rows = Array.from(parent.rows);
rows.forEach((row) => {
this.deleteFusionCells(row, count);
});
}
deleteColumns(count) {
this.deleteCells(this.thead, count);
this.deleteCells(this.tbody, count);
}
static isCountIncreased(oldVal, newVal) {
return newVal > oldVal;
}
updateContent(attr, oldVal, newVal) {
const isIncreased = FusionTable.isCountIncreased(oldVal, newVal);
const difference = FusionTable.checkDifference(oldVal, newVal);
switch (attr) {
case 'rows':
this.updateRows(difference, isIncreased);
break;
case 'columns':
this.updateColumns(difference, isIncreased);
break;
default:
break;
}
}
static checkDifference(oldVal, newVal) {
return Math.abs(oldVal - newVal);
}
updateRows(count, isIncreased) {
isIncreased ? this.addRows() : this.deleteRows(count);
}
updateColumns(count, isIncreased) {
isIncreased ? this.addColumns() : this.deleteColumns(count);
}
fillTable(prop, oldV, newV) {
(!oldV) ? this.initTable() : this.updateContent(prop, oldV, newV);
}
updateTable(changedProps) {
Array.from(changedProps.keys()).every((prop) => {
const newV = +this[prop];
const oldV = +changedProps.get(prop);
(!newV) ? this.clearTable() : this.fillTable(prop, oldV, newV);
return true;
});
}
setWidthValue(value) {
return (this.prevTableOffsetWidth > value) ? this.prevTableOffsetWidth : value;
}
isMinTableWidth() {
return this.prevTableOffsetWidth === this.table.offsetWidth;
}
compareWidth(value) {
if (this.table) {
if (value < this.table.offsetWidth) {
this.isMinTableWidth() ? this.setMinWidth(this.prevTableOffsetWidth) : this.setMinWidth();
}
this.prevTableOffsetWidth = this.table.offsetWidth;
}
}
static isStructureAttr(changedProps) {
return changedProps.has('rows') || changedProps.has('columns');
}
static isTableStyleAttrs(changedProps) {
const tableStyleProps = [
'border-color',
'border-width',
'background-color',
];
return tableStyleProps.filter(prop => changedProps.has(prop)).pop();
}
static isCellStyleAttrs(changedProps) {
const cellStyleProps = [
'color',
'font-size',
'font-family',
'font-weight',
'font-style',
'padding-top',
'padding-bottom',
'padding-left',
'padding-right',
];
return cellStyleProps.filter(prop => changedProps.has(prop)).pop();
}
update(changedProps) {
const tableStyleProps = FusionTable.isTableStyleAttrs(changedProps);
const cellsStyleProps = FusionTable.isCellStyleAttrs(changedProps);
if (!this.isRendered) {
this.initTable();
} else if (FusionTable.isStructureAttr(changedProps)) {
this.updateTable(changedProps);
} else if (tableStyleProps) {
this.setAttribute(tableStyleProps, this[tableStyleProps]);
} else if (cellsStyleProps) {
this.setupItemsStyles(cellsStyleProps);
}
super.update(changedProps);
}
setupItemsStyles(prop) {
const items = this.getExistCells();
items.forEach((item) => {
item.setAttribute(prop, this[prop]);
});
}
setMinWidth(value = 0) {
this.style['min-width'] = `${value}px`;
}
firstUpdated(changedProps) {
super.firstUpdated(changedProps);
this.addCellsListeners();
this.generateMissedCells = false;
}
static getStyle() {
const styleRoot = super.getStyle();
return `
${styleRoot}
:host {
display: block;
}
:host table {
width:100%;
height: 100%;
border-collapse: separate;
border-spacing: 0;
background: var(--background-color);
border-radius: var(--border-radius);
}
:host thead td {
font-weight: bold;
}
:host thead tr:first-child td{
border-top: var(--border-width) solid var(--border-color);
}
:host tr td:first-child {
border-left: var(--border-width) solid var(--border-color);
}
:host thead tr:first-child td:first-child {
border-top-left-radius: var(--border-radius);
}
:host thead tr:first-child td:last-child {
border-top-right-radius: var(--border-radius);
}
:host tbody tr:last-child td:first-child {
border-bottom-left-radius: var(--border-radius);
}
:host tbody tr:last-child td:last-child {
border-bottom-right-radius: var(--border-radius);
}
:host td {
position: relative;
border-right: var(--border-width) solid var(--border-color);
border-bottom: var(--border-width) solid var(--border-color);
color: var(--color);
font-size: var(--font-size);
}`;
}
render() {
super.render();
return html`
<style>
${FusionTable.getStyle()}
</style>
${this.table}
${FusionTable.getSystemSlotTemplate()}
`;
}
}
export { FusionTableCell, FusionTable };