Search code examples
javascripthtmlclipboardclipboard.js

ClipboardJS - copy data from `data-clipboard-text` held in a separate element


In this snippet, I am using Clipboard.js to copy text from the a element, copying the data held in the data-clipboard-text attribute.

That works fine as shown here:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
  <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>

<a class="btn btn-sm btn-primary copy_data" data-clipboard-text="that, that and the other">Copy</a>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.4/clipboard.min.js"></script>
<script>

var clipboard = new ClipboardJS('.copy_data');;

clipboard.on('success', function(e) {
e.trigger.innerHTML = "Copied!"
setTimeout(function() {
e.trigger.innerHTML = "Copy"
}, 1800);
e.clearSelection();
});

</script>
  </body>

</html>

The issue I am struggling with is working out if it is possible to have the copy link still at the top of the page, but for the data that is copied to be defined against a separate element?

For example, instead of this:

<a class="btn btn-sm btn-primary copy_data" data-clipboard-text="that, that and the other">Copy</a>

Can I do this:

<a class="btn btn-sm btn-primary copy_data">Copy</a>

With the element containing the data to be copied further down the page - e.g.

<div data-clipboard-text="that, that and the other"></div>

This might seem like a silly request, but the reason I'm asking is that due to the way the pages are built where I'm using the copy functionality, the copy button needs to be at the top of the page, but at the point that the HTML is written for displaying the copy button, the content to copy has not been generated yet - it won't be generated until further down the page.

Therefore I thought if I could still hold the data to be held in the data-clipboard-text attribute, but still have the copy button at the top of the page, that would solve it.

However, I can't work out how to achieve that result using Clipboard.js. Ideally I would still like to use Clipboard.js for the copy functionality.

Edit: I have seen the "Copy text from another element" option from the clipboard.js site:

<!-- Target -->
<input id="foo" value="https://github.com/zenorocha/clipboard.js.git">

<!-- Trigger -->
<button class="btn" data-clipboard-target="#foo">
    <img src="assets/clippy.svg" alt="Copy to clipboard">
</button>

However, rather than copying the content from an input element or textarea for example, I wanted to copy the data from the data-clipboard-text attribute of a different element but I wasn't sure how to do that?

Thanks


Solution

  • You can either use the standard trigger (which copies the text inside the element/input) or implement your own custom trigger like this:

    new ClipboardJS('.my-default-trigger')
    
    new ClipboardJS('.my-custom-trigger', {
      text: function(trigger) {
        const targetSelector = trigger.getAttribute('data-clipboard-target')
        const target = document.querySelector(targetSelector)
        return target.getAttribute('data-clipboard-text')
      }
    })
    <html>
      <head>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.11/clipboard.min.js" crossorigin="anonymous"></script>
      </head>
      <body>
        <div id="my-target" data-clipboard-text="some text inside data-clipboard-text">some text inside the element</div>
    
        <button class="my-custom-trigger" data-clipboard-target="#my-target">
          Copy to clipboard (custom trigger)
        </button>
        
        <button class="my-default-trigger" data-clipboard-target="#my-target">
          Copy to clipboard (default trigger)
        </button>
      </body>
    </html>