| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 | 
							- import Vue from 'vue';
 
- import scrollbarWidth from 'element-ui/src/utils/scrollbar-width';
 
- import { parseHeight } from './util';
 
- class TableLayout {
 
-   constructor(options) {
 
-     this.observers = [];
 
-     this.table = null;
 
-     this.store = null;
 
-     this.columns = null;
 
-     this.fit = true;
 
-     this.showHeader = true;
 
-     this.height = null;
 
-     this.scrollX = false;
 
-     this.scrollY = false;
 
-     this.bodyWidth = null;
 
-     this.fixedWidth = null;
 
-     this.rightFixedWidth = null;
 
-     this.tableHeight = null;
 
-     this.headerHeight = 44; // Table Header Height
 
-     this.appendHeight = 0; // Append Slot Height
 
-     this.footerHeight = 44; // Table Footer Height
 
-     this.viewportHeight = null; // Table Height - Scroll Bar Height
 
-     this.bodyHeight = null; // Table Height - Table Header Height
 
-     this.fixedBodyHeight = null; // Table Height - Table Header Height - Scroll Bar Height
 
-     this.gutterWidth = scrollbarWidth();
 
-     for (let name in options) {
 
-       if (options.hasOwnProperty(name)) {
 
-         this[name] = options[name];
 
-       }
 
-     }
 
-     if (!this.table) {
 
-       throw new Error('table is required for Table Layout');
 
-     }
 
-     if (!this.store) {
 
-       throw new Error('store is required for Table Layout');
 
-     }
 
-   }
 
-   updateScrollY() {
 
-     const height = this.height;
 
-     if (height === null) return false;
 
-     const bodyWrapper = this.table.bodyWrapper;
 
-     if (this.table.$el && bodyWrapper) {
 
-       const body = bodyWrapper.querySelector('.el-table__body');
 
-       const prevScrollY = this.scrollY;
 
-       const scrollY = body.offsetHeight > this.bodyHeight;
 
-       this.scrollY = scrollY;
 
-       return prevScrollY !== scrollY;
 
-     }
 
-     return false;
 
-   }
 
-   setHeight(value, prop = 'height') {
 
-     if (Vue.prototype.$isServer) return;
 
-     const el = this.table.$el;
 
-     value = parseHeight(value);
 
-     this.height = value;
 
-     if (!el && (value || value === 0)) return Vue.nextTick(() => this.setHeight(value, prop));
 
-     if (typeof value === 'number') {
 
-       el.style[prop] = value + 'px';
 
-       this.updateElsHeight();
 
-     } else if (typeof value === 'string') {
 
-       el.style[prop] = value;
 
-       this.updateElsHeight();
 
-     }
 
-   }
 
-   setMaxHeight(value) {
 
-     this.setHeight(value, 'max-height');
 
-   }
 
-   getFlattenColumns() {
 
-     const flattenColumns = [];
 
-     const columns = this.table.columns;
 
-     columns.forEach((column) => {
 
-       if (column.isColumnGroup) {
 
-         flattenColumns.push.apply(flattenColumns, column.columns);
 
-       } else {
 
-         flattenColumns.push(column);
 
-       }
 
-     });
 
-     return flattenColumns;
 
-   }
 
-   updateElsHeight() {
 
-     if (!this.table.$ready) return Vue.nextTick(() => this.updateElsHeight());
 
-     const { headerWrapper, appendWrapper, footerWrapper } = this.table.$refs;
 
-     this.appendHeight = appendWrapper ? appendWrapper.offsetHeight : 0;
 
-     if (this.showHeader && !headerWrapper) return;
 
-     // fix issue (https://github.com/ElemeFE/element/pull/16956)
 
-     const headerTrElm = headerWrapper ? headerWrapper.querySelector('.el-table__header tr') : null;
 
-     const noneHeader = this.headerDisplayNone(headerTrElm);
 
-     const headerHeight = this.headerHeight = !this.showHeader ? 0 : headerWrapper.offsetHeight;
 
-     if (this.showHeader && !noneHeader && headerWrapper.offsetWidth > 0 && (this.table.columns || []).length > 0 && headerHeight < 2) {
 
-       return Vue.nextTick(() => this.updateElsHeight());
 
-     }
 
-     const tableHeight = this.tableHeight = this.table.$el.clientHeight;
 
-     const footerHeight = this.footerHeight = footerWrapper ? footerWrapper.offsetHeight : 0;
 
-     if (this.height !== null) {
 
-       this.bodyHeight = tableHeight - headerHeight - footerHeight + (footerWrapper ? 1 : 0);
 
-     }
 
-     this.fixedBodyHeight = this.scrollX ? (this.bodyHeight - this.gutterWidth) : this.bodyHeight;
 
-     const noData = !(this.store.states.data && this.store.states.data.length);
 
-     this.viewportHeight = this.scrollX ? tableHeight - (noData ? 0 : this.gutterWidth) : tableHeight;
 
-     this.updateScrollY();
 
-     this.notifyObservers('scrollable');
 
-   }
 
-   headerDisplayNone(elm) {
 
-     if (!elm) return true;
 
-     let headerChild = elm;
 
-     while (headerChild.tagName !== 'DIV') {
 
-       if (getComputedStyle(headerChild).display === 'none') {
 
-         return true;
 
-       }
 
-       headerChild = headerChild.parentElement;
 
-     }
 
-     return false;
 
-   }
 
-   updateColumnsWidth() {
 
-     if (Vue.prototype.$isServer) return;
 
-     const fit = this.fit;
 
-     const bodyWidth = this.table.$el.clientWidth;
 
-     let bodyMinWidth = 0;
 
-     const flattenColumns = this.getFlattenColumns();
 
-     let flexColumns = flattenColumns.filter((column) => typeof column.width !== 'number');
 
-     flattenColumns.forEach((column) => { // Clean those columns whose width changed from flex to unflex
 
-       if (typeof column.width === 'number' && column.realWidth) column.realWidth = null;
 
-     });
 
-     if (flexColumns.length > 0 && fit) {
 
-       flattenColumns.forEach((column) => {
 
-         bodyMinWidth += column.width || column.minWidth || 80;
 
-       });
 
-       const scrollYWidth = this.scrollY ? this.gutterWidth : 0;
 
-       if (bodyMinWidth <= bodyWidth - scrollYWidth) { // DON'T HAVE SCROLL BAR
 
-         this.scrollX = false;
 
-         const totalFlexWidth = bodyWidth - scrollYWidth - bodyMinWidth;
 
-         if (flexColumns.length === 1) {
 
-           flexColumns[0].realWidth = (flexColumns[0].minWidth || 80) + totalFlexWidth;
 
-         } else {
 
-           const allColumnsWidth = flexColumns.reduce((prev, column) => prev + (column.minWidth || 80), 0);
 
-           const flexWidthPerPixel = totalFlexWidth / allColumnsWidth;
 
-           let noneFirstWidth = 0;
 
-           flexColumns.forEach((column, index) => {
 
-             if (index === 0) return;
 
-             const flexWidth = Math.floor((column.minWidth || 80) * flexWidthPerPixel);
 
-             noneFirstWidth += flexWidth;
 
-             column.realWidth = (column.minWidth || 80) + flexWidth;
 
-           });
 
-           flexColumns[0].realWidth = (flexColumns[0].minWidth || 80) + totalFlexWidth - noneFirstWidth;
 
-         }
 
-       } else { // HAVE HORIZONTAL SCROLL BAR
 
-         this.scrollX = true;
 
-         flexColumns.forEach(function(column) {
 
-           column.realWidth = column.minWidth;
 
-         });
 
-       }
 
-       this.bodyWidth = Math.max(bodyMinWidth, bodyWidth);
 
-       this.table.resizeState.width = this.bodyWidth;
 
-     } else {
 
-       flattenColumns.forEach((column) => {
 
-         if (!column.width && !column.minWidth) {
 
-           column.realWidth = 80;
 
-         } else {
 
-           column.realWidth = column.width || column.minWidth;
 
-         }
 
-         bodyMinWidth += column.realWidth;
 
-       });
 
-       this.scrollX = bodyMinWidth > bodyWidth;
 
-       this.bodyWidth = bodyMinWidth;
 
-     }
 
-     const fixedColumns = this.store.states.fixedColumns;
 
-     if (fixedColumns.length > 0) {
 
-       let fixedWidth = 0;
 
-       fixedColumns.forEach(function(column) {
 
-         fixedWidth += column.realWidth || column.width;
 
-       });
 
-       this.fixedWidth = fixedWidth;
 
-     }
 
-     const rightFixedColumns = this.store.states.rightFixedColumns;
 
-     if (rightFixedColumns.length > 0) {
 
-       let rightFixedWidth = 0;
 
-       rightFixedColumns.forEach(function(column) {
 
-         rightFixedWidth += column.realWidth || column.width;
 
-       });
 
-       this.rightFixedWidth = rightFixedWidth;
 
-     }
 
-     this.notifyObservers('columns');
 
-   }
 
-   addObserver(observer) {
 
-     this.observers.push(observer);
 
-   }
 
-   removeObserver(observer) {
 
-     const index = this.observers.indexOf(observer);
 
-     if (index !== -1) {
 
-       this.observers.splice(index, 1);
 
-     }
 
-   }
 
-   notifyObservers(event) {
 
-     const observers = this.observers;
 
-     observers.forEach((observer) => {
 
-       switch (event) {
 
-         case 'columns':
 
-           observer.onColumnsChange(this);
 
-           break;
 
-         case 'scrollable':
 
-           observer.onScrollableChange(this);
 
-           break;
 
-         default:
 
-           throw new Error(`Table Layout don't have event ${event}.`);
 
-       }
 
-     });
 
-   }
 
- }
 
- export default TableLayout;
 
 
  |