Просмотр исходного кода

better browser hacks for scrollgrid

Adam Shaw 6 лет назад
Родитель
Сommit
7b0e3e19fb

+ 1 - 1
packages/core/src/main.ts

@@ -175,7 +175,7 @@ export { DelayedRunner } from './util/runner'
 
 export { default as SimpleScrollGrid, SimpleScrollGridSection } from './scrollgrid/SimpleScrollGrid'
 export {
-  CssDimValue, ScrollerLike, SectionConfig, ColCss, ChunkConfig, doSizingHacks, hasShrinkWidth, renderMicroColGroup,
+  CssDimValue, ScrollerLike, SectionConfig, ColCss, ChunkConfig, hasShrinkWidth, renderMicroColGroup,
   getScrollGridClassNames, getSectionClassNames, getChunkVGrow, getNeedsYScrolling, renderChunkContent, computeForceScrollbars, computeShrinkWidth,
   getChunkClassNames, ChunkContentCallbackArgs
 } from './scrollgrid/util'

+ 43 - 2
packages/core/src/scrollgrid/Scroller.tsx

@@ -11,7 +11,7 @@ export interface ScrollerProps {
   vGrow?: boolean
   maxHeight?: CssDimValue
   style?: object // complex object, bad for purecomponent, but who cares because has children anyway
-  className?: string
+  className?: string // can kill at some pt?
   children?: ComponentChildren
   elRef?: Ref<HTMLElement>
 }
