Selaa lähdekoodia

fix how getBoundingClientRect is used

Adam Shaw 7 vuotta sitten
vanhempi
sitoutus
20f4be4a32
3 muutettua tiedostoa jossa 39 lisäystä ja 19 poistoa
  1. 5 4
      src/basic/DayGrid.ts
  2. 11 14
      src/common/Popover.ts
  3. 23 1
      src/util/dom-geom.ts

+ 5 - 4
src/basic/DayGrid.ts

@@ -9,6 +9,7 @@ import {
   removeElement,
   ElementContent
 } from '../util/dom-manip'
+import { computeRect } from '../util/dom-geom'
 import View from '../View'
 import CoordCache from '../common/CoordCache'
 import Popover from '../common/Popover'
@@ -430,7 +431,7 @@ export default class DayGrid extends DateComponent {
   // `row` is the row number.
   computeRowLevelLimit(row): (number | false) {
     let rowEl = this.rowEls[row] // the containing "fake" row div
-    let rowBottom = rowEl.getBoundingClientRect().bottom
+    let rowBottom = rowEl.getBoundingClientRect().bottom // relative to viewport!
     let trEls = findChildren(this.eventRenderer.rowStructs[row].tbodyEl) as HTMLTableRowElement[]
     let i
     let trEl: HTMLTableRowElement
@@ -627,7 +628,7 @@ export default class DayGrid extends DateComponent {
       className: 'fc-more-popover ' + view.calendar.theme.getClass('popover'),
       content: this.renderSegPopoverContent(row, col, segs),
       parentEl: view.el, // attach to root of view. guarantees outside of scrollbars.
-      top: topEl.getBoundingClientRect().top,
+      top: computeRect(topEl).top,
       autoHide: true, // when the user clicks elsewhere, hide the popover
       viewportConstrain: this.opt('popoverViewportConstrain'),
       hide: () => {
@@ -645,9 +646,9 @@ export default class DayGrid extends DateComponent {
     // Determine horizontal coordinate.
     // We use the moreWrap instead of the <td> to avoid border confusion.
     if (this.isRTL) {
-      options.right = moreWrap.getBoundingClientRect().right + 1 // +1 to be over cell border
+      options.right = computeRect(moreWrap).right + 1 // +1 to be over cell border
     } else {
-      options.left = moreWrap.getBoundingClientRect().left - 1 // -1 to be over cell border
+      options.left = computeRect(moreWrap).left - 1 // -1 to be over cell border
     }
 
     this.segPopover = new Popover(options)

+ 11 - 14
src/common/Popover.ts

@@ -15,7 +15,7 @@ Options:
 
 import { ElementContent, removeElement, createElement, applyStyle } from '../util/dom-manip'
 import { listenBySelector } from '../util/dom-event'
-import { getScrollParent } from '../util/dom-geom'
+import { getScrollParent, computeRect, computeViewportRect } from '../util/dom-geom'
 
 export interface PopoverOptions {
   className?: string
@@ -115,7 +115,8 @@ export default class Popover {
   position() {
     let options = this.options
     let el = this.el
-    let rect = el.getBoundingClientRect()
+    let elDims = el.getBoundingClientRect() // only used for width,height
+    let origin = computeRect(el.offsetParent)
     let scrollEl = getScrollParent(el)
     let viewportRect
     let top // the "position" (not "offset") values for the popover
@@ -126,33 +127,28 @@ export default class Popover {
     if (options.left !== undefined) {
       left = options.left
     } else if (options.right !== undefined) {
-      left = options.right - rect.width // derive the left value from the right value
+      left = options.right - elDims.width // derive the left value from the right value
     } else {
       left = 0
     }
 
     if (scrollEl) {
-      viewportRect = scrollEl.getBoundingClientRect()
+      viewportRect = computeRect(scrollEl)
     } else {
-      viewportRect = {
-        top: 0,
-        left: 0,
-        width: document.documentElement.clientWidth,
-        height: document.documentElement.clientHeight
-      }
+      viewportRect = computeViewportRect()
     }
 
     // constrain to the view port. if constrained by two edges, give precedence to top/left
     if (options.viewportConstrain !== false) {
-      top = Math.min(top, viewportRect.top + viewportRect.height - rect.height - this.margin)
+      top = Math.min(top, viewportRect.top + viewportRect.height - elDims.height - this.margin)
       top = Math.max(top, viewportRect.top + this.margin)
-      left = Math.min(left, viewportRect.left + viewportRect.width - rect.width - this.margin)
+      left = Math.min(left, viewportRect.left + viewportRect.width - elDims.width - this.margin)
       left = Math.max(left, viewportRect.left + this.margin)
     }
 
     applyStyle(el, {
-      top: top - rect.top,
-      left: left - rect.left
+      top: top - origin.top,
+      left: left - origin.left
     })
   }
 
@@ -160,6 +156,7 @@ export default class Popover {
   // Triggers a callback. Calls a function in the option hash of the same name.
   // Arguments beyond the first `name` are forwarded on.
   // TODO: better code reuse for this. Repeat code
+  // can kill this???
   trigger(name) {
     if (this.options[name]) {
       this.options[name].apply(this, Array.prototype.slice.call(arguments, 1))

+ 23 - 1
src/util/dom-geom.ts

@@ -51,7 +51,7 @@ export function computeEdges(el, getPadding = false): EdgeInfo {
 
 
 export function computeInnerRect(el, goWithinPadding = false) {
-  let outerRect = el.getBoundingClientRect()
+  let outerRect = computeRect(el)
   let edges = computeEdges(el, goWithinPadding)
   let res = {
     left: outerRect.left + edges.borderLeft + edges.scrollbarLeft,
@@ -71,6 +71,28 @@ export function computeInnerRect(el, goWithinPadding = false) {
 }
 
 
+export function computeRect(el) {
+  let rect = el.getBoundingClientRect()
+
+  return {
+    left: rect.left + window.scrollX,
+    top: rect.top + window.scrollY,
+    right: rect.right + window.scrollX,
+    bottom: rect.bottom + window.scrollY
+  }
+}
+
+
+export function computeViewportRect() {
+  return {
+    top: window.scrollY,
+    left: window.scrollX,
+    width: document.documentElement.clientWidth,
+    height: document.documentElement.clientHeight
+  }
+}
+
+
 export function computeHeightAndMargins(el: HTMLElement) {
   let computed = window.getComputedStyle(el)
   return el.offsetHeight +