Lesson 19 - Bootstrap - Popovers
In the previous lesson, Bootstrap - Modal dialogs, we learned how to use modal dialogs. In today's tutorial, we're going to focus on Popovers in Bootstrap.
Popovers
Popovers are similar to tooltips but they aren't shown and hidden when hovered over, they react on clicking instead. Bootstrap adopted them from the iOS platform. This component is also based on the Popper.js library, similarly to Dropdowns. If you built Bootstrap's JavaScript by yourself, you'd need the plugin for Tooltips as well to make Popovers work, otherwise you can just load Bootstrap's JavaScript bundle or load "popper.min.js" separately, before Bootstrap.
Initialization
For optimization reasons, popovers are not initialized based on data attributes like the components we've talked about up until now. We have to initialize them manually e.g. via data attributes in JavaScript:
$(function () { $('[data-toggle="popover"]').popover(); });
Another initialization approach is to use a wrapper. We'd wrap an element from which we want to create the popover in another element and create the popover from that. Sometimes it may happen that the popover styles collide with our styles. The wrapper approach solves this problem since the popover is created from the wrapper which has no styles.
$(function () { $('.my-popover').popover({ container: 'body' }); });
Other properties
Bootstrap would like us to know these things about Popovers:
- If the title or content is an empty string, the popover will not be displayed. It isn't showed when we try to display the popover on a hidden element either.
- When combined with more complex components such as e.g. input groups or button groups, assign
container: body
to prevent problems with rendering. - To display a popover from an element with the
disabled
attribute or the.disabled
class, it's necessary to wrap this element and display the popover using this wrapper. - When applying popovers on links which wraps over multiple lines, the popover
will be centered depending on the total width of these links. To change this
behavior, assign the
white-space: nowrap
style to the<a>
element. - If we wanted to remove elements from which we've created the popovers, we would have to hide these popovers first.
Example
Let's have a look at 4 buttons which display popovers in different directions around them when clicked.
<button type="button" class="btn btn-primary" data-container="body" data-toggle="popover" data-placement="top" data-content="Text of the popover placed at the top."> Top </button> <button type="button" class="btn btn-secondary" data-container="body" data-toggle="popover" data-placement="right" data-content="Text of the popover placed at the right."> Right </button> <button type="button" class="btn btn-success" data-container="body" data-toggle="popover" data-placement="bottom" data-content="Text of the popover placed at the bottom."> Bottom </button> <button type="button" class="btn btn-danger" data-container="body" data-toggle="popover" data-placement="left" data-content="Text of the popover placed at the left."> Left </button> <script> $(function () { $('[data-toggle="popover"]').popover(); }); </script>
Notice that explicit initialization in JavaScript is necessary. The result:
In the example above, because of the browser screen size the bottom popover will also be shown on the top and the left one on the right.
Hiding when clicked outside of the popover
You surely tried and noticed that the popover closes only when the button is
clicked again. This behavior can be changed so that the popover will close when
clicked anywhere outside of the popover. We can create such popover using the
data-trigger="focus"
data attribute.
<a tabindex="0" class="btn btn-lg btn-primary" role="button" data-toggle="popover" data-trigger="focus" title="Hiding the popover" data-content="This content will be hidden when clicked anywhere outside.">Popover test</a>
The result in the browser:
We could achieve the same behavior by setting up the
trigger: focus
property in JavaScript. For buttons of this type, we
should use only <a>
elements with the "button" role and
tabindex=0
. This behavior may not be supported on the
<button>
element in some browsers.
JavaScript
That's all for popovers, it's just a simple component As always, let's have a look at how
the component is controlled directly in JavaScript.
Properties
We can set all the properties listed below using data attributes as well. To
get the name of the attribute, we just add the data-
prefix to the
property. If we wanted to initialize the properties in JavaScript, we can do so
by passing an object with these properties to the popover()
method:
$(function () { $('[data-toggle="popover"]').popover({ animation: false, title: "Info" }); });
animation
- Should an animation be applied? (true
by default)container
- Binds the popover to a given element.container: body
causes the popover to stick to the<body>
element, making it stay at the right place even when the screen size is reduced. The default value isfalse
.content
- The content of the popover showed by default if no content defined in thedata-content
data attribute of the element. If we pass a function, it'll be called in the context of the element which the popover is bound to. The default value is""
(an empty string).delay
- The delay in milliseconds before showing/hiding the popover. We can pass either one number or specify both values by passing an object with the following structure:delay: { "show": 250, "hide": 50 }
. The default value is0
.html
- Whether HTML content is supported incontent
. The default value isfalse
making all the inserted content plain text (using thetext()
jQuery method).placement
- Determines the position of the popover, we can provide the values"auto"
,"top"
,"bottom"
,"left"
, and"right"
, the default is"right"
. We can also pass a function to which will be passed the DOM element with the popover as the first parameter and the button element as the second parameter. Thethis
context is set to the popover instance.selector
- If we provide a particular selector to this property, the popovers will work even on dynamically inserted content. Otherwise, the popovers will become active only on elements present at the first page load. The default value isfalse
.template
- The HTML template from which the popup is created. The title will be placed into an element with the.popover-header
class. The content will be placed into.popover-body
. An element with the.arrow
class will be used as the arrow. The element wraping the whole popover should have the.popover
class assigned. The default value is:
'<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-header"></h3><div class="popover-body"></div></div>'
title
- Represents the default title if not specified by thedata-title
data attribute of a given element. We can also pass a function which is then called in the context ofthis
referencing the element the popover is bound to. The default value is""
(empty string).trigger
- Specifies the way the popover is displayed/hidden. We can pass the values"click"
,"hover"
,"focus"
,"manual"
. We can even enter multiple values, separated by a comma, except for"manual"
which cannot be combined. The default value is"click"
.offset
- Allows to move the popover relatively to the button. We move it either by the same distance in both directions, providing only a single value, or providing two values separated by a comma. We provide multiple values as a string (e.g."10%, 10px"
). We can also use math expressions. The default value is0
.fallbackPlacement
- Specifies in what position will the popover be if it doesn't fit in the predefined one. We can provide the values"flip"
,"clockwise"
,"counterclockwise"
or an array of values. The default value is"flip"
.
Methods
All the methods are called asynchronously and are passing control flow before the animation (transition) finishes. If we call a method on a popover which transition is currently in progress, this call will be ignored.
We can pass one of the following parameters to the popover()
method:
settings
- We can pass an object with properties to specify settings we shown above."show"
- Shows the popover of an element. Passes the control flow before the animation finishes and the element is actually hidden/shown."hide"
- Hides the popover of an element. Passes the control flow before the animation finishes and the element is actually hidden/shown."toggle"
- Hides/shows the popover of an element. Passes the control flow before the animation finishes and the element is actually hidden/shown."dispose"
- Hides and disposes the popover of an element. You may not be able to dispose popovers with theselector
specified."enable"
- Enables the popover of a given element to be displayed. Displaying is enabled to popovers by default."disable"
- Disables the displaying of the popover of a particular element."toggleEnabled"
- Enables/disables the popover of a particular element to be displayed."update"
- Updates the popover position.
Events
Under certain circumstances we may need to handle individual popover events. There are 5 of them:
show.bs.popover
- Is called immediately aftershow
is called. The element is typically not shown yet because the animation is playing.shown.bs.popover
- Is called right when the popover is shown (once the animation finishes).hide.bs.popover
- Is called immediately afterhide
is called. The element is typically not hidden yet because the animation is playing.hidden.bs.popover
- Is called when the popover is hidden (once the animation finishes).inserted.bs.popover
- Is called after theshow.bs.popover
event, when the template is added to the page DOM.
Handling an event could look like this:
$('#info-popover').on('hidden.bs.popover', function () { // some reaction... });
In the next lesson, Bootstrap - Scrollspy, we'll talk about the Scrollspy component.