@@ -19,7 +19,7 @@ export interface ScrollerProps {
 
 export default class Scroller extends BaseComponent<ScrollerProps> implements ScrollerLike {
 
-  private el: HTMLElement
+  private el: HTMLElement // TODO: just use this.base?
 
 
   render(props: ScrollerProps) {
@@ -52,6 +52,47 @@ export default class Scroller extends BaseComponent<ScrollerProps> implements Sc
   }
 
 
+  componentDidMount() {
+    this.handleSizing()
+    this.context.addResizeHandler(this.handleSizing)
+  }
+
+
+  componentDidUpdate(prevProps: ScrollerProps) {
+    this.handleSizing()
+  }
+
+
+  componentWillUnmount() {
+    this.context.removeResizeHandler(this.handleSizing)
+  }
+
+
+  handleSizing = () => { // SIZING HACKS
+    let rootEl = this.el
+    let childNodes = rootEl.childNodes
+
+    if (childNodes.length === 1) {
+      let tableEl = childNodes[0] as HTMLElement
+      if (tableEl.nodeName === 'TABLE') {
+
+        // for IE tables vertically expanding really jankily, esp DURING scrolling
+        // do first. might affect y-scrollbars which affect clientWidth
+        if (tableEl.classList.contains('vgrow')) {
+          tableEl.style.height = (rootEl.clientHeight - 1) + 'px' // -1 for IE
+        }
+
+        // for Safari bug, change in y-scrollbars wouldn't change table width (with 100% width)
+        // won't do anything if the <col>s already have an opinion about width
+        // important not do when no scrollbars. was getting false positives.
+        if (this.props.overflowY !== 'hidden') {
+          tableEl.style.width = rootEl.clientWidth + 'px'
+        }
+      }
+    }
+  }
+
+
   needsXScrolling() {
     return this.el.scrollWidth > this.el.clientWidth + 1 || // IE shittiness
       this.props.overflowX === 'auto' && Boolean(this.getXScrollbarWidth()) // hack safeguard

+ 37 - 16
packages/core/src/scrollgrid/SimpleScrollGrid.tsx

@@ -4,7 +4,7 @@ import { BaseComponent, setRef, componentNeedsResize } from '../vdom-util'
 import Scroller, { OverflowValue } from './Scroller'
 import RefMap from '../util/RefMap'
 import { ColCss, SectionConfig, renderMicroColGroup, computeShrinkWidth, getScrollGridClassNames, getSectionClassNames, getNeedsYScrolling,
-  renderChunkContent, getChunkVGrow, doSizingHacks, computeForceScrollbars, ChunkConfig, hasShrinkWidth, CssDimValue, getChunkClassNames } from './util'
+  renderChunkContent, getChunkVGrow, computeForceScrollbars, ChunkConfig, hasShrinkWidth, CssDimValue, getChunkClassNames } from './util'
 
 
 export interface SimpleScrollGridProps {
@@ -70,20 +70,42 @@ export default class SimpleScrollGrid extends BaseComponent<SimpleScrollGridProp
     let needsYScrolling = getNeedsYScrolling(this.props, sectionConfig, chunkConfig) // TODO: do lazily
     let overflowY: OverflowValue = this.state.forceYScrollbars ? 'scroll' : (needsYScrolling ? 'auto' : 'hidden')
     let content = renderChunkContent(sectionConfig, chunkConfig, microColGroupNode, '', true)
-
-    return (
-      <td class={getChunkClassNames(sectionConfig, this.context)} ref={chunkConfig.elRef}>
-        <Scroller
-          ref={this.scrollerRefs.createRef(sectionI)}
-          elRef={this.scrollerElRefs.createRef(sectionI, chunkConfig)}
-          className={chunkConfig.scrollerClassName}
-          overflowY={overflowY}
-          overflowX='hidden'
-          maxHeight={sectionConfig.maxHeight}
-          vGrow={getChunkVGrow(this.props, sectionConfig, chunkConfig)}
-        >{content}</Scroller>
-      </td>
-    )
+    let vGrow = getChunkVGrow(this.props, sectionConfig, chunkConfig)
+
+    // TODO: cleaner solution
+    // in browsers other than Chrome, the height of the inner table was taking precedence over scroller's liquid height,
+    // making it so there's never be scrollbars
+    if (vGrow) {
+      return (
+        <td class={getChunkClassNames(sectionConfig, this.context)} ref={chunkConfig.elRef}>
+          <div style={{ position: 'relative' }} class='vgrow'>
+            <Scroller
+              ref={this.scrollerRefs.createRef(sectionI)}
+              elRef={this.scrollerElRefs.createRef(sectionI, chunkConfig)}
+              className={[ chunkConfig.scrollerClassName, vGrow ? 'vgrow--absolute' : '' ].join(' ')}
+              overflowY={overflowY}
+              overflowX='hidden'
+              maxHeight={sectionConfig.maxHeight}
+              vGrow={vGrow}
+            >{content}</Scroller>
+          </div>
+        </td>
+      )
+    } else {
+      return (
+        <td class={getChunkClassNames(sectionConfig, this.context)} ref={chunkConfig.elRef}>
+          <Scroller
+            ref={this.scrollerRefs.createRef(sectionI)}
+            elRef={this.scrollerElRefs.createRef(sectionI, chunkConfig)}
+            className={[ chunkConfig.scrollerClassName ].join(' ')}
+            overflowY={overflowY}
+            overflowX='hidden'
+            maxHeight={sectionConfig.maxHeight}
+            vGrow={vGrow}
+          >{content}</Scroller>
+        </td>
+      )
+    }
   }
 
 
@@ -111,7 +133,6 @@ export default class SimpleScrollGrid extends BaseComponent<SimpleScrollGridProp
 
 
   handleSizing = () => {
-    doSizingHacks(this.base as HTMLElement)
 
     if (hasShrinkWidth(this.props.cols)) {
       this.setState({

+ 0 - 36
packages/core/src/scrollgrid/util.tsx

@@ -1,6 +1,5 @@
 import { VNode, h, Ref } from '../vdom'
 import { findElements } from '../util/dom-manip'
-// import { computeInnerRect } from '../util/dom-geom'
 import ComponentContext from '../component/ComponentContext'
 
 
@@ -56,41 +55,6 @@ export function computeShrinkWidth(chunkEls: HTMLElement[]) { // all in same COL
 }
 
 
-export function doSizingHacks(rootEl: HTMLElement) { // TODO: needs to run on window resize fetch!!
-
-  // // for Safari
-  // // TODO: in Scroller class?
-  // let hGrowTables = findElements(rootEl, '.scroller > table')
-  // for (let tableEl of hGrowTables) {
-  //   if (tableEl.style.position == 'relative') {
-  //     tableEl.style.position = ''
-  //   } else {
-  //     tableEl.style.position = 'relative'
-  //   }
-  // }
-  //
-  // from scss:
-  // width: 100%; /* hack to force re-sizing this inner element when scrollbars appear/disappear */
-
-  // // for Firefox for all cells
-  // // for Safari(?) for cells with rowspans
-  // let vGrowEls = findElements(rootEl, 'td > .vgrow')
-  // for (let vGrowEl of vGrowEls) {
-  //   let cellEl = vGrowEl.parentNode as HTMLElement
-  //   let cellInnerRect = computeInnerRect(cellEl, true) // TODO: cache!
-  //   let cellInnerHeight = cellInnerRect.bottom - cellInnerRect.top
-  //   let vGrowHeight = vGrowEl.getBoundingClientRect().height
-  //   let lacking = cellInnerHeight - vGrowHeight
-
-  //   if (lacking > 0.5) {
-  //     let cellEl = vGrowEl.parentNode as HTMLElement
-  //     cellEl.style.position = 'relative'
-  //     vGrowEl.classList.add('vgrow--absolute')
-  //   }
-  // }
-}
-
-
 export interface ScrollerLike { // have scrollers implement?
   needsYScrolling(): boolean
   needsXScrolling(): boolean

+ 3 - 7
packages/core/src/styles/_scrollgrid.scss

@@ -18,15 +18,11 @@
 
 }
 
-table.vgrow > * > tr > * { // cells
-  height: auto; // if height is set, rows wont expand evenly
-}
-
 .scrollgrid__section { // a <tr>
-  height: 1px;
+  height: 0;
 
   > td {
-    height: 1px; // needs a height so vgrow's within grow
+    height: 0; // needs a height so vgrow's within grow
   }
 }
 
@@ -34,7 +30,7 @@ table.vgrow > * > tr > * { // cells
   height: auto; // undo 1px height. will cancel height:100% also
 
   > td {
-    height: auto;
+    height: 100%; // FF needs this instead of auto
   }
 }