2

I like letting my popovers stay open until the user explicitly closes them.

One of the nice features of the new Bootstrap Popovers is that they automatically re-position when the user changes device orientation, scroll or resize the window. They even follow along as the content re-flows - e.g. as a paragraph is wrapped and the element grows or shrinks in length while you resize the window - all the popovers on the screen will keep re-positioning to be near their target.

How does the Popover plugin know that the page is being re-flowed so that it triggers the popover re-positioning?

My webapp is dynamic, user actions cause elements to grow/shrink, toggle on/off, etc. At the moment, when I change the page via code, the popovers get left behind - they don't get re-positioned near their target.

One workaround to this, as a user, is to just scroll the screen a little bit and Bootstrap will re-position the popovers and everything looks right again.

I'm trying to figure out a way to re-position the popovers when I change the page layout via code.

Hence the question: how does Popover re-positioning work (and can I hook into it so I can trigger it automatically).

EDIT: I've just noticed that the popovers will re-position just fine if the "dynamic" content happens to be the Bootstrap navbar collapsing/expanding because of a tap on the navbar-toggler.

Shorn
  • 19,077
  • 15
  • 90
  • 168

2 Answers2

5

There's two parts to this question.

  1. How does popper.js know when to update the popovers?
  2. How does the popover change position?

Answering these backwards:

2: How does the popover change position?

You need the update method of the popover:

$('#element').popover('update')

I've done a quick demo here:

https://jsfiddle.net/pktyptyp/

First, click the green button to open the popover. Then use button 2 to move the popover toggle. Now the toggle and the popover no longer line up. So finally use button 3 to reposition the popover by its toggle.

The docs for this are tucked under the popover methods section here:

http://getbootstrap.com/docs/4.0/components/popovers/#methods

If you wanted to update every popover on your page and not just a specific one, then you could do:

$('[data-toggle="popover"]').popover('update')

How does popper.js know when to update the popovers?

Popper will be subscribing to events like window.scroll and window.resize. You can see this in a bit of their source code:

https://github.com/FezVrasta/popper.js/blob/master/packages/popper/src/utils/setupEventListeners.js

The update method won't be called immediately in that event handler - there'll be something that gets passed back to the Boostrap widget, which in turn will call the popover update method.

I am fairly sure Popper & the Popover widget will not be looking at the position of the individual toggles. This is partly because unless the toggles are positioned, their left/top properties will always be 'auto' so it will be hard to work out if they are moving. Or to put it another way, when the window scrolls, the toggle has not moved within the document, but the popover (which is absolutely positioned) needs updating. So this is a bit of a broad brush - they are looking out for the entire window changing, assuming the popovers are out of position, then triggering more events to update them.

If anyone knows more about this, though, please tell me in the comments!

You have a bit of an advantage in that you know when you change your UI, so you can call 'update' on all the Popovers at will. This to me seems like the ideal approach.

However, if your toggles are absolutely positioned, you could do this a bit more automatically by watching their position. Here's an example with an absolutely-positioned toggle and in this example, the popover moves automatically without the third button click.

https://jsfiddle.net/pktyptyp/1/

sifriday
  • 4,342
  • 1
  • 13
  • 24
  • Upvoted for pointing out the update method (which I did figure out eventually on my own). But the question is really about how does bootstrap/popper know that stuff is changing on screen so that it then knows to update the popovers? – Shorn Oct 20 '17 at 06:50
  • 1
    I did wonder if that was what you were asking. Popper will watch events like window.resize and scrolling - https://github.com/FezVrasta/popper.js/blob/master/packages/popper/src/utils/setupEventListeners.js It might watch a couple of other events, too (not sure). But you have the advantage of knowing when your UI changes (you changed it in code) so you can call 'update' directly, which seems neater? If you wanted a more automatic approach, you could watch the x,y position of your toggle and when it changes, call update. – sifriday Oct 20 '17 at 09:38
  • 1
    I just updated my answer to expand on the above a bit. – sifriday Oct 20 '17 at 09:55
  • Yes - I do have my app working now by calling update from everywhere that content currently changes. Easy enough for now, but things are going to get complicated as the app grows. But still, that's a separate question, I think this pretty much covers it for Popper/Bootstrap. – Shorn Oct 20 '17 at 11:15
1

I don't know how the logic work behind that because on Bootstrap we use Popper.js to handle that so if you want to understand the logic behind that you can browser this : https://github.com/FezVrasta/popper.js

Johann-S
  • 1,181
  • 1
  • 10
  • 10
  • So Bootstrap isn't doing anything to update the popper positioning? But then the question as asked still stands - how does Popper know when to update the popover positions? – Shorn Oct 20 '17 at 06:51