27

I've successfully installed clipboard.js and have gotten snippets of text to copy to the clipboard upon click. I'm going to be nesting these snippets of text (or the "btn"s they're within) in the cells of a table.

My challenge:

I need the snippets of text to give me a Tooltip "Copied!" message so that people are aware they are clickable. A great example of this is on the clipboard.js documentation page -- click on any of the buttons that cut or copy to see the tooltip message.

From clipboard.js' documentation:

Although copy/cut operations with execCommand aren't supported on Safari yet (including mobile), it gracefully degrades because Selection is supported.

That means you can show a tooltip saying Copied! when success event is called and Press Ctrl+C to copy when error event is called because the text is already selected.

I'm not particularly adept at JS (it took me a few hours to get this far). So I'm at a dead end... was able to install everything on WP, enqueue the script, and add the text/ functionality:

 <!-- 1. Define some markup -->
    <div id="btn" data-clipboard-text="1">
        <span>text to click</span>
    </div>

    <!-- 2. Include library -->
    <script src="/path/to/dist/clipboard.min.js"></script>

    <!-- 3. Instantiate clipboard by passing a HTML element -->
    <script>
    var btn = document.getElementById('btn');
    var clipboard = new Clipboard(btn);

    clipboard.on('success', function(e) {
    console.log(e);
    console.info('Action:', e.action);
    console.info('Text:', e.text);
    console.info('Trigger:', e.trigger);
    });

    clipboard.on('error', function(e) {
        console.log(e);
        console.error('Action:', e.action);
        console.error('Trigger:', e.trigger);
    });
    </script>

What should I add? Thanks!

Zeno Rocha
  • 3,226
  • 1
  • 23
  • 27
PercentSharp
  • 486
  • 1
  • 5
  • 16

2 Answers2

70

Seems like all you want to do is integrating Clipboard.js with a Tooltip solution.

So here's how you can accomplish that using Bootstrap's Tooltip.

// Tooltip

$('button').tooltip({
  trigger: 'click',
  placement: 'bottom'
});

function setTooltip(btn, message) {
  $(btn).tooltip('hide')
    .attr('data-original-title', message)
    .tooltip('show');
}

function hideTooltip(btn) {
  setTimeout(function() {
    $(btn).tooltip('hide');
  }, 1000);
}

// Clipboard

var clipboard = new Clipboard('button');

clipboard.on('success', function(e) {
  setTooltip(e.trigger, 'Copied!');
  hideTooltip(e.trigger);
});

clipboard.on('error', function(e) {
  setTooltip(e.trigger, 'Failed!');
  hideTooltip(e.trigger);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.10/clipboard.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet"/>

<button class="btn btn-primary" data-clipboard-text="It worked!">Click me</button>
<button class="btn btn-primary" data-clipboard-text="It worked again!">Click me</button>
Zeno Rocha
  • 3,226
  • 1
  • 23
  • 27
  • Thanks for this -- I couldn't find any examples of an operating "success!" bootstrap tooltip on clipboard.js' demo folder. I did make some progress though... 1.I installed and enqued tooltips.js and snippets.js from the clipboardjs.com's source code that you linked. 2. I changed my first bit to `` 3. I added tooltip to `var clipboard = new Clipboard(btn); clipboard.on('success', function(e) { showTooltip('Copied!', e.trigger,); });` – PercentSharp May 24 '16 at 00:15
  • If I use `showTooltip(e.trigger, 'Copied!');` instead of `showTooltip('Copied!', e.trigger,)`, the site shrinks my copyable text into a little button upon click (nothing to do with tooltips). So I'm still baffled as to what I should add next! – PercentSharp May 24 '16 at 00:21
  • I edited my response in order to use Bootstrap's tooltip as required – Zeno Rocha May 24 '16 at 17:40
  • Thank you! This worked -- was able to get everything as a button + the tooltip showed. Any idea what I'd need to tweak to achieve the same function without rendering a button though? i.e. I'd like the text within the button to be actual highlightable text in case things fail. I tried replacing the "button" class with a text-driven class like h4 to no avail. – PercentSharp May 24 '16 at 20:33
  • Also, I attempted to add several buttons by copying the markup: `` and `` but when I click on one the tooltip triggers on all -- thanks for your help – PercentSharp May 24 '16 at 20:46
  • I just edited the code snippet so you can see how multiple buttons would look like. – Zeno Rocha Jun 15 '16 at 19:21
  • beautiful thank you... in the case that I'd want the text in the buttons to be highlightable, this is impossible right? – PercentSharp Jun 26 '16 at 03:50
  • @NateSirrah is your question related to clipboard.js? – Zeno Rocha Jun 27 '16 at 20:08
  • I believe so -- is there a way for buttons to have text within that is able to be copied so that in the event that the clipboard.js script is stripped the item can still be copied? – PercentSharp Jun 28 '16 at 22:00
  • @NateSirrah please create a new question so I can better help you – Zeno Rocha Jun 28 '16 at 22:04
  • 6
    It's better to use tooltip('destroy') to completely remove the tooltip. Otherwise it'll just come back on hover. – David De Sloovere May 31 '17 at 11:03
  • only this worked for me: https://webdesign.tutsplus.com/tutorials/copy-to-clipboard-made-easy-with-clipboardjs--cms-25086 – Ömer An Jun 13 '19 at 17:03
  • I was using the latest version so `new ClipboardJS ` – Vipertecpro Feb 21 '20 at 04:03
8

I've come up with a slight improvement to Zeno's code, which wraps it in a jQuery function, and supports copying from an arbitrary element:

if (typeof $.uf === 'undefined') {
    $.uf = {};
}

$.uf.copy = function (button) {
    var _this = this;

    var clipboard = new ClipboardJS(button, {
        text: function(trigger) {
            var el = $(trigger).closest('.js-copy-container').find('.js-copy-target');
            if (el.is(':input')) {
                return el.val();
            } else {
                return el.html();
            }
        }
    });

    clipboard.on('success', function(e) {
        setTooltip(e.trigger, 'Copied!');
        hideTooltip(e.trigger);
    });

    clipboard.on('error', function(e) {
        setTooltip(e.trigger, 'Failed!');
        hideTooltip(e.trigger);
    });

    function setTooltip(btn, message) {
        $(btn)
        .attr('data-original-title', message)
        .tooltip('show');
    }
    
    function hideTooltip(btn) {
        setTimeout(function() {
            $(btn).tooltip('hide')
            .attr('data-original-title', "");
        }, 1000);
    }

    // Tooltip
    $(button).tooltip({
        trigger: 'click'
    });
};

// Link all copy buttons
$.uf.copy('.js-copy-trigger');
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.10/clipboard.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>

<form>
 <div class="form-group">
  <label>Email</label>
  <div class="input-group js-copy-container">
    <input type="text" class="form-control js-copy-target" name="email" autocomplete="off" value="example@example.com" placeholder="Email goes here" disabled>
    <span class="input-group-btn">
      <button class="btn btn-default js-copy-trigger" type="button">Copy</button>
    </span>
  </div>
 </div>
</form>

You'll notice that we have our button with a class of js-copy-trigger, and the text/control to be copied with the js-copy-target class. Both of these are wrapped in a common js-copy-container class.

This is much better than using id targets, because you often need to generate multiple copy buttons (for example, in a table), and ids must be unique on a page.

goodeye
  • 2,389
  • 6
  • 35
  • 68
alexw
  • 8,468
  • 6
  • 54
  • 86