Home > front end >  Show popup on mouse location
Show popup on mouse location

Time:01-13

I am having troubles with getting a popup to come up at the exact location of my mouse click. I want to be able to click a DIV (that is inside a table cell) and for a popup to show up whenever this div is clicked.

Right now I have the popup working, however no matter what I try the popup DIV is half way down the page.

HTML

<ul  style="display:none;" id="xxx<?php echo $fetch['unit_no']; ?>" role="menu" aria-labelledby="menuitems">
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#"</i>Link 1</a></li>
    <li role="presentation"><a role="menuitem" tabindex="-1" href="#"</i>Link 2</a></li>

</ul>

JQUERY

$(document).ready(function () {
        $('#myDiv<?php echo $fetch['unit_no']; ?>').click(function (e) {
            var myDiv = document.getElementById('myDiv<?php echo $fetch['unit_no']; ?>');
            var leftx = e.pageX-myDiv.offsetLeft;
            var topy = e.pageY-myDiv.offsetTop;

            $("#xxx<?php echo $fetch['unit_no']; ?>")
                .css({
                    position: 'absolute',
                    left: leftx,
                    top: topy,
                    display: 'block'
                })
           
        });
    });

Screenshot of what is happening below:

enter image description here

Is this to do with the positioning of the DIV?

CodePudding user response:

It depends whether your popup is position absolute or fixed and the parent has any position other than static set, and if the popup is inside the wrapper or not; or a direct child of body.

Three examples ahead:

  1. Absolute popup as child of a non-static parent (has Pros and Cons)
  2. Fixed popup (has Pros and Cons)
  3. Absolute popup as immediate child of document <body> (Best)

1. Move absolute child to X,Y coordinates within parent

Case: position: absolute; popup inside a position: relative; parent.

  • If the parent has scrollbars (overflow value other than visible)
X = Event.pageX   Parent.scrollLeft - Parent.offsetLeft
Y = Event.pageY   Parent.scrollTop - Parent.offsetTop
  • If the Parent has no scrollbars (Don't use this!):
// !! Bad practice !!
X = Event.pageX - Parent.offsetLeft   
Y = Event.pageY - Parent.offsetTop    

Example:

const EL = (sel, el) => (el||document).querySelector(sel);

const EL_area  = EL("#area");
const EL_popup = EL("#popup");

const showPopup = (evt) => {
  const EL_btn = evt.currentTarget;
  
  Object.assign(EL_popup.style, {
    left: `${evt.pageX   EL_btn.scrollLeft - EL_btn.offsetLeft}px`,
    top:  `${evt.pageY   EL_btn.scrollTop - EL_btn.offsetTop}px`,
    display: `block`,
  });
};

EL_area.addEventListener("click", showPopup);
body {
  height: 300vh; /* Just to force some scrollbars */
}

#area {
  position: relative;  /* this is needed! */  
  height: 150px;
  background: #eee;
  margin: 40px;
}

#popup {
  position: absolute;
  height: 30px;
  background: gold;
  display: none;
}
<div id="area">
  Click here to shop popup, and scroll the window
  <div id="popup">Popup</div>
</div>

Pros:

  • Even if the page is scrolled, the popup stays still inside the wrapping element

Cons:

  • Additional code is needed to prevent the popup move if he was the actual Event target - to allow inner content to be interacted with and the popup not move.
  • The popup needs to be child of a specific parent Element, which leads to poor Popup and code reusability. PS: A solution would be using: SomeClickedElement.append(EL_popup).
  • The wrapping parent element (#area) needs to have a position set (other than static), i.e: position: relative;

2. Move fixed element to X,Y coordinates

Case: position: fixed; popup outside (or inside) of parent, but usually as child of <body>.

X = Event.clientX  
Y = Event.clientY

Example:

const EL = (sel, el) => (el||document).querySelector(sel);

const EL_area  = EL("#area");
const EL_popup = EL("#popup");

const showPopup = (evt) => {
  Object.assign(EL_popup.style, {
    left: `${evt.clientX}px`,
    top: `${evt.clientY}px`,
    display: `block`,
  });
};

EL_area.addEventListener("click", showPopup);
body {
  height: 300vh; /* Just to force some scrollbars */
}

#area {
  /* position: relative; /* not necessary any more */
  height: 150px;
  background: #eee;
  margin: 40px;
}

#popup {
  position: fixed;
  height: 30px;
  background: gold;
  display: none;
}
<div id="area">
  Click here to shop popup, and scroll the window
</div>

