diff --git a/packages/table/src/resize-event.js b/packages/table/src/resize-event.js new file mode 100644 index 000000000..a02a9ec10 --- /dev/null +++ b/packages/table/src/resize-event.js @@ -0,0 +1,156 @@ +/** +* Modified from https://github.com/sdecima/javascript-detect-element-resize +* +* version: 0.5.3 +**/ + +const requestFrame = (function() { + const raf = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || + function(fn) { + return window.setTimeout(fn, 20); + }; + return function(fn) { + return raf(fn); + }; +})(); + +const cancelFrame = (function() { + const cancel = window.cancelAnimationFrame || window.mozCancelAnimationFrame || window.webkitCancelAnimationFrame || window.clearTimeout; + return function(id) { + return cancel(id); + }; +})(); + +const resetTrigger = function(element) { + const trigger = element.__resizeTrigger__; + const expand = trigger.firstElementChild; + const contract = trigger.lastElementChild; + const expandChild = expand.firstElementChild; + + contract.scrollLeft = contract.scrollWidth; + contract.scrollTop = contract.scrollHeight; + expandChild.style.width = expand.offsetWidth + 1 + 'px'; + expandChild.style.height = expand.offsetHeight + 1 + 'px'; + expand.scrollLeft = expand.scrollWidth; + expand.scrollTop = expand.scrollHeight; +}; + +const checkTriggers = function(element) { + return element.offsetWidth !== element.__resizeLast__.width || element.offsetHeight !== element.__resizeLast__.height; +}; + +const scrollListener = function(event) { + resetTrigger(this); + if (this.__resizeRAF__) cancelFrame(this.__resizeRAF__); + this.__resizeRAF__ = requestFrame(() => { + if (checkTriggers(this)) { + this.__resizeLast__.width = this.offsetWidth; + this.__resizeLast__.height = this.offsetHeight; + this.__resizeListeners__.forEach((fn) => { + fn.call(this, event); + }); + } + }); +}; + +/* Detect CSS Animations support to detect element display/re-attach */ +const attachEvent = document.attachEvent; +const DOM_PREFIXES = 'Webkit Moz O ms'.split(' '); +const START_EVENTS = 'webkitAnimationStart animationstart oAnimationStart MSAnimationStart'.split(' '); +const RESIZE_ANIMATION_NAME = 'resizeanim'; +let animation = false; +let keyFramePrefix = ''; +let animationStartEvent = 'animationstart'; + +if (!attachEvent) { + const testElement = document.createElement('fakeelement'); + if (testElement.style.animationName !== undefined) { + animation = true; + } + + if (animation === false) { + let prefix = ''; + for (var i = 0; i < DOM_PREFIXES.length; i++) { + if (testElement.style[DOM_PREFIXES[i] + 'AnimationName'] !== undefined) { + prefix = DOM_PREFIXES[i]; + keyFramePrefix = '-' + prefix.toLowerCase() + '-'; + animationStartEvent = START_EVENTS[i]; + animation = true; + break; + } + } + } +} + +let stylesCreated = false; +const createStyles = function() { + if (!stylesCreated) { + const animationKeyframes = `@${keyFramePrefix}keyframes ${RESIZE_ANIMATION_NAME} { from { opacity: 0; } to { opacity: 0; } } `; + const animationStyle = `${keyFramePrefix}animation: 1ms ${RESIZE_ANIMATION_NAME};`; + + // opacity: 0 works around a chrome bug https://code.google.com/p/chromium/issues/detail?id=286360 + const css = `${animationKeyframes} + .resize-triggers { ${animationStyle} visibility: hidden; opacity: 0; } + .resize-triggers, .resize-triggers > div, .contract-trigger:before { content: \" \"; display: block; position: absolute; top: 0; left: 0; height: 100%; width: 100%; overflow: hidden; } + .resize-triggers > div { background: #eee; overflow: auto; } + .contract-trigger:before { width: 200%; height: 200%; }`; + + const head = document.head || document.getElementsByTagName('head')[0]; + const style = document.createElement('style'); + + style.type = 'text/css'; + if (style.styleSheet) { + style.styleSheet.cssText = css; + } else { + style.appendChild(document.createTextNode(css)); + } + + head.appendChild(style); + stylesCreated = true; + } +}; + +export const addResizeListener = function(element, fn) { + if (attachEvent) { + element.attachEvent('onresize', fn); + } else { + if (!element.__resizeTrigger__) { + if (getComputedStyle(element).position === 'static') { + element.style.position = 'relative'; + } + createStyles(); + element.__resizeLast__ = {}; + element.__resizeListeners__ = []; + + const resizeTrigger = element.__resizeTrigger__ = document.createElement('div'); + resizeTrigger.className = 'resize-triggers'; + resizeTrigger.innerHTML = '
'; + element.appendChild(resizeTrigger); + + resetTrigger(element); + element.addEventListener('scroll', scrollListener, true); + + /* Listen for a css animation to detect element display/re-attach */ + if (animationStartEvent) { + resizeTrigger.addEventListener(animationStartEvent, function(event) { + if (event.animationName === RESIZE_ANIMATION_NAME) { + resetTrigger(element); + } + }); + } + } + element.__resizeListeners__.push(fn); + } +}; + +export const removeResizeListener = function(element, fn) { + if (attachEvent) { + element.detachEvent('onresize', fn); + } else { + element.__resizeListeners__.splice(element.__resizeListeners__.indexOf(fn), 1); + if (!element.__resizeListeners__.length) { + element.removeEventListener('scroll', scrollListener); + element.__resizeTrigger__ = !element.removeChild(element.__resizeTrigger__); + } + } +}; diff --git a/packages/table/src/table.vue b/packages/table/src/table.vue index f6f1c1af9..3b6628bd2 100644 --- a/packages/table/src/table.vue +++ b/packages/table/src/table.vue @@ -25,6 +25,7 @@ import debounce from 'throttle-debounce/debounce'; import { getScrollBarWidth, orderBy } from './util'; import objectAssign from 'object-assign'; + import { addResizeListener, removeResizeListener } from './resize-event'; let gridIdSeed = 1; let GUTTER_WIDTH; @@ -299,10 +300,10 @@ this.$calcColumns(); if (!this.$ready && this.fit) { - this.windowResizeListener = throttle(100, () => { + this.windowResizeListener = throttle(50, () => { this.$calcColumns(); }); - window.addEventListener('resize', this.windowResizeListener); + addResizeListener(this.$el, this.windowResizeListener); } this.$nextTick(() => { @@ -395,7 +396,7 @@ } if (this.windowResizeListener) { - window.removeEventListener('resize', this.windowResizeListener); + removeResizeListener(this.$el, this.windowResizeListener); } }, diff --git a/packages/theme-default/src/table.css b/packages/theme-default/src/table.css index a8db7d17e..bddd2686e 100644 --- a/packages/theme-default/src/table.css +++ b/packages/theme-default/src/table.css @@ -55,7 +55,6 @@ & th, td { height: 20px; - max-width: 250px; min-width: 0; box-sizing: border-box; text-overflow: ellipsis;