Skip to content

Commit

Permalink
1.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
Yair Even Or authored and Yair Even Or committed Oct 2, 2021
1 parent dda3320 commit 5381373
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 17 deletions.
23 changes: 19 additions & 4 deletions dist/position.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* @yaireo/position - Position a DOM element at a certain X,Y or next to another element
*
* @version v1.0.7
* @version v1.1.0
* @homepage https://jsbin.com/beqosub/edit?html,css,output
*/

Expand All @@ -14,8 +14,8 @@
* @param {Array} offset distance (in pixels) from original placement position ("10px 20px" or just "10px" for both horizontal & vertical)
*/

const position = props => {
var {target, ref, offset, placement, prevPlacement, useRaf = true} = props,
const position = props => {
var {target, ref, offset, placement, prevPlacement, useRaf = true, track} = props,
pos = {x:ref.x, y:ref.y, h:0, w:0},
refRect = (ref && ref.x) ? {...ref} : {},
refWindow,
Expand Down Expand Up @@ -81,7 +81,7 @@
target.setAttribute('data-placement', placement.join(' '));
target.setAttribute('data-pos-overflow', Object.entries(overflow).reduce((acc, [k,v]) => v ? `${acc} ${k}` : acc , '').trim());
[
['pos-left', pos.x], // overflow.right ? vpSize.w - targetSize.w : pos.x
['pos-left', overflow.right ? vpSize.w - targetSize.w : pos.x],
['pos-top', pos.y], // pos.y > offset[1] ? pos.y : 0
['pos-target-width', targetSize.w],
['pos-target-height', targetSize.h],
Expand All @@ -94,6 +94,21 @@
].forEach(([k,v]) => target.style.setProperty('--'+k, Math.round(v)))
})

// auto-reposition on any ancestor scroll
if( track?.scroll && !target.position__trackedScroll ){
// mark the node as tracked
target.position__trackedScroll = true;

// if any ancestor of refElement was scrolled, re-position the target
window.addEventListener('scroll', onScroll, true)

function onScroll(e){
// make sure the scrolled element contains the ref element
if( e.target.contains(refElement) )
position(props)
}
}

return {pos, placement}
}

Expand Down
27 changes: 17 additions & 10 deletions dist/position.umd.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
/**
* @yaireo/position - Position a DOM element at a certain X,Y or next to another element
*
* @version v1.0.7
* @version v1.1.0
* @homepage https://jsbin.com/beqosub/edit?html,css,output
*/

/**
* @yaireo/position - Position a DOM element at a certain X,Y or next to another element
*
* @version v1.1.0
* @homepage https://jsbin.com/beqosub/edit?html,css,output
*/

Expand All @@ -12,13 +19,13 @@
* @param {String} placement [above/below/center & left/right/center] or mix of two (only works if "ref" is an HTML Element)
* @param {Array} prevPlacement used when calculated new position overflows
* @param {Array} offset distance (in pixels) from original placement position ("10px 20px" or just "10px" for both horizontal & vertical)
*/const c=a=>{var e,{target:f,ref:g,offset:h,placement:i,prevPlacement:j,useRaf:k=!0}=a,l={x:g.x,y:g.y,h:0,w:0},m=g&&g.x?{...g}:{},n=document.documentElement,o={w:n.clientWidth,h:n.clientHeight},p={w:f.clientWidth,h:f.clientHeight};// [horizontal, vertical]
*/const c=a=>{var e,{target:f,ref:g,offset:h,placement:i,prevPlacement:j,useRaf:l=!0,track:k}=a,m={x:g.x,y:g.y,h:0,w:0},n=g&&g.x?{...g}:{},o=document.documentElement,p={w:o.clientWidth,h:o.clientHeight},q={w:f.clientWidth,h:f.clientHeight};// [horizontal, vertical]
// if "ref" is a DOM element, get [x,y] coordinates and adjust according to desired placement
if(d=k?d:a=>a(),j=j||[],i=(i||" ").split(" ").map((b,a)=>b?b:["center","below"][a]),h=h?[h[0]||0,h[1]||h[0]||0]:[0,0],g.parentNode&&(e=g.ownerDocument.defaultView,m=g.getBoundingClientRect(),l.x=m.x,l.y=m.y,l.w=m.width,l.h=m.height,e!=e.parent))// if ref element is within an iframe, get it's position relative to the viewport and not its local window
for(let a of e.parent.document.getElementsByTagName("iframe"))if(a.contentWindow===e){let b=a.getBoundingClientRect();l.x+=b.x,l.y+=b.y}// horizontal
"left"==i[0]?l.x-=p.w+h[0]:"right"==i[0]?l.x+=l.w+h[0]:l.x-=p.w/2-l.w/2,"above"==i[1]?l.y-=p.h+h[1]:"below"==i[1]?l.y+=l.h+h[1]:l.y-=p.h/2-l.h/2;const q={top:0>l.y,bottom:l.y+p.h>o.h,left:0>l.x,right:l.x+p.w>o.w},r=b=>c({...a,placement:b.join(" "),prevPlacement:i});// horizontal fix for overflows
return q.left&&"right"!=j[0]?r(["right",i[1]]):q.right&&"left"!=j[0]?r(["left",i[1]]):q.bottom&&"above"!=j[1]?r([i[0],"above"]):q.top&&"below"!=j[1]?r([i[0],"below"]):(d(()=>{f.setAttribute("positioned",!0),f.setAttribute("data-placement",i.join(" ")),f.setAttribute("data-pos-overflow",Object.entries(q).reduce((a,[b,c])=>c?`${a} ${b}`:a,"").trim()),[["pos-left",l.x],// overflow.right ? vpSize.w - targetSize.w : pos.x
["pos-top",l.y],// pos.y > offset[1] ? pos.y : 0
["pos-target-width",p.w],["pos-target-height",p.h],["pos-ref-width",m.width||0],["pos-ref-height",m.height||0],["pos-ref-left",m.x],["pos-ref-top",m.y],["window-scroll-y",window.scrollY],["window-scroll-x",window.scrollX]].forEach(([a,c])=>f.style.setProperty("--"+a,b(c)))}),{pos:l,placement:i});// vertical fix for overflows
// update target's position
};let d=requestAnimationFrame||(a=>setTimeout(a,1e3/60));a.default=c});
if(d=l?d:a=>a(),j=j||[],i=(i||" ").split(" ").map((b,a)=>b?b:["center","below"][a]),h=h?[h[0]||0,h[1]||h[0]||0]:[0,0],g.parentNode&&(e=g.ownerDocument.defaultView,n=g.getBoundingClientRect(),m.x=n.x,m.y=n.y,m.w=n.width,m.h=n.height,e!=e.parent))// if ref element is within an iframe, get it's position relative to the viewport and not its local window
for(let a of e.parent.document.getElementsByTagName("iframe"))if(a.contentWindow===e){let b=a.getBoundingClientRect();m.x+=b.x,m.y+=b.y}// horizontal
"left"==i[0]?m.x-=q.w+h[0]:"right"==i[0]?m.x+=m.w+h[0]:m.x-=q.w/2-m.w/2,"above"==i[1]?m.y-=q.h+h[1]:"below"==i[1]?m.y+=m.h+h[1]:m.y-=q.h/2-m.h/2;const r={top:0>m.y,bottom:m.y+q.h>p.h,left:0>m.x,right:m.x+q.w>p.w},s=b=>c({...a,placement:b.join(" "),prevPlacement:i});// horizontal fix for overflows
if(r.left&&"right"!=j[0])return s(["right",i[1]]);if(r.right&&"left"!=j[0])return s(["left",i[1]]);// vertical fix for overflows
if(r.bottom&&"above"!=j[1])return s([i[0],"above"]);if(r.top&&"below"!=j[1])return s([i[0],"below"]);// update target's position
// auto-reposition on any ancestor scroll
if(d(()=>{f.setAttribute("positioned",!0),f.setAttribute("data-placement",i.join(" ")),f.setAttribute("data-pos-overflow",Object.entries(r).reduce((a,[b,c])=>c?`${a} ${b}`:a,"").trim()),[["pos-left",r.right?p.w-q.w:m.x],["pos-top",m.y],// pos.y > offset[1] ? pos.y : 0
["pos-target-width",q.w],["pos-target-height",q.h],["pos-ref-width",n.width||0],["pos-ref-height",n.height||0],["pos-ref-left",n.x],["pos-ref-top",n.y],["window-scroll-y",window.scrollY],["window-scroll-x",window.scrollX]].forEach(([a,c])=>f.style.setProperty("--"+a,b(c)))}),k?.scroll&&!f.position__trackedScroll){f.position__trackedScroll=!0,window.addEventListener("scroll",function(b){b.target.contains(refElement)&&c(a)},!0)}return{pos:m,placement:i}};let d=requestAnimationFrame||(a=>setTimeout(a,1e3/60));a.default=c});
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@yaireo/position",
"version": "1.0.7",
"version": "1.1.0",
"homepage": "https://jsbin.com/beqosub/edit?html,css,output",
"description": "Position a DOM element at a certain X,Y or next to another element",
"keywords": [
Expand Down

0 comments on commit 5381373

Please sign in to comment.