<div id="popup">Popup fixed</div>

Pros:

  • If placed outside of the parent (#area) - no additional code is necessary to prevent it from moving if the click initiated inside of it.
  • Better code reusability. Depending on the clicked element you can reuse the same popup by just changing its content.
  • The wrapping parent element (#area) does not need to have a position.
  • Event.clientX and Event.clientY is all it takes to move it to the new position.

Cons:

  • If the page is scrolled, the popup position is fixed in relation to the window. A solution is make it hide on page scroll, or more complicated - move it by the change difference in coordinates.

3. (Best!) Move absolute (in-body) element to X,Y coordinates

Case: position: absolute; popup as immediate child of body

X = Event.clientX   window.scrollX
Y = Event.clientY   window.scrollY

Example:

const EL = (sel, el) => (el||document).querySelector(sel);

const EL_area  = EL("#area");
const EL_popup = EL("#popup");

const showPopup = (evt) => {
  Object.assign(EL_popup.style, {
    left: `${evt.clientX   window.scrollX}px`,
    top: `${evt.clientY   window.scrollY}px`,
    display: `block`,
  });
};

EL_area.addEventListener("click", showPopup);
body {
  height: 300vh; /* Just to force some scrollbars */
}

#area {
  /* position: relative; /* not necessary any more */
  height: 150px;
  background: #eee;
  margin: 40px;
}

#popup {
  position: absolute;
  height: 30px;
  background: gold;
  display: none;
}
<div id="area">
  Click here to shop popup, and scroll the window
</div>

<div id="popup">Popup fixed</div>

Pros:

  • Even If the page is scrolled, the popup position is "anchored" in the same position relative to the document, not to the scrolling window.
  • (Unless the Event.currentTarget is the entire "body") the popup will not change position if its contents are clicked.

Suggestions for all cases:

  • For an improved UX (User Experience) a "floating" popup, needs additional calculation, and that is — determining the remaining available space in order to fit it in the window without hiding parts of it (a min-max of the coordinates and the actual popup size and available window width,height). I let this one for the reader since the answer is getting pretty lengthy - unless explicitly required in comments.
  • Additional code is necessary to close a Popup if the user clicks outside of it. This can be achieved by simply checking if on click — the Event.target.closest("#popup") !== EL_popup (Close the popup if true). The same sometimes applies for Context-menus, but rarely for window-centered Modals — which have a dedicated close button.

Best practice example:

const EL = (sel, el) => (el||document).querySelector(sel);

let EL_popup; // To remember the currently active popup: 
const handler_popup = (evt) => {
  // Get clicked target
  const EL_targ = evt.target;
  
  // Clicked a popup, do nothing (Comment this line if not needed)
  if (EL_targ.closest(".popup")) return;

  // Close currently open popup (if any):
  if (EL_popup) EL_popup.classList.remove("is-active");
  
  // Get initiator button
  const EL_btn = EL_targ.closest("[data-popup]");
  
  // Not a valid button
  if (!EL_btn) return;
  
  // Get the popup
  EL_popup = EL(EL_btn.dataset.popup);  
  
  // No matching popup in this page, do nothing
  if (!EL_popup) return; 

  // Show popup
  Object.assign(EL_popup.style, {
    left: `${evt.clientX   window.scrollX}px`,
    top: `${evt.clientY   window.scrollY}px`,
  });
  EL_popup.classList.add("is-active");
  
};

EL("body").addEventListener("click", handler_popup);
body {
  min-height: 300vh;
}

#area {
  background: #eee;
  padding: 10px;
}

.popup {
  position: absolute;
  background: gold;
  display: none;
}
.popup.is-active {
  display: block;
}
<div id="area" data-popup="#popup-one">Show "popup one"</div>

<button data-popup="#popup-two" type="button">Show "popup two"</button>

<br>Click anywhere to close an open popup  
<br>Click inside a popup. It will not close ()

<div  id="popup-one">Popup one!</div>
<div  id="popup-two">Popup TWO!</div>

CodePudding user response:

If you're looking to get a popup at the exact location of the mouse click, you really only need to know where the mouse is clicking in the window. Your click listener is already targeting the DIV so this will only register clicks in this area so you could just use event.clientX and event.clientY to get the pointer location.

$('#myDiv').click(function (event) {

  $("#xxx").css({
    left: event.clientX,
    top: event.clientY,
    display: 'block'
  });

});

CodePudding user response:

use Position : "absolute" for make your div in exact position.

  •  Tags:  
  • Related