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 or disabled 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">&middot;</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.

Sample image
Sample image caption.
<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.

Viewport constraints for popovers.

<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.

Test viewport constraints for popovers.

<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">&times;</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:
How to position the popover - top | bottom | reverse | forward | auto.
When "auto" is specified with a directional value, it will dynamically reorient the popover. For example, if placement is "auto reverse", the popover will display to the left when possible, otherwise it will display right. (Opposite horizontal directions apply for rtl mode.) When just "auto" is specified, a best fit approach will be used.

object:
This is a way to custom position a popover in a specific place not handled by the standard placement locations. A custom positioned popover is forced to using the <body> as the container to make positioning easier. Object structure is: placement: { top: 5, left: 10 }, the same as jQuery offset.

function:
A function call can return either a string or object placement type. The function allows access to the complete popover data-api, as well as passing the popover target and trigger as arguments.

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: container: 'body'

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: viewport: '#viewport'.

If a function is given, it is called with the triggering element DOM node as its only argument. The this context is set to the popover instance.

This option maps to the .boundariesElement option in Popper, so it will accept values of 'viewport', 'window', 'scrollParent', or an HTMLElement reference (JavaScript only). For more information refer to Popper's preventOverflow docs.

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" >&times;</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: 'class-1 class-2'.

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 afterHide event when invoked from the unlink method, or before if set to automatically unlink.

This event may need to be listened for using event delegation, since all cfw.popover namespaced events will be detached from the trigger element as part of the unlink process.

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 cfw.popover namespaced events will be detached from the trigger element as part of the unlink process.

$('#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:

  1. An item with an event handler that makes a callback to create a new popover is interacted with.
  2. Call as needed:
    • $('#myPopover').CFW_Popover('hide');
    • or $('#myPopover').CFW_Popover('unlink');
    • or $('#myPopover').CFW_Popover('dispose');
  3. Update/create the popover object and insert into DOM.
  4. Initialize the popover: $('#myPopover').CFW_Popover(options); with desired options.
  5. 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.