dd7ba0095bef82aaf5e642039b554175fd01f2292731178a70f594472c59f47230830f7847354edc06693a8b284acfc7d7676db7bb08f8ee6c6ea02212bdf3 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726
  1. var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
  2. function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  3. import { addClass, empty, getScrollbarWidth, hasClass, innerHeight, outerWidth } from './../../../helpers/dom/element';
  4. import Overlay from './overlay/_base';
  5. var performanceWarningAppeared = false;
  6. /**
  7. * @class TableRenderer
  8. */
  9. var TableRenderer = function () {
  10. /**
  11. * @param {WalkontableTable} wtTable
  12. */
  13. function TableRenderer(wtTable) {
  14. _classCallCheck(this, TableRenderer);
  15. this.wtTable = wtTable;
  16. this.wot = wtTable.instance;
  17. // legacy support
  18. this.instance = wtTable.instance;
  19. this.rowFilter = wtTable.rowFilter;
  20. this.columnFilter = wtTable.columnFilter;
  21. this.TABLE = wtTable.TABLE;
  22. this.THEAD = wtTable.THEAD;
  23. this.TBODY = wtTable.TBODY;
  24. this.COLGROUP = wtTable.COLGROUP;
  25. this.rowHeaders = [];
  26. this.rowHeaderCount = 0;
  27. this.columnHeaders = [];
  28. this.columnHeaderCount = 0;
  29. this.fixedRowsTop = 0;
  30. this.fixedRowsBottom = 0;
  31. }
  32. /**
  33. *
  34. */
  35. _createClass(TableRenderer, [{
  36. key: 'render',
  37. value: function render() {
  38. if (!this.wtTable.isWorkingOnClone()) {
  39. var skipRender = {};
  40. this.wot.getSetting('beforeDraw', true, skipRender);
  41. if (skipRender.skipRender === true) {
  42. return;
  43. }
  44. }
  45. this.rowHeaders = this.wot.getSetting('rowHeaders');
  46. this.rowHeaderCount = this.rowHeaders.length;
  47. this.fixedRowsTop = this.wot.getSetting('fixedRowsTop');
  48. this.fixedRowsBottom = this.wot.getSetting('fixedRowsBottom');
  49. this.columnHeaders = this.wot.getSetting('columnHeaders');
  50. this.columnHeaderCount = this.columnHeaders.length;
  51. var columnsToRender = this.wtTable.getRenderedColumnsCount();
  52. var rowsToRender = this.wtTable.getRenderedRowsCount();
  53. var totalColumns = this.wot.getSetting('totalColumns');
  54. var totalRows = this.wot.getSetting('totalRows');
  55. var workspaceWidth = void 0;
  56. var adjusted = false;
  57. if (Overlay.isOverlayTypeOf(this.wot.cloneOverlay, Overlay.CLONE_BOTTOM) || Overlay.isOverlayTypeOf(this.wot.cloneOverlay, Overlay.CLONE_BOTTOM_LEFT_CORNER)) {
  58. // do NOT render headers on the bottom or bottom-left corner overlay
  59. this.columnHeaders = [];
  60. this.columnHeaderCount = 0;
  61. }
  62. if (totalColumns >= 0) {
  63. // prepare COL and TH elements for rendering
  64. this.adjustAvailableNodes();
  65. adjusted = true;
  66. // adjust column widths according to user widths settings
  67. this.renderColumnHeaders();
  68. // Render table rows
  69. this.renderRows(totalRows, rowsToRender, columnsToRender);
  70. if (!this.wtTable.isWorkingOnClone()) {
  71. workspaceWidth = this.wot.wtViewport.getWorkspaceWidth();
  72. this.wot.wtViewport.containerWidth = null;
  73. }
  74. this.adjustColumnWidths(columnsToRender);
  75. this.markOversizedColumnHeaders();
  76. this.adjustColumnHeaderHeights();
  77. }
  78. if (!adjusted) {
  79. this.adjustAvailableNodes();
  80. }
  81. this.removeRedundantRows(rowsToRender);
  82. if (!this.wtTable.isWorkingOnClone() || this.wot.isOverlayName(Overlay.CLONE_BOTTOM)) {
  83. this.markOversizedRows();
  84. }
  85. if (!this.wtTable.isWorkingOnClone()) {
  86. this.wot.wtViewport.createVisibleCalculators();
  87. this.wot.wtOverlays.refresh(false);
  88. this.wot.wtOverlays.applyToDOM();
  89. var hiderWidth = outerWidth(this.wtTable.hider);
  90. var tableWidth = outerWidth(this.wtTable.TABLE);
  91. if (hiderWidth !== 0 && tableWidth !== hiderWidth) {
  92. // Recalculate the column widths, if width changes made in the overlays removed the scrollbar, thus changing the viewport width.
  93. this.adjustColumnWidths(columnsToRender);
  94. }
  95. if (workspaceWidth !== this.wot.wtViewport.getWorkspaceWidth()) {
  96. // workspace width changed though to shown/hidden vertical scrollbar. Let's reapply stretching
  97. this.wot.wtViewport.containerWidth = null;
  98. var firstRendered = this.wtTable.getFirstRenderedColumn();
  99. var lastRendered = this.wtTable.getLastRenderedColumn();
  100. var defaultColumnWidth = this.wot.getSetting('defaultColumnWidth');
  101. var rowHeaderWidthSetting = this.wot.getSetting('rowHeaderWidth');
  102. rowHeaderWidthSetting = this.instance.getSetting('onModifyRowHeaderWidth', rowHeaderWidthSetting);
  103. if (rowHeaderWidthSetting != null) {
  104. for (var i = 0; i < this.rowHeaderCount; i++) {
  105. var width = Array.isArray(rowHeaderWidthSetting) ? rowHeaderWidthSetting[i] : rowHeaderWidthSetting;
  106. width = width == null ? defaultColumnWidth : width;
  107. this.COLGROUP.childNodes[i].style.width = width + 'px';
  108. }
  109. }
  110. for (var _i = firstRendered; _i < lastRendered; _i++) {
  111. var _width = this.wtTable.getStretchedColumnWidth(_i);
  112. var renderedIndex = this.columnFilter.sourceToRendered(_i);
  113. this.COLGROUP.childNodes[renderedIndex + this.rowHeaderCount].style.width = _width + 'px';
  114. }
  115. }
  116. this.wot.getSetting('onDraw', true);
  117. } else if (this.wot.isOverlayName(Overlay.CLONE_BOTTOM)) {
  118. this.wot.cloneSource.wtOverlays.adjustElementsSize();
  119. }
  120. }
  121. /**
  122. * @param {Number} renderedRowsCount
  123. */
  124. }, {
  125. key: 'removeRedundantRows',
  126. value: function removeRedundantRows(renderedRowsCount) {
  127. while (this.wtTable.tbodyChildrenLength > renderedRowsCount) {
  128. this.TBODY.removeChild(this.TBODY.lastChild);
  129. this.wtTable.tbodyChildrenLength--;
  130. }
  131. }
  132. /**
  133. * @param {Number} totalRows
  134. * @param {Number} rowsToRender
  135. * @param {Number} columnsToRender
  136. */
  137. }, {
  138. key: 'renderRows',
  139. value: function renderRows(totalRows, rowsToRender, columnsToRender) {
  140. var lastTD = void 0,
  141. TR = void 0;
  142. var visibleRowIndex = 0;
  143. var sourceRowIndex = this.rowFilter.renderedToSource(visibleRowIndex);
  144. var isWorkingOnClone = this.wtTable.isWorkingOnClone();
  145. while (sourceRowIndex < totalRows && sourceRowIndex >= 0) {
  146. if (!performanceWarningAppeared && visibleRowIndex > 1000) {
  147. performanceWarningAppeared = true;
  148. console.warn('Performance tip: Handsontable rendered more than 1000 visible rows. Consider limiting the number ' + 'of rendered rows by specifying the table height and/or turning off the "renderAllRows" option.');
  149. }
  150. if (rowsToRender !== void 0 && visibleRowIndex === rowsToRender) {
  151. // We have as much rows as needed for this clone
  152. break;
  153. }
  154. TR = this.getOrCreateTrForRow(visibleRowIndex, TR);
  155. // Render row headers
  156. this.renderRowHeaders(sourceRowIndex, TR);
  157. // Add and/or remove TDs to TR to match the desired number
  158. this.adjustColumns(TR, columnsToRender + this.rowHeaderCount);
  159. lastTD = this.renderCells(sourceRowIndex, TR, columnsToRender);
  160. if (!isWorkingOnClone ||
  161. // Necessary to refresh oversized row heights after editing cell in overlays
  162. this.wot.isOverlayName(Overlay.CLONE_BOTTOM)) {
  163. // Reset the oversized row cache for this row
  164. this.resetOversizedRow(sourceRowIndex);
  165. }
  166. if (TR.firstChild) {
  167. // if I have 2 fixed columns with one-line content and the 3rd column has a multiline content, this is
  168. // the way to make sure that the overlay will has same row height
  169. var height = this.wot.wtTable.getRowHeight(sourceRowIndex);
  170. if (height) {
  171. // Decrease height. 1 pixel will be "replaced" by 1px border top
  172. height--;
  173. TR.firstChild.style.height = height + 'px';
  174. } else {
  175. TR.firstChild.style.height = '';
  176. }
  177. }
  178. visibleRowIndex++;
  179. sourceRowIndex = this.rowFilter.renderedToSource(visibleRowIndex);
  180. }
  181. }
  182. /**
  183. * Reset the oversized row cache for the provided index
  184. *
  185. * @param {Number} sourceRow Row index
  186. */
  187. }, {
  188. key: 'resetOversizedRow',
  189. value: function resetOversizedRow(sourceRow) {
  190. if (this.wot.getSetting('externalRowCalculator')) {
  191. return;
  192. }
  193. if (this.wot.wtViewport.oversizedRows && this.wot.wtViewport.oversizedRows[sourceRow]) {
  194. this.wot.wtViewport.oversizedRows[sourceRow] = void 0;
  195. }
  196. }
  197. /**
  198. * Check if any of the rendered rows is higher than expected, and if so, cache them
  199. */
  200. }, {
  201. key: 'markOversizedRows',
  202. value: function markOversizedRows() {
  203. if (this.wot.getSetting('externalRowCalculator')) {
  204. return;
  205. }
  206. var rowCount = this.instance.wtTable.TBODY.childNodes.length;
  207. var expectedTableHeight = rowCount * this.instance.wtSettings.settings.defaultRowHeight;
  208. var actualTableHeight = innerHeight(this.instance.wtTable.TBODY) - 1;
  209. var previousRowHeight = void 0;
  210. var rowInnerHeight = void 0;
  211. var sourceRowIndex = void 0;
  212. var currentTr = void 0;
  213. var rowHeader = void 0;
  214. var totalRows = this.instance.getSetting('totalRows');
  215. if (expectedTableHeight === actualTableHeight && !this.instance.getSetting('fixedRowsBottom')) {
  216. // If the actual table height equals rowCount * default single row height, no row is oversized -> no need to iterate over them
  217. return;
  218. }
  219. while (rowCount) {
  220. rowCount--;
  221. sourceRowIndex = this.instance.wtTable.rowFilter.renderedToSource(rowCount);
  222. previousRowHeight = this.instance.wtTable.getRowHeight(sourceRowIndex);
  223. currentTr = this.instance.wtTable.getTrForRow(sourceRowIndex);
  224. rowHeader = currentTr.querySelector('th');
  225. if (rowHeader) {
  226. rowInnerHeight = innerHeight(rowHeader);
  227. } else {
  228. rowInnerHeight = innerHeight(currentTr) - 1;
  229. }
  230. if (!previousRowHeight && this.instance.wtSettings.settings.defaultRowHeight < rowInnerHeight || previousRowHeight < rowInnerHeight) {
  231. this.instance.wtViewport.oversizedRows[sourceRowIndex] = ++rowInnerHeight;
  232. }
  233. }
  234. }
  235. /**
  236. * Check if any of the rendered columns is higher than expected, and if so, cache them.
  237. */
  238. }, {
  239. key: 'markOversizedColumnHeaders',
  240. value: function markOversizedColumnHeaders() {
  241. var overlayName = this.wot.getOverlayName();
  242. if (!this.columnHeaderCount || this.wot.wtViewport.hasOversizedColumnHeadersMarked[overlayName] || this.wtTable.isWorkingOnClone()) {
  243. return;
  244. }
  245. var columnCount = this.wtTable.getRenderedColumnsCount();
  246. for (var i = 0; i < this.columnHeaderCount; i++) {
  247. for (var renderedColumnIndex = -1 * this.rowHeaderCount; renderedColumnIndex < columnCount; renderedColumnIndex++) {
  248. this.markIfOversizedColumnHeader(renderedColumnIndex);
  249. }
  250. }
  251. this.wot.wtViewport.hasOversizedColumnHeadersMarked[overlayName] = true;
  252. }
  253. /**
  254. *
  255. */
  256. }, {
  257. key: 'adjustColumnHeaderHeights',
  258. value: function adjustColumnHeaderHeights() {
  259. var columnHeaders = this.wot.getSetting('columnHeaders');
  260. var children = this.wot.wtTable.THEAD.childNodes;
  261. var oversizedColumnHeaders = this.wot.wtViewport.oversizedColumnHeaders;
  262. for (var i = 0, len = columnHeaders.length; i < len; i++) {
  263. if (oversizedColumnHeaders[i]) {
  264. if (!children[i] || children[i].childNodes.length === 0) {
  265. return;
  266. }
  267. children[i].childNodes[0].style.height = oversizedColumnHeaders[i] + 'px';
  268. }
  269. }
  270. }
  271. /**
  272. * Check if column header for the specified column is higher than expected, and if so, cache it
  273. *
  274. * @param {Number} col Index of column
  275. */
  276. }, {
  277. key: 'markIfOversizedColumnHeader',
  278. value: function markIfOversizedColumnHeader(col) {
  279. var sourceColIndex = this.wot.wtTable.columnFilter.renderedToSource(col);
  280. var level = this.columnHeaderCount;
  281. var defaultRowHeight = this.wot.wtSettings.settings.defaultRowHeight;
  282. var previousColHeaderHeight = void 0;
  283. var currentHeader = void 0;
  284. var currentHeaderHeight = void 0;
  285. var columnHeaderHeightSetting = this.wot.getSetting('columnHeaderHeight') || [];
  286. while (level) {
  287. level--;
  288. previousColHeaderHeight = this.wot.wtTable.getColumnHeaderHeight(level);
  289. currentHeader = this.wot.wtTable.getColumnHeader(sourceColIndex, level);
  290. if (!currentHeader) {
  291. /* eslint-disable no-continue */
  292. continue;
  293. }
  294. currentHeaderHeight = innerHeight(currentHeader);
  295. if (!previousColHeaderHeight && defaultRowHeight < currentHeaderHeight || previousColHeaderHeight < currentHeaderHeight) {
  296. this.wot.wtViewport.oversizedColumnHeaders[level] = currentHeaderHeight;
  297. }
  298. if (Array.isArray(columnHeaderHeightSetting)) {
  299. if (columnHeaderHeightSetting[level] != null) {
  300. this.wot.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting[level];
  301. }
  302. } else if (!isNaN(columnHeaderHeightSetting)) {
  303. this.wot.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting;
  304. }
  305. if (this.wot.wtViewport.oversizedColumnHeaders[level] < (columnHeaderHeightSetting[level] || columnHeaderHeightSetting)) {
  306. this.wot.wtViewport.oversizedColumnHeaders[level] = columnHeaderHeightSetting[level] || columnHeaderHeightSetting;
  307. }
  308. }
  309. }
  310. /**
  311. * @param {Number} sourceRowIndex
  312. * @param {HTMLTableRowElement} TR
  313. * @param {Number} columnsToRender
  314. * @returns {HTMLTableCellElement}
  315. */
  316. }, {
  317. key: 'renderCells',
  318. value: function renderCells(sourceRowIndex, TR, columnsToRender) {
  319. var TD = void 0;
  320. var sourceColIndex = void 0;
  321. for (var visibleColIndex = 0; visibleColIndex < columnsToRender; visibleColIndex++) {
  322. sourceColIndex = this.columnFilter.renderedToSource(visibleColIndex);
  323. if (visibleColIndex === 0) {
  324. TD = TR.childNodes[this.columnFilter.sourceColumnToVisibleRowHeadedColumn(sourceColIndex)];
  325. } else {
  326. TD = TD.nextSibling; // http://jsperf.com/nextsibling-vs-indexed-childnodes
  327. }
  328. // If the number of headers has been reduced, we need to replace excess TH with TD
  329. if (TD.nodeName == 'TH') {
  330. TD = replaceThWithTd(TD, TR);
  331. }
  332. if (!hasClass(TD, 'hide')) {
  333. TD.className = '';
  334. }
  335. TD.removeAttribute('style');
  336. this.wot.wtSettings.settings.cellRenderer(sourceRowIndex, sourceColIndex, TD);
  337. }
  338. return TD;
  339. }
  340. /**
  341. * @param {Number} columnsToRender Number of columns to render.
  342. */
  343. }, {
  344. key: 'adjustColumnWidths',
  345. value: function adjustColumnWidths(columnsToRender) {
  346. var scrollbarCompensation = 0;
  347. var sourceInstance = this.wot.cloneSource ? this.wot.cloneSource : this.wot;
  348. var mainHolder = sourceInstance.wtTable.holder;
  349. var defaultColumnWidth = this.wot.getSetting('defaultColumnWidth');
  350. var rowHeaderWidthSetting = this.wot.getSetting('rowHeaderWidth');
  351. if (mainHolder.offsetHeight < mainHolder.scrollHeight) {
  352. scrollbarCompensation = getScrollbarWidth();
  353. }
  354. this.wot.wtViewport.columnsRenderCalculator.refreshStretching(this.wot.wtViewport.getViewportWidth() - scrollbarCompensation);
  355. rowHeaderWidthSetting = this.instance.getSetting('onModifyRowHeaderWidth', rowHeaderWidthSetting);
  356. if (rowHeaderWidthSetting != null) {
  357. for (var i = 0; i < this.rowHeaderCount; i++) {
  358. var width = Array.isArray(rowHeaderWidthSetting) ? rowHeaderWidthSetting[i] : rowHeaderWidthSetting;
  359. width = width == null ? defaultColumnWidth : width;
  360. this.COLGROUP.childNodes[i].style.width = width + 'px';
  361. }
  362. }
  363. for (var renderedColIndex = 0; renderedColIndex < columnsToRender; renderedColIndex++) {
  364. var _width2 = this.wtTable.getStretchedColumnWidth(this.columnFilter.renderedToSource(renderedColIndex));
  365. this.COLGROUP.childNodes[renderedColIndex + this.rowHeaderCount].style.width = _width2 + 'px';
  366. }
  367. }
  368. /**
  369. * @param {HTMLTableCellElement} TR
  370. */
  371. }, {
  372. key: 'appendToTbody',
  373. value: function appendToTbody(TR) {
  374. this.TBODY.appendChild(TR);
  375. this.wtTable.tbodyChildrenLength++;
  376. }
  377. /**
  378. * @param {Number} rowIndex
  379. * @param {HTMLTableRowElement} currentTr
  380. * @returns {HTMLTableCellElement}
  381. */
  382. }, {
  383. key: 'getOrCreateTrForRow',
  384. value: function getOrCreateTrForRow(rowIndex, currentTr) {
  385. var TR = void 0;
  386. if (rowIndex >= this.wtTable.tbodyChildrenLength) {
  387. TR = this.createRow();
  388. this.appendToTbody(TR);
  389. } else if (rowIndex === 0) {
  390. TR = this.TBODY.firstChild;
  391. } else {
  392. // http://jsperf.com/nextsibling-vs-indexed-childnodes
  393. TR = currentTr.nextSibling;
  394. }
  395. if (TR.className) {
  396. TR.removeAttribute('class');
  397. }
  398. return TR;
  399. }
  400. /**
  401. * @returns {HTMLTableCellElement}
  402. */
  403. }, {
  404. key: 'createRow',
  405. value: function createRow() {
  406. var TR = document.createElement('TR');
  407. for (var visibleColIndex = 0; visibleColIndex < this.rowHeaderCount; visibleColIndex++) {
  408. TR.appendChild(document.createElement('TH'));
  409. }
  410. return TR;
  411. }
  412. /**
  413. * @param {Number} row
  414. * @param {Number} col
  415. * @param {HTMLTableCellElement} TH
  416. */
  417. }, {
  418. key: 'renderRowHeader',
  419. value: function renderRowHeader(row, col, TH) {
  420. TH.className = '';
  421. TH.removeAttribute('style');
  422. this.rowHeaders[col](row, TH, col);
  423. }
  424. /**
  425. * @param {Number} row
  426. * @param {HTMLTableCellElement} TR
  427. */
  428. }, {
  429. key: 'renderRowHeaders',
  430. value: function renderRowHeaders(row, TR) {
  431. for (var TH = TR.firstChild, visibleColIndex = 0; visibleColIndex < this.rowHeaderCount; visibleColIndex++) {
  432. // If the number of row headers increased we need to create TH or replace an existing TD node with TH
  433. if (!TH) {
  434. TH = document.createElement('TH');
  435. TR.appendChild(TH);
  436. } else if (TH.nodeName == 'TD') {
  437. TH = replaceTdWithTh(TH, TR);
  438. }
  439. this.renderRowHeader(row, visibleColIndex, TH);
  440. // http://jsperf.com/nextsibling-vs-indexed-childnodes
  441. TH = TH.nextSibling;
  442. }
  443. }
  444. /**
  445. * Adjust the number of COL and TH elements to match the number of columns and headers that need to be rendered
  446. */
  447. }, {
  448. key: 'adjustAvailableNodes',
  449. value: function adjustAvailableNodes() {
  450. this.adjustColGroups();
  451. this.adjustThead();
  452. }
  453. /**
  454. * Renders the column headers
  455. */
  456. }, {
  457. key: 'renderColumnHeaders',
  458. value: function renderColumnHeaders() {
  459. if (!this.columnHeaderCount) {
  460. return;
  461. }
  462. var columnCount = this.wtTable.getRenderedColumnsCount();
  463. for (var i = 0; i < this.columnHeaderCount; i++) {
  464. var TR = this.getTrForColumnHeaders(i);
  465. for (var renderedColumnIndex = -1 * this.rowHeaderCount; renderedColumnIndex < columnCount; renderedColumnIndex++) {
  466. var sourceCol = this.columnFilter.renderedToSource(renderedColumnIndex);
  467. this.renderColumnHeader(i, sourceCol, TR.childNodes[renderedColumnIndex + this.rowHeaderCount]);
  468. }
  469. }
  470. }
  471. /**
  472. * Adjusts the number of COL elements to match the number of columns that need to be rendered
  473. */
  474. }, {
  475. key: 'adjustColGroups',
  476. value: function adjustColGroups() {
  477. var columnCount = this.wtTable.getRenderedColumnsCount();
  478. while (this.wtTable.colgroupChildrenLength < columnCount + this.rowHeaderCount) {
  479. this.COLGROUP.appendChild(document.createElement('COL'));
  480. this.wtTable.colgroupChildrenLength++;
  481. }
  482. while (this.wtTable.colgroupChildrenLength > columnCount + this.rowHeaderCount) {
  483. this.COLGROUP.removeChild(this.COLGROUP.lastChild);
  484. this.wtTable.colgroupChildrenLength--;
  485. }
  486. if (this.rowHeaderCount) {
  487. addClass(this.COLGROUP.childNodes[0], 'rowHeader');
  488. }
  489. }
  490. /**
  491. * Adjusts the number of TH elements in THEAD to match the number of headers and columns that need to be rendered
  492. */
  493. }, {
  494. key: 'adjustThead',
  495. value: function adjustThead() {
  496. var columnCount = this.wtTable.getRenderedColumnsCount();
  497. var TR = this.THEAD.firstChild;
  498. if (this.columnHeaders.length) {
  499. for (var i = 0, len = this.columnHeaders.length; i < len; i++) {
  500. TR = this.THEAD.childNodes[i];
  501. if (!TR) {
  502. TR = document.createElement('TR');
  503. this.THEAD.appendChild(TR);
  504. }
  505. this.theadChildrenLength = TR.childNodes.length;
  506. while (this.theadChildrenLength < columnCount + this.rowHeaderCount) {
  507. TR.appendChild(document.createElement('TH'));
  508. this.theadChildrenLength++;
  509. }
  510. while (this.theadChildrenLength > columnCount + this.rowHeaderCount) {
  511. TR.removeChild(TR.lastChild);
  512. this.theadChildrenLength--;
  513. }
  514. }
  515. var theadChildrenLength = this.THEAD.childNodes.length;
  516. if (theadChildrenLength > this.columnHeaders.length) {
  517. for (var _i2 = this.columnHeaders.length; _i2 < theadChildrenLength; _i2++) {
  518. this.THEAD.removeChild(this.THEAD.lastChild);
  519. }
  520. }
  521. } else if (TR) {
  522. empty(TR);
  523. }
  524. }
  525. /**
  526. * @param {Number} index
  527. * @returns {HTMLTableCellElement}
  528. */
  529. }, {
  530. key: 'getTrForColumnHeaders',
  531. value: function getTrForColumnHeaders(index) {
  532. return this.THEAD.childNodes[index];
  533. }
  534. /**
  535. * @param {Number} row
  536. * @param {Number} col
  537. * @param {HTMLTableCellElement} TH
  538. * @returns {*}
  539. */
  540. }, {
  541. key: 'renderColumnHeader',
  542. value: function renderColumnHeader(row, col, TH) {
  543. TH.className = '';
  544. TH.removeAttribute('style');
  545. return this.columnHeaders[row](col, TH, row);
  546. }
  547. /**
  548. * Add and/or remove the TDs to match the desired number
  549. *
  550. * @param {HTMLTableCellElement} TR Table row in question
  551. * @param {Number} desiredCount The desired number of TDs in the TR
  552. */
  553. }, {
  554. key: 'adjustColumns',
  555. value: function adjustColumns(TR, desiredCount) {
  556. var count = TR.childNodes.length;
  557. while (count < desiredCount) {
  558. var TD = document.createElement('TD');
  559. TR.appendChild(TD);
  560. count++;
  561. }
  562. while (count > desiredCount) {
  563. TR.removeChild(TR.lastChild);
  564. count--;
  565. }
  566. }
  567. /**
  568. * @param {Number} columnsToRender
  569. */
  570. }, {
  571. key: 'removeRedundantColumns',
  572. value: function removeRedundantColumns(columnsToRender) {
  573. while (this.wtTable.tbodyChildrenLength > columnsToRender) {
  574. this.TBODY.removeChild(this.TBODY.lastChild);
  575. this.wtTable.tbodyChildrenLength--;
  576. }
  577. }
  578. }]);
  579. return TableRenderer;
  580. }();
  581. function replaceTdWithTh(TD, TR) {
  582. var TH = document.createElement('TH');
  583. TR.insertBefore(TH, TD);
  584. TR.removeChild(TD);
  585. return TH;
  586. }
  587. function replaceThWithTd(TH, TR) {
  588. var TD = document.createElement('TD');
  589. TR.insertBefore(TD, TH);
  590. TR.removeChild(TH);
  591. return TD;
  592. }
  593. export default TableRenderer;