| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533 |
- 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; }; }();
- function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
- import { getScrollbarWidth, getScrollTop, getStyle, offset, outerHeight, outerWidth } from './../../../helpers/dom/element';
- import { objectEach } from './../../../helpers/object';
- import EventManager from './../../../eventManager';
- import ViewportColumnsCalculator from './calculator/viewportColumns';
- import ViewportRowsCalculator from './calculator/viewportRows';
- /**
- * @class Viewport
- */
- var Viewport = function () {
- /**
- * @param wotInstance
- */
- function Viewport(wotInstance) {
- var _this = this;
- _classCallCheck(this, Viewport);
- this.wot = wotInstance;
- // legacy support
- this.instance = this.wot;
- this.oversizedRows = [];
- this.oversizedColumnHeaders = [];
- this.hasOversizedColumnHeadersMarked = {};
- this.clientHeight = 0;
- this.containerWidth = NaN;
- this.rowHeaderWidth = NaN;
- this.rowsVisibleCalculator = null;
- this.columnsVisibleCalculator = null;
- this.eventManager = new EventManager(this.wot);
- this.eventManager.addEventListener(window, 'resize', function () {
- _this.clientHeight = _this.getWorkspaceHeight();
- });
- }
- /**
- * @returns {number}
- */
- _createClass(Viewport, [{
- key: 'getWorkspaceHeight',
- value: function getWorkspaceHeight() {
- var trimmingContainer = this.instance.wtOverlays.topOverlay.trimmingContainer;
- var elemHeight = void 0;
- var height = 0;
- if (trimmingContainer === window) {
- height = document.documentElement.clientHeight;
- } else {
- elemHeight = outerHeight(trimmingContainer);
- // returns height without DIV scrollbar
- height = elemHeight > 0 && trimmingContainer.clientHeight > 0 ? trimmingContainer.clientHeight : Infinity;
- }
- return height;
- }
- }, {
- key: 'getWorkspaceWidth',
- value: function getWorkspaceWidth() {
- var width = void 0;
- var totalColumns = this.wot.getSetting('totalColumns');
- var trimmingContainer = this.instance.wtOverlays.leftOverlay.trimmingContainer;
- var overflow = void 0;
- var stretchSetting = this.wot.getSetting('stretchH');
- var docOffsetWidth = document.documentElement.offsetWidth;
- var preventOverflow = this.wot.getSetting('preventOverflow');
- if (preventOverflow) {
- return outerWidth(this.instance.wtTable.wtRootElement);
- }
- if (this.wot.getSetting('freezeOverlays')) {
- width = Math.min(docOffsetWidth - this.getWorkspaceOffset().left, docOffsetWidth);
- } else {
- width = Math.min(this.getContainerFillWidth(), docOffsetWidth - this.getWorkspaceOffset().left, docOffsetWidth);
- }
- if (trimmingContainer === window && totalColumns > 0 && this.sumColumnWidths(0, totalColumns - 1) > width) {
- // in case sum of column widths is higher than available stylesheet width, let's assume using the whole window
- // otherwise continue below, which will allow stretching
- // this is used in `scroll_window.html`
- // TODO test me
- return document.documentElement.clientWidth;
- }
- if (trimmingContainer !== window) {
- overflow = getStyle(this.instance.wtOverlays.leftOverlay.trimmingContainer, 'overflow');
- if (overflow == 'scroll' || overflow == 'hidden' || overflow == 'auto') {
- // this is used in `scroll.html`
- // TODO test me
- return Math.max(width, trimmingContainer.clientWidth);
- }
- }
- if (stretchSetting === 'none' || !stretchSetting) {
- // if no stretching is used, return the maximum used workspace width
- return Math.max(width, outerWidth(this.instance.wtTable.TABLE));
- }
- // if stretching is used, return the actual container width, so the columns can fit inside it
- return width;
- }
- /**
- * Checks if viewport has vertical scroll
- *
- * @returns {Boolean}
- */
- }, {
- key: 'hasVerticalScroll',
- value: function hasVerticalScroll() {
- return this.getWorkspaceActualHeight() > this.getWorkspaceHeight();
- }
- /**
- * Checks if viewport has horizontal scroll
- *
- * @returns {Boolean}
- */
- }, {
- key: 'hasHorizontalScroll',
- value: function hasHorizontalScroll() {
- return this.getWorkspaceActualWidth() > this.getWorkspaceWidth();
- }
- /**
- * @param from
- * @param length
- * @returns {Number}
- */
- }, {
- key: 'sumColumnWidths',
- value: function sumColumnWidths(from, length) {
- var sum = 0;
- while (from < length) {
- sum += this.wot.wtTable.getColumnWidth(from);
- from++;
- }
- return sum;
- }
- /**
- * @returns {Number}
- */
- }, {
- key: 'getContainerFillWidth',
- value: function getContainerFillWidth() {
- if (this.containerWidth) {
- return this.containerWidth;
- }
- var mainContainer = this.instance.wtTable.holder;
- var fillWidth = void 0;
- var dummyElement = void 0;
- dummyElement = document.createElement('div');
- dummyElement.style.width = '100%';
- dummyElement.style.height = '1px';
- mainContainer.appendChild(dummyElement);
- fillWidth = dummyElement.offsetWidth;
- this.containerWidth = fillWidth;
- mainContainer.removeChild(dummyElement);
- return fillWidth;
- }
- /**
- * @returns {Number}
- */
- }, {
- key: 'getWorkspaceOffset',
- value: function getWorkspaceOffset() {
- return offset(this.wot.wtTable.TABLE);
- }
- /**
- * @returns {Number}
- */
- }, {
- key: 'getWorkspaceActualHeight',
- value: function getWorkspaceActualHeight() {
- return outerHeight(this.wot.wtTable.TABLE);
- }
- /**
- * @returns {Number}
- */
- }, {
- key: 'getWorkspaceActualWidth',
- value: function getWorkspaceActualWidth() {
- return outerWidth(this.wot.wtTable.TABLE) || outerWidth(this.wot.wtTable.TBODY) || outerWidth(this.wot.wtTable.THEAD); // IE8 reports 0 as <table> offsetWidth;
- }
- /**
- * @returns {Number}
- */
- }, {
- key: 'getColumnHeaderHeight',
- value: function getColumnHeaderHeight() {
- if (isNaN(this.columnHeaderHeight)) {
- this.columnHeaderHeight = outerHeight(this.wot.wtTable.THEAD);
- }
- return this.columnHeaderHeight;
- }
- /**
- * @returns {Number}
- */
- }, {
- key: 'getViewportHeight',
- value: function getViewportHeight() {
- var containerHeight = this.getWorkspaceHeight();
- var columnHeaderHeight = void 0;
- if (containerHeight === Infinity) {
- return containerHeight;
- }
- columnHeaderHeight = this.getColumnHeaderHeight();
- if (columnHeaderHeight > 0) {
- containerHeight -= columnHeaderHeight;
- }
- return containerHeight;
- }
- /**
- * @returns {Number}
- */
- }, {
- key: 'getRowHeaderWidth',
- value: function getRowHeaderWidth() {
- var rowHeadersHeightSetting = this.instance.getSetting('rowHeaderWidth');
- var rowHeaders = this.instance.getSetting('rowHeaders');
- if (rowHeadersHeightSetting) {
- this.rowHeaderWidth = 0;
- for (var i = 0, len = rowHeaders.length; i < len; i++) {
- this.rowHeaderWidth += rowHeadersHeightSetting[i] || rowHeadersHeightSetting;
- }
- }
- if (this.wot.cloneSource) {
- return this.wot.cloneSource.wtViewport.getRowHeaderWidth();
- }
- if (isNaN(this.rowHeaderWidth)) {
- if (rowHeaders.length) {
- var TH = this.instance.wtTable.TABLE.querySelector('TH');
- this.rowHeaderWidth = 0;
- for (var _i = 0, _len = rowHeaders.length; _i < _len; _i++) {
- if (TH) {
- this.rowHeaderWidth += outerWidth(TH);
- TH = TH.nextSibling;
- } else {
- // yes this is a cheat but it worked like that before, just taking assumption from CSS instead of measuring.
- // TODO: proper fix
- this.rowHeaderWidth += 50;
- }
- }
- } else {
- this.rowHeaderWidth = 0;
- }
- }
- this.rowHeaderWidth = this.instance.getSetting('onModifyRowHeaderWidth', this.rowHeaderWidth) || this.rowHeaderWidth;
- return this.rowHeaderWidth;
- }
- /**
- * @returns {Number}
- */
- }, {
- key: 'getViewportWidth',
- value: function getViewportWidth() {
- var containerWidth = this.getWorkspaceWidth();
- var rowHeaderWidth = void 0;
- if (containerWidth === Infinity) {
- return containerWidth;
- }
- rowHeaderWidth = this.getRowHeaderWidth();
- if (rowHeaderWidth > 0) {
- return containerWidth - rowHeaderWidth;
- }
- return containerWidth;
- }
- /**
- * Creates:
- * - rowsRenderCalculator (before draw, to qualify rows for rendering)
- * - rowsVisibleCalculator (after draw, to measure which rows are actually visible)
- *
- * @returns {ViewportRowsCalculator}
- */
- }, {
- key: 'createRowsCalculator',
- value: function createRowsCalculator() {
- var _this2 = this;
- var visible = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- var height = void 0;
- var pos = void 0;
- var fixedRowsTop = void 0;
- var scrollbarHeight = void 0;
- var fixedRowsBottom = void 0;
- var fixedRowsHeight = void 0;
- var totalRows = void 0;
- this.rowHeaderWidth = NaN;
- if (this.wot.wtSettings.settings.renderAllRows) {
- height = Infinity;
- } else {
- height = this.getViewportHeight();
- }
- pos = this.wot.wtOverlays.topOverlay.getScrollPosition() - this.wot.wtOverlays.topOverlay.getTableParentOffset();
- if (pos < 0) {
- pos = 0;
- }
- fixedRowsTop = this.wot.getSetting('fixedRowsTop');
- fixedRowsBottom = this.wot.getSetting('fixedRowsBottom');
- totalRows = this.wot.getSetting('totalRows');
- if (fixedRowsTop) {
- fixedRowsHeight = this.wot.wtOverlays.topOverlay.sumCellSizes(0, fixedRowsTop);
- pos += fixedRowsHeight;
- height -= fixedRowsHeight;
- }
- if (fixedRowsBottom && this.wot.wtOverlays.bottomOverlay.clone) {
- fixedRowsHeight = this.wot.wtOverlays.bottomOverlay.sumCellSizes(totalRows - fixedRowsBottom, totalRows);
- height -= fixedRowsHeight;
- }
- if (this.wot.wtTable.holder.clientHeight === this.wot.wtTable.holder.offsetHeight) {
- scrollbarHeight = 0;
- } else {
- scrollbarHeight = getScrollbarWidth();
- }
- return new ViewportRowsCalculator(height, pos, this.wot.getSetting('totalRows'), function (sourceRow) {
- return _this2.wot.wtTable.getRowHeight(sourceRow);
- }, visible ? null : this.wot.wtSettings.settings.viewportRowCalculatorOverride, visible, scrollbarHeight);
- }
- /**
- * Creates:
- * - columnsRenderCalculator (before draw, to qualify columns for rendering)
- * - columnsVisibleCalculator (after draw, to measure which columns are actually visible)
- *
- * @returns {ViewportRowsCalculator}
- */
- }, {
- key: 'createColumnsCalculator',
- value: function createColumnsCalculator() {
- var _this3 = this;
- var visible = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- var width = this.getViewportWidth();
- var pos = void 0;
- var fixedColumnsLeft = void 0;
- this.columnHeaderHeight = NaN;
- pos = this.wot.wtOverlays.leftOverlay.getScrollPosition() - this.wot.wtOverlays.leftOverlay.getTableParentOffset();
- if (pos < 0) {
- pos = 0;
- }
- fixedColumnsLeft = this.wot.getSetting('fixedColumnsLeft');
- if (fixedColumnsLeft) {
- var fixedColumnsWidth = this.wot.wtOverlays.leftOverlay.sumCellSizes(0, fixedColumnsLeft);
- pos += fixedColumnsWidth;
- width -= fixedColumnsWidth;
- }
- if (this.wot.wtTable.holder.clientWidth !== this.wot.wtTable.holder.offsetWidth) {
- width -= getScrollbarWidth();
- }
- return new ViewportColumnsCalculator(width, pos, this.wot.getSetting('totalColumns'), function (sourceCol) {
- return _this3.wot.wtTable.getColumnWidth(sourceCol);
- }, visible ? null : this.wot.wtSettings.settings.viewportColumnCalculatorOverride, visible, this.wot.getSetting('stretchH'), function (stretchedWidth, column) {
- return _this3.wot.getSetting('onBeforeStretchingColumnWidth', stretchedWidth, column);
- });
- }
- /**
- * Creates rowsRenderCalculator and columnsRenderCalculator (before draw, to determine what rows and
- * cols should be rendered)
- *
- * @param fastDraw {Boolean} If `true`, will try to avoid full redraw and only update the border positions.
- * If `false` or `undefined`, will perform a full redraw
- * @returns fastDraw {Boolean} The fastDraw value, possibly modified
- */
- }, {
- key: 'createRenderCalculators',
- value: function createRenderCalculators() {
- var fastDraw = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
- if (fastDraw) {
- var proposedRowsVisibleCalculator = this.createRowsCalculator(true);
- var proposedColumnsVisibleCalculator = this.createColumnsCalculator(true);
- if (!(this.areAllProposedVisibleRowsAlreadyRendered(proposedRowsVisibleCalculator) && this.areAllProposedVisibleColumnsAlreadyRendered(proposedColumnsVisibleCalculator))) {
- fastDraw = false;
- }
- }
- if (!fastDraw) {
- this.rowsRenderCalculator = this.createRowsCalculator();
- this.columnsRenderCalculator = this.createColumnsCalculator();
- }
- // delete temporarily to make sure that renderers always use rowsRenderCalculator, not rowsVisibleCalculator
- this.rowsVisibleCalculator = null;
- this.columnsVisibleCalculator = null;
- return fastDraw;
- }
- /**
- * Creates rowsVisibleCalculator and columnsVisibleCalculator (after draw, to determine what are
- * the actually visible rows and columns)
- */
- }, {
- key: 'createVisibleCalculators',
- value: function createVisibleCalculators() {
- this.rowsVisibleCalculator = this.createRowsCalculator(true);
- this.columnsVisibleCalculator = this.createColumnsCalculator(true);
- }
- /**
- * Returns information whether proposedRowsVisibleCalculator viewport
- * is contained inside rows rendered in previous draw (cached in rowsRenderCalculator)
- *
- * @param {Object} proposedRowsVisibleCalculator
- * @returns {Boolean} Returns `true` if all proposed visible rows are already rendered (meaning: redraw is not needed).
- * Returns `false` if at least one proposed visible row is not already rendered (meaning: redraw is needed)
- */
- }, {
- key: 'areAllProposedVisibleRowsAlreadyRendered',
- value: function areAllProposedVisibleRowsAlreadyRendered(proposedRowsVisibleCalculator) {
- if (this.rowsVisibleCalculator) {
- if (proposedRowsVisibleCalculator.startRow < this.rowsRenderCalculator.startRow || proposedRowsVisibleCalculator.startRow === this.rowsRenderCalculator.startRow && proposedRowsVisibleCalculator.startRow > 0) {
- return false;
- } else if (proposedRowsVisibleCalculator.endRow > this.rowsRenderCalculator.endRow || proposedRowsVisibleCalculator.endRow === this.rowsRenderCalculator.endRow && proposedRowsVisibleCalculator.endRow < this.wot.getSetting('totalRows') - 1) {
- return false;
- }
- return true;
- }
- return false;
- }
- /**
- * Returns information whether proposedColumnsVisibleCalculator viewport
- * is contained inside column rendered in previous draw (cached in columnsRenderCalculator)
- *
- * @param {Object} proposedColumnsVisibleCalculator
- * @returns {Boolean} Returns `true` if all proposed visible columns are already rendered (meaning: redraw is not needed).
- * Returns `false` if at least one proposed visible column is not already rendered (meaning: redraw is needed)
- */
- }, {
- key: 'areAllProposedVisibleColumnsAlreadyRendered',
- value: function areAllProposedVisibleColumnsAlreadyRendered(proposedColumnsVisibleCalculator) {
- if (this.columnsVisibleCalculator) {
- if (proposedColumnsVisibleCalculator.startColumn < this.columnsRenderCalculator.startColumn || proposedColumnsVisibleCalculator.startColumn === this.columnsRenderCalculator.startColumn && proposedColumnsVisibleCalculator.startColumn > 0) {
- return false;
- } else if (proposedColumnsVisibleCalculator.endColumn > this.columnsRenderCalculator.endColumn || proposedColumnsVisibleCalculator.endColumn === this.columnsRenderCalculator.endColumn && proposedColumnsVisibleCalculator.endColumn < this.wot.getSetting('totalColumns') - 1) {
- return false;
- }
- return true;
- }
- return false;
- }
- /**
- * Resets values in keys of the hasOversizedColumnHeadersMarked object after updateSettings.
- */
- }, {
- key: 'resetHasOversizedColumnHeadersMarked',
- value: function resetHasOversizedColumnHeadersMarked() {
- objectEach(this.hasOversizedColumnHeadersMarked, function (value, key, object) {
- object[key] = void 0;
- });
- }
- }]);
- return Viewport;
- }();
- export default Viewport;
|