Today, you have brought up a couple of queries, both of which I believe can be addressed by dynamically creating the popover during the click event.
To position the popover in the middle of the element, one can calculate and provide an "offset" option. Refer to the red circle & the togglePopover_toCenter
function in the example
For pointing the popover to where the mouse is located at the time of clicking, it requires attaching an event listener that utilizes the mouse coordinates to adjust the popover's positioning upon generation.
Check out the blue circle & the togglePopover_toMouse
function in the sample provided
function togglePopover_toCenter(event) {
const targetElement = event.target;
// Dispose of any existing popover for this element.
const oldPopover = bootstrap.Popover.getInstance(targetElement);
if (oldPopover){
oldPopover.dispose();
}
const generatePopover = (element) => {
// Obtain the element's width
const boundingRect = element.getBoundingClientRect();
const elementWidth = boundingRect.width;
// Calculate the necessary "distance" value for the offset option
// Half of the element's width, converted to negative, adding back the default 8 for the triangle
const offsetDistance = (elementWidth/2 * -1) + 8;
// Set up the popover using the offset attribute
const popover = new bootstrap.Popover(
element,
{
html: true,
sanitize: false,
trigger: 'manual',
content: 'Nice',
offset: [0, offsetDistance]
}
);
return popover;
}
const newPopover = generatePopover(targetElement);
newPopover.toggle();
}
function togglePopover_toMouse(event) {
//Dispose of any existing popover for this element.
const oldPopover = bootstrap.Popover.getInstance(event.target);
if (oldPopover){
oldPopover.dispose();
}
const generatePopover_toMouse = (event) =>{
// Get the clicked element
const targetElement = event.target;
// Set up the popover
const popover = new bootstrap.Popover(
targetElement,
{
html: true,
sanitize: false,
trigger: 'manual',
content: 'Nice'
}
);
// Obtain the clicked element's boundRect
const boundingRect = targetElement.getBoundingClientRect();
const x = event.clientX - boundingRect.left; //x position within the element.
const y = event.clientY - boundingRect.top; //y position within the element.
// Set up an event listener to move the popover after it is shown
targetElement.addEventListener('shown.bs.popover',() => {
if (popover.tip){
popover.tip.style.left = `${x - boundingRect.width}px`;
popover.tip.style.top = `${y - (boundingRect.height/2)}px`;
}
});
popover.toggle();
}
// Create a new popover by passing in the click event
generatePopover_toMouse(event);
}
<script src="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="52303d3d26212620332212677c627c60">[email protected]</a>/dist/js/bootstrap.bundle.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="54363b3b20272026352414617a647a66">[email protected]</a>/dist/css/bootstrap.min.css" rel="stylesheet"/>
<svg onclick="togglePopover_toCenter(event)" height="100" width="100">
<circle id="test" cx="50" cy="50" r="40" stroke="black" stroke width="3" fill="red" />
</svg>
<br />
<svg onclick="togglePopover_toMouse(event)" height="100" width="100">
<circle id="test" cx="50" cy="50" r="40" stroke="black" stroke width="3" fill="blue" />
</svg>