How to position modal dialog at x,y coordinates of click event?

The Objective:

I’m attempting to create a modal dialog that pops up at the event.clientX/Y coordinates of a click event, but which corner of the dialog box sits at the x,y position depends on which view port quadrant the event is in.

The positioning scheme is simple. The dialog box’ top/bottom edge should be positioned at the event.clientY coordinate depending on whether .clientY is in the upper/lower half of the view port. The box’ left/right edge should be at the.clientX coordinate depending on whether .clientX is in the left/right half of the view port. Thus, if the event is in the upper left quadrant, the dialog’s upper left corner will sit at .clientX/Y, if in the lower right quadrant, then its lower right corner will sit at x,y, etc.

The Problem:

I have the solution to positioning the dialog on the x-axis but the solution to positioning it on the y-axis is proving elusive. The problem is that the correct corner sometimes sits at x,y and sometimes is offset up or down from x,y. The discrepancy seems to be proportional to the amount the page has been scrolled. As the page is scrolled up, the discrepancy grows larger. The problem is intractable for me.

Illustrations:

There is a pen, Popup Project, on CodePen. The positioning function begins on JS line 233. There are three screenshots, screenshot 0, screenshot 1, and screenshot 2 illustrating the problem. The dialog’s behavior can be seen on the /test-table page of my website, but also on the pen and, if tested locally, there.

The Code:

The function I’m using is:

// positon popup on page relative to cursor
// position at time of click event  
function positionPopupOnPage( evt ) {

    var vpWH = [];                    // viewport Width-Height
    var vpW, vpH;
    var coordX = evt.clientX;
    var coordY = evt.clientY;

    vpWH = getViewPortWidthHeight();
    vpW = vpWH[0];
    vpH = vpWH[1];
   popup.style.visibility = 'hidden';
   popup.style.position = 'absolute';
  // if not display: block, .offsetWidth & .offsetHeight === 0
  popup.style.display = 'block';
  popup.style.zIndex = '10100';

  if ( coordX > vpW/2 ) { coordX -= popup.offsetWidth; }
  if ( coordY > vpH/2 ) { coordY -= popup.offsetHeight; }
  popup.style.top = coordY + 'px';
  popup.style.left = coordX + 'px';
  popup.style.visibility = 'visible';
}    // end fn positionPopupOnPage

Mille Grazie

Any help will be greatly appreciated. Thank you for your interest in my question and for your time.

-Steve

1 Like

The trick, for me, was to realize 4 things:

  1. An absolutely positioned element, which the div popup is, is positioned from the page top not the view port top.
  2. As the page is scrolled up, one has to account for the distance scrolled up, i.e. the distance from the view port top to the page top.
  3. That distance is obtained by document.body.scrollTop.
  4. Add that distance to the distance from the click point to the view port top, i.e. event.clientY, to get the total distance to use in setting popup’s CSS top property.

The correct function to solve the problem then becomes:

// positon popup on page relative to cursor
// position at time of click event  
function positionPopupOnPage( evt ) {

var VPWH = [];                  // view port width / height
var intVPW, intVPH;             // view port width / height
var intCoordX = evt.clientX;    
var intCoordY = evt.clientY;    // distance from click point to view port top
var intDistanceScrolledUp = document.body.scrollTop;
      // distance the page has been scrolled up from view port top
var intPopupOffsetTop = intDistanceScrolledUp + intCoordY;
    // add the two for total distance from click point y to top of page

var intDistanceScrolledLeft = document.body.scrollLeft;
var intPopupOffsetLeft = intDistanceScrolledLeft + intCoordX;

VPWH = getViewPortWidthHeight();    // view port Width/Height
intVPW = VPWH[0];
intVPH = VPWH[1];

popup.style.position = 'absolute';
        // if not display: block, .offsetWidth & .offsetHeight === 0
popup.style.display = 'block';
popup.style.zIndex = '10100';

if ( intCoordX > intVPW/2 ) { intPopupOffsetLeft -= popup.offsetWidth; }
      // if x is in the right half of the viewport, pull popup left by its width
if ( intCoordY > intVPH/2 ) { intPopupOffsetTop -= popup.offsetHeight; }
    // if y is in the bottom half of view port, pull popup up by its height

popup.style.top = intPopupOffsetTop + 'px';
popup.style.left = intPopupOffsetLeft + 'px';
}   // end fn positionPopupOnPage

With thanks to user ershwetabansal on CSS Tricks for leading me to point 2 above.

3 Likes

I wasn’t quite sure where you want to popup to appear, but I wonder if you could just have used position: fixed to position it in relation to the viewport.

1 Like

Hah! All that work and all my inventiveness only to find out there’s a simpler and better way. There’s always a better way. I guess that’s why I’m the novice and you’re the administrator. :slight_smile: But I don’t know if I’ll implement your solution. I’m already feeling separation anxiety from mine. :wink:

Thanks.

1 Like

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.