@@ -78,7 +78,7 @@ function calculatePosition(referenceOffset: Offset, reference: HTMLElement, targ
7878
7979export namespace position {
8080 export function getRelativeOffset ( target : HTMLElement ) : Offset {
81- // start with the inital element offsets
81+ // start with the initial element offsets
8282 let offsets = {
8383 left : target . offsetLeft ,
8484 top : target . offsetTop
@@ -93,9 +93,53 @@ export namespace position {
9393 }
9494
9595 export function getAbsoluteOffset ( target : HTMLElement ) : Offset {
96+ let positionedElement ;
97+ let currentNode = target ;
98+ let margins = {
99+ top : 0 ,
100+ left : 0
101+ } ;
102+
103+ // searches either for a parent `positionedElement` or for
104+ // containing elements with additional margins
105+ // once we have a `positionedElement` we can stop searching
106+ // since we use offsetParent we end up skipping most elements
107+ while ( currentNode . offsetParent && ! positionedElement ) {
108+ const computed = getComputedStyle ( currentNode . offsetParent ) ;
109+ if ( computed . position !== "static" ) {
110+ positionedElement = currentNode . offsetParent ;
111+ }
112+
113+ // find static elements with additional margins
114+ // since they tend to throw off our positioning
115+ // (usually this is just the body)
116+ if (
117+ computed . position === "static" &&
118+ computed . marginLeft &&
119+ computed . marginTop
120+ ) {
121+ if ( parseInt ( computed . marginTop , 10 ) ) {
122+ margins . top += parseInt ( computed . marginTop , 10 ) ;
123+ }
124+ if ( parseInt ( computed . marginLeft , 10 ) ) {
125+ margins . left += parseInt ( computed . marginLeft , 10 ) ;
126+ }
127+ }
128+
129+ currentNode = currentNode . offsetParent as HTMLElement ;
130+ }
131+
132+ // if we don't find any `relativeElement` on our walk
133+ // default to the body
134+ if ( ! positionedElement ) {
135+ positionedElement = document . body ;
136+ }
137+
138+ const targetRect = target . getBoundingClientRect ( ) ;
139+ const relativeRect = positionedElement . getBoundingClientRect ( ) ;
96140 return {
97- top : target . getBoundingClientRect ( ) . top ,
98- left : target . getBoundingClientRect ( ) . left - document . body . getBoundingClientRect ( ) . left
141+ top : targetRect . top - relativeRect . top + margins . top ,
142+ left : targetRect . left - relativeRect . left + margins . left
99143 } ;
100144 }
101145
0 commit comments