twitter-bootstrapbootstrap-5

How to enable Bootstrap popovers only for certain (large) breakpoints?


I have a fully working popover:

Markup:

<a data-bs-toggle="popover"
   data-bs-trigger="focus hover"
   data-bs-placement="bottom"
   data-bs-html="true"
   data-bs-content="My popover content"
   href="#">
   Click me
</a>

Invocation:

<script>
    const popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
    const popoverList = popoverTriggerList.map(function (popoverTriggerEl) {
        return new BootstrapPopover(popoverTriggerEl);
    })
</script>

As soon as I hover over my "click link", popover appears the way I want but it also appears when I tap my finger on touchable devices like iPad.

How can I either:

  1. completely disable popover for breakpoints smaller than large
  2. completely disable popover for "touchable" devices

Any hints would be appreciated as I cannot find anything related in the docs.


Solution

  • You need two methods to return current bootstrap breakpoint name as well as method that will return bool based on whether device is touchable or not:

    exports.getBootstrapBreakpoint = function () {
        if (window.matchMedia('(min-width: 1200px)').matches) {
            return 'xl';
        } else if (window.matchMedia('(min-width: 992px)').matches) {
            return 'lg';
        } else if (window.matchMedia('(min-width: 768px)').matches) {
            return 'md';
        } else if (window.matchMedia('(min-width: 576px)').matches) {
            return 'sm';
        } else {
            return 'xs';
        }
    }
    

    Above widths are the default ones for Bootstrap 5.3.3.

    exports.isTouchable = function () {
        return ('ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0);
    }
    

    Next define a method that will trigger a custom event on: load, window resize and device orientation change, but since these can flood an avalanche of events, we need to debounce them:

    let resizeTimeout;
    $(window).on('load resize orientationchange', function () {
        clearTimeout(resizeTimeout);
    
        resizeTimeout = setTimeout(function () {
            $(window).trigger('resized');
        }, 250);
    });
    

    At this point resized is the name of custom event we will trigger every 250 ms.

    Finally we can control the existence of our desired popover via the following logic that combines everything we wrote so far:

    $(window).on('resized', function () {
        const isTouchable = helpers.isTouchable();
        const breakpoint = helpers.getBootstrapBreakpoint();
        const eligible = [
            'lg',
            'xl',
        ];
    
        if (isTouchable) {
            $('#cart-popover').popover('dispose');
        } else {
            if (!eligible.includes(breakpoint)) {
                $('#cart-popover').popover('dispose');
            } else {
                $('#cart-popover').popover();
            }
        }
    });