| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446 |
- import {addClass, outerHeight, outerWidth} from './../helpers/dom/element';
- import {arrayEach} from './../helpers/array';
- /**
- * @class GhostTable
- * @util
- */
- class GhostTable {
- constructor(hotInstance) {
- /**
- * Handsontable instance.
- *
- * @type {Core}
- */
- this.hot = hotInstance;
- /**
- * Container element where every table will be injected.
- *
- * @type {HTMLElement|null}
- */
- this.container = null;
- /**
- * Flag which determine is table was injected to DOM.
- *
- * @type {Boolean}
- */
- this.injected = false;
- /**
- * Added rows collection.
- *
- * @type {Array}
- */
- this.rows = [];
- /**
- * Added columns collection.
- *
- * @type {Array}
- */
- this.columns = [];
- /**
- * Samples prepared for calculations.
- *
- * @type {Map}
- * @default {null}
- */
- this.samples = null;
- /**
- * Ghost table settings.
- *
- * @type {Object}
- * @default {Object}
- */
- this.settings = {
- useHeaders: true
- };
- }
- /**
- * Add row.
- *
- * @param {Number} row Row index.
- * @param {Map} samples Samples Map object.
- */
- addRow(row, samples) {
- if (this.columns.length) {
- throw new Error('Doesn\'t support multi-dimensional table');
- }
- if (!this.rows.length) {
- this.container = this.createContainer(this.hot.rootElement.className);
- }
- const rowObject = {row};
- this.rows.push(rowObject);
- this.samples = samples;
- this.table = this.createTable(this.hot.table.className);
- this.table.colGroup.appendChild(this.createColGroupsCol());
- this.table.tr.appendChild(this.createRow(row));
- this.container.container.appendChild(this.table.fragment);
- rowObject.table = this.table.table;
- }
- /**
- * Add a row consisting of the column headers.
- */
- addColumnHeadersRow(samples) {
- if (this.hot.getColHeader(0) != null) {
- const rowObject = {row: -1};
- this.rows.push(rowObject);
- this.container = this.createContainer(this.hot.rootElement.className);
- this.samples = samples;
- this.table = this.createTable(this.hot.table.className);
- this.table.colGroup.appendChild(this.createColGroupsCol());
- this.table.tHead.appendChild(this.createColumnHeadersRow());
- this.container.container.appendChild(this.table.fragment);
- rowObject.table = this.table.table;
- }
- }
- /**
- * Add column.
- *
- * @param {Number} column Column index.
- * @param {Map} samples Samples Map object.
- */
- addColumn(column, samples) {
- if (this.rows.length) {
- throw new Error('Doesn\'t support multi-dimensional table');
- }
- if (!this.columns.length) {
- this.container = this.createContainer(this.hot.rootElement.className);
- }
- const columnObject = {col: column};
- this.columns.push(columnObject);
- this.samples = samples;
- this.table = this.createTable(this.hot.table.className);
- if (this.getSetting('useHeaders') && this.hot.getColHeader(column) !== null) {
- this.hot.view.appendColHeader(column, this.table.th);
- }
- this.table.tBody.appendChild(this.createCol(column));
- this.container.container.appendChild(this.table.fragment);
- columnObject.table = this.table.table;
- }
- /**
- * Get calculated heights.
- *
- * @param {Function} callback Callback which will be fired for each calculated row.
- */
- getHeights(callback) {
- if (!this.injected) {
- this.injectTable();
- }
- arrayEach(this.rows, (row) => {
- // -1 <- reduce border-top from table
- callback(row.row, outerHeight(row.table) - 1);
- });
- }
- /**
- * Get calculated widths.
- *
- * @param {Function} callback Callback which will be fired for each calculated column.
- */
- getWidths(callback) {
- if (!this.injected) {
- this.injectTable();
- }
- arrayEach(this.columns, (column) => {
- callback(column.col, outerWidth(column.table));
- });
- }
- /**
- * Set the Ghost Table settings to the provided object.
- *
- * @param {Object} settings New Ghost Table Settings
- */
- setSettings(settings) {
- this.settings = settings;
- }
- /**
- * Set a single setting of the Ghost Table.
- *
- * @param {String} name Setting name.
- * @param {*} value Setting value.
- */
- setSetting(name, value) {
- if (!this.settings) {
- this.settings = {};
- }
- this.settings[name] = value;
- }
- /**
- * Get the Ghost Table settings.
- *
- * @returns {Object|null}
- */
- getSettings() {
- return this.settings;
- }
- /**
- * Get a single Ghost Table setting.
- *
- * @param {String} name
- * @returns {Boolean|null}
- */
- getSetting(name) {
- if (this.settings) {
- return this.settings[name];
- }
- return null;
- }
- /**
- * Create colgroup col elements.
- *
- * @returns {DocumentFragment}
- */
- createColGroupsCol() {
- const d = document;
- const fragment = d.createDocumentFragment();
- if (this.hot.hasRowHeaders()) {
- fragment.appendChild(this.createColElement(-1));
- }
- this.samples.forEach((sample) => {
- arrayEach(sample.strings, (string) => {
- fragment.appendChild(this.createColElement(string.col));
- });
- });
- return fragment;
- }
- /**
- * Create table row element.
- *
- * @param {Number} row Row index.
- * @returns {DocumentFragment} Returns created table row elements.
- */
- createRow(row) {
- const d = document;
- const fragment = d.createDocumentFragment();
- const th = d.createElement('th');
- if (this.hot.hasRowHeaders()) {
- this.hot.view.appendRowHeader(row, th);
- fragment.appendChild(th);
- }
- this.samples.forEach((sample) => {
- arrayEach(sample.strings, (string) => {
- let column = string.col;
- let cellProperties = this.hot.getCellMeta(row, column);
- cellProperties.col = column;
- cellProperties.row = row;
- let renderer = this.hot.getCellRenderer(cellProperties);
- const td = d.createElement('td');
- renderer(this.hot, td, row, column, this.hot.colToProp(column), string.value, cellProperties);
- fragment.appendChild(td);
- });
- });
- return fragment;
- }
- createColumnHeadersRow() {
- const d = document;
- const fragment = d.createDocumentFragment();
- if (this.hot.hasRowHeaders()) {
- const th = d.createElement('th');
- this.hot.view.appendColHeader(-1, th);
- fragment.appendChild(th);
- }
- this.samples.forEach((sample) => {
- arrayEach(sample.strings, (string) => {
- let column = string.col;
- const th = d.createElement('th');
- this.hot.view.appendColHeader(column, th);
- fragment.appendChild(th);
- });
- });
- return fragment;
- }
- /**
- * Create table column elements.
- *
- * @param {Number} column Column index.
- * @returns {DocumentFragment} Returns created column table column elements.
- */
- createCol(column) {
- const d = document;
- const fragment = d.createDocumentFragment();
- this.samples.forEach((sample) => {
- arrayEach(sample.strings, (string) => {
- let row = string.row;
- let cellProperties = this.hot.getCellMeta(row, column);
- cellProperties.col = column;
- cellProperties.row = row;
- let renderer = this.hot.getCellRenderer(cellProperties);
- const td = d.createElement('td');
- const tr = d.createElement('tr');
- renderer(this.hot, td, row, column, this.hot.colToProp(column), string.value, cellProperties);
- tr.appendChild(td);
- fragment.appendChild(tr);
- });
- });
- return fragment;
- }
- /**
- * Remove table from document and reset internal state.
- */
- clean() {
- this.rows.length = 0;
- this.rows[-1] = void 0;
- this.columns.length = 0;
- if (this.samples) {
- this.samples.clear();
- }
- this.samples = null;
- this.removeTable();
- }
- /**
- * Inject generated table into document.
- *
- * @param {HTMLElement} [parent=null]
- */
- injectTable(parent = null) {
- if (!this.injected) {
- (parent || this.hot.rootElement).appendChild(this.container.fragment);
- this.injected = true;
- }
- }
- /**
- * Remove table from document.
- */
- removeTable() {
- if (this.injected && this.container.container.parentNode) {
- this.container.container.parentNode.removeChild(this.container.container);
- this.container = null;
- this.injected = false;
- }
- }
- /**
- * Create col element.
- *
- * @param {Number} column Column index.
- * @returns {HTMLElement}
- */
- createColElement(column) {
- const d = document;
- const col = d.createElement('col');
- col.style.width = `${this.hot.view.wt.wtTable.getStretchedColumnWidth(column)}px`;
- return col;
- }
- /**
- * Create table element.
- *
- * @param {String} className
- * @returns {Object}
- */
- createTable(className = '') {
- const d = document;
- const fragment = d.createDocumentFragment();
- const table = d.createElement('table');
- const tHead = d.createElement('thead');
- const tBody = d.createElement('tbody');
- const colGroup = d.createElement('colgroup');
- const tr = d.createElement('tr');
- const th = d.createElement('th');
- if (this.isVertical()) {
- table.appendChild(colGroup);
- }
- if (this.isHorizontal()) {
- tr.appendChild(th);
- tHead.appendChild(tr);
- table.style.tableLayout = 'auto';
- table.style.width = 'auto';
- }
- table.appendChild(tHead);
- if (this.isVertical()) {
- tBody.appendChild(tr);
- }
- table.appendChild(tBody);
- addClass(table, className);
- fragment.appendChild(table);
- return {fragment, table, tHead, tBody, colGroup, tr, th};
- }
- /**
- * Create container for tables.
- *
- * @param {String} className
- * @returns {Object}
- */
- createContainer(className = '') {
- const d = document;
- const fragment = d.createDocumentFragment();
- const container = d.createElement('div');
- className = `htGhostTable htAutoSize ${className.trim()}`;
- addClass(container, className);
- fragment.appendChild(container);
- return {fragment, container};
- }
- /**
- * Checks if table is raised vertically (checking rows).
- *
- * @returns {Boolean}
- */
- isVertical() {
- return !!(this.rows.length && !this.columns.length);
- }
- /**
- * Checks if table is raised horizontally (checking columns).
- *
- * @returns {Boolean}
- */
- isHorizontal() {
- return !!(this.columns.length && !this.rows.length);
- }
- }
- export default GhostTable;
|