jquerybootstrap-5popper.js

Bootstrap tooltips not working on iOS or Android


I have Bootstrap (popper.js) tooltips working great on desktop Chrome, Firefox and Edge, but for the life of me I can't get them working on iOS (iPhone and iPad) or Android (a Nokia Blue), as well as various BrowserStack devices. Here's my code

HTML

<div class="d-block pb-3">
    <button class="btn-submit btn btn-primary d-inline-block mt-3 align-middle" type="submit" id="calc1" style="width:92px;">Calculate</button>
    <span class="d-inline-block mt-3 px-1 align-middle" style="width:4px;"></span>
    <input id="res1" type="text" class="results form-control d-inline-block mt-3 align-middle" readonly>
    <span id="clippy1" class="clippy clippy-with" data-clipboard-target="#res1">
        <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16">
            <path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/>
             <path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>
        </svg>
    </span>
    <span class="d-inline-block mt-3 ps-2 align-middle" style="width:16px;"> </span>
</div>

JS (main.js)

$(document).ready(function(){

    function clipboard_handler(e) {
        var t = "#" + e.trigger.id,
            f = $(t).closest("form"),
            i = f.find(".clippy"),
            b = f.find("[readonly]");
        b.blur();

        if (e.text == "") {
            i.empty().append('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-x" viewBox="0 0 16 16"><path d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/></svg>');
            setTimeout(() => {
                i.empty().append('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"><path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/><path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/></svg>');
            }, 600);
        } else {
            i.empty().append('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-check" viewBox="0 0 16 16"><path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z"/></svg>');
            i.tooltip({title: "Copied!", delay: { "show": "1", "hide": "600" }});
            setTimeout(() => {
                i.empty().append('<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-clipboard" viewBox="0 0 16 16"><path d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z"/><path d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/></svg>');
                i.tooltip("dispose");
            }, 600);
        }
    }


    $(".clippy").on('click touchstart tap',function(){
        clipboard.on('success', function(e) {
            clipboard_handler(e);
            e.clearSelection();
        });
        clipboard.on('error', function(e) {
            clipboard_handler(e);
        });
    });
});

Bootstrap 5.1, clipboardjs and my own JS

<script src="jquery-3.6.0.min.js"></script>
<script src="bootstrap.bundle.min.js"></script>
<script src="clipboard.min.js"></script>
<script src="main.js"></script>

EDIT:

I've also checked the console log on the BrowserStack sessions, and there is no errors reported.

EDIT:

I've also changed my js code to the below, and it doesn't make any change in the mobile devices listed above, and still works on desktop.


i.tooltip({title: "Copied!"});
setTimeout(() => {
    i.tooltip("dispose");
}, 600);


Solution

  • I'm agreeing with the comment from Cooleronie. I was rushing through implementing a small feature and failed to read the docs (and then over-thinking it)! My original aim of having tooltips reading "Copy to clipboard" on hover with desktop devices, and "Copied!" on copy with desktop and mobile works great now, without it being glitchy. I've tested the below code on Windows 10, Ubuntu, iOS (iPad and iPhone), and Android.

    Here is the (truncated) code:

    HTML

    <span id="clippy1" class="clippy clippy-with" data-clipboard-target="#res1" data-bs-original-title="Copy to clipboard" data-bs-trigger="hover">
    

    JS

    $(document).ready(function(){
    
        function is_touch_enabled() {
            return  ( 'ontouchstart' in window ) ||
                    ( navigator.maxTouchPoints > 0 ) ||
                    ( navigator.msMaxTouchPoints > 0 );
        }
    
        document.querySelectorAll('.clippy').forEach(function(a) {
            if (is_touch_enabled()) {
                $(".clippy").attr("data-bs-trigger", "manual");
            }
            var b = new bootstrap.Tooltip(a);
            a.addEventListener('mouseleave', function() {
                b.hide();
            })
        });
    
    
        function clipboard_handler(e) {
            var t = "#" + e.trigger.id,
                f = $(t).closest("form"),
                i = f.find(".clippy"),
                b = f.find("[readonly]");
            b.blur();
    
            if (e.text == "") {
                i.tooltip("hide");
                }, 600);
            } else {
                i.attr('data-bs-original-title', 'Copied!');
                i.tooltip("show");
                setTimeout(() => {
                    i.tooltip("hide");
                    i.attr('data-bs-original-title', 'Copy to clipboard');
                }, 800);
            }
        }
    
    
        $(".clippy").on('click touchstart tap',function(){
            clipboard.on('success', function(e) {
                clipboard_handler(e);
                e.clearSelection();
            });
            clipboard.on('error', function(e) {
                clipboard_handler(e);
            });
        });
    
    });