Popover popover.js
A more robust version of a tooltip, that allows for larger pieces of content or interactive functionality.
Notices
Widget Dependencies
Popover requires the following:
- Tooltip widget for the base functionality.
- Drag widget for drag functionality.
- The third-party library Popper to provide dynamic positioning and viewport detection.
Overview
Important notes about using the popover widget:
- Specify
container: 'body'
to avoid rendering problems in more complex components (like our input groups, button groups, etc). - Triggering popovers on hidden elements will not work.
- Popovers for
.disabled
ordisabled
elements must be triggered on a wrapper element. - When triggered from anchors that wrap across multiple lines, popovers will be centered between the anchors' overall width. Use
white-space: nowrap;
on your<a>
s to avoid this behavior.
Examples
Default Toggle Example
<button type="button" class="btn btn-info" data-cfw="popover" title="Click Popover Example" data-cfw-popover-content="Click the trigger or close button to close me." data-cfw-popover-placement="forward">Click to toggle popover</button>
Four Directions
Four options are available: top, forward( right), bottom, and reverse (left) aligned.
Heads up! When using the right-to-left, rtl
, variant of Figuration all horizontal directions will be reversed. Meaning left becomes right, and vice-versa.
<button type="button" class="btn" data-cfw="popover" data-cfw-popover-container="body" data-cfw-popover-placement="top" data-cfw-popover-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">
Popover on top
</button>
<button type="button" class="btn" data-cfw="popover" data-cfw-popover-container="body" data-cfw-popover-placement="forward" data-cfw-popover-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">
Forward popover
</button>
<button type="button" class="btn" data-cfw="popover" data-cfw-popover-container="body" data-cfw-popover-placement="bottom" data-cfw-popover-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">
Popover on bottom
</button>
<button type="button" class="btn" data-cfw="popover" data-cfw-popover-container="body" data-cfw-popover-placement="reverse" data-cfw-popover-content="Vivamus sagittis lacus vel augue laoreet rutrum faucibus.">
Reverse popover
</button>
Hover Example
<button type="button" class="btn btn-info" id="cf-example-hover-popover" data-cfw="popover" title="Hover Popover Example" data-cfw-popover-content="Stop hovering over the trigger or the popover to auto-close." data-cfw-popover-placement="forward" data-cfw-popover-trigger="hover focus">Hover/focus to show popover</button>
Dismissable Example
Use the focus
trigger to dismiss popovers on the user's next click of a different element than the toggle element.
<button type="button" class="btn btn-info" data-cfw="popover" title="Dismissable Popover example" data-cfw-popover-content="Click on an element other than the trigger or popover to close." data-cfw-popover-trigger="focus">Dismissable popover</button>
Draggable Example
Allow users to move popovers around the screen by enabling the drag
option. Drag support mouse, keyboard (with arrow keys), and touch movement.
<button type="button" class="btn btn-info" data-cfw="popover" title="Draggable Popover Example" data-cfw-popover-content="Click the trigger or close link to close me." data-cfw-popover-placement="forward" data-cfw-popover-drag="true">Draggable popover</button>
Popover with HTML
<button type="button" class="btn btn-info" data-cfw="popover" data-cfw-popover-html="true" data-cfw-popover-placement="forward" data-cfw-popover-content="<em>Popover</em> <u>with</u> <b>HTML</b>" title="<em>Popover</em> <u>with</u> <b>HTML</b>">Popover with HTML</button>
If using more complex HTML, using a data attribute might not be optimal. A better option would be to use the Javascript options, or with a pre-generated popover, as shown in the following example.
<button type="button" class="btn btn-info" id="html-popover">Popover with HTML</button>
<script>
$('#html-popover').CFW_Popover({
html: true,
title: '<em>Popover</em> <u>with</u> <b>HTML</b>',
content: '<span aria-hidden="true">·</span> <em>Popover</em> <u>with</u> <b>HTML</b>'
});
</script>
Pre-generated Popover
Have complex content that you would like to show in a popover, or one that is updated dynamically? Create the popover and then link to it with the target
option.
Popover title
Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.
<button type="button" class="btn btn-info" data-cfw="popover" data-cfw-popover-target="#popoverExample0" data-cfw-popover-placement="forward">Show Popover</button>
<div class="popover" id="popoverExample0">
<h3 class="popover-header">Popover title</h3>
<div class="popover-body">
<p>Sed posuere consectetur est at lobortis. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum.</p>
<figure class="figure">
<img src="/assets/4.4/img/test.gif" class="figure-img img-fluid" alt="Sample image">
<figcaption class="figure-caption">Sample image caption.</figcaption>
</figure>
</div>
<div class="popover-arrow"></div>
</div>
Custom Placement
Locate a popover anywhere you need with the placement
option.
<button type="button" class="btn btn-info" id="cf-example-placed-popover" title="Custom placed popover" data-cfw-popover-content="Look, I am way over here!">Custom Placement Popover</button>
<script>
$('#cf-example-placed-popover').CFW_Popover({
placement : function(tip, trigger) {
var $trigger = $(trigger);
var loc = {};
var pos = $trigger.offset();
loc.top = pos.top;
loc.left = pos.left + $trigger.parent().width() - $trigger.outerWidth();
return loc;
}
});
</script>
Custom Container
When you have some styles on a parent element that interfere with a popover, you may want to specify a custom container
so that the popover's HTML appears within that element instead. This is common in elements with overflow styles, or dimensions smaller than the popover, such as responsive tables or input groups.
$('#example-popover').CFW_Popover({
container: 'body'
});
Another situation where you will want to set an explicit custom container
are popovers inside a modal dialog, to make sure that the popover itself is appended to the modal. This is particularly important for popovers that contain interactive elements – modal dialogs will trap focus, so unless the popover is a child element of the modal, users won't be able to focus or activate these interactive elements.
$('#example-popover').CFW_Popover({
container: '#example-modal .modal-body'
});
Viewport Constrainment
Keep popovers in their place with the viewport
option.
<div class="container-viewport" id="viewport-popover">
<p class="viewport-text">Viewport constraints for popovers.</p>
<button type="button" class="btn btn-info popover-viewport-bottom" title="This should be shifted to the right">Shift Right</button>
<button type="button" class="btn btn-info popover-viewport-right" title="This should be shifted down">Shift Down</button>
<button type="button" class="btn btn-info float-end popover-viewport-bottom" title="This should be shifted to the left">Shift Left</button>
<button type="button" class="btn btn-info popover-viewport-right btn-bottom" title="This should be shifted up">Shift Up</button>
<button type="button" class="btn btn-info popover-viewport-drag btn-drag" title="This should be confined to the viewport box">Drag Test (click)</button>
</div>
<script>
$('.popover-viewport-right').CFW_Popover({
placement: 'forward',
viewport: '#viewport-popover',
padding: 2
});
$('.popover-viewport-bottom').CFW_Popover({
placement: 'bottom',
viewport: '#viewport-popover',
padding: 2
});
$('.popover-viewport-drag').CFW_Popover({
drag: true,
viewport: '#viewport-popover',
padding: 2
});
</script>
Fixed Draggable
Create a fixed
position draggable popover by overriding the popperConfig options with a positionFixed: true
setting.
<button class="btn popover-drag-fixed btn-secondary" title="This should be confined to the window">Fixed Drag</button>
<script>
$('.popover-drag-fixed').CFW_Popover({
drag: true,
popperConfig: {
positionFixed: true
}
});
</script>
If a fixed
position draggable popover is constrained by a viewport, then it will not move when the container is scrolled, but will attempt to stay inside the viewport if the body is scrolled.
<div class="container-viewport container-viewport-scroll" id="viewport-popover-scroll">
<p class="viewport-text">Test viewport constraints for popovers.</p>
<button class="btn popover-viewport-drag-fixed-scroll btn-drag" title="This should be confined to the viewport box">Fixed Drag</button>
</div>
<script>
$('.popover-viewport-drag-fixed-scroll').CFW_Popover({
placement: 'reverse',
drag: true,
viewport: '#viewport-popover-scroll',
popperConfig: {
positionFixed: true
}
});
</script>
Disabled Elements
Elements with the disabled
attribute aren't interactive, meaning users cannot hover or click them to trigger a popover (or tooltip). As a workaround, you'll want to trigger the popover from a wrapper <div>
or <span>
, ideally made keyboard-focusable using tabindex="0"
.
For disabled popover triggers, you may also prefer data-cfw-popover-trigger="hover focus"
so that the popover appears as immediate visual feedback to your users as they may not expect to click on a disabled element.
<span class="d-inline-block" tabindex="0" data-cfw="popover" data-cfw-popover-trigger="hover focus" data-cfw-popover-content="Popover for disabled item">
<button class="btn btn-primary" type="button" disabled>Disabled button</button>
</span>
Usage
The popover widget, by default, generates content and markup on demand, and by default places popovers after their trigger element.
Via Data Attributes
Toggle
The required markup for a popover is only a data-cfw="popover"
attribute and title
or a data-cfw-popover-content=""
on the HTML element you wish to have a popover. The generated markup of a popover is rather simple, though it does require a position (by default, set to top by the widget).
If the popover item is already created, you can link to it using data-cfw-popover-target="#somePopover"
, or href="#somePopover"
. The proper role
and aria-
attributes will be automatically created to link the trigger and target elements.
Dismiss
Dismissal can be achieved with data-cfw-dismiss
attributes on a button within the popover as demonstrated below:
<button type="button" class="close" data-cfw-dismiss="popover" aria-label="Close"><span aria-hidden="true">×</span></button>
or on a button outside the popover using the additional data-cfw-popover-target
as demonstrated below:
<button type="button" class="close" data-cfw-dismiss="popover" data-cfw-popover-target="#myPopover">Close popover</button>
Via JavaScript
Enable manually with:
$('#myPopover').CFW_Popover();
Close Triggers
Any element with a data attribute of data-cfw-dismiss="popover"
within the popover element will act as a close trigger for the popover. There can be multiple close triggers, such as a header/titlebar close and a cancel button in the footer.
Draggable Popovers
The added functionality from the Drag widget allows for touch and mouse dragging to be available.
The drag event handlers will auto-enable when a data-cfw-drag="popover"
trigger item is found within the popover item. The drag
option will insert a drag trigger into the popover element, resulting in invoking the drag handlers.
Draggable popovers will force the following settings:
container: 'body'
trigger: 'click'
Options
Options can be passed via data attributes or JavaScript. For data attributes, append the option name to data-cfw-popover
, as in data-cfw-popover-placement="forward"
.
Name | Type | Default | Description |
---|---|---|---|
target |
string | null |
The selector of the target popover. |
display |
string | block |
Value of CSS display rule when popover is visible. |
animate |
boolean | true |
If popover items should fade in and out. |
placement |
string | object | function | 'top' |
string:
object:
function: function myPopoverAlign(tip, trigger) { // this - popover data-api // tip -> popover target // trigger -> popover trigger } |
trigger |
string | 'click' |
How popover is triggered - click | hover | focus | manual. You may pass multiple triggers; separate them with a space. manual cannot be combined with any other trigger. |
delay |
number| object | show:0, hide:250 |
Delay showing and hiding the popover (ms) - does not apply to manual trigger type. If a number is supplied, delay is applied to both hide/show. Object structure is:delay: { show: 500, hide: 100 }
|
container |
string | false | false |
Appends the popover to a specific element. Example: Note: Figuration is still using Popper v1, due to legacy support of IE11, and there is a known issue regarding using a positioned container that was not resolved until Popper v2. For the time being, be sure to use containers that are not positioned. |
viewport |
string | element | function | 'scrollParent' |
Keeps the popover within the bounds of this element. Example: If a function is given, it is called with the triggering element DOM node as its only argument. The This option maps to the |
padding |
integer | 0 |
Spacing, in pixels, to keep the popover away from the viewport edge. |
html |
boolean | false |
Insert HTML into the popover. If false, jQuery's text method will be used to insert content into the DOM. Use text if you're worried about XSS attacks. |
closetext |
string | '<span aria-hidden="true" >×</span>' |
Visible text for close links when using option trigger: 'click' |
closesrtext |
string | 'Close' |
Screen reader only text alternative for close links when using option trigger: 'click' |
title |
string | function | '' |
Default title value if title attribute isn't present. |
content |
string | function | '' |
Default title value if data-cfw-popover-content attribute isn't present. |
customClass |
string | function | '' |
Add classes to the popover when it is shown. Note that these classes will be added in addition to any classes specified in the template. To add multiple classes, separate them with spaces: You can also pass a function that should return a single string containing additional class names. |
unlink |
boolean | false |
If the unlink method should be called when the popover is hidden. This leaves the popover behind in the DOM. |
dispose |
boolean | false |
If the dispose method should be called when the popover is hidden. This will remove the popover from the DOM. |
drag |
boolean | false |
If the popover should have a drag handle inserted. |
dragtext |
string | '<span aria-hidden="true" >+</span>' |
Visible text for the auto-inserted drag handle. |
dragsrtext |
string | 'Drag' |
Screen reader only text alternative for the auto-inserted drag handle. |
dragstep |
integer | 10 |
Pixel increment to move the popover when using arrow keys on a drag handle. |
show |
boolean | false |
Show the popover automatically at the end of initialization. This will force the trigger option to a setting of 'click' . |
popperConfig |
null | object | null |
Pass a customized Popper configuration that will override the default Popper configuration. |
$('#myPopover').CFW_Popover({
placement: 'forward'
});
Methods
Method calls can be made on either the trigger or the target <div class="popover">
element.
Method Name | Description |
---|---|
toggle |
Toggles a popover item to be shown or hidden. |
show |
Shows an element's popover. |
hide |
Hides an element's popover. |
locateUpdate |
Update the positioning of a popover. Can be useful after an AJAX content update. |
unlink |
Hides the popover, removes events and attributes from both trigger and popover. |
dispose |
Calls the `unlink` method, and then removes the popover from the DOM. |
$('#myPopover').CFW_Popover('show');
Events
Event callbacks happen on the toggle/trigger element.
Event Type | Description |
---|---|
init.cfw.popover |
This event fires after the popover item is initialized. |
beforeShow.cfw.popover |
This event is fired immediately when the show method is called. If the popover container is not present, it is created just after this event is called. |
afterShow.cfw.popover |
This event is fired when a popover has been made visible to the user (will wait for CSS transitions to complete). |
beforeHide.cfw.popover |
This event is fired immediately when the hide method is called. |
afterHide.cfw.popover |
This event is fired when a popover has been hidden from the user (will wait for CSS transitions to complete). |
inserted.cfw.popover |
This event is fired after the beforeShow.cfw.popover event when the popover has been added to the DOM. |
dragStart.cfw.popover |
This event is fired at the start of the drag action. |
dragEnd.cfw.popover |
This event is fired at the end of the drag action. |
beforeUnlink.cfw.popover |
This event is fired immediately when the unlink method is called. This event can occur after the beforeHide event if set to automatically unlink, or before if called via method. |
afterUnlink.cfw.popover |
This event is fired on the trigger element when a popover item has been unlinked from its trigger item and the data-api removed. This event can occur after the This event may need to be listened for using event delegation, since all |
dispose.cfw.popover |
This event is fired immediately before the popover item is removed from the DOM. This event may need to be listened for using event delegation, since all |
$('#myPopover').on('afterHide.cfw.popover', function() {
// do something...
});
Server-side Apps
Popovers are designed to hopefully work with server side applications, such as Apache Wicket, and other instances where the server-side application might need to create or update the popover content after the initial page load.
A quick example:
- An item with an event handler that makes a callback to create a new popover is interacted with.
-
Call as needed:
$('#myPopover').CFW_Popover('hide');
- or
$('#myPopover').CFW_Popover('unlink');
- or
$('#myPopover').CFW_Popover('dispose');
- Update/create the popover object and insert into DOM.
- Initialize the popover:
$('#myPopover').CFW_Popover(options);
with desired options. - Show popover:
$('#myPopover').CFW_Popover('show');
Accessibility
Consider Keyboard and Assistive Technology Users
You should only add popovers to HTML elements that are traditionally keyboard-focusable and interactive (such as links or form controls). Although arbitrary HTML elements (such as <span>
s) can be made focusable by adding the tabindex="0"
attribute, this will add potentially annoying and confusing tab stops on non-interactive elements for keyboard users. In addition, most assistive technologies currently do not announce the tooltip in this situation. Additionally, do not rely solely on hover
as the trigger for your popovers as this will make them impossible to trigger for keyboard users.
Avoid adding an excessive amount of content in popovers with the html
option. Once popovers are displayed, their content is tied to the trigger element with the aria-describedby
attribute, causing all of the popover’s content to be announced to assistive technology users as one long, uninterrupted stream.
Key Commands
The following key commands are handled when focus is inside the popover, or on the popover trigger:
- Esc - Close the popover
Focus Handling
Popovers have additional focus handling when using keyboard navigation.
If navigating from above the popover's trigger (typically with the Tab key), the trigger becomes focused, the next forward focus will move from the trigger to the first focusable item inside the popover.
If navigating from below the popover's trigger (typically with the Shift + Tab key combination), when the trigger is focused, focus will be moved from the trigger to the last focusable item inside the popover.
When navigating forward, out the bottom of the popover, the focus will be moved to the next focusable item in the document relative to the trigger. This is done so that if the container
option is used, the focus will move to next logical item. Otherwise, when using container: body
, the focus will potentially drop off the end of the HTML document, leaving a keyboard user in an akward situation.
When navigating backward, out the top of the popover, the focus will be moved to the trigger.
This will not necessarily work with some assistive technologies reading modes.
SASS Reference
Variables
The available Customization options, or Sass variables, that can be customized for the popover component.
Name | Type | Default | Description |
---|---|---|---|
$enable-popover |
boolean | true |
Enable the generation of the popover component classes.
Smaller segements of the popover component classes can be disabled with the following $enable-* variables.
|
$enable-popover-arrow |
boolean | true |
Enable the generation popover arrows classes. |
$enable-popover-header |
boolean | true |
Enable the generation popover header class. |
$enable-popover-body |
boolean | true |
Enable the generation popover body class. |
$enable-popover-close |
boolean | true |
Enable the generation popover close button class. |
$enable-popover-drag |
boolean | true |
Enable the generation popover drag button class. |
$enable-popover-draggable |
boolean | true |
Enable the generation draggable popover class. |
$popover-font-size |
string | .9375rem |
Font size for popover container. |
$popover-bg |
string | $component-bg |
Background color for popover container. |
$popover-margin |
string | .125rem |
Spacing offset for popover container. |
$popover-max-width |
string | rem(288px) (18rem) |
Max width for popover container. |
$popover-border-width |
string | $border-width |
Border width for popover container. |
$popover-border-color |
string | $component-overlay-border-color |
Border color for popover container. |
$popover-border-radius |
string | .3125rem |
Border radius for popover container. |
$popover-inner-border-radius |
string | calc(#{$popover-border-radius} - #{$popover-border-width}) |
Border radius for popover header and body. |
$popover-box-shadow |
string | map-get($shadows, "d2") |
Border radius for popover container. |
$popover-header-padding-y |
string | .5rem |
Vertical padding for popover header. |
$popover-header-padding-x |
string | .75rem |
Horizontal padding for popover header. |
$popover-header-font-size |
string | $font-size-base |
Font size for popover header. |
$popover-header-font-weight |
string | null |
Font weight for popover header. |
$popover-header-color |
string | $headings-color |
Text color for popover header. |
$popover-header-bg |
string | $component-section-bg |
Background color for popover header. |
$popover-header-border-width |
string | $border-width |
Border width for popover header. |
$popover-header-border-color |
string | $component-section-border-color |
Border color for popover header. |
$popover-control-padding-y |
string | .125rem |
Vertical padding for close and drag buttons in popover header. |
$popover-control-padding-x |
string | .3125rem |
Horizontal padding for close and drag buttons in popover header. |
$popover-body-padding-y |
string | .5rem |
Vertical padding for popover body. |
$popover-body-padding-x |
string | .75rem |
Horizontal padding for popover body. |
$popover-body-color |
string | $body-color |
Text color for popover body. |
$popover-arrow-width |
string | 1.25rem |
Width for popover arrow, when placed on top or bottom. Height when used on sides. |
$popover-arrow-height |
string | .625rem |
Height for popover arrow, when placed on top or bottom. Width when used on sides. |
$popover-arrow-color |
string | $popover-bg |
Inner color for popover arrow. |
$popover-arrow-outer0color |
string | $popover-border-color |
Border color for popover arrow. |
Mixins
No mixins